summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorTaybin Rutkin <taybin@taybin.com>2005-09-25 18:42:24 +0000
committerTaybin Rutkin <taybin@taybin.com>2005-09-25 18:42:24 +0000
commit209d967b1bb80a9735d690d8f4f0455ecb9970ca (patch)
tree9d76ddcd7c1ac9d91bb2b1a33d31b66ce4ded5de /gtk2_ardour
parente4b9aed743fc765219ac775905a221c017c88fba (diff)
Initial import of gtk2_ardour.
git-svn-id: svn://localhost/trunk/ardour2@24 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/.cvsignore7
-rw-r--r--gtk2_ardour/SConscript227
-rw-r--r--gtk2_ardour/ab.xpm648
-rw-r--r--gtk2_ardour/about.cc498
-rw-r--r--gtk2_ardour/about.h80
-rw-r--r--gtk2_ardour/add_route_dialog.cc148
-rw-r--r--gtk2_ardour/add_route_dialog.h39
-rwxr-xr-xgtk2_ardour/ardbg12
-rwxr-xr-xgtk2_ardour/ardev13
-rw-r--r--gtk2_ardour/ardour_dialog.cc169
-rw-r--r--gtk2_ardour/ardour_dialog.h81
-rw-r--r--gtk2_ardour/ardour_image_compositor_socket.h167
-rw-r--r--gtk2_ardour/ardour_message.cc73
-rw-r--r--gtk2_ardour/ardour_message.h49
-rw-r--r--gtk2_ardour/ardour_ui.cc3385
-rw-r--r--gtk2_ardour/ardour_ui.h728
-rw-r--r--gtk2_ardour/ardour_ui.rc1976
-rw-r--r--gtk2_ardour/ardour_ui2.cc785
-rw-r--r--gtk2_ardour/ardour_ui_dependents.cc109
-rw-r--r--gtk2_ardour/ardour_ui_dialogs.cc454
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc315
-rw-r--r--gtk2_ardour/ardour_ui_mixer.cc45
-rwxr-xr-xgtk2_ardour/arprof9
-rwxr-xr-xgtk2_ardour/arval4
-rw-r--r--gtk2_ardour/audio_clock.cc1698
-rw-r--r--gtk2_ardour/audio_clock.h176
-rw-r--r--gtk2_ardour/audio_time_axis.cc2001
-rw-r--r--gtk2_ardour/audio_time_axis.h331
-rw-r--r--gtk2_ardour/automation_gain_line.cc60
-rw-r--r--gtk2_ardour/automation_gain_line.h36
-rw-r--r--gtk2_ardour/automation_line.cc1293
-rw-r--r--gtk2_ardour/automation_line.h223
-rw-r--r--gtk2_ardour/automation_pan_line.cc57
-rw-r--r--gtk2_ardour/automation_pan_line.h35
-rw-r--r--gtk2_ardour/automation_selectable.h21
-rw-r--r--gtk2_ardour/automation_selection.h12
-rw-r--r--gtk2_ardour/automation_time_axis.cc796
-rw-r--r--gtk2_ardour/automation_time_axis.h121
-rw-r--r--gtk2_ardour/axis_view.cc96
-rw-r--r--gtk2_ardour/axis_view.h97
-rw-r--r--gtk2_ardour/canvas-curve.h66
-rw-r--r--gtk2_ardour/canvas-imageframe.c586
-rw-r--r--gtk2_ardour/canvas-imageframe.h80
-rw-r--r--gtk2_ardour/canvas-ruler.c381
-rw-r--r--gtk2_ardour/canvas-ruler.h68
-rw-r--r--gtk2_ardour/canvas-simpleline.c371
-rw-r--r--gtk2_ardour/canvas-simpleline.h66
-rw-r--r--gtk2_ardour/canvas-simplerect.c587
-rw-r--r--gtk2_ardour/canvas-simplerect.h72
-rw-r--r--gtk2_ardour/canvas-waveview.c1013
-rw-r--r--gtk2_ardour/canvas-waveview.h128
-rw-r--r--gtk2_ardour/check_mark.h50
-rw-r--r--gtk2_ardour/connection_editor.cc692
-rw-r--r--gtk2_ardour/connection_editor.h147
-rw-r--r--gtk2_ardour/crossfade_edit.cc1343
-rw-r--r--gtk2_ardour/crossfade_edit.h195
-rw-r--r--gtk2_ardour/crossfade_view.cc263
-rw-r--r--gtk2_ardour/crossfade_view.h84
-rw-r--r--gtk2_ardour/crossfade_xpms.h316
-rw-r--r--gtk2_ardour/curvetest.cc51
-rw-r--r--gtk2_ardour/default_keys.cc113
-rw-r--r--gtk2_ardour/editing.cc104
-rw-r--r--gtk2_ardour/editing.h170
-rw-r--r--gtk2_ardour/editing_syms.h157
-rw-r--r--gtk2_ardour/editor.cc4655
-rw-r--r--gtk2_ardour/editor.h1823
-rw-r--r--gtk2_ardour/editor_audiotrack.cc65
-rw-r--r--gtk2_ardour/editor_canvas_events.cc999
-rw-r--r--gtk2_ardour/editor_cursors.cc121
-rw-r--r--gtk2_ardour/editor_edit_groups.cc210
-rw-r--r--gtk2_ardour/editor_enums.h10
-rw-r--r--gtk2_ardour/editor_export_audio.cc437
-rw-r--r--gtk2_ardour/editor_hscroller.cc270
-rw-r--r--gtk2_ardour/editor_imageframe.cc1179
-rw-r--r--gtk2_ardour/editor_keyboard.cc144
-rw-r--r--gtk2_ardour/editor_keys.cc268
-rw-r--r--gtk2_ardour/editor_markers.cc911
-rw-r--r--gtk2_ardour/editor_mixer.cc311
-rw-r--r--gtk2_ardour/editor_mouse.cc4584
-rw-r--r--gtk2_ardour/editor_nudge.cc30
-rw-r--r--gtk2_ardour/editor_ops.cc3627
-rw-r--r--gtk2_ardour/editor_region_list.cc925
-rw-r--r--gtk2_ardour/editor_route_list.cc444
-rw-r--r--gtk2_ardour/editor_rulers.cc1602
-rw-r--r--gtk2_ardour/editor_scrub.cc0
-rw-r--r--gtk2_ardour/editor_selection_list.cc185
-rw-r--r--gtk2_ardour/editor_tempodisplay.cc493
-rw-r--r--gtk2_ardour/editor_timefx.cc239
-rw-r--r--gtk2_ardour/editor_xpms195
-rw-r--r--gtk2_ardour/enums.h26
-rw-r--r--gtk2_ardour/export_dialog.cc1391
-rw-r--r--gtk2_ardour/export_dialog.h132
-rw-r--r--gtk2_ardour/extra_bind.h138
-rw-r--r--gtk2_ardour/gain_automation_time_axis.cc75
-rw-r--r--gtk2_ardour/gain_automation_time_axis.h33
-rw-r--r--gtk2_ardour/gain_meter.cc762
-rw-r--r--gtk2_ardour/gain_meter.h156
-rw-r--r--gtk2_ardour/gettext.h82
-rw-r--r--gtk2_ardour/ghostregion.cc68
-rw-r--r--gtk2_ardour/ghostregion.h47
-rw-r--r--gtk2_ardour/gprofhelper.c117
-rw-r--r--gtk2_ardour/grouped_buttons.cc96
-rw-r--r--gtk2_ardour/grouped_buttons.h49
-rw-r--r--gtk2_ardour/gtk-custom-hruler.c239
-rw-r--r--gtk2_ardour/gtk-custom-hruler.h70
-rw-r--r--gtk2_ardour/gtk-custom-ruler.c367
-rw-r--r--gtk2_ardour/gtk-custom-ruler.h111
-rw-r--r--gtk2_ardour/gtkscrolledwindow.c972
-rw-r--r--gtk2_ardour/gui_thread.h10
-rw-r--r--gtk2_ardour/i18n.h16
-rw-r--r--gtk2_ardour/imageframe_socket_handler.cc2353
-rw-r--r--gtk2_ardour/imageframe_socket_handler.h705
-rw-r--r--gtk2_ardour/imageframe_time_axis.cc440
-rw-r--r--gtk2_ardour/imageframe_time_axis.h200
-rw-r--r--gtk2_ardour/imageframe_time_axis_group.cc461
-rw-r--r--gtk2_ardour/imageframe_time_axis_group.h299
-rw-r--r--gtk2_ardour/imageframe_time_axis_view.cc460
-rw-r--r--gtk2_ardour/imageframe_time_axis_view.h271
-rw-r--r--gtk2_ardour/imageframe_view.cc395
-rw-r--r--gtk2_ardour/imageframe_view.h212
-rw-r--r--gtk2_ardour/io_menu.h25
-rw-r--r--gtk2_ardour/io_selector.cc857
-rw-r--r--gtk2_ardour/io_selector.h182
-rw-r--r--gtk2_ardour/keyboard.cc1006
-rw-r--r--gtk2_ardour/keyboard.h153
-rw-r--r--gtk2_ardour/keyboard_target.cc258
-rw-r--r--gtk2_ardour/keyboard_target.h82
-rw-r--r--gtk2_ardour/library_ui.cc1541
-rw-r--r--gtk2_ardour/library_ui.h307
-rw-r--r--gtk2_ardour/location_ui.cc886
-rw-r--r--gtk2_ardour/location_ui.h198
-rw-r--r--gtk2_ardour/logmeter.h49
-rw-r--r--gtk2_ardour/main.cc498
-rw-r--r--gtk2_ardour/marker.cc449
-rw-r--r--gtk2_ardour/marker.h107
-rw-r--r--gtk2_ardour/marker_time_axis.cc333
-rw-r--r--gtk2_ardour/marker_time_axis.h164
-rw-r--r--gtk2_ardour/marker_time_axis_view.cc400
-rw-r--r--gtk2_ardour/marker_time_axis_view.h239
-rw-r--r--gtk2_ardour/marker_view.cc142
-rw-r--r--gtk2_ardour/marker_view.h133
-rw-r--r--gtk2_ardour/meter_bridge.cc256
-rw-r--r--gtk2_ardour/meter_bridge.h90
-rw-r--r--gtk2_ardour/meter_bridge_strip.cc238
-rw-r--r--gtk2_ardour/meter_bridge_strip.h104
-rw-r--r--gtk2_ardour/misc_xpms632
-rw-r--r--gtk2_ardour/mixer_strip.cc1466
-rw-r--r--gtk2_ardour/mixer_strip.h257
-rw-r--r--gtk2_ardour/mixer_ui.cc1063
-rw-r--r--gtk2_ardour/mixer_ui.h180
-rw-r--r--gtk2_ardour/new_session_dialog.cc342
-rw-r--r--gtk2_ardour/new_session_dialog.h98
-rw-r--r--gtk2_ardour/option_editor.cc2051
-rw-r--r--gtk2_ardour/option_editor.h282
-rw-r--r--gtk2_ardour/opts.cc154
-rw-r--r--gtk2_ardour/opts.h44
-rw-r--r--gtk2_ardour/pan_automation_time_axis.cc92
-rw-r--r--gtk2_ardour/pan_automation_time_axis.h29
-rw-r--r--gtk2_ardour/panner2d.cc636
-rw-r--r--gtk2_ardour/panner2d.h115
-rw-r--r--gtk2_ardour/panner_ui.cc658
-rw-r--r--gtk2_ardour/panner_ui.h121
-rw-r--r--gtk2_ardour/pixmaps/SConscript10
-rw-r--r--gtk2_ardour/pixmaps/hslider00.xpm179
-rw-r--r--gtk2_ardour/pixmaps/hslider01.xpm25
-rw-r--r--gtk2_ardour/pixmaps/set-next-button.xpm1833
-rw-r--r--gtk2_ardour/pixmaps/small-round-button-01.xpm598
-rw-r--r--gtk2_ardour/pixmaps/toggle-button-00.xpm354
-rw-r--r--gtk2_ardour/pixmaps/toggle-button-01.xpm365
-rw-r--r--gtk2_ardour/pixmaps/vslider00.xpm197
-rw-r--r--gtk2_ardour/pixmaps/vslider01.xpm206
-rw-r--r--gtk2_ardour/playlist_selection.h12
-rw-r--r--gtk2_ardour/playlist_selector.cc249
-rw-r--r--gtk2_ardour/playlist_selector.h65
-rw-r--r--gtk2_ardour/plugin_selector.cc418
-rw-r--r--gtk2_ardour/plugin_selector.h92
-rw-r--r--gtk2_ardour/plugin_ui.cc933
-rw-r--r--gtk2_ardour/plugin_ui.h230
-rw-r--r--gtk2_ardour/po/.cvsignore14
-rw-r--r--gtk2_ardour/po/de_DE.po5179
-rw-r--r--gtk2_ardour/po/el_GR.po5195
-rw-r--r--gtk2_ardour/po/es_ES.po5194
-rw-r--r--gtk2_ardour/po/fr_FR.po5198
-rw-r--r--gtk2_ardour/po/it_IT.po5079
-rw-r--r--gtk2_ardour/po/pt_BR.po5104
-rw-r--r--gtk2_ardour/po/pt_PT.po5094
-rw-r--r--gtk2_ardour/po/ru_RU.po5178
-rw-r--r--gtk2_ardour/point_selection.h12
-rw-r--r--gtk2_ardour/prompter.cc32
-rw-r--r--gtk2_ardour/prompter.h32
-rw-r--r--gtk2_ardour/public_editor.cc144
-rw-r--r--gtk2_ardour/public_editor.h187
-rw-r--r--gtk2_ardour/redirect_automation_line.cc95
-rw-r--r--gtk2_ardour/redirect_automation_line.h64
-rw-r--r--gtk2_ardour/redirect_automation_time_axis.cc169
-rw-r--r--gtk2_ardour/redirect_automation_time_axis.h43
-rw-r--r--gtk2_ardour/redirect_box.cc1203
-rw-r--r--gtk2_ardour/redirect_box.h175
-rw-r--r--gtk2_ardour/redirect_selection.h12
-rw-r--r--gtk2_ardour/region_editor.cc739
-rw-r--r--gtk2_ardour/region_editor.h178
-rw-r--r--gtk2_ardour/region_gain_line.cc96
-rw-r--r--gtk2_ardour/region_gain_line.h43
-rw-r--r--gtk2_ardour/region_selection.cc204
-rw-r--r--gtk2_ardour/region_selection.h56
-rw-r--r--gtk2_ardour/regionview.cc1406
-rw-r--r--gtk2_ardour/regionview.h187
-rw-r--r--gtk2_ardour/rgb_macros.h288
-rw-r--r--gtk2_ardour/route_params_ui.cc705
-rw-r--r--gtk2_ardour/route_params_ui.h184
-rw-r--r--gtk2_ardour/route_redirect_selection.cc183
-rw-r--r--gtk2_ardour/route_redirect_selection.h64
-rw-r--r--gtk2_ardour/route_selection.h12
-rw-r--r--gtk2_ardour/route_ui.cc852
-rw-r--r--gtk2_ardour/route_ui.h140
-rw-r--r--gtk2_ardour/selectable.h41
-rw-r--r--gtk2_ardour/selection.cc573
-rw-r--r--gtk2_ardour/selection.h134
-rw-r--r--gtk2_ardour/selection_templates.h80
-rw-r--r--gtk2_ardour/send_ui.cc152
-rw-r--r--gtk2_ardour/send_ui.h79
-rw-r--r--gtk2_ardour/splash.ppm32
-rw-r--r--gtk2_ardour/streamview.cc921
-rw-r--r--gtk2_ardour/streamview.h171
-rw-r--r--gtk2_ardour/strip_selection.h10
-rw-r--r--gtk2_ardour/tempo_dialog.cc333
-rw-r--r--gtk2_ardour/tempo_dialog.h70
-rw-r--r--gtk2_ardour/time_axis_view.cc803
-rw-r--r--gtk2_ardour/time_axis_view.h290
-rw-r--r--gtk2_ardour/time_axis_view_item.cc950
-rw-r--r--gtk2_ardour/time_axis_view_item.h453
-rw-r--r--gtk2_ardour/time_selection.cc108
-rw-r--r--gtk2_ardour/time_selection.h38
-rw-r--r--gtk2_ardour/track_selection.h10
-rw-r--r--gtk2_ardour/transport_xpms181
-rw-r--r--gtk2_ardour/utils.cc520
-rw-r--r--gtk2_ardour/utils.h74
-rw-r--r--gtk2_ardour/visual_time_axis.cc491
-rw-r--r--gtk2_ardour/visual_time_axis.h277
-rw-r--r--gtk2_ardour/vst_pluginui.cc124
240 files changed, 136995 insertions, 0 deletions
diff --git a/gtk2_ardour/.cvsignore b/gtk2_ardour/.cvsignore
new file mode 100644
index 0000000000..95bc1a733d
--- /dev/null
+++ b/gtk2_ardour/.cvsignore
@@ -0,0 +1,7 @@
+ardour
+ardourx
+ardour.bin
+version.h
+version.cc
+*.mo
+*.pot
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
new file mode 100644
index 0000000000..6ee7c5701b
--- /dev/null
+++ b/gtk2_ardour/SConscript
@@ -0,0 +1,227 @@
+# -*- python -*-
+
+import os
+import os.path
+import glob
+
+Import('env install_prefix final_prefix config_prefix libraries i18n version')
+
+gtkardour = env.Copy()
+
+#
+# this defines the version number of the GTK interface to ardour
+#
+
+domain = 'gtk_ardour'
+
+gtkardour.Append(DOMAIN=domain, MAJOR=1,MINOR=0,MICRO=0)
+gtkardour.Append(CXXFLAGS="-DPACKAGE=\\\"" + domain + "\\\"")
+gtkardour.Append(PACKAGE=domain)
+gtkardour.Append(POTFILE=domain + '.pot')
+
+gtkardour.Merge ( [libraries['ardour2'],
+ libraries['gtkmm2ext'],
+ libraries['midi++2'],
+ libraries['pbd3'],
+ libraries['gtkmm2'],
+ libraries['sigc2'],
+ libraries['libgnomecanvasmm'],
+ libraries['sysmidi'],
+ libraries['sndfile'],
+ libraries['lrdf'],
+ libraries['glibmm2'],
+ libraries['pangomm'],
+ libraries['atkmm'],
+ libraries['gdkmm2'],
+ libraries['gtk2'],
+ libraries['libgnomecanvas2'],
+ libraries['xml'],
+ libraries['soundtouch'],
+ libraries['raptor'],
+ libraries['samplerate'],
+ libraries['jack']]
+ )
+
+if gtkardour['VST']:
+ gtkardour.Merge ([ libraries['fst']])
+
+gtkardour_files=Split("""
+add_route_dialog.cc
+ardour_dialog.cc
+ardour_message.cc
+audio_clock.cc
+automation_gain_line.cc
+axis_view.cc
+default_keys.cc
+editing.cc
+gain_automation_time_axis.cc
+grouped_buttons.cc
+gtk-custom-hruler.c
+gtk-custom-ruler.c
+keyboard.cc
+keyboard_target.cc
+meter_bridge_strip.cc
+opts.cc
+pan_automation_time_axis.cc
+prompter.cc
+redirect_automation_line.cc
+redirect_automation_time_axis.cc
+route_redirect_selection.cc
+tempo_dialog.cc
+time_selection.cc
+version.cc
+ardour_ui_dependents.cc
+ardour_ui_mixer.cc
+automation_pan_line.cc
+curvetest.cc
+editor_scrub.cc
+ghostregion.cc
+gtkscrolledwindow.c
+imageframe_time_axis.cc
+imageframe_time_axis_view.cc
+imageframe_view.cc
+marker.cc
+marker_time_axis.cc
+marker_time_axis_view.cc
+marker_view.cc
+public_editor.cc
+region_gain_line.cc
+region_selection.cc
+selection.cc
+ardour_ui_ed.cc
+canvas-ruler.c
+canvas-simpleline.c
+canvas-simplerect.c
+canvas-waveview.c
+editor_audiotrack.cc
+editor_canvas_events.cc
+editor_cursors.cc
+editor_export_audio.cc
+editor_keys.cc
+editor_nudge.cc
+editor_timefx.cc
+imageframe_time_axis_group.cc
+send_ui.cc
+time_axis_view.cc
+editor_markers.cc
+editor_tempodisplay.cc
+main.cc
+panner2d.cc
+region_editor.cc
+streamview.cc
+utils.cc
+automation_time_axis.cc
+connection_editor.cc
+crossfade_edit.cc
+crossfade_view.cc
+editor_hscroller.cc
+editor_mixer.cc
+imageframe_socket_handler.cc
+location_ui.cc
+route_ui.cc
+time_axis_view_item.cc
+visual_time_axis.cc
+ardour_ui.cc
+ardour_ui2.cc
+ardour_ui_dialogs.cc
+audio_time_axis.cc
+automation_line.c
+canvas-imageframe.cc
+about.cc
+editor.cc
+editor_edit_groups.cc
+editor_imageframe.cc
+editor_keyboard.cc
+editor_mouse.cc
+editor_ops.cc
+editor_region_list.cc
+editor_route_list.cc
+editor_rulers.cc
+editor_selection_list.cc
+export_dialog.cc
+gain_meter.cc
+io_selector.cc
+library_ui.cc
+meter_bridge.cc
+mixer_strip.cc
+mixer_ui.cc
+new_session_dialog.cc
+option_editor.cc
+panner_ui.cc
+playlist_selector.cc
+plugin_selector.cc
+plugin_ui.cc
+redirect_box.cc
+regionview.cc
+route_params_ui.cc
+""")
+
+extra_sources = []
+vst_files = [ 'vst_pluginui.cc' ]
+
+if env['VST']:
+ extra_sources += vst_files
+
+gtkardour.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
+gtkardour.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
+gtkardour.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+
+versionflag = '-DVERSIONSTRING=\\\"' + env['VERSION'] + '\\\"'
+
+gtkardour.Append(CXXFLAGS=versionflag)
+
+gtkardour.VersionBuild(['version.cc','version.h'], 'SConscript')
+
+executable = 'ardour.bin'
+
+ardour = gtkardour.Program(target = executable, source = gtkardour_files + extra_sources)
+
+Default(ardour)
+
+if env['VERSIONED']:
+ Default (env.VersionedExecutable ('tagged_executable', ardour))
+
+if env['NLS']:
+ i18n (gtkardour, gtkardour_files + extra_sources, env)
+
+#install
+
+
+env.Alias('install', env.InstallAs(os.path.join(install_prefix, 'bin')+'/ardour', ardour))
+env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour_ui.rc'))
+env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour'), 'splash.ppm'))
+
+#dist
+env.Alias ('tarball', env.Distribute (env['DISTTREE'],
+ [ 'SConscript',
+ 'i18n.h', 'gettext.h',
+ 'editor_xpms', 'misc_xpms', 'transport_xpms',
+ 'ardour_ui.rc', 'splash.ppm'
+ ] +
+ gtkardour_files + vst_files +
+ glob.glob('po/*.po') + glob.glob('*.h')))
+
+# generate a prototype full-featured ardour_ui.rc file
+
+env.Alias ('protorc', env.Command ('proto.rc', gtkardour_files, """
+ grep set_name $SOURCES | \
+sed 's/.*("\([a-zA-Z_][a-zA-Z_]*\)").*/\\1/' | \
+grep -v '\\.' | sort | uniq | \
+awk '/\\./ {} { printf ("style \\"%s\\"\\n{\\n\
+ fg[NORMAL] = { 0, 0, 0 }\\n\
+ fg[ACTIVE] = { 0, 0, 0 }\\n\
+ fg[SELECTED] = { 0, 0, 0 }\\n\
+ bg[NORMAL] = { 0, 0, 0 }\\n\
+ bg[ACTIVE] = { 0, 0, 0 }\\n\
+ bg[SELECTED] = { 0, 0, 0 }\\n\
+}\\nwidget \\"*%s\\" style \\"%s\\"\\nwidget \\"*%s*\\" style \\"%s\\"\\n\\n", \
+ $$0, $$0, $$0, $$0, $$0) }' > $TARGET && \
+ grep 'color_map\[[a-zA-Z_][a-zA-Z]*\]' $SOURCES | \
+ sed 's/.*\[\([a-zA-Z_][a-zA-Z_]*\)].*/\\1/'| \
+ sort | uniq | \
+ awk '{ printf ("style \\"%s\\"\\n{\\n\
+ fg[NORMAL] = { 0, 0, 0 }\\n\
+ fg[ACTIVE] = { 0, 0, 0 }\\n\
+}\\nwidget \\"*%s\\" style \\"%s\\"\\n \\n\\n", $$0, $$0, $$0) }' >> $TARGET ;
+"""
+))
diff --git a/gtk2_ardour/ab.xpm b/gtk2_ardour/ab.xpm
new file mode 100644
index 0000000000..7496178e78
--- /dev/null
+++ b/gtk2_ardour/ab.xpm
@@ -0,0 +1,648 @@
+/* XPM */
+static const gchar * about_xpm[] = {
+"256 256 389 2",
+" c None",
+". c #DF94BA",
+"+ c #DE94BA",
+"@ c #DD94BB",
+"# c #DC94BB",
+"$ c #DB94BC",
+"% c #DA94BC",
+"& c #D994BC",
+"* c #D894BD",
+"= c #D794BD",
+"- c #D694BE",
+"; c #D594BE",
+"> c #D494BF",
+", c #D394BF",
+"' c #D294BF",
+") c #D194C0",
+"! c #D094C0",
+"~ c #CF94C1",
+"{ c #CE94C1",
+"] c #CD94C1",
+"^ c #CD95C2",
+"/ c #CC95C2",
+"( c #CB95C3",
+"_ c #CA95C3",
+": c #C995C3",
+"< c #C895C4",
+"[ c #C795C4",
+"} c #C695C5",
+"| c #C595C5",
+"1 c #C495C6",
+"2 c #C395C6",
+"3 c #9F7EC4",
+"4 c #8C72C4",
+"5 c #C295C6",
+"6 c #554EC1",
+"7 c #1E2BBF",
+"8 c #C195C7",
+"9 c #544EC2",
+"0 c #C095C7",
+"a c #8A72C4",
+"b c #C095C8",
+"c c #BF95C8",
+"d c #8972C5",
+"e c #BE95C8",
+"f c #534EC2",
+"g c #BD95C9",
+"h c #8872C6",
+"i c #BC95C9",
+"j c #8772C6",
+"k c #BB95CA",
+"l c #524EC3",
+"m c #BA95CA",
+"n c #BA96CA",
+"o c #8672C6",
+"p c #524FC3",
+"q c #B996CA",
+"r c #8572C6",
+"s c #B896CB",
+"t c #8572C7",
+"u c #514FC3",
+"v c #B796CB",
+"w c #8472C7",
+"x c #B696CC",
+"y c #8372C8",
+"z c #B596CC",
+"A c #504FC3",
+"B c #7267C6",
+"C c #A48ACB",
+"D c #947FC9",
+"E c #AB89C8",
+"F c #A88AC9",
+"G c #7467C6",
+"H c #4043C2",
+"I c #625BC5",
+"J c #655AC3",
+"K c #AA89C9",
+"L c #645BC4",
+"M c #8272C8",
+"N c #B496CD",
+"O c #2F37C1",
+"P c #504FC4",
+"Q c #A989C9",
+"R c #3037C0",
+"S c #997EC7",
+"T c #B396CD",
+"U c #927FCA",
+"V c #8172C8",
+"W c #7167C7",
+"X c #A38ACB",
+"Y c #3F43C2",
+"Z c #B296CD",
+"` c #4F4FC4",
+" . c #A28ACB",
+".. c #A28ACC",
+"+. c #B296CE",
+"@. c #927FCB",
+"#. c #7067C7",
+"$. c #8172C9",
+"%. c #605BC6",
+"&. c #B196CE",
+"*. c #635BC4",
+"=. c #8072C9",
+"-. c #A18ACC",
+";. c #B096CE",
+">. c #4143C1",
+",. c #4243C1",
+"'. c #7F72C9",
+"). c #A08ACC",
+"!. c #6F67C7",
+"~. c #5F5BC6",
+"{. c #B096CF",
+"]. c #AC89C8",
+"^. c #A08ACD",
+"/. c #3F43C3",
+"(. c #7F72CA",
+"_. c #907FCB",
+":. c #6F67C8",
+"<. c #AF96CF",
+"[. c #967FC8",
+"}. c #4E4FC4",
+"|. c #8F7FCB",
+"1. c #3E43C3",
+"2. c #9F8ACD",
+"3. c #AE96CF",
+"4. c #7E72CA",
+"5. c #6E67C8",
+"6. c #2E37C1",
+"7. c #9E8ACD",
+"8. c #AD96D0",
+"9. c #7D72CA",
+"0. c #4E4FC5",
+"a. c #5E5BC7",
+"b. c #AC96D0",
+"c. c #4D4FC5",
+"d. c #8D7FCC",
+"e. c #9C8ACE",
+"f. c #AB96D0",
+"g. c #7C72CA",
+"h. c #8C7FCC",
+"i. c #AB96D1",
+"j. c #7C72CB",
+"k. c #AA96D1",
+"l. c #7B72CB",
+"m. c #3D43C3",
+"n. c #6C67C9",
+"o. c #A78ACA",
+"p. c #7367C6",
+"q. c #2F37C0",
+"r. c #977FC8",
+"s. c #A996D2",
+"t. c #4C4FC5",
+"u. c #7B72CC",
+"v. c #A896D2",
+"w. c #7A72CC",
+"x. c #A58ACB",
+"y. c #A797D2",
+"z. c #7973CC",
+"A. c #957FC8",
+"B. c #A697D3",
+"C. c #4B4FC6",
+"D. c #5B5BC8",
+"E. c #A597D3",
+"F. c #7873CC",
+"G. c #2D37C1",
+"H. c #6967CA",
+"I. c #A497D4",
+"J. c #7773CD",
+"K. c #958BD2",
+"L. c #9B7EC6",
+"M. c #877FCF",
+"N. c #A397D4",
+"O. c #4A4FC6",
+"P. c #3C43C4",
+"Q. c #6867CB",
+"R. c #A297D5",
+"S. c #7673CE",
+"T. c #595BC9",
+"U. c #2D37C2",
+"V. c #A197D5",
+"W. c #7573CE",
+"X. c #847FD0",
+"Y. c #978BD1",
+"Z. c #3B43C4",
+"`. c #938BD3",
+" + c #A097D5",
+".+ c #968BD1",
+"++ c #6D67C8",
+"@+ c #6667CB",
+"#+ c #494FC6",
+"$+ c #928BD3",
+"%+ c #837FD0",
+"&+ c #585BC9",
+"*+ c #5A5BC8",
+"=+ c #605BC5",
+"-+ c #9F97D6",
+";+ c #837FD1",
+">+ c #6667CC",
+",+ c #7473CE",
+"'+ c #494FC7",
+")+ c #918BD3",
+"!+ c #6767CB",
+"~+ c #3C43C3",
+"{+ c #9A8AD0",
+"]+ c #5C5BC7",
+"^+ c #8E7FCB",
+"/+ c #9E97D6",
+"(+ c #6567CC",
+"_+ c #908BD3",
+":+ c #7373CE",
+"<+ c #987FC8",
+"[+ c #8E7FCC",
+"}+ c #575BC9",
+"|+ c #9D97D7",
+"1+ c #595BC8",
+"2+ c #867FCF",
+"3+ c #997EC8",
+"4+ c #817FD2",
+"5+ c #7373CF",
+"6+ c #8F8BD4",
+"7+ c #9C97D7",
+"8+ c #9B97D8",
+"9+ c #9A97D8",
+"0+ c #9997D8",
+"a+ c #9997D9",
+"b+ c #9897D9",
+"c+ c #9797D9",
+"d+ c #9797DA",
+"e+ c #9697DA",
+"f+ c #6E73D1",
+"g+ c #7273CF",
+"h+ c #7173D0",
+"i+ c #898BD7",
+"j+ c #3943C5",
+"k+ c #545BCB",
+"l+ c #6167CD",
+"m+ c #464FC8",
+"n+ c #2C37C2",
+"o+ c #9597DA",
+"p+ c #9D8ACE",
+"q+ c #484FC7",
+"r+ c #555BCA",
+"s+ c #6D73D1",
+"t+ c #6167CE",
+"u+ c #7C7FD3",
+"v+ c #9C8ACF",
+"w+ c #948BD2",
+"x+ c #7F7FD3",
+"y+ c #7073D0",
+"z+ c #6F73D0",
+"A+ c #7C7FD4",
+"B+ c #6067CE",
+"C+ c #888BD7",
+"D+ c #8B8BD6",
+"E+ c #8E8BD4",
+"F+ c #6A67CA",
+"G+ c #8C7FCD",
+"H+ c #474FC7",
+"I+ c #6F73D1",
+"J+ c #7B7FD4",
+"K+ c #8A8BD7",
+"L+ c #6267CD",
+"M+ c #6367CD",
+"N+ c #3A43C5",
+"O+ c #615BC5",
+"P+ c #9B8ACF",
+"Q+ c #827FD1",
+"R+ c #7D7FD3",
+"S+ c #857FD0",
+"T+ c #6967CB",
+"U+ c #937FCA",
+"V+ c #7566C5",
+"W+ c #917FCB",
+"X+ c #555BCB",
+"Y+ c #5D5BC7",
+"Z+ c #7E7FD3",
+"`+ c #535BCB",
+" @ c #474FC8",
+".@ c #6467CC",
+"+@ c #7467C5",
+"@@ c #957FC9",
+"#@ c #645AC4",
+"$@ c #7567C5",
+"%@ c #5B5BC7",
+"&@ c #565BCA",
+"*@ c #8C8BD5",
+"=@ c #8A8BD6",
+"-@ c #887FCF",
+";@ c #807FD3",
+">@ c #3A43C4",
+",@ c #8B7FCD",
+"'@ c #7267C7",
+")@ c #998AD0",
+"!@ c #6B67CA",
+"~@ c #807FD2",
+"{@ c #8B8BD5",
+"]@ c #8A7FCE",
+"^@ c #6467CD",
+"/@ c #988BD0",
+"(@ c #8D8BD5",
+"_@ c #575BCA",
+":@ c #9358B7",
+"<@ c #700999",
+"[@ c #A587CA",
+"}@ c #9058B8",
+"|@ c #A487CB",
+"1@ c #8A48B2",
+"2@ c #77199F",
+"3@ c #8338AC",
+"4@ c #9967BE",
+"5@ c #9E77C5",
+"6@ c #8438AC",
+"7@ c #9767BE",
+"8@ c #A587CB",
+"9@ c #8438AB",
+"0@ c #7D29A5",
+"a@ c #9158B8",
+"b@ c #7E29A5",
+"c@ c #8B48B2",
+"d@ c #9F77C4",
+"e@ c #9867BE",
+"f@ c #A077C4",
+"g@ c #9D67BC",
+"h@ c #9C67BC",
+"i@ c #A477C2",
+"j@ c #A687CA",
+"k@ c #A067BA",
+"l@ c #B187C5",
+"m@ c #9E67BB",
+"n@ c #78199F",
+"o@ c #8638AA",
+"p@ c #8638AB",
+"q@ c #9967BD",
+"r@ c #8C48B1",
+"s@ c #8538AB",
+"t@ c #A787C9",
+"u@ c #A077C3",
+"v@ c #A377C2",
+"w@ c #8F48B0",
+"x@ c #8029A4",
+"y@ c #8838AA",
+"z@ c #9957B4",
+"A@ c #A677C1",
+"B@ c #7F29A5",
+"C@ c #9A67BD",
+"D@ c #A887C9",
+"E@ c #A177C3",
+"F@ c #8738AA",
+"G@ c #B386C5",
+"H@ c #7F29A4",
+"I@ c #A987C9",
+"J@ c #9B67BD",
+"K@ c #9458B7",
+"L@ c #8D48B1",
+"M@ c #A277C3",
+"N@ c #9B67BC",
+"O@ c #A777C1",
+"P@ c #A266BA",
+"Q@ c #9658B6",
+"R@ c #A277C2",
+"S@ c #A987C8",
+"T@ c #AC87C7",
+"U@ c #A577C2",
+"V@ c #AA87C8",
+"W@ c #AB76BF",
+"X@ c #9658B5",
+"Y@ c #9558B7",
+"Z@ c #AB87C8",
+"`@ c #8E48B1",
+" # c #8838A9",
+".# c #8938A9",
+"+# c #9558B6",
+"@# c #8E48B0",
+"## c #AB87C7",
+"$# c #AD87C7",
+"%# c #9F67BA",
+"&# c #AD87C6",
+"*# c #9858B5",
+"=# c #AE87C6",
+"-# c #9758B5",
+";# c #9F67BB",
+"># c #9048AF",
+",# c #AF87C6",
+"'# c #A777C0",
+")# c #A977BF",
+"!# c #A877C0",
+"~# c #9958B4",
+"{# c #A167BA",
+"]# c #AA76BF",
+"^# c #B286C5",
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + ",
+". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ + ",
+". + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # @ + ",
+". + @ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # $ # @ + ",
+". + @ # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ # @ + ",
+". + @ # $ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % & % $ # @ + ",
+". + @ # $ % & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & * & % $ # @ + ",
+". + @ # $ % & * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * = * & % $ # @ + ",
+". + @ # $ % & * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = - = * & % $ # @ + ",
+". + @ # $ % & * = - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 4 4 4 4 4 4 4 4 4 4 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 7 7 7 7 7 7 7 7 7 7 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 7 7 7 7 7 7 7 7 7 7 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 a 7 7 7 7 7 7 7 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b 9 7 7 7 7 7 7 9 b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c d 7 7 7 7 7 7 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e d 7 7 7 7 7 7 f e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g h 7 7 7 7 7 7 f g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i j 7 7 7 7 7 7 f i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i j 7 7 7 7 7 7 f i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k j 7 7 7 7 7 7 l k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n o 7 7 7 7 7 7 p n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q r 7 7 7 7 7 7 p q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s t 7 7 7 7 7 7 u s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s t 7 7 7 7 7 7 u s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v w 7 7 7 7 7 7 u v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x y 7 7 7 7 7 7 u x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v y y A A A A A B y z z z z z z z z z z z z z z z z z z z z z z z z z z z z z C y A A A y z z z z z z z z z z z z z z y y A A A A A y y D y 7 7 7 7 7 7 A z z z z z z z z z z z z z z z z z z y B A A A A B y z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z x v s s q m k i E h f 9 9 a 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n F G H 7 7 7 7 7 7 7 7 7 7 7 A D z z z z z z z z z 7 7 7 7 7 7 7 7 7 7 7 y z z z z I 7 7 7 7 7 A z z z z z z z z z z z D A 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 A z z z z z z z z z z z z z z z D H 7 7 7 7 7 7 7 7 7 7 H D z z z z z z z z z z z A 7 7 7 7 7 7 7 7 7 7 A z z z z z z z A 7 7 7 7 7 7 7 7 7 7 A z z z z z z 7 7 7 7 7 7 7 7 7 7 7 t s q m k J 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i K L 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 M N N N N N N N N 7 7 7 7 7 7 7 7 7 7 7 M N N C O 7 7 7 7 7 7 P N N N N N N N N N C P 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 P N N N N N N N N N N N N N C H 7 7 7 7 7 O P P O 7 7 7 7 7 H C N N N N N N N N N P 7 7 7 7 7 7 7 7 7 7 P N N N N N N N P 7 7 7 7 7 7 7 7 7 7 P N N N N N N 7 7 7 7 7 7 7 7 7 7 7 t s q Q R 7 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i S 7 7 7 7 7 7 I D z N T U P 7 7 7 7 7 7 V T T T T T T T V V W O 7 7 7 7 7 7 7 V T X O 7 7 7 7 7 7 7 P T T T T T T T T U O 7 7 7 7 7 7 Y V X T T T V W Y 7 7 7 7 7 7 P T T T T T T T T T T T T V 7 7 7 7 7 O U T T T T U O 7 7 7 7 7 V T T T T T T T T U V V Y 7 7 7 7 7 7 7 P T T T T T T T U V V Y 7 7 7 7 7 7 7 P T T T T T T V V W O 7 7 7 7 7 7 7 t s F R 7 7 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 7 w x z z N T Z Z ` 7 7 7 7 7 O Z Z Z Z Z Z Z Z Z Z .7 7 7 7 7 7 7 V Z O 7 7 7 7 7 7 7 7 ` Z Z Z Z Z Z Z V 7 7 7 7 7 7 O V Z Z Z Z Z Z Z Z V 7 7 7 7 7 7 ` Z Z Z Z Z Z Z Z Z Z Z V 7 7 7 7 7 O .Z Z Z Z Z Z .O 7 7 7 7 7 V Z Z Z Z Z Z Z Z Z Z Z Y 7 7 7 7 7 7 ` Z Z Z Z Z Z Z Z Z Z Z Y 7 7 7 7 7 7 ` Z Z Z Z Z Z Z Z Z ..7 7 7 7 7 7 7 t s R 7 7 7 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 H v x z z N T Z +.@.7 7 7 7 7 7 #.+.+.+.+.+.+.+.+.+.+.Y 7 7 7 7 7 7 $.%.7 7 7 7 7 7 7 7 7 ` +.+.+.+.+.+...O 7 7 7 7 7 O ..+.+.+.+.+.+.+.+.+.$.7 7 7 7 7 7 ` +.+.+.+.+.+.+.+.+.+.$.7 7 7 7 7 O ..+.+.+.+.+.+.+.+...7 7 7 7 7 7 @.+.+.+.+.+.+.+.+.+.+.#.7 7 7 7 7 7 ` +.+.+.+.+.+.+.+.+.+.+.#.7 7 7 7 7 7 ` +.+.+.+.+.+.+.+.&.+.Y 7 7 7 7 7 7 t *.7 7 7 7 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 *.v x z z N T Z +.&.7 7 7 7 7 7 ` &.&.&.&.&.&.&.&.&.&.` 7 7 7 7 7 7 %.7 7 7 Y =.=.Y 7 7 7 ` &.&.&.&.&.&.O 7 7 7 7 7 7 -.&.&.&.&.&.&.&.&.&.&.=.7 7 7 7 7 7 ` &.&.&.&.&.&.&.&.&.-.O 7 7 7 7 7 #.&.&.&.&.&.&.&.&.&.&.#.7 7 7 7 7 O -.&.&.&.&.&.&.&.&.&.=.7 7 7 7 7 7 ` &.&.&.&.&.&.&.&.&.&.&.=.7 7 7 7 7 7 ` &.&.&.&.&.&.&.;.&.+.` 7 7 7 7 7 7 *.7 7 7 >.j j ,.7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 t v x z z N T Z +.&.7 7 7 7 7 7 7 ;.;.;.;.;.;.;.;.;.;.` 7 7 7 7 7 7 7 7 O '.;.;.;.).7 7 7 ` ;.;.;.;.;.!.7 7 7 7 7 7 !.;.;.;.;.;.;.;.;.;.;.;.'.7 7 7 7 7 7 ` ;.;.;.;.;.;.;.;.;.` 7 7 7 7 7 O ;.;.;.;.;.;.;.;.;.;.;.;.O 7 7 7 7 7 ~.;.;.;.;.;.;.;.;.;.'.7 7 7 7 7 7 ` ;.;.;.;.;.;.;.;.;.;.;.'.7 7 7 7 7 7 ` ;.;.;.;.;.;.{.;.&.+.` 7 7 7 7 7 7 7 7 R o k i i ].7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 t v x z z N T Z +.&.` 7 7 7 7 7 7 ^.{.{.{.{.{.{.{.{.{.` 7 7 7 7 7 7 7 O ^.{.{.{.{.{./.7 7 ` {.{.{.{.^.7 7 7 7 7 7 O {.{.{.{.{.{.{.{.{.{.{.{.(.7 7 7 7 7 7 ` {.{.{.{.{.{.{.{._.7 7 7 7 7 7 :.{.{.{.{.{.{.{.{.{.{.{.{.:.7 7 7 7 7 7 _.{.{.{.{.{.{.{.{.(.7 7 7 7 7 7 ` {.{.{.{.{.{.{.{.{.{.{.(.7 7 7 7 7 7 ` {.{.{.{.{.<.{.;.&.+.` 7 7 7 7 7 7 7 R F m k i i g ,.7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i S l p p u [.v x z z N T Z +.&.` 7 7 7 7 7 7 (.<.<.<.<.<.<.<.<.<.}.7 7 7 7 7 7 7 |.<.<.<.<.<.<.}.7 7 }.<.<.<.<.~.7 7 7 7 7 7 :.<.<.<.<.<.<.<.<.<.<.<.<.(.7 7 7 7 7 7 }.<.<.<.<.<.<.<.<.1.7 7 7 7 7 7 2.<.<.<.<.<.<.<.<.<.<.<.<.2.7 7 7 7 7 7 }.<.<.<.<.<.<.<.<.(.7 7 7 7 7 7 }.<.<.<.<.<.<.<.<.<.<.<.(.7 7 7 7 7 7 }.<.<.<.<.3.<.{.;.&.+.` 7 7 7 7 7 7 7 [.q m k i i g f 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 4.3.3.3.3.3.3.3.3.3.}.7 7 7 7 7 7 5.3.3.3.3.3.3.3.}.7 7 }.3.3.3.3.6.7 7 7 7 7 7 3.3.3.3.3.3.3.3.3.3.3.3.3.4.7 7 7 7 7 7 }.3.3.3.3.3.3.3.7.7 7 7 7 7 7 1.3.3.3.3.3.3.3.3.3.3.3.3.3.3.1.7 7 7 7 7 7 7.3.3.3.3.3.3.3.4.7 7 7 7 7 7 }.3.3.3.3.3.3.3.3.3.3.3.4.7 7 7 7 7 7 }.3.3.3.8.3.<.{.;.&.+.` 7 7 7 7 7 7 G s q m k i i g f 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.0.7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.5.7 7 7 7 7 7 a.8.8.8.8.8.8.8.8.8.8.8.8.8.8.a.7 7 7 7 7 7 5.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.0.7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.8.8.8.8.8.a.7 7 7 7 7 7 5.8.8.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.0.7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 9.b.b.b.b.b.b.b.b.b.c.7 7 7 7 7 7 9.b.b.b.b.b.b.b.b.b.b.b.b.b.b.6.7 7 7 7 7 7 d.b.b.b.b.b.b.b.b.b.b.b.b.b.9.7 7 7 7 7 7 c.b.b.b.b.b.b.b.7 7 7 7 7 7 7 e.b.b.b.b.b.b.b.b.b.b.b.b.b.b.d.7 7 7 7 7 7 7 b.b.b.b.b.b.b.9.7 7 7 7 7 7 c.b.b.b.b.b.b.b.b.b.b.b.9.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 g.f.f.f.f.f.f.f.f.f.c.7 7 7 7 7 7 g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.7 7 7 7 7 7 7 f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.7 7 7 7 7 7 c.f.f.f.f.f.f.h.7 7 7 7 7 7 7 f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.7 7 7 7 7 7 7 h.f.f.f.f.f.f.g.7 7 7 7 7 7 c.f.f.f.f.f.f.f.f.f.f.f.g.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.i.i.i.i.i.i.i.i.c.7 7 7 7 7 7 j.i.i.i.i.i.i.i.i.i.i.i.i.i.j.7 7 7 7 7 7 7 i.i.i.i.i.i.i.i.i.i.i.i.i.i.j.7 7 7 7 7 7 c.i.i.i.i.i.i.j.7 7 7 7 7 7 7 i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.7 7 7 7 7 7 7 j.i.i.i.i.i.i.j.7 7 7 7 7 7 c.i.i.i.i.i.i.i.i.i.i.i.j.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z C V V $.=.Y 7 7 7 7 7 7 g.i.k.k.k.k.k.k.k.k.c.7 7 7 7 7 7 l.k.k.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 m.k.k.k.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 c.k.k.k.k.k.k.n.7 7 7 7 7 7 m.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.m.7 7 7 7 7 7 l.k.k.k.k.k.k.l.7 7 7 7 7 7 c.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s o.p.u q.7 7 7 7 7 7 7 7 7 7 7 7 7 g.i.k.k.k.k.k.k.k.k.c.7 7 7 7 7 7 l.k.k.k.k.k.k.k.k.k.k.k.k.k.n.7 7 7 7 7 7 c.k.k.k.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 c.k.k.k.k.k.k.c.7 7 7 7 7 7 c.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.c.7 7 7 7 7 7 c.k.k.k.k.k.k.l.7 7 7 7 7 7 c.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r.H 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 g.i.k.k.s.s.s.s.s.s.t.7 7 7 7 7 7 u.s.s.s.s.s.s.s.s.s.s.s.s.s.t.7 7 7 7 7 7 t.s.s.s.s.s.s.s.s.s.s.s.s.s.s.u.7 7 7 7 7 7 t.s.s.s.s.s.s.t.7 7 7 7 7 7 t.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.t.7 7 7 7 7 7 t.s.s.s.s.s.s.u.7 7 7 7 7 7 t.s.s.s.s.s.s.s.s.s.s.s.u.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k p 7 7 7 7 7 7 I M T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.v.v.v.t.7 7 7 7 7 7 w.v.v.v.v.v.v.v.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.v.v.v.w.7 7 7 7 7 7 t.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.w.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.w.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i E R 7 7 7 7 7 q.C z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.v.v.v.t.7 7 7 7 7 7 w.v.v.v.v.v.v.v.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.v.v.v.w.7 7 7 7 7 7 t.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.w.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.w.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i R 7 7 7 7 7 q.x.z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.y.y.t.7 7 7 7 7 7 z.y.y.y.y.y.y.y.y.y.y.y.y.y.t.7 7 7 7 7 7 t.y.y.y.y.y.y.y.y.y.y.y.y.y.y.z.7 7 7 7 7 7 t.y.y.y.y.y.y.t.7 7 7 7 7 7 t.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.t.7 7 7 7 7 7 t.y.y.y.y.y.y.z.7 7 7 7 7 7 t.y.y.y.y.y.y.y.y.y.y.y.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g J 7 7 7 7 7 7 A.x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 z.B.B.B.B.B.B.B.B.B.B.B.B.B.C.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.B.B.B.z.7 7 7 7 7 7 C.B.B.B.B.B.B.C.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.C.7 7 7 7 7 7 C.B.B.B.B.B.B.z.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e ].7 7 7 7 7 7 H v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 z.B.B.B.B.B.B.B.B.B.B.B.B.B.C.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.B.B.B.z.7 7 7 7 7 7 C.B.B.B.B.B.B.D.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.C.7 7 7 7 7 7 D.B.B.B.B.B.B.z.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e J 7 7 7 7 7 7 G v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 F.E.E.E.E.E.E.E.E.E.E.E.E.E.C.7 7 7 7 7 7 G.E.E.E.E.E.E.E.E.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.G.7 7 7 7 7 7 F.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.E.E.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e ,.7 7 7 7 7 7 t v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 F.E.E.E.E.E.E.E.E.E.E.E.E.E.H.7 7 7 7 7 7 7 E.E.E.E.E.E.E.E.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.F.7 7 7 7 7 7 G.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.7 7 7 7 7 7 7 F.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.E.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e 7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 J.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 7 I.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 C.I.I.I.I.I.I.K.7 7 7 7 7 7 7 I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.7 7 7 7 7 7 7 K.I.I.I.I.I.I.J.7 7 7 7 7 7 C.I.I.I.I.I.I.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c L.7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 J.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 7 M.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 C.I.I.I.I.I.I.I.G.7 7 7 7 7 7 I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 G.I.I.I.I.I.I.I.J.7 7 7 7 7 7 C.I.I.I.I.I.N.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c d 7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 J.N.N.N.N.N.N.N.N.N.N.N.N.N.N.7 7 7 7 7 7 7 J.N.N.N.N.N.N.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.N.N.N.N.O.7 7 7 7 7 7 J.N.N.N.N.N.N.N.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.N.N.N.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c d 7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 J.N.N.N.N.N.N.N.N.N.N.N.N.N.N.P.7 7 7 7 7 7 O.N.N.N.N.N.N.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.N.N.N.N.J.7 7 7 7 7 7 Q.N.N.N.N.N.N.N.N.N.N.N.N.N.N.O.7 7 7 7 7 7 J.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.R.N.N.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c d 7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 S.R.R.R.R.R.R.R.R.R.R.R.R.R.R.T.7 7 7 7 7 7 7 R.R.R.R.R.R.R.R.R.R.R.R.R.Q.7 7 7 7 7 7 O.R.R.R.R.R.R.R.R.U.7 7 7 7 7 O.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.7 7 7 7 7 7 R.R.R.R.R.R.R.R.S.7 7 7 7 7 7 O.R.R.V.R.N.N.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c d 7 7 7 7 7 7 7 t v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 W.V.V.V.V.V.V.V.V.V.V.V.V.V.V.X.7 7 7 7 7 7 7 W.V.V.V.V.V.V.V.V.V.V.V.W.7 7 7 7 7 7 7 O.V.V.V.V.V.V.V.V.T.7 7 7 7 7 7 V.V.V.V.V.V.V.V.V.V.V.V.V.X.7 7 7 7 7 7 T.V.V.V.V.V.V.V.V.X.7 7 7 7 7 7 U.V.V.V.R.N.N.I.I.E.E.Y.G.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e 7 7 7 7 7 7 7 *.v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 W.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.U.7 7 7 7 7 7 Z.V.V.V.V.V.V.V.V.V.V.W.7 7 7 7 7 7 7 7 O.V.V.V.V.V.V.V.V.`.U.7 7 7 7 7 W.V.V.V.V.V.V.V.V.V.V.V.V.T.7 7 7 7 7 7 `.V.V.V.V.V.V.V.V.V.7 7 7 7 7 7 7 +V.V.R.N.N.I.I.E..+G.7 7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e R 7 7 7 7 7 7 R v x z z N T Z +.-.O 7 7 7 7 7 7 ++i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 W.V. + + + + + + + + + + + + + +@+7 7 7 7 7 7 7 @+ + + + + + + + +W.7 7 #+7 7 7 7 7 7 #+ + + + + + + + + +@+7 7 7 7 7 Z. + + + + + + + + + + +$+7 7 7 7 7 7 @+ + + + + + + + + + +7 7 7 7 7 7 7 W.V.V.R.N.N.I.I.F.G.7 C.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e J 7 7 7 7 7 7 7 u x z z N T Z @.O 7 ` 7 7 7 7 7 c.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 W.V. + + + + + + + + + + + + + + +U.7 7 7 7 7 7 7 @+ + + + + +$+#+7 7 #+W.7 7 7 7 7 7 #+ + + + + + + + + + +Z.7 7 7 7 7 %+ + + + + + + + + + +&+7 7 7 7 7 Z. + + + + + + + + + + +#+7 7 7 7 7 7 U.V.V.R.N.N.K.*+7 7 C.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e ].7 7 7 7 7 7 7 7 u D z N U =+7 7 O ^.}.7 7 7 7 1.i.k.k.s.v.v.y.B.B.7 7 7 7 7 7 7 O.V. + +-+-+-+-+-+-+-+-+-+-+-+-+-+;+7 7 7 7 7 7 7 7 Z.>+,+,+'+7 7 7 U.)+,+7 7 7 7 7 7 7 -+-+-+-+-+-+-+-+-+-+)+U.7 7 7 7 U.)+-+-+-+-+-+-+-+-+,+7 7 7 7 7 U.)+-+-+-+-+-+-+-+-+-+-+-+>+7 7 7 7 7 7 7 U.!+S.J.O.7 7 7 ~+B.z.7 7 7 7 7 7 7 f.b.8.8.3.<.{.;.&.+.7 7 7 7 7 7 7 u s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g J 7 7 7 7 7 7 7 7 7 7 7 7 7 7 O ).{.(.7 7 7 7 7 j.k.k.{+v.v.y.Y.C.7 7 7 7 7 7 7 7 !+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+&+7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 )+-+,+7 7 7 7 7 7 7 '+)+-+-+-+-+-+-+-+-+-+)+U.7 7 7 7 U.)+-+-+-+-+-+-+,+7 7 7 7 7 U.)+-+-+-+-+-+-+-+-+-+-+-+-+)+7 7 7 7 7 7 7 7 7 7 7 7 7 7 G..+B.z.7 7 7 7 7 7 7 c.e.8.8.3.<.{.;.-.` 7 7 7 7 7 7 7 7 G q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i f 7 7 7 7 7 7 7 7 7 7 7 7 O -.;.{.<.6.7 7 7 7 7 7 7 ]+v.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 '+-+-+-+-+-+-+-+-+-+-+-+-+-+-+'+7 7 7 7 7 7 7 7 7 7 7 7 U.,+-+-+,+7 7 7 7 7 7 7 7 7 7 7 -+-+-+-+-+-+-+-+)+Z.7 7 7 7 7 &+;+-+-+;+&+7 7 7 7 7 Z.)+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&+7 7 7 7 7 7 7 7 7 7 7 7 P..+E.B.z.7 7 7 7 7 7 7 7 7 7 7 3.<.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 l i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i l 7 7 7 7 7 7 7 7 7 7 Y ..&.;.{.<.^+7 7 7 7 7 7 7 t.v.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 '+-+-+/+/+/+/+/+/+/+/+/+/+/+/+/+(+7 7 7 7 7 7 7 7 7 7 U._+/+/+/+:+7 7 7 7 7 7 7 7 7 7 7 /+/+/+/+/+/+/+/+/+/+(+7 7 7 7 7 7 7 7 7 7 7 7 7 U.(+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+'+7 7 7 7 7 7 7 7 7 7 *+I.E.E.B.z.7 7 7 7 7 7 7 7 7 7 7 3.<.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 l i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k <+>.7 7 7 7 7 7 H U Z +.&.;.{.<.3.[+6.7 7 7 7 m.u.v.w.z.z.z.F.F.J.J.J.J.S.W.W.W.W.;+-+-+/+/+/+/+/+/+/+/+/+/+/+/+/+/+_+}+7 7 7 7 7 7 Z.(+/+/+/+/+/+_+:+:+:+:+:+:+:+:+:+:+:+/+/+/+/+/+/+/+/+/+/+/+/+(+Z.7 7 7 7 7 7 7 7 '+:+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+|+/+/+>+U.7 7 7 7 7 7 1+2+I.I.E.E.B.Y.z.w.w.u.l.l.j.g.9.9.9.3.<.(.'.=.$.V V M y y y w t t r o 3+i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s t w y y z N T Z +.&.;.{.<.3.8.8.d.g.j.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+4+5+5+5+6+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+4+5+5+5+5+6+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+/+/+-+-+)+W.W.W.X.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+7 7 7 7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.C.7 7 7 7 u.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i E j o r t t w y y y M V V @.&.;.{.<.3.8.8.b.f.i.k.k.u.w.w.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+g+g+h+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+i+j+7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+k+l+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.Y.6.7 7 u.k.k.i.f.d.9.9.7.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i S l >.7 7 7 7 u A A O 7 7 7 7 Y (.<.3.8.8.b.f.i.k.k.7 7 7 y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+m+7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+i+7 n+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n *.7 7 7 x z z N T U %.O 7 7 1.7.8.8.b.f.i.k.k.7 7 7 y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+m+7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+o+e+e+e+e+e+k+7 7 l+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.-.` 7 7 6.p+8.b.f.i.k.k.t.t.t.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+q+q+q+8+9+9+9+0+r+j+7 b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+7 7 7 j+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.++0.0.^+<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.` 7 7 6.p+b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+t+7 7 7 7 u+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.^.7 7 7 a.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+j+k+n+7 7 k+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.~.7 7 7 e.f.v+l.l.u.w.w.y.B.B.E.E.I.I.w+Q.O.O.T.%+ +,+,+,+:+_+6+5+g+g+g+h+8+9+9+x+y+7 7 7 z+z+z+u+c+c+d+e+A+t+m+m+m+B+C+o+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+A+7 i+k+7 7 7 D+b+b+a+a+0+0+9+x+h+h+h+g+E+7+|+|+:+:+,+,+,+ + +V.V.R.N.N.K.J.C.C.C.F+m.7 7 u.k.k.j.g.9.9.9.7.<.{.;.&.+.Z T C B A u u t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.|.7 7 7 ++f.G+c.6.7 7 7 y.B.B.E.E.I.J.7 7 Q.W.O.7 7 Z.7 7 7 _+4+q+n+7 7 7 8+9+9+H+7 7 7 7 7 7 7 m+c+c+I+n+7 n+m+m+n+7 n+J+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+m+m+e+K+7 7 7 L+b+b+a+a+0+0+9+M+N+7 7 7 g+7+|+|+'+U.7 7 7 + +V.V.R.N.Q.7 7 7 C.C.C.7 7 7 u.k.k.c.1.7 7 7 4.<.{.;.&.+.Z O+7 7 B y u 7 R r.m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.7 7 7 c.f.i.k.P+7 7 7 y.B.B.E.E.J.7 7 Q.R.V.V.Z.7 '+-+)+Q+/+|+|+E+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+m+7 n+i+e+e+i+7 7 n+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+i+7 A+e+d+m+7 7 n+b+b+a+a+0+0+9+9+9+N+7 7 g+7+|+|+/+_+7 7 7 + +V.V.R.1+7 7 G..+E.B.B.t.7 7 u.k.k.i.f.1.7 7 4.<.{.;.&.+.` 7 7 D z x v u 7 7 o k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.1.7 7 6.f.i.k.k.7 7 7 y.B.B.E.E.G.7 7 N.R.V.V.W.7 7 ;+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+m+7 m+e+e+e+e+j+7 7 C+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+k+j+e+e+d+u+7 7 7 R+b+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.V.S+7 7 G.K.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.$.7 7 O+z z x v s 7 7 R k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.}.7 7 7 f.i.k.k.7 7 7 y.B.B.E..+7 7 O.N.R.V.V.$+7 7 '+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+A+f+A+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+n+t+e+e+d+c+n+7 7 j+b+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.V.P.7 7 T+I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.O 7 7 U+z z x v s u 7 7 V+i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.}.7 7 7 f.i.k.k.7 7 7 y.B.B.E.F.7 7 O.N.R.V.V. +7 7 7 -+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+f+n+e+e+e+d+c+l+7 7 7 D+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.`.7 7 7 K.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.W+7 7 7 N z z x v s t 7 7 R i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.}.7 7 7 f.i.k.k.7 7 7 y.B.B.E.F.7 7 O.N.R.V.V. +7 7 7 -+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+j+k+e+e+e+d+c+c+7 7 7 X+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.W.7 7 G.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.=.7 7 Y N z z x v s [.7 7 7 i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.}.7 7 7 f.i.k.k.7 7 7 y.B.B.E.F.7 7 O.N.R.V.V. +7 7 U.-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+f+f+f+j+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+A+7 i+e+e+e+d+c+c+k+7 7 n+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.T.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.` 7 7 P N z z x v s s 7 7 7 j i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.1.7 7 1.f.i.k.k.7 7 7 y.B.B.E.E.7 7 P.N.R.V.V.%+7 7 '+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+f+j+7 n+m+m+n+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+k+j+e+e+e+e+d+c+c+u+7 7 7 y+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.O.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.` 7 7 P N z z x v s s 7 7 7 j i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.7 7 7 Y+f.i.k.k.7 7 7 y.B.B.E.E.*+7 7 w+R.V.V.@+7 7 )+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+m+7 7 m+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+7 j+m+m+m+m+m+m+m+m+7 7 7 j+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.O.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.` 7 7 P N z z x v s s 7 7 7 j i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.|.7 7 7 9.f.i.k.k.7 7 7 y.B.B.E.E.I.C.7 O.R.V.`.U.7 ,+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+z+7 7 j+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+B+n+m+m+m+m+m+m+m+m+m+j+7 7 7 Z+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.O.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.` 7 7 P N z z x v s s 7 7 7 j i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.:.7 7 6.b.f.i.k.k.7 7 7 y.B.B.E.E.I.I.Q.7 P.O.U.U.W.-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+j+7 7 t+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+n+t+e+e+e+e+e+d+c+c+c+b+n+7 7 X+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.O.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.#.7 7 P N z z x v s o.7 7 7 E i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.6.7 7 5.b.f.i.k.k.7 7 7 y.B.B.E.E.I.K.G.O.S+W.W. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+7 7 7 f+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+J+7 e+e+e+e+e+e+d+c+c+c+b+L+7 7 7 0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.W.7 7 7 I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.=.7 7 O N z z x v s t 7 7 7 i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.~.7 7 1.8.b.f.i.k.k.7 7 7 y.B.B.E.E.K.G.7 w+R.V.V. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+7 7 7 f+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+j+`+e+e+e+e+e+e+d+c+c+c+b+D+7 7 7 L+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.X.7 7 7 K.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.7 7 7 N z z x v s *.7 7 l i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.'.7 7 6.p+8.b.f.i.k.k.7 7 7 y.B.B.E.E.C.7 7 J.R.V.V. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+n+7 7 b+b+b+c+c+7 7 7 k+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+C+7 C+e+e+e+e+e+e+d+c+c+c+b+b+ @7 7 n+0+9+9+9+q+7 7 .@7+|+|+/+'+7 7 7 + +V.V.U.7 7 *+I.E.E.B.z.7 7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.%.7 7 M z z x v s R 7 7 3+i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n +@7 7 7 @@z z N T Z +.#.7 7 1.7.8.8.b.f.i.k.k.7 7 7 y.B.B.E.E.*+7 7 7 7 7 7 7 7 '+>+-+/+/+|+|+7+7 7 7 8+9+9+9+0+H+7 7 D+b+b+c+c+k+7 7 7 f+e+i+t+n+7 7 B+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+`+j+o+e+e+e+e+e+e+d+c+c+c+b+b+z+7 7 7 L+9+9+9+h+7 7 n+E+|+5+U.}+7 7 7 + +V.V.Q.7 7 7 T+E..+D.G.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.+.O 7 H z z x v t 7 7 #@k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i E j $@R 7 7 7 q.B y M V ` 7 7 O :.<.3.8.8.b.f.v+l.Y+7 7 7 %@z.Y.E.E.K.P.7 7 7 7 7 7 7 7 7 U./+/+6+5+&@7 7 7 &@h+*@9+0+Z+7 7 @z+L+c+c+=@n+7 7 7 7 7 n+C+`+7 n+s+C+s+B+n+7 7 j+s+J+o+o+o+o+o+o+o+o+J+B+7 n+s+i+e+e+e+e+e+d+c+c+c+D+z+ @7 7 7 7 M+*@9+8+n+7 7 7 7 7 '+/+7 7 7 #+W.V.V.R.O.7 7 7 7 7 G.Y.t.7 7 6.l.P+j.++6.7 7 1.(._.;.&.+. .O 7 A C x w R 7 p m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i S l p p u u u u A A P P ` $.W+;.{.<.3.8.8.b.f.G+c.c.t.t.t.t.C.-@E.E.K.P.O.J.S.W.W.W.Z.7 7 7 (+/+4+q+q+q+q+q+q+H+x+9+0+0+y+j+7 7 j+c+c+c+K+m+7 7 n+k+i+o+C+j+7 n+J+m+m+m+m+m+m+m+B+o+o+o+o+o+o+o+o+B+m+m+m+m+A+e+e+e+e+e+d+c+c+c+R+ @ @ @ @H+H+H+x+9+8+;@>@7 7 >@5+/+/+'+'+'+#+#+V.V.R.N.Q.G.7 7 *+Y.B.F+t.t.t.c.,@c.c.c.0.0.}.}.:.;.&.+.Z T '@H 7 7 7 u [.q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.F.7 7 N.N.R.V.V. + +'+7 7 '+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B..+7 7 C.N.N.R.V.V. + +,+7 7 '+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.F.7 7 C.N.N.R.V.V. + +>+7 7 :+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.M.7 7 7 w+N.R.V.V. + +U.7 U./+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.C.7 7 O.w+R.V.V.$+Z.7 Z.)+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.T+G.7 7 O.O.Z.7 Z.>+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+m+7 7 7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z y M V V $.=.'.(.2.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.F.J.J.J.J.S.`.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+K+n+7 7 I+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+_+:+,+;+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z A P 7 7 7 7 ` ` |.3.8.8.b.f.i.c.c.s.v.v.y.B.B.E.C.C.G.7 P.O.X.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+m+7 7 z+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+:+7 7 '+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N P 7 7 ` ;.{.<.3.8.8.b.f.i.7 7 s.v.v.y.B.B.E.E.I.J.P.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+m+7 7 z+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+:+7 7 '+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N W 7 7 Y ;.{.<.3.8.8.b.f.j.7 7 u.v.v.y.B.B.E.E.I.C.1+N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+c+c+c+c+m+7 7 z+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+z+m+7 z+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+*@H+n+q+8+7+7+7+|+|+Q+'+'+>+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N X 7 7 7 ;.{.<.3.8.8.b.f.c.7 7 ]+v.v.y.B.B.E.E.I.7 2+N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+ @7 7 z+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+ @7 7 z+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+a+a+0+0+h+7 7 q+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T O 7 7 '.{.<.3.8.8.b.f.7 7 7 6.v.v.y.B.B.E.E.M.G.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+ @7 7 z+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+ @7 7 z+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+a+a+0+0+h+7 7 q+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T =+7 7 ` {.<.3.8.8.b.g.7 6.7 7 )@v.y.B.B.E.E.*+*+N.N.R.V.V. + +-+)+>+'+'+q+5+7+7+7+8+8+*@h+h+y+y+Z+b+b+L+ @L+b+b+ @7 7 z+b+b+b+R+z+z+z+z+R+b+b+b+b+D+L+ @ @ @z+D+b+b+D+z+j+7 7 X+z+z+z+b+b+b+b+D+z+ @ @ @X+R+b+a+a+0+y+r+7 7 N+h+g+g+E+4+5+:+:+,+;+-+ + +V.V.R.N.N.J.C.C.C.F+Y.y.v.v.s.k.l.j.g.9.9.8.3.<.:.` ` #.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T V 7 7 O {.<.3.8.8.b.c.c.Y+7 7 !@v.y.B.B.E.E.G.M.N.N.R.V.V. + +&+7 7 (+:+q+7 n+~@7+8+8+x+H+7 7 7 @D+n+7 7 @a+a+ @7 7 y+a+a+a+L+ @7 7 @L+a+a+a+y+7 7 X+y+X+7 7 Z+a+y+7 7 7 7 7 7 7 7 a+a+D+j+7 7 @ @j+7 7 L+a+a+0+7 7 7 7 7 7 7 7 g+(+q+7 7 7 '+-+ + +V.V.R.J.G.7 C.F.H.7 7 F+v.v.s.k.c.6.7 7 7 8.4.6.7 7 7 7 ` T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z 7 7 7 ^.<.3.8.8.b.7 j.l.7 7 t.v.y.B.B.E.M.7 I.N.N.R.V.V. +#+7 7 ;+/+/+|+q+7 7 g+8+8+9+9+M+7 7 @j+7 7 7 @a+a+ @7 7 y+a+a+a+a+y+7 y+a+a+a+a+Z+7 7 X+a+a+a+X+7 y+a+a+a+ @7 7 y+a+a+a+a+a+y+7 7 y+a+a+a+j+7 7 Z+a+0+0+h+7 7 q+8+7+7+7+|+|+(+7 7 '+-+ + +V.V.S.7 7 *+I.E.E.z.7 7 t.v.s.k.k.v+7 7 7 9.7 }.(.!.7 7 7 U N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z Y 7 7 :.<.3.8.8.9.7 i.k.7 7 7 v.y.B.B.E.*+C.I.N.N.R.V.V.W.7 7 &+-+/+/+|+|+7 7 n+8+8+9+9+h+7 7 7 n+Z+{@7 H+0+0+H+7 7 y+0+0+0+{@n+L+0+0+0+0+0+r+7 7 y+0+0+0+y+7 y+0+0+0+H+7 7 y+0+0+0+0+0+y+7 7 0+0+0+0+L+7 7 L+0+0+0+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +V.`.U.7 G.I.I.E.E.B.C.7 7 ]@s.k.k.i.7 7 7 1.^+<.{.;.` 7 7 O+N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z #.7 7 ` <.3.8.8.c.c.i.k.c.7 7 w.y.B.B.E.G.J.I.N.N.R.V.V.U.7 7 ;+-+/+/+|+|+q+7 7 ^@8+9+9+y+7 7 n+{@0+0+j+H+0+0+H+7 7 y+0+0+0+j+H+0+0+0+0+0+0+H+7 7 y+0+0+0+y+7 y+0+0+0+H+7 7 y+0+0+0+0+0+{@y+y+0+0+0+0+y+7 7 H+0+0+0+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +V.T.7 7 1+I.I.E.E.B.z.7 7 m.s.k.k.i.7 7 7 p+3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z @.7 7 7 <.3.8.8.7 g.i.k.n.7 7 ]+y.B.B..+7 I.I.N.N.R.V.X.7 7 7 -+-+/+/+|+|+g+7 7 n+8+9+9+h+7 7 H+9+9+9+9+9+9+9+H+7 7 h+9+9+H+n+*@9+9+9+9+9+9+H+7 7 N+9+9+9+9+9+9+9+9+9+H+7 7 h+9+9+9+9+9+9+9+9+9+9+9+9+h+7 7 H+9+9+9+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +V.U.7 7 J.I.I.E.E.B.B.7 7 7 ]@k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.7 7 7 (.3.8.9.7 f.i.k.P+7 7 6.y.B.B.H.C.I.I.N.N.R.V.W.7 7 Z.-+-+/+/+|+|+~@7 7 7 8+9+9+h+7 7 H+9+9+9+9+9+9+9+H+7 7 h+9+h+7 x+9+9+9+9+9+9+9+M+7 7 7 H+9+9+9+9+9+9+9+9+H+7 7 h+9+9+9+9+9+9+9+9+9+9+9+9+h+7 7 H+9+9+9+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +V.7 7 7 w+I.I.E.E.B.B.6.7 7 u.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.` 7 7 ~.3.8.0.c.f.i.k.k.6.7 7 /@B.B.~+F.I.I.N.N.R.V.O.7 7 '+-+-+/+/+|+|+7+7 7 7 h+9+9+h+7 7 H+9+9+9+9+9+9+9+H+7 7 h+*@7 M+9+9+9+9+9+9+9+9+9+n+7 7 7 n+h+9+9+9+9+9+9+H+7 7 h+9+9+9+9+9+9+9+9+9+x+h+h+r+7 7 H+9+9+9+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +W.7 7 7 N.I.I.E.E.B.B.t.7 7 t.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.=.7 7 1.3.8.7 9.f.i.k.k.t.7 7 F+B.Y.7 .+I.I.N.N.R.V.O.7 7 '+-+-+/+/+|+|+7+7 7 7 h+8+8+h+7 7 q+8+8+8+8+8+8+8+q+7 7 &@n+7 n+8+8+8+8+8+8+8+8+8+(@N+7 7 7 7 q+(@8+8+8+8+q+7 7 h+8+8+8+8+8+8+(@q+7 7 q+q+N+7 7 q+8+8+8+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +W.7 7 7 N.I.I.E.E.B.B.t.7 7 t.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.-.7 7 7 7.9.7 b.f.i.k.k.u.7 7 t.B.F+~+E.I.I.N.N.R.V.O.7 7 '+-+-+/+/+|+|+7+7 7 7 h+8+8+h+7 7 q+8+8+8+8+8+8+8+q+7 7 &@N+7 7 q+8+8+8+8+8+8+8+8+8+8+^@7 7 7 7 n+(@8+8+8+q+7 7 h+8+8+8+8+8+h+7 7 n+(@8+8+h+7 7 q+8+8+8+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +W.7 7 7 N.I.I.E.E.B.B.t.7 7 t.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.O 7 7 4.0.0.b.f.i.k.k.s.7 7 7 B.~+H.E.I.I.N.N.R.V.O.7 7 '+-+-+/+/+|+|+7+7 7 7 g+7+7+g+7 7 q+7+7+7+7+7+7+7+q+7 7 g+E+7 7 7 g+7+7+7+7+7+7+7+7+7+7+E+>@7 7 7 n+E+7+7+q+7 7 g+7+7+7+7+E+n+7 7 E+7+7+7+g+7 7 q+7+7+7+g+7 7 q+7+7+7+7+|+|+:+7 7 '+-+ + +W.7 7 7 N.I.I.E.E.B.B.t.7 7 t.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.~.7 7 }.7 9.b.f.i.k.k.s.m.7 7 F+7 .+E.I.I.N.N.R.V.!+7 7 '+-+-+/+/+|+|+E+7 7 7 E+7+7+g+7 7 q+7+7+7+7+7+7+7+q+7 7 g+7+.@7 7 n+E+7+7+7+7+7+7+7+7+7+7+7+.@7 7 7 .@7+7+q+7 7 g+7+7+7+7+.@7 7 >@7+7+7+7+g+7 7 q+7+7+7+g+7 7 q+7+7+7+7+|+|+:+7 7 '+-+ + +`.7 7 7 N.I.I.E.E.B.B.m.7 7 !@k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.'.7 7 7 7 8.b.f.i.k.k.s.!@7 7 G.~+E.E.I.I.N.N.R.V.W.7 7 U.-+-+/+/+|+7+g+7 7 7 7+7+7+g+7 7 q+7+7+7+7+7+7+7+q+7 7 g+7+7+q+7 7 q+7+7+7+7+7+7+7+7+7+7+7+7+&@7 7 q+7+7+q+7 7 g+7+7+7+7+q+7 7 q+7+7+7+7+g+7 7 q+7+7+7+g+7 7 q+7+7+7+7+|+|+:+7 7 '+-+ + +V.7 7 7 2+I.I.E.E.B.B.7 7 7 u.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.7 7 7 0.8.b.f.i.k.k.s.]@7 7 7 D.E.E.I.I.N.N.R.V.V.7 7 7 -+-+/+/+|+|+_@7 7 q+|+|+|+5+7 7 q+|+|+|+|+|+|+|+q+7 7 5+|+|+6+n+7 7 (+|+|+|+|+q+7 |+|+|+|+|+5+7 7 q+|+|+q+7 7 5+|+|+|+|+q+7 7 q+|+|+|+|+5+7 7 q+|+|+|+5+7 7 q+|+|+|+|+|+|+:+7 7 '+-+ + +V.O.7 7 J.I.I.E.E.B.-@7 7 7 s.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;./.7 7 5.8.b.f.i.k.k.s.v.6.7 7 -@E.E.I.I.N.N.R.V.V.&+7 7 ,+-+/+|+|+|+n+7 7 4+|+|+|+5+7 7 q+|+|+|+|+|+|+|+q+7 7 5+|+|+|+5+7 7 7 6+|+|+|+q+7 |+|+|+|+|+5+7 7 (+|+|+_@7 7 5+|+|+|+|+q+7 7 n+|+|+|+|+5+7 7 q+|+|+|+4+7 7 q+|+|+|+|+|+|+:+7 7 '+-+ + +V.X.7 7 O.I.I.E.E.B.D.7 7 ]+s.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.:.7 7 p+8.b.f.i.k.k.s.v.t.7 G.B.E.E.I.I.N.N.R.V.V. +U.7 Z.-+/+/+/+:+7 7 }+/+/+/+/+:+7 7 '+/+/+/+/+/+/+/+'+7 7 :+/+/+/+/+'+7 7 U./+/+/+'+7 Q+/+/+/+/+}+7 7 _+/+/+:+7 7 (+/+/+/+/+Q+7 7 7 '+/+/+:+U.U.7 Z./+/+/+/+7 7 Z./+/+/+/+/+/+:+7 7 '+-+ + +V.V.T.7 7 K.I.E.E.Y.G.7 6.v.s.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;._.7 1.8.8.b.f.i.k.k.s.v.w.7 D.B.E.E.I.I.N.N.R.V.V. +$+U.7 '+_+/+:+U.7 '+/+/+/+_+:+U.7 7 7 (+Q+/+/+/+Q+(+7 7 7 U.:+_+/+/+/+U.7 7 Z.:+/+'+7 U.Q+/+/+(+7 7 :+/+/+/+/+U.7 U.:+:+Q+/+/+'+7 7 7 7 7 7 :+Q+7 7 (+Q+/+/+}+7 7 (+:+:+/+Q+:+Z.7 7 U.>+W. +V.V.R.O.7 G.M.E..+~+7 6.)@v.s.k.l.c.7 7 7 0.4.<.^.'.O 7 7 7 '@D z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.7 5.8.8.b.f.i.k.k.s.v.v.7 z.B.E.E.I.I.N.N.R.V.V. + +-+>+Z.7 7 7 '+;+-+-+-+-+;+'+'+'+'+'+'+>+-+-+-+>+'+'+'+'+'+'+;+-+-+-+;+'+'+'+'+-+-+;+'+U.7 7 7 '+;+-+-+-+-+-+)+'+7 7 U.;+-+-+-+&+U.7 7 '+;+-+-+&+7 7 >+-+-+-+&+U.7 7 >+-+>+'+'+'+'+'+'+#+ +V.V.R.N.2+C.7 7 7 ~+F+y.v.v.s.k.c.c.c.c.0.0.}.<._.` ` ` ` P P B z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.:@<@<@<@[@k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.}@<@<@<@|@k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.|@1@2@3@2@1@k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.4@<@<@i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.5@6@6@i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.7@<@<@i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.2@<@8@i.6@2@i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.9@<@9@f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.1@<@0@f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.9@<@9@f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.a@<@9@f.f.9@9@f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.b@<@c@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.a@9@a@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.d@9@c@b.b.b.b.0@<@c@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.0@<@e@b.b.c@e@b.b.b.b.b.b.b.b.b.b.b.b.[@c@0@b.b.b.b.b.b.b.b.b.b.b.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.<@<@4@8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.2@<@4@8.8.8.8.<@<@4@8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.<@<@f@8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.c@<@9@8.8.8.8.8.8.8.8.8.8.8.8.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N g@h@i@&.;.{.<.f@<@<@j@8.j@4@4@8.8.8.8.8.8.8.4@4@4@8.8.8.8.8.8.8.8.8.j@4@j@8.8.8.8.8.8.8.8.8.8.8.8.8.4@4@j@8.8.8.8.8.8.f@4@f@8.8.8.8.8.8.8.8.8.8.8.8.8.<@<@f@8.8.8.f@<@<@j@8.j@4@4@8.8.8.8.8.8.8.j@4@4@8.8.8.8.8.8.8.8.8.8.8.4@<@<@8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.9@<@c@8.8.8.8.8.8.8.8.8.8.8.8.8.8.3.<.{.;.&.+.i@g@N z z x v k@k@l@m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z m@n@o@h@p@2@;.{.3.q@<@<@3.r@<@<@<@s@3.3.3.t@s@<@s@s@<@2@t@3.t@2@<@<@r@q@<@<@q@s@<@<@<@3.3.u@2@<@<@q@q@2@<@<@2@t@3.3.3.t@b@2@q@s@2@2@<@<@r@3.3.3.3.3.3.s@<@<@<@<@<@s@3.q@<@<@3.r@<@<@<@s@3.3.3.3.t@b@r@q@2@2@u@3.3.3.3.3.3.3.t@<@<@<@<@<@<@q@u@2@<@<@q@3.3.b@<@<@s@3.q@<@<@<@<@<@<@:@<@<@<@3.3.u@2@<@<@q@3.q@<@<@<@v@p@<@<@N z z w@x@k@y@<@z@k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x A@<@B@T Z h@<@;.<.<.s@<@s@s@r@C@s@<@<@<.<.<.r@<@C@<.<.s@<@s@<.<.<.<@<@s@2@b@<@D@<.C@<@b@<.<.<.C@<@<@C@b@C@:@<@<@C@<.<.D@2@<@D@<.D@<@2@<.D@<.<.<.<.<.<.<.<.r@<@2@<.<.<.<.s@<@s@s@r@C@s@<@<@<.<.<.D@2@:@<.<.C@<@b@<.<.<.<.<.<.<.<.<.s@<@s@<.<.<.<.C@<@<@D@<.<.<.<@<@:@<.<.E@<@<@E@<.<.<.s@<@b@<.<.<.C@<@<@D@<.<.C@<@<@p@B@n@B@N z F@x@v s s <@<@G@i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x H@<@g@T Z h@p@{.{.{.b@<@2@I@{.{.J@<@<@{.{.{.K@L@{.{.{.s@<@s@{.{.M@<@<@s@{.J@<@{.{.s@<@s@{.{.{.K@<@<@J@{.{.{.<@<@J@{.{.b@<@L@{.{.{.<@<@M@{.{.{.{.{.{.{.{.{.s@<@s@{.{.{.{.b@<@2@I@{.{.J@<@<@{.{.{.2@2@{.{.{.J@<@<@{.{.{.{.{.{.{.{.{.<@<@K@{.{.{.{.J@<@<@{.{.{.M@<@<@J@{.{.J@<@<@{.{.{.{.s@<@s@{.{.{.L@<@<@{.{.{.L@<@<@N@+.o@o@N w@<@O@v s s <@<@P@i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x <@<@Q@T Z i@R@;.;.;.<@<@N@;.;.;.s@<@s@;.;.;.;.;.;.;.;.<@<@K@;.;.N@<@<@;.;.S@R@;.;.b@<@N@;.;.;.s@<@s@;.;.;.N@<@<@;.;.S@<@<@N@;.;.;.<@<@N@;.;.;.;.;.;.;.;.;.<@<@N@;.;.;.;.<@<@N@;.;.;.s@<@s@;.;.L@<@s@;.;.;.N@<@<@;.;.;.;.;.;.;.;.S@<@<@N@;.;.;.;.s@<@s@;.;.;.N@<@<@;.;.;.s@<@s@;.;.;.;.<@<@N@;.;.;.s@<@s@;.;.;.s@<@s@&.+.i@T@U@<@<@x v s s <@<@P@i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x n@<@n@g@Z &.&.&.&.v@<@<@V@&.&.&.B@<@L@&.&.&.&.&.&.&.V@<@<@N@&.&.p@<@p@&.&.&.&.&.&.<@<@v@&.&.&.2@<@K@&.&.&.K@<@2@&.&.N@<@<@&.&.&.v@<@<@v@&.&.&.&.&.&.&.&.V@<@<@v@&.&.&.v@<@<@V@&.&.&.B@<@L@&.&.<@<@N@&.&.&.p@<@2@&.&.&.&.&.&.&.&.N@<@<@&.&.&.&.&.B@<@L@&.&.&.L@<@2@&.&.&.B@<@L@&.&.&.V@<@<@v@&.&.&.2@<@L@&.&.&.<@<@N@&.+.Z T F@<@F@x v s k@<@<@W@i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x X@<@<@<@Y@+.+.+.+.h@<@<@+.+.+.+.<@<@h@+.+.+.Z@Y@p@p@B@<@<@+.+.+.B@<@`@+.+.+.+.+.i@<@<@+.+.+.+.<@<@h@+.+.+.p@<@p@+.+.h@<@<@+.+.+.Y@<@B@+.+.+.+.+.+.+.+.+.h@<@<@+.+.+.+.h@<@<@+.+.+.+.<@<@h@+.h@<@<@p@p@p@p@p@p@Y@+.+.+.+.+.+.+.+.`@<@B@+.+.+.+.+.<@<@h@+.+.+.p@<@p@+.+.+.<@<@h@+.+.+.h@<@<@+.+.+.+.<@<@h@+.+.Z@<@<@i@+.+.Z T <@<@H@F@y@y@y@ #.#k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z X@<@<@<@o@Z Z Z o@<@o@Z Z Z i@<@<@Z Z Z +#<@n@i@Z @#<@n@Z Z Z <@<@h@Z Z Z Z Z +#<@B@Z Z Z h@<@<@Z Z Z Z n@<@h@Z Z ##<@<@Z Z Z n@<@##Z Z Z Z Z Z Z Z Z @#<@B@Z Z Z Z o@<@o@Z Z Z i@<@<@Z Z @#<@<@Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z o@<@o@Z Z Z Z i@<@<@##Z Z Z <@<@+#Z Z i@<@<@##Z Z Z @#<@B@Z Z Z h@<@<@##Z Z h@<@<@Z Z Z Z i@<@<@m@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z g@n@<@<@i@T T B@<@@#T T T g@<@n@T T +#<@n@T@T T B@<@o@T T i@<@<@T@T T T T T o@<@o@T T T +#<@n@T T T T <@<@i@T T T g@<@g@T o@n@g@T T T T T T T T T T B@<@o@T T T T B@<@@#T T T g@<@n@T T o@<@<@T T T T T T T T T T T T T T T <@<@g@T T T T +#<@<@T T T T <@<@g@T T +#<@<@T T T T B@<@o@T T T g@<@<@T T T @#<@B@T T T T g@<@<@m@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z N N g@<@<@g@N N <@<@g@N N N F@<@F@N N <@<@@#N N N <@<@Q@N N g@<@n@N N N N N N n@<@g@N N N F@<@F@N N N g@<@<@N N N N U@B@@#F@Q@$#N N N N N N N N N N N <@<@g@N N N N <@<@g@N N N F@<@F@N N F@<@<@N N N N N N N N N N N N N N $#<@<@U@N N N N F@<@F@N N N g@<@<@N N N F@<@F@N N N N <@<@g@N N N F@<@F@N N N F@<@@#N N N N g@<@<@m@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s %#<@z z z z <@<@A@z A@<@<@&#z z z H@<@m@z m@<@<@m@z z A@<@<@m@z z F@<@F@z z z z z &#<@<@m@z z z n@<@X@z z z X@<@F@z z z m@<@&#z z z z z z z z z z z z z z A@<@<@m@z z z A@<@<@&#z z z H@<@m@z z F@<@<@z z z z z z z z z z z z z z m@<@<@z z z z z n@<@X@z z z X@<@n@z z z n@<@F@z z z A@<@<@&#z z z H@<@w@z z z <@<@m@z z z z m@<@<@m@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s *#F@z z z &#<@n@z z m@<@n@z z z z <@<@A@z m@<@<@m@z z X@<@<@z z z H@<@X@z z z z z m@<@<@z z z z <@<@A@z z z F@<@w@z z z <@<@w@m@m@m@A@z z z z z z z z z z m@<@<@z z z z m@<@n@z z z z <@<@A@z z A@<@<@X@z z z z z z z z z z z z z w@<@H@z z z z z <@<@m@z z X@n@<@F@z z z <@<@m@z z z m@<@<@z z &#w@<@<@m@z z &#<@<@&#z z z z z n@<@H@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s F@x@x x x F@<@O@x x x@<@x@=#x x -#<@<@O@x O@<@<@n@;#w@F@n@<@x x O@<@<@-#x x x x =#F@<@<@O@x x -#<@<@O@x x =#<@<@w@x x x x@<@<@<@<@<@<@n@=#x x x x x x x x ;#<@<@=#=#x x x@<@x@=#x x -#<@<@O@x x x F@<@<@w@;#;#F@w@x x x x x x x =#x@<@x@=#x x x x <@<@n@F@n@;#n@<@x@x x x <@<@-#x =#x ;#<@<@x@F@n@;#<@<@-#x x w@<@<@=#x x x x x ;#<@<@x@%#k@>#x@m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s v ,#>#x@y@x@y@,#v ,#y@y@y@y@y@v >#y@y@y@y@'#v >#<@<@x@%#v *#<@x@*#y@y@y@y@*#v v '#y@y@y@y@y@'#>#y@y@y@y@'#%#y@y@y@y@*#v ,#x@*#%#%#%#>#<@<@y@v v v v v v v v v >#<@<@x@,#y@y@y@y@y@v >#y@y@y@y@'#v v v >#n@<@<@x@*#,#v v v v v v '#y@y@y@y@y@'#v v v %#<@<@x@'#v y@y@y@*#v v %#n@<@n@'#v v y@<@<@>#,#'#y@y@y@'#y@y@y@y@y@'#v v v v v %#x@<@<@n@>#)#m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s k@<@>#s s s s s y@<@y@s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s n@<@k@s s s s s x@<@!#s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q <@<@~#q q q q {#<@ #q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m z@<@n@]#m ^#z@<@z@m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ { ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! ~ ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ! { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ) ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ' ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > , ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; > ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - = * & % $ # @ + ",
+". + @ # $ % & * = ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - = * & % $ # @ + ",
+". + @ # $ % & * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - = * & % $ # @ + ",
+". + @ # $ % & = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * & % $ # @ + ",
+". + @ # $ % * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * & % $ # @ + ",
+". + @ # $ & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & % $ # @ + ",
+". + @ # % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % $ # @ + ",
+". + @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ # @ + ",
+". + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @ + ",
+". @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + ",
+"+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "};
diff --git a/gtk2_ardour/about.cc b/gtk2_ardour/about.cc
new file mode 100644
index 0000000000..f5f127cea3
--- /dev/null
+++ b/gtk2_ardour/about.cc
@@ -0,0 +1,498 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <cstdio>
+#include <ctime>
+#include <cstdlib>
+
+#include <gtk--/label.h>
+#include <gtk--/text.h>
+#include <gtk--/scrolledwindow.h>
+#include <gtk--/notebook.h>
+
+#include <ardour/ardour.h>
+#include <ardour/version.h>
+
+#include "utils.h"
+#include "version.h"
+
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/doi.h>
+
+#include "about.h"
+#include "rgb_macros.h"
+#include "ardour_ui.h"
+
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace std;
+using namespace SigC;
+using namespace ARDOUR;
+
+#ifdef WITH_PAYMENT_OPTIONS
+
+/* XPM */
+static const gchar * paypal_xpm[] = {
+"62 31 33 1",
+" c None",
+". c #325781",
+"+ c #154170",
+"@ c #C1CDDA",
+"# c #4E6E92",
+"$ c #D1D5DA",
+"% c #88A0B8",
+"& c #B4C4D3",
+"* c #C8D3DE",
+"= c #D7E1E9",
+"- c #002158",
+"; c #F6F8FA",
+"> c #44658B",
+", c #E7ECF0",
+"' c #A4B7CA",
+") c #9DB0C4",
+"! c #E3F1F7",
+"~ c #708CA9",
+"{ c #E1E7ED",
+"] c #567698",
+"^ c #7C96B1",
+"/ c #E7F5FA",
+"( c #EEF1F4",
+"_ c #6883A2",
+": c #244873",
+"< c #BBBBBB",
+"[ c #E9E9E9",
+"} c #063466",
+"| c #22364D",
+"1 c #94A7BD",
+"2 c #000000",
+"3 c #EAF7FC",
+"4 c #FFFFFF",
+"1'111111111111111111111111111111111111111111111111111111111%_#",
+"%333333333333333333333333333333333333333333333333333333333333.",
+"%444444444444444444444444444444444444444444444444444444444444:",
+"_4333333!!!!!!33333333333333333333!!!!!!33333333333!%%%%1334[:",
+"_444444@+}}}}+>)44444444444444444,:}}}}}.^(44444444@}..+.44($:",
+"_433333^:&&&&)_}_33///33333333333&+)&&&'~+./3///333^.(;#]33($:",
+"_444444>_444444'}_>...#%####~,]##..444444=+#]...>1;#_4;.144($:",
+"_43333!+'4,>#=4(:+_%%%]}}#~#}_+~~:]44_>&44#}_%%%_+>:14=}@33($:",
+"_44444*+$4&--)4(+%44444%-)4=--'4{+14,}-~44##44444&}}*4)+444($:",
+"_433331:;4):_;4*}_]:.$4*-~4{}>44#-=4@.#{4;+>_:.&4,++;4_#333($:",
+"_44444_#444444=.-.%&*,41-#4(:@4'-:(44444(_-:^&*,4*}#44.%444($:",
+"_43333:%4;@@'~+-%44*&44]-.;;'4,:-#44*@&%:-];4{'(4)-%4{+&333($:",
+"_4444{}@4*}}+>#:;4^-#4;.>+,444_+:^4(:}+.]}=4'-+(4_-&4&+{444($:",
+"_4333'+(41:*=3'.44*)(4=+)+*44@}%+@4=}&=/@}{4{1{44:+,4^.3333($:",
+"_4444~>,,]#444*})(;**,':*}'4;._@}=,%:444(+~(;{&,*}.,,>~4444($:",
+"_4333>}}}}^3333~}::}}}}>].;4^+=~}}}}]3333'}+:}}}}}}}}}'3333($:",
+"_4444$@@@@(44444$))@*@*^}$4=}14=@@@@{44444=))&*@@@@@@@;4444($:",
+"_433333333333333333333=+:%%.>/33333333333333333333333333333($:",
+"_4444444444444444444441....>=444444444444444444444444444444($:",
+"_4333333333333333333333333333333333333333333333333333333333($:",
+"_4444444444444444444444444444444444444444444444444444444444($:",
+"_4333333333333333333333333333333333333333333333333333333333($:",
+"_4444442222444222442444242444244222242444242222244222244444($:",
+"_4333332333232333233232332232233233332233233323332333333333($:",
+"_4444442222442222244424442424244222442424244424444222444444($:",
+"_4333332333332333233323332333233233332332233323333333233333($:",
+"_4444442444442444244424442444244222242444244424442222444444($:",
+"_433333333333333333333333333333333333333333333333333333333344:",
+"#4([[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[=&:",
+".=&<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<1|",
+"::||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"};
+#endif
+
+static gint
+stoppit (GdkEventButton* ev, Gtk::Notebook* notebook)
+{
+ gtk_signal_emit_stop_by_name (GTK_OBJECT(notebook->gtkobj()),
+ "button_release_event");
+ return TRUE;
+}
+
+static const char* author_names[] = {
+ N_("Marcus Andersson"),
+ N_("Jeremy Hall"),
+ N_("Steve Harris"),
+ N_("Tim Mayberry"),
+ N_("Mark Stewart"),
+ N_("Sam Chessman"),
+ N_("Jack O'Quin"),
+ N_("Matt Krai"),
+ N_("Ben Bell"),
+ N_("Gerard van Dongen"),
+ N_("Thomas Charbonnel"),
+ N_("Nick Mainsbridge"),
+ N_("Colin Law"),
+ N_("Sampo Savolainen"),
+ N_("Joshua Leach"),
+ N_("Rob Holland"),
+ N_("Per Sigmond"),
+ N_("Doug Mclain"),
+ 0
+};
+
+static const char* translators[] = {
+ N_("French:\n\tAlain Fréhel <alain.frehel@free.fr>"),
+ N_("German:\n\tKarsten Petersen <kapet@kapet.de>"),
+ N_("Italian:\n\tFilippo Pappalardo <filippo@email.it>"),
+ N_("Portuguese:\n\tRui Nuno Capela <rncbc@rncbc.org>"),
+ N_("Brazilian Portuguese:\n\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\
+\n\tChris Ross <chris@tebibyte.org>"),
+ N_("Spanish:\n\t Alex Krohn <alexkrohn@fastmail.fm>"),
+ N_("Russian:\n\t Igor Blinov <pitstop@nm.ru>"),
+ 0
+};
+
+
+About::About (ARDOUR_UI * ui)
+ : Window (GTK_WINDOW_TOPLEVEL), _ui (ui)
+#ifdef WITH_PAYMENT_OPTIONS
+ , paypal_pixmap (paypal_xpm)
+#endif
+{
+ using namespace Notebook_Helpers;
+
+ about_index = 0;
+ about_cnt = 0;
+ drawn = false;
+
+ Gtk::Label* small_label = manage (new Label (_(
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n")));
+
+ Gtk::Label* version_label =
+ manage (new Label
+ (compose(_("Ardour: %1\n(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"),
+ VERSIONSTRING,
+ gtk_ardour_major_version,
+ gtk_ardour_minor_version,
+ gtk_ardour_micro_version,
+ libardour_major_version,
+ libardour_minor_version,
+ libardour_micro_version)));
+
+ Notebook* notebook = manage (new Notebook);
+
+ ScrolledWindow* author_scroller = manage (new ScrolledWindow);
+ Text* author_text = manage (new Text);
+
+ author_text->set_editable (false);
+ author_text->set_name (X_("AboutText"));
+
+ string str = _(
+"Primary author:\n\t\
+Paul Davis\n\n\
+Major developers:\n\t\
+Jesse Chappell\n\t\
+Taybin Rutkin\n\
+Contributors:\n\t");
+
+ for (int32_t n = 0; author_names[n] != 0; ++n) {
+ str += _(author_names[n]);
+ str += "\n\t";
+ }
+
+ author_text->insert (str);
+
+ author_scroller->add (*author_text);
+ author_scroller->set_usize (-1, 75);
+ author_scroller->set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ ScrolledWindow* translator_scroller = manage (new ScrolledWindow);
+ Text* translator_text = manage (new Text);
+
+ translator_text->set_editable (false);
+ translator_text->set_name (X_("AboutText"));
+
+ str = "";
+
+ for (int32_t n = 0; translators[n] != 0; ++n) {
+ str += _(translators[n]);
+ str += '\n';
+ }
+
+ translator_text->insert (str);
+
+ translator_scroller->add (*translator_text);
+ translator_scroller->set_usize (-1, 75);
+ translator_scroller->set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ Label* author_tab_label = manage (new Label (_("Authors")));
+ Label* translator_tab_label = manage (new Label (_("Translators")));
+
+ notebook->pages().push_back (TabElem (*author_scroller, *author_tab_label));
+ notebook->pages().push_back (TabElem (*translator_scroller, *translator_tab_label));
+
+ notebook->set_name ("AboutNoteBook");
+ notebook->button_release_event.connect_after (bind (slot (stoppit), notebook));
+
+ logo_pixmap = 0;
+ logo_height = 0;
+ logo_width = 0;
+
+ set_name ("AboutWindow");
+ set_title ("ardour: about");
+ set_wmclass ("ardour_about", "Ardour");
+
+ vbox.set_border_width (5);
+ vbox.set_spacing (5);
+
+ if (load_logo_size ()) {
+ logo_area.set_usize (logo_width, logo_height);
+ load_logo (*this);
+
+ vbox.pack_start (logo_area, false, false);
+ logo_area.expose_event.connect (slot (*this, &About::logo_area_expose));
+ } else {
+ expose_event.connect (slot (*this, &About::logo_area_expose));
+ }
+
+ small_label->set_name ("AboutWindowSmallLabel");
+ version_label->set_name("AboutWindowSmallLabel");
+
+ first_label.set_name ("AboutWindowLabel");
+ third_label.set_name ("AboutWindowPDLabel");
+ second_label.set_name ("AboutWindowLabel");
+
+ subvbox.pack_start (*small_label, false, false);
+ subvbox.pack_start (*version_label, false, false);
+ subvbox.pack_start (*notebook, true, true);
+
+#ifdef WITH_PAYMENT_OPTIONS
+ paypal_button.add (paypal_pixmap);
+
+ HBox *payment_box = manage (new HBox);
+ payment_box->pack_start (paypal_button, true, false);
+
+ subvbox.pack_start (*payment_box, false, false);
+#endif
+
+ delete_event.connect (bind (slot (just_hide_it), static_cast<Gtk::Window*> (this)));
+
+ add (vbox);
+ add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
+
+ set_position (GTK_WIN_POS_CENTER);
+
+ show_all ();
+ subvbox.hide ();
+
+ /* wait for the first logo expose event to complete so that
+ we know we are fully drawn.
+ */
+
+ while (!drawn) {
+ gtk_main_iteration ();
+ }
+}
+
+About::~About ()
+{
+}
+
+void
+About::show_sub (bool yn)
+{
+ if (yn) {
+ vbox.pack_start (subvbox, true, true);
+ subvbox.show_all ();
+ } else {
+ vbox.remove (subvbox);
+ subvbox.hide ();
+ }
+}
+
+gint
+About::button_release_event_impl (GdkEventButton* ev)
+{
+ hide();
+
+ if (!_ui->shown ()) {
+ /* show it immediately */
+ _ui->show();
+ }
+
+ return TRUE;
+}
+
+void
+About::realize_impl ()
+{
+ Window::realize_impl ();
+ get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+ // get_window().set_decorations (GdkWMDecoration (0));
+}
+
+bool
+About::load_logo_size ()
+{
+ gchar buf[1024];
+ FILE *fp;
+ string path = find_data_file ("splash.ppm");
+
+ if (path.length() == 0) {
+ return false;
+ }
+
+ if ((fp = fopen (path.c_str(), "rb")) == 0) {
+ error << compose (_("cannot open splash image file \"%1\""), path) << endmsg;
+ return false;
+ }
+
+ fgets (buf, sizeof (buf), fp);
+ if (strcmp (buf, "P6\n") != 0) {
+ fclose (fp);
+ return false;
+ }
+
+ fgets (buf, sizeof (buf), fp);
+ fgets (buf, sizeof (buf), fp);
+ sscanf (buf, "%d %d", &logo_width, &logo_height);
+ fclose (fp);
+ return true;
+}
+
+bool
+About::load_logo (Gtk::Window& window)
+{
+ GdkGC* gc;
+ gchar buf[1024];
+ guchar *pixelrow;
+ FILE *fp;
+ gint count;
+ gint i;
+ string path;
+
+ path = find_data_file ("splash.ppm");
+
+ if (path.length() == 0) {
+ return false;
+ }
+
+ if ((fp = fopen (path.c_str(), "rb")) == 0) {
+ return false;
+ }
+
+ fgets (buf, sizeof (buf), fp);
+ if (strcmp (buf, "P6\n") != 0) {
+ fclose (fp);
+ return false;
+ }
+
+ fgets (buf, sizeof (buf), fp);
+ fgets (buf, sizeof (buf), fp);
+ sscanf (buf, "%d %d", &logo_width, &logo_height);
+
+ fgets (buf, sizeof (buf), fp);
+ if (strcmp (buf, "255\n") != 0) {
+ fclose (fp);
+ return false;
+ }
+
+ Gtk::Preview preview (GTK_PREVIEW_COLOR);
+
+ preview.size (logo_width, logo_height);
+ pixelrow = new guchar[logo_width * 3];
+
+ for (i = 0; i < logo_height; i++) {
+ count = fread (pixelrow, sizeof (unsigned char), logo_width * 3, fp);
+ if (count != (logo_width * 3))
+ {
+ delete [] pixelrow;
+ fclose (fp);
+ return false;
+ }
+ preview.draw_row (pixelrow, 0, i, logo_width);
+ }
+
+ window.realize ();
+
+ logo_pixmap = gdk_pixmap_new (GTK_WIDGET(window.gtkobj())->window, logo_width, logo_height,
+ gtk_preview_get_visual()->depth);
+ gc = gdk_gc_new (logo_pixmap);
+ gtk_preview_put (preview.gtkobj(), logo_pixmap, gc, 0, 0, 0, 0, logo_width, logo_height);
+ gdk_gc_destroy (gc);
+
+ delete [] pixelrow;
+ fclose (fp);
+
+ return true;
+}
+
+gint
+About::logo_area_expose (GdkEventExpose* ev)
+{
+ if (!drawn) {
+ drawn = true;
+ }
+
+ if (logo_pixmap) {
+ logo_area.get_window().draw_pixmap (logo_area.get_style()->get_black_gc(),
+ Gdk_Pixmap (logo_pixmap),
+ 0, 0,
+ ((logo_area.width() - logo_width) / 2),
+ ((logo_area.height() - logo_height) / 2),
+ logo_width, logo_height);
+ gdk_flush ();
+ }
+
+ return FALSE;
+}
+
+#ifdef WITH_PAYMENT_OPTIONS
+void
+About::goto_paypal ()
+{
+ char buf[PATH_MAX+16];
+ char *argv[4];
+ char *docfile = "foo";
+ int grandchild;
+
+ if (fork() == 0) {
+
+ /* child */
+
+ if ((grandchild = fork()) == 0) {
+
+ /* grandchild */
+
+ argv[0] = "mozilla";
+ argv[1] = "-remote";
+ snprintf (buf, sizeof(buf), "openurl(%s)", docfile);
+ argv[2] = buf;
+ argv[3] = 0;
+
+ execvp ("mozilla", argv);
+ error << "could not start mozilla" << endmsg;
+
+ } else {
+ int status;
+ waitpid (grandchild, &status, 0);
+ }
+
+ }
+}
+#endif
diff --git a/gtk2_ardour/about.h b/gtk2_ardour/about.h
new file mode 100644
index 0000000000..363bc57f33
--- /dev/null
+++ b/gtk2_ardour/about.h
@@ -0,0 +1,80 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_about_h__
+#define __ardour_gtk_about_h__
+
+#include <gtk--/window.h>
+#include <gtk--/pixmap.h>
+#include <gtk-canvas.h>
+
+class ARDOUR_UI;
+
+class About : public Gtk::Window
+{
+ public:
+ About (ARDOUR_UI *);
+ ~About ();
+
+ void show_sub (bool yn);
+
+ protected:
+ void realize_impl ();
+
+ private:
+ Gtk::DrawingArea logo_area;
+ GdkPixmap* logo_pixmap;
+ Gtk::Label first_label;
+ Gtk::Label second_label;
+ Gtk::Label third_label;
+ Gtk::VBox vbox;
+ Gtk::VBox subvbox;
+
+ vector<string> authors;
+ vector<string> supporters;
+
+ uint32_t about_index;
+ uint32_t about_cnt;
+ int logo_height;
+ int logo_width;
+ bool drawn;
+ bool support;
+ ARDOUR_UI * _ui;
+
+ SigC::Connection timeout_connection;
+
+ bool load_logo_size ();
+ bool load_logo (Gtk::Window&);
+ gint logo_area_expose (GdkEventExpose*);
+
+ gint button_release_event_impl (GdkEventButton*);
+ gint start_animating ();
+ void stop_animating ();
+
+ void gone_hidden ();
+
+#ifdef WITH_PAYMENT_OPTIONS
+ Gtk::Pixmap paypal_pixmap;
+ Gtk::Button paypal_button;
+ void goto_paypal ();
+#endif
+};
+
+#endif /* __ardour_gtk_about_h__ */
diff --git a/gtk2_ardour/add_route_dialog.cc b/gtk2_ardour/add_route_dialog.cc
new file mode 100644
index 0000000000..669248a371
--- /dev/null
+++ b/gtk2_ardour/add_route_dialog.cc
@@ -0,0 +1,148 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdio>
+#include <cmath>
+
+#include <sigc++/bind.h>
+
+#include <gtkmmext/utils.h>
+
+#include "utils.h"
+#include "add_route_dialog.h"
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace Gtkmmext;
+using namespace SigC;
+
+extern std::vector<string> channel_combo_strings;
+
+AddRouteDialog::AddRouteDialog ()
+ : ArdourDialog ("add route dialog"),
+ ok_button (_("OK")),
+ cancel_button (_("Cancel")),
+ track_button (_("Tracks")),
+ bus_button (_("Busses")),
+ routes_adjustment (1, 1, 32, 1, 4),
+ routes_spinner (routes_adjustment)
+{
+ set_name ("AddRouteDialog");
+ set_title (_("ardour: add track/bus"));
+ set_wmclass (X_("ardour_add_track_bus"), "Ardour");
+ set_position (GTK_WIN_POS_MOUSE);
+ set_keyboard_input (true);
+
+ name_template_entry.set_name ("AddRouteDialogNameTemplateEntry");
+ track_button.set_name ("AddRouteDialogRadioButton");
+ bus_button.set_name ("AddRouteDialogRadioButton");
+ ok_button.set_name ("AddRouteDialogButton");
+ cancel_button.set_name ("AddRouteDialogButton");
+ routes_spinner.set_name ("AddRouteDialogSpinner");
+
+ bus_button.set_group (track_button.group());
+ track_button.set_active (true);
+
+ HBox *hbrb = manage (new HBox);
+
+ hbrb->set_spacing (6);
+ hbrb->pack_start (*(manage (new Label (_("Add")))), false, false);
+ hbrb->pack_start (routes_spinner, false, false);
+ hbrb->pack_start (track_button, false, false);
+ hbrb->pack_start (bus_button, false, false);
+
+ channel_combo.set_popdown_strings (channel_combo_strings);
+ channel_combo.set_value_in_list (true, false);
+ channel_combo.set_name (X_("ChannelCountSelector"));
+ channel_combo.get_entry()->set_name (X_("ChannelCountSelector"));
+ channel_combo.get_popwin()->set_name (X_("ChannelCountSelector"));
+
+ VBox *vbcc = manage (new VBox);
+
+ vbcc->set_spacing (6);
+ vbcc->pack_start (*(manage (new Label ("Channel configuration"))), false, false);
+ vbcc->pack_start (channel_combo, false, false);
+
+#if NOT_USEFUL_YET
+ HBox *hbnt = manage (new HBox);
+
+ hbnt->pack_start (*(manage (new Label (_("Name (template)")))), false, false);
+ hbnt->pack_start (name_template_entry, true, true);
+#endif
+
+ HBox* hbbut = manage (new HBox);
+
+ set_usize_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose
+ set_usize_to_display_given_text (cancel_button, _("Cancel"), 20, 15);
+
+ hbbut->set_homogeneous (true);
+ hbbut->set_spacing (6);
+ hbbut->pack_end (cancel_button, false, false);
+ hbbut->pack_end (ok_button, false, false);
+
+ HBox* hbbutouter = manage (new HBox);
+ hbbutouter->set_border_width (12);
+ hbbutouter->pack_end (*hbbut, false, false);
+
+ VBox* vb2 = manage (new VBox);
+
+ vb2->set_border_width (12);
+ vb2->set_spacing (6);
+ vb2->pack_start (*hbrb, false, false);
+ vb2->pack_start (*vbcc, false, false);
+#if NOT_USEFUL_YET
+ vb2->pack_start (*hbnt, false, false);
+#endif
+ vb2->pack_start (*hbbutouter, false, false);
+
+ add (*vb2);
+
+ delete_event.connect (slot (*this, &ArdourDialog::wm_close_event));
+ ok_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 0));
+ cancel_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 1));
+}
+
+AddRouteDialog::~AddRouteDialog ()
+{
+}
+
+bool
+AddRouteDialog::track ()
+{
+ return track_button.get_active ();
+}
+
+string
+AddRouteDialog::name_template ()
+{
+ return name_template_entry.get_text ();
+}
+
+int
+AddRouteDialog::count ()
+{
+ return (int) floor (routes_adjustment.get_value ());
+}
+
+int
+AddRouteDialog::channels ()
+{
+ return channel_combo_get_channel_count (channel_combo);
+}
diff --git a/gtk2_ardour/add_route_dialog.h b/gtk2_ardour/add_route_dialog.h
new file mode 100644
index 0000000000..bbfe1efda6
--- /dev/null
+++ b/gtk2_ardour/add_route_dialog.h
@@ -0,0 +1,39 @@
+#ifndef __gtk_ardour_add_route_dialog_h__
+#define __gtk_ardour_add_route_dialog_h__
+
+#include <string>
+
+#include <gtk--/entry.h>
+#include <gtk--/radiobutton.h>
+#include <gtk--/adjustment.h>
+#include <gtk--/spinbutton.h>
+#include <gtk--/button.h>
+
+#include <gtkmmext/click_box.h>
+
+#include "ardour_dialog.h"
+
+class AddRouteDialog : public ArdourDialog
+{
+ public:
+ AddRouteDialog ();
+ ~AddRouteDialog ();
+
+ bool track ();
+ std::string name_template ();
+ int channels ();
+ int count ();
+
+ Gtk::Button ok_button;
+ Gtk::Button cancel_button;
+
+ private:
+ Gtk::Entry name_template_entry;
+ Gtk::RadioButton track_button;
+ Gtk::RadioButton bus_button;
+ Gtk::Adjustment routes_adjustment;
+ Gtk::SpinButton routes_spinner;
+ Gtk::Combo channel_combo;
+};
+
+#endif /* __gtk_ardour_add_route_dialog_h__ */
diff --git a/gtk2_ardour/ardbg b/gtk2_ardour/ardbg
new file mode 100755
index 0000000000..fd54fe809a
--- /dev/null
+++ b/gtk2_ardour/ardbg
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if [ -x ./ardour.bin ] ; then
+ # scons executable
+ export LD_LIBRARY_PATH=../libs/ardour
+ exec gdb ./ardour.bin
+else
+ # autofoo/make executable
+ export LD_LIBRARY_PATH=../libs/ardour/.libs
+ exec gdb ./ardour
+fi
+
diff --git a/gtk2_ardour/ardev b/gtk2_ardour/ardev
new file mode 100755
index 0000000000..6594e4c11f
--- /dev/null
+++ b/gtk2_ardour/ardev
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+
+if [ -x ./ardour.bin ] ; then
+ # scons executable
+ export LD_LIBRARY_PATH=../libs/ardour
+ exec ./ardour.bin --novst $*
+else
+ # autofoo/make executable
+ export LD_LIBRARY_PATH=../libs/ardour
+ exec ./ardour --novst $*
+fi
+
diff --git a/gtk2_ardour/ardour_dialog.cc b/gtk2_ardour/ardour_dialog.cc
new file mode 100644
index 0000000000..9a5a64a2f2
--- /dev/null
+++ b/gtk2_ardour/ardour_dialog.cc
@@ -0,0 +1,169 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <iostream>
+
+#include <gtkmmext/doi.h>
+
+#include "ardour_dialog.h"
+#include "keyboard.h"
+#include "ardour_ui.h"
+
+
+ArdourDialog::ArdourDialog (string name)
+ : Gtk::Window (GTK_WINDOW_TOPLEVEL),
+ KeyboardTarget (*this, name)
+{
+ session = 0;
+ kbd_input = false;
+ running = false;
+ _run_status = 0;
+ _within_hiding = false;
+ hide_on_stop = true;
+}
+
+ArdourDialog::~ArdourDialog ()
+{
+}
+
+gint
+ArdourDialog::enter_notify_event_impl (GdkEventCrossing *ev)
+{
+ if (ev->detail != GDK_NOTIFY_INFERIOR) {
+ Keyboard::the_keyboard().set_current_dialog (this);
+ }
+ return FALSE;
+}
+
+gint
+ArdourDialog::leave_notify_event_impl (GdkEventCrossing *ev)
+{
+ if (ev->detail != GDK_NOTIFY_INFERIOR) {
+ Keyboard::the_keyboard().set_current_dialog (0);
+ }
+ return FALSE;
+}
+
+gint
+ArdourDialog::unmap_event_impl (GdkEventAny *ev)
+{
+ _within_hiding = true;
+ Hiding (); /* EMIT_SIGNAL */
+ _within_hiding = false;
+ return Gtk::Window::unmap_event_impl (ev);
+}
+
+void
+ArdourDialog::wm_close()
+{
+ stop (-1);
+ ARDOUR_UI::instance()->allow_focus(false);
+}
+
+void
+ArdourDialog::wm_doi ()
+{
+ if (!hide_on_stop) {
+ Hiding (); /* EMIT_SIGNAL */
+ }
+ stop (-1);
+ delete_when_idle (this);
+}
+
+gint
+ArdourDialog::wm_close_event (GdkEventAny* ev)
+{
+ wm_close ();
+ return TRUE;
+}
+
+gint
+ArdourDialog::wm_doi_event (GdkEventAny* ev)
+{
+ wm_doi ();
+ return TRUE;
+}
+
+gint
+ArdourDialog::wm_doi_event_stop (GdkEventAny* ev)
+{
+ stop (-1);
+ return TRUE;
+}
+
+void
+ArdourDialog::set_hide_on_stop (bool yn)
+{
+ hide_on_stop = yn;
+}
+
+void
+ArdourDialog::close ()
+{
+ hide_all ();
+
+ if (kbd_input) {
+ ARDOUR_UI::instance()->allow_focus (false);
+ }
+}
+
+void
+ArdourDialog::stop (int rr)
+{
+ _run_status = rr;
+
+ if (hide_on_stop) {
+ Hiding (); /* EMIT_SIGNAL */
+ hide_all ();
+
+ if (kbd_input) {
+ ARDOUR_UI::instance()->allow_focus (false);
+ }
+ }
+
+ if (running) {
+ Gtk::Main::quit ();
+ running = false;
+ }
+}
+
+void
+ArdourDialog::run ()
+{
+ show_all ();
+
+ if (kbd_input) {
+ ARDOUR_UI::instance()->allow_focus (true);
+ }
+
+ running = true;
+ Gtk::Main::run ();
+}
+
+void
+ArdourDialog::set_keyboard_input (bool yn)
+{
+ kbd_input = yn;
+}
+
+int
+ArdourDialog::run_status ()
+{
+ return _run_status;
+}
diff --git a/gtk2_ardour/ardour_dialog.h b/gtk2_ardour/ardour_dialog.h
new file mode 100644
index 0000000000..d6b1ece72b
--- /dev/null
+++ b/gtk2_ardour/ardour_dialog.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_dialog_h__
+#define __ardour_dialog_h__
+
+#include <ardour/ardour.h>
+#include <gtk--/window.h>
+
+#include "keyboard_target.h"
+
+namespace ARDOUR {
+ class Session;
+};
+
+/*
+ * This virtual parent class is so that each dialog box uses the
+ * same mechanism to declare its closing, and to have a common
+ * method of connecting and disconnecting from a Session.
+ */
+class ArdourDialog : public Gtk::Window, public KeyboardTarget
+{
+ public:
+ ArdourDialog (string name);
+ ~ArdourDialog();
+
+ bool within_hiding() const { return _within_hiding; }
+
+ void run ();
+ void stop (int);
+ void close ();
+ void set_keyboard_input (bool yn);
+ void set_hide_on_stop (bool yn);
+ int run_status();
+
+ gint enter_notify_event_impl (GdkEventCrossing*);
+ gint leave_notify_event_impl (GdkEventCrossing*);
+ gint unmap_event_impl (GdkEventAny *);
+
+ ARDOUR::Session *session;
+
+ virtual void set_session (ARDOUR::Session* s) {
+ session = s;
+ }
+
+ virtual void session_gone () {
+ set_session (0);
+ }
+
+ void quit ();
+ void wm_close();
+ void wm_doi ();
+ gint wm_close_event (GdkEventAny *);
+ gint wm_doi_event (GdkEventAny *);
+ gint wm_doi_event_stop (GdkEventAny *);
+
+ private:
+ int _run_status;
+ bool _within_hiding;
+ bool kbd_input;
+ bool running;
+ bool hide_on_stop;
+};
+
+#endif // __ardour_dialog_h__
diff --git a/gtk2_ardour/ardour_image_compositor_socket.h b/gtk2_ardour/ardour_image_compositor_socket.h
new file mode 100644
index 0000000000..ad0a7b79c6
--- /dev/null
+++ b/gtk2_ardour/ardour_image_compositor_socket.h
@@ -0,0 +1,167 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+
+#ifndef __ardour_image_comp_h__
+#define __ardour_image_comp_h__
+
+#include <string>
+
+namespace ardourvis
+{
+ /** Simple version number */
+ const int32_t MSG_VERSION = 1 ;
+
+ /** the default port we use */
+ const int32_t DEFAULT_PORT = 30000 ;
+
+ /** the maximum buffer size we will use to send receive a message (image data handled differently) */
+ const int32_t MAX_MSG_SIZE = 256 ;
+
+ /** the number of characters used for a value describing the characters within a textual data element */
+ const int32_t TEXT_SIZE_CHARS = 3 ;
+
+ /** the number of characters we use for time values within a message */
+ const int32_t TIME_VALUE_CHARS = 10 ;
+
+ /** the number of charachters we use for other value data, ie image width/height values */
+ const int32_t IMAGE_SIZE_CHARS = 3 ;
+
+ /** the number of characters used to for the size of the image data message */
+ const int32_t IMAGE_DATA_MESSAGE_SIZE_CHARS = 32 ;
+
+ // ------------------------------------------------------------------------- //
+ // Main Actions
+ // we join the action chars with items to create the message
+ // with the exception of the return values, all messages begin with one
+ // of these message parts
+
+ /** Insert an Item */
+ const std::string INSERT_ITEM = "IN" ;
+
+ /** Remove an Item */
+ const std::string REMOVE_ITEM = "RM" ;
+
+ /** Rename a named item */
+ const std::string RENAME_ITEM = "MV" ;
+
+ /** Request some aditional data */
+ const std::string REQUEST_DATA = "RQ" ;
+
+ /** Return of a data request */
+ const std::string RETURN_DATA = "RD" ;
+
+ /** Update a item */
+ const std::string ITEM_UPDATE = "IU" ;
+
+ /** Select an Item */
+ const std::string ITEM_SELECTED = "IS" ;
+
+ /** Sesion Action */
+ const std::string SESSION_ACTION = "SA" ;
+
+ /** Sesion Action */
+ const std::string SHUTDOWN = "SD" ;
+
+
+ // ------------------------------------------------------------------------- //
+ // Return values
+ const std::string RETURN_TRUE = "RT1" ;
+ const std::string RETURN_FALSE = "RT0" ;
+
+
+
+ // ------------------------------------------------------------------------- //
+ // Updateable attributes
+
+ /** Update the position of a time axis item */
+ const std::string POSITION_CHANGE = "PC" ;
+
+ /** Update the duration of a time axis item */
+ const std::string DURATION_CHANGE = "DC" ;
+
+ /** Enable the position lock constraint no a time axis item */
+ const std::string POSITION_LOCK_CHANGE = "PL" ;
+
+ /** Enable the duration lock constraint no a time axis item */
+ const std::string DURATION_LOCK_CHANGE = "PL" ;
+
+ /** Update the Maximum duration of a time axis item (_Upper _Duration) */
+ const std::string MAX_DURATION_CHANGE = "UD" ;
+
+ /** Enable the Maximum duration constraint of a time axis item (_Enable _Upper (Duration)) */
+ const std::string MAX_DURATION_ENABLE_CHANGE = "EU" ;
+
+ /** Update the Minimum duration of a time axis item (_Lowerr _Duration) */
+ const std::string MIN_DURATION_CHANGE = "LD" ;
+
+ /** Enable the Minimum duration constraint of a time axis item (_Enable _Lower (Duration)) */
+ const std::string MIN_DURATION_ENABLE_CHANGE = "EL" ;
+
+ /** Refresh the image data of an imageframe item (original image has been altered?) */
+ const std::string IMAGE_REFRESH = "IR" ;
+
+ /** the session sample rate has changed */
+ const std::string SAMPLE_RATE_CHANGE = "RC" ;
+
+
+
+ // ------------------------------------------------------------------------- //
+ // Requestable data items
+
+ /** RGB data of the iamge */
+ // this is probably a bad choice of string !
+ const std::string IMAGE_RGB_DATA = "ID" ;
+
+ /** the (path) name of the Ardour session */
+ const std::string SESSION_NAME = "SN" ;
+
+ /** the current sample rate */
+ const std::string SAMPLE_RATE = "SR" ;
+
+ /** the (path) name of the image compositor session */
+ const std::string COMPOSITOR_SESSION = "CS" ;
+
+
+ // ------------------------------------------------------------------------- //
+ // Session Actions - follwed by session path
+
+ /** Close a session */
+ const std::string CLOSE_SESSION = "CS" ;
+
+ /** Open a session */
+ const std::string OPEN_SESSION = "OS" ;
+
+
+
+ // ------------------------------------------------------------------------- //
+ // Items
+
+ const std::string IMAGEFRAME_TIME_AXIS = "IT" ;
+ const std::string MARKER_TIME_AXIS = "MT" ;
+ const std::string IMAGEFRAME_ITEM = "II" ;
+ const std::string MARKER_ITEM = "MI" ;
+
+ /** or an ImageFrameTimeAxisGroup */
+ const std::string IMAGEFRAME_GROUP = "IG" ;
+
+} /* namespace ardour_visual */
+
+#endif /* __ardour_image_comp_socket_h__ */
diff --git a/gtk2_ardour/ardour_message.cc b/gtk2_ardour/ardour_message.cc
new file mode 100644
index 0000000000..52b7ab567c
--- /dev/null
+++ b/gtk2_ardour/ardour_message.cc
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+
+*/
+
+#include "ardour_message.h"
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtk;
+
+
+ArdourMessage::ArdourMessage (Gtk::Window* parent,
+ string name, string msg,
+ bool grab_focus, bool auto_run)
+ : ArdourDialog (name),
+ ok_button (_("OK"))
+{
+ set_keyboard_input (true);
+
+ label.set_text (msg);
+ label.set_alignment (0.5, 0.5);
+ label.set_name (X_("PrompterLabel"));
+
+ ok_button.set_name ("EditorGTKButton");
+ ok_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 1));
+
+ packer.set_spacing (10);
+ packer.set_border_width (10);
+ packer.pack_start (label);
+ packer.pack_start (ok_button);
+
+ set_name (X_("Prompter"));
+ set_position (GTK_WIN_POS_MOUSE);
+ set_modal (true);
+ add (packer);
+ show_all ();
+
+ realize();
+ get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ if (grab_focus) {
+ ok_button.grab_focus ();
+ }
+
+ if (parent) {
+ set_transient_for (*parent);
+ }
+
+ if (auto_run) {
+ run ();
+ }
+}
+
+ArdourMessage::~ArdourMessage()
+{
+}
diff --git a/gtk2_ardour/ardour_message.h b/gtk2_ardour/ardour_message.h
new file mode 100644
index 0000000000..11f4c09340
--- /dev/null
+++ b/gtk2_ardour/ardour_message.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+
+*/
+
+#ifndef __ardour_message_h__
+#define __ardour_message_h__
+
+#include <string>
+
+#include <gtk--/box.h>
+#include <gtk--/button.h>
+#include <gtk--/label.h>
+
+#include "ardour_dialog.h"
+
+class ArdourMessage : public ArdourDialog
+{
+ public:
+ ArdourMessage (Gtk::Window* parent,
+ std::string name, std::string msg,
+ bool grabfocus = true,
+ bool autorun = true);
+ ~ArdourMessage();
+
+ private:
+ Gtk::VBox packer;
+ Gtk::Button ok_button;
+ Gtk::Label label;
+
+};
+
+#endif // __ardour_message_h__
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
new file mode 100644
index 0000000000..1dcada4a7c
--- /dev/null
+++ b/gtk2_ardour/ardour_ui.cc
@@ -0,0 +1,3385 @@
+/*
+ Copyright (C) 1999-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+#include <cmath>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <cerrno>
+#include <fstream>
+
+#include <iostream>
+
+#include <gtk--.h>
+#include <pbd/error.h>
+#include <pbd/basename.h>
+#include <pbd/pathscanner.h>
+#include <pbd/failed_constructor.h>
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/pix.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/click_box.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/fastmeter.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/popup.h>
+
+#include <midi++/port.h>
+#include <midi++/mmc.h>
+
+#include <ardour/ardour.h>
+#include <ardour/port.h>
+#include <ardour/audioengine.h>
+#include <ardour/playlist.h>
+#include <ardour/utils.h>
+#include <ardour/diskstream.h>
+#include <ardour/filesource.h>
+#include <ardour/recent_sessions.h>
+#include <ardour/session_diskstream.h>
+#include <ardour/port.h>
+#include <ardour/audio_track.h>
+
+#include "ardour_ui.h"
+#include "ardour_message.h"
+#include "public_editor.h"
+#include "audio_clock.h"
+#include "keyboard.h"
+#include "mixer_ui.h"
+#include "prompter.h"
+#include "opts.h"
+#include "keyboard_target.h"
+#include "add_route_dialog.h"
+#include "new_session_dialog.h"
+#include "about.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtkmmext;
+using namespace Gtk;
+using namespace SigC;
+
+ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
+SoundFileSelector* ARDOUR_UI::sfdb_window = 0;
+
+SigC::Signal1<void,bool> ARDOUR_UI::Blink;
+SigC::Signal0<void> ARDOUR_UI::RapidScreenUpdate;
+SigC::Signal0<void> ARDOUR_UI::SuperRapidScreenUpdate;
+SigC::Signal1<void,jack_nframes_t> ARDOUR_UI::Clock;
+
+/* XPM */
+static const gchar *h_meter_strip_xpm[] = {
+"186 5 187 2",
+" c None",
+". c #2BFE00",
+"+ c #2DFE00",
+"@ c #2FFE01",
+"# c #32FE01",
+"$ c #34FE02",
+"% c #36FE02",
+"& c #38FE03",
+"* c #3BFE03",
+"= c #3DFD04",
+"- c #3FFD04",
+"; c #41FD05",
+"> c #44FD05",
+", c #46FD06",
+"' c #48FD06",
+") c #4AFD07",
+"! c #4DFD07",
+"~ c #4FFD08",
+"{ c #51FC08",
+"] c #53FC09",
+"^ c #56FC09",
+"/ c #58FC09",
+"( c #5AFC0A",
+"_ c #5CFC0A",
+": c #5FFC0B",
+"< c #61FC0B",
+"[ c #63FB0C",
+"} c #65FB0C",
+"| c #68FB0D",
+"1 c #6AFB0D",
+"2 c #6CFB0E",
+"3 c #6EFB0E",
+"4 c #71FB0F",
+"5 c #73FB0F",
+"6 c #75FB10",
+"7 c #77FA10",
+"8 c #7AFA11",
+"9 c #7CFA11",
+"0 c #7EFA12",
+"a c #80FA12",
+"b c #83FA12",
+"c c #85FA13",
+"d c #87FA13",
+"e c #89FA14",
+"f c #8CF914",
+"g c #8EF915",
+"h c #90F915",
+"i c #92F916",
+"j c #95F916",
+"k c #97F917",
+"l c #99F917",
+"m c #9BF918",
+"n c #9EF818",
+"o c #A0F819",
+"p c #A2F819",
+"q c #A4F81A",
+"r c #A7F81A",
+"s c #A9F81A",
+"t c #ABF81B",
+"u c #ADF81B",
+"v c #B0F81C",
+"w c #B2F71C",
+"x c #B4F71D",
+"y c #B6F71D",
+"z c #B9F71E",
+"A c #BBF71E",
+"B c #BDF71F",
+"C c #BFF71F",
+"D c #C2F720",
+"E c #C4F720",
+"F c #C6F621",
+"G c #C8F621",
+"H c #CBF622",
+"I c #CDF622",
+"J c #CFF623",
+"K c #D1F623",
+"L c #D4F624",
+"M c #D6F624",
+"N c #D8F524",
+"O c #DAF525",
+"P c #DDF525",
+"Q c #DFF526",
+"R c #E1F526",
+"S c #E3F527",
+"T c #E6F527",
+"U c #E8F528",
+"V c #EAF528",
+"W c #ECF429",
+"X c #EFF429",
+"Y c #F1F42A",
+"Z c #F3F42A",
+"` c #F5F42B",
+" . c #F8F42B",
+".. c #FAF42C",
+"+. c #FCF42C",
+"@. c #FFF42D",
+"#. c #FFF22C",
+"$. c #FFF12B",
+"%. c #FFF02A",
+"&. c #FFEF2A",
+"*. c #FFEE29",
+"=. c #FFED28",
+"-. c #FFEC28",
+";. c #FFEB27",
+">. c #FFE926",
+",. c #FFE826",
+"'. c #FFE725",
+"). c #FFE624",
+"!. c #FFE524",
+"~. c #FFE423",
+"{. c #FFE322",
+"]. c #FFE222",
+"^. c #FFE021",
+"/. c #FFDF20",
+"(. c #FFDE20",
+"_. c #FFDD1F",
+":. c #FFDC1E",
+"<. c #FFDB1E",
+"[. c #FFDA1D",
+"}. c #FFD91C",
+"|. c #FFD71B",
+"1. c #FFD61B",
+"2. c #FFD51A",
+"3. c #FFD419",
+"4. c #FFD319",
+"5. c #FFD218",
+"6. c #FFD117",
+"7. c #FFD017",
+"8. c #FFCF16",
+"9. c #FFCD15",
+"0. c #FFCC15",
+"a. c #FFCB14",
+"b. c #FFCA13",
+"c. c #FFC913",
+"d. c #FFC812",
+"e. c #FFC711",
+"f. c #FFC611",
+"g. c #FFC410",
+"h. c #FFC30F",
+"i. c #FFC20F",
+"j. c #FFC10E",
+"k. c #FFC00D",
+"l. c #FFBF0C",
+"m. c #FFBE0C",
+"n. c #FFBD0B",
+"o. c #FFBB0A",
+"p. c #FFBA0A",
+"q. c #FFB909",
+"r. c #FFB808",
+"s. c #FFB708",
+"t. c #FFB607",
+"u. c #FFB506",
+"v. c #FFB406",
+"w. c #FFB205",
+"x. c #FFB104",
+"y. c #FFB004",
+"z. c #FFAF03",
+"A. c #FFAE02",
+"B. c #FFAD02",
+"C. c #FFAC01",
+"D. c #FFAB00",
+"E. c #FFA900",
+"F. c #F11F00",
+"G. c #F21E00",
+"H. c #F21C00",
+"I. c #F31B00",
+"J. c #F31A00",
+"K. c #F41800",
+"L. c #F41700",
+"M. c #F51600",
+"N. c #F61400",
+"O. c #F61300",
+"P. c #F71100",
+"Q. c #F71000",
+"R. c #F80F00",
+"S. c #F90D00",
+"T. c #F90C00",
+"U. c #FA0B00",
+"V. c #FA0900",
+"W. c #FB0800",
+"X. c #FC0600",
+"Y. c #FC0500",
+"Z. c #FD0400",
+"`. c #FD0200",
+" + c #FE0100",
+".+ c #FE0000",
+"++ c #FF0000",
+". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
+". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+",
+". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
+". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++",
+". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"};
+
+/* XPM */
+static const gchar * v_meter_strip_xpm[] = {
+"5 250 230 2",
+" c None",
+". c #FE0000",
+"+ c #FF0000",
+"@ c #FE0100",
+"# c #FD0200",
+"$ c #FD0300",
+"% c #FD0400",
+"& c #FC0500",
+"* c #FC0600",
+"= c #FC0700",
+"- c #FB0800",
+"; c #FA0900",
+"> c #FA0A00",
+", c #FA0B00",
+"' c #F90C00",
+") c #F90D00",
+"! c #F80E00",
+"~ c #F80F00",
+"{ c #F71000",
+"] c #F71100",
+"^ c #F61200",
+"/ c #F61300",
+"( c #F61400",
+"_ c #F51600",
+": c #F41700",
+"< c #F41800",
+"[ c #F31A00",
+"} c #F31B00",
+"| c #F21C00",
+"1 c #F21E00",
+"2 c #F11F00",
+"3 c #F54A00",
+"4 c #FFA900",
+"5 c #FFAB00",
+"6 c #FFAC01",
+"7 c #FFAD02",
+"8 c #FFAE02",
+"9 c #FFAF03",
+"0 c #FFB004",
+"a c #FFB104",
+"b c #FFB205",
+"c c #FFB406",
+"d c #FFB506",
+"e c #FFB607",
+"f c #FFB708",
+"g c #FFB808",
+"h c #FFB909",
+"i c #FFBA0A",
+"j c #FFBB0A",
+"k c #FFBC0A",
+"l c #FFBD0B",
+"m c #FFBE0C",
+"n c #FFBF0C",
+"o c #FFC00D",
+"p c #FFC10E",
+"q c #FFC20F",
+"r c #FFC30F",
+"s c #FFC410",
+"t c #FFC511",
+"u c #FFC611",
+"v c #FFC711",
+"w c #FFC812",
+"x c #FFC913",
+"y c #FFCA13",
+"z c #FFCB14",
+"A c #FFCC15",
+"B c #FFCD15",
+"C c #FFCF16",
+"D c #FFD017",
+"E c #FFD117",
+"F c #FFD218",
+"G c #FFD319",
+"H c #FFD419",
+"I c #FFD51A",
+"J c #FFD61B",
+"K c #FFD71B",
+"L c #FFD81C",
+"M c #FFD91C",
+"N c #FFDA1D",
+"O c #FFDB1E",
+"P c #FFDC1E",
+"Q c #FFDD1F",
+"R c #FFDE20",
+"S c #FFDF20",
+"T c #FFE021",
+"U c #FFE222",
+"V c #FFE322",
+"W c #FFE423",
+"X c #FFE524",
+"Y c #FFE624",
+"Z c #FFE725",
+"` c #FFE826",
+" . c #FFE926",
+".. c #FFEA26",
+"+. c #FFEB27",
+"@. c #FFEC28",
+"#. c #FFED28",
+"$. c #FFEE29",
+"%. c #FFEF2A",
+"&. c #FFF02A",
+"*. c #FFF12B",
+"=. c #FFF22C",
+"-. c #FFF32D",
+";. c #FFF42D",
+">. c #FDF42C",
+",. c #FBF42C",
+"'. c #FAF42C",
+"). c #F8F42B",
+"!. c #F6F42B",
+"~. c #F4F42B",
+"{. c #F3F42A",
+"]. c #F1F42A",
+"^. c #F0F429",
+"/. c #EEF429",
+"(. c #ECF429",
+"_. c #EAF528",
+":. c #E9F528",
+"<. c #E7F528",
+"[. c #E5F527",
+"}. c #E3F527",
+"|. c #E2F526",
+"1. c #E0F526",
+"2. c #DFF526",
+"3. c #DDF525",
+"4. c #DBF525",
+"5. c #D9F525",
+"6. c #D8F524",
+"7. c #D6F624",
+"8. c #D5F624",
+"9. c #D3F624",
+"0. c #D1F623",
+"a. c #CFF623",
+"b. c #CEF622",
+"c. c #CCF622",
+"d. c #CBF622",
+"e. c #C9F621",
+"f. c #C7F621",
+"g. c #C5F621",
+"h. c #C4F720",
+"i. c #C2F720",
+"j. c #C0F71F",
+"k. c #BEF71F",
+"l. c #BDF71F",
+"m. c #BBF71E",
+"n. c #BAF71E",
+"o. c #B8F71E",
+"p. c #B6F71D",
+"q. c #B5F71D",
+"r. c #B3F71D",
+"s. c #B2F71C",
+"t. c #B0F81C",
+"u. c #AEF81B",
+"v. c #ACF81B",
+"w. c #ABF81B",
+"x. c #A9F81A",
+"y. c #A8F81A",
+"z. c #A6F81A",
+"A. c #A4F81A",
+"B. c #A2F819",
+"C. c #A1F819",
+"D. c #9FF819",
+"E. c #9EF818",
+"F. c #9BF918",
+"G. c #9AF917",
+"H. c #98F917",
+"I. c #97F917",
+"J. c #95F916",
+"K. c #93F916",
+"L. c #91F916",
+"M. c #90F915",
+"N. c #8EF915",
+"O. c #8DF914",
+"P. c #8BF914",
+"Q. c #89FA14",
+"R. c #87FA13",
+"S. c #86FA13",
+"T. c #84FA13",
+"U. c #83FA12",
+"V. c #81FA12",
+"W. c #7FFA12",
+"X. c #7DFA12",
+"Y. c #7CFA11",
+"Z. c #7AFA11",
+"`. c #78FA10",
+" + c #76FA10",
+".+ c #75FB10",
+"++ c #73FB0F",
+"@+ c #72FB0F",
+"#+ c #70FB0F",
+"$+ c #6EFB0E",
+"%+ c #6DFB0E",
+"&+ c #6BFB0E",
+"*+ c #6AFB0D",
+"=+ c #68FB0D",
+"-+ c #66FB0C",
+";+ c #64FB0C",
+">+ c #63FB0C",
+",+ c #61FC0B",
+"'+ c #60FC0B",
+")+ c #5EFC0B",
+"!+ c #5CFC0A",
+"~+ c #5AFC0A",
+"{+ c #59FC09",
+"]+ c #57FC09",
+"^+ c #56FC09",
+"/+ c #53FC09",
+"(+ c #52FC08",
+"_+ c #50FC08",
+":+ c #4FFD08",
+"<+ c #4DFD07",
+"[+ c #4BFD07",
+"}+ c #49FD07",
+"|+ c #48FD06",
+"1+ c #46FD06",
+"2+ c #45FD05",
+"3+ c #43FD05",
+"4+ c #41FD05",
+"5+ c #3FFD04",
+"6+ c #3EFD04",
+"7+ c #3CFD04",
+"8+ c #3BFE03",
+"9+ c #39FE03",
+"0+ c #37FE02",
+"a+ c #35FE02",
+"b+ c #34FE02",
+"c+ c #32FE01",
+"d+ c #30FE01",
+"e+ c #2EFE01",
+"f+ c #2DFE00",
+"g+ c #2BFE00",
+". . + + + ",
+". . + + + ",
+"@ @ @ @ @ ",
+"# # # # # ",
+"$ $ $ $ $ ",
+"% % % % % ",
+"& & & & & ",
+"* * * * * ",
+"= = = = = ",
+"- - - - - ",
+"; ; ; ; ; ",
+"> > > > > ",
+", , , , , ",
+"' ' ' ' ' ",
+") ) ) ) ) ",
+"! ! ! ! ! ",
+"~ ~ ~ ~ ~ ",
+"{ { { { { ",
+"] ] ] ] ] ",
+"^ ^ ^ ^ ^ ",
+"/ / / / / ",
+"( ( ( ( ( ",
+"_ _ _ _ _ ",
+": : : : : ",
+": : : : : ",
+"< < < < < ",
+"[ [ [ [ [ ",
+"} } } } } ",
+"} } } } } ",
+"| | | | | ",
+"1 1 1 1 1 ",
+"2 2 2 2 2 ",
+"3 3 3 3 3 ",
+"4 4 4 4 4 ",
+"5 5 5 5 5 ",
+"6 6 6 6 6 ",
+"6 6 6 6 6 ",
+"7 7 7 7 7 ",
+"8 8 8 8 8 ",
+"9 9 9 9 9 ",
+"9 9 9 9 9 ",
+"0 0 0 0 0 ",
+"a a a a a ",
+"a a a a a ",
+"b b b b b ",
+"c c c c c ",
+"d d d d d ",
+"d d d d d ",
+"e e e e e ",
+"f f f f f ",
+"g g g g g ",
+"g g g g g ",
+"h h h h h ",
+"i i i i i ",
+"j j j j j ",
+"k k k k k ",
+"l l l l l ",
+"m m m m m ",
+"n n n n n ",
+"n n n n n ",
+"o o o o o ",
+"p p p p p ",
+"q q q q q ",
+"q q q q q ",
+"r r r r r ",
+"s s s s s ",
+"t t t t t ",
+"u u u u u ",
+"v v v v v ",
+"w w w w w ",
+"x x x x x ",
+"x x x x x ",
+"y y y y y ",
+"z z z z z ",
+"A A A A A ",
+"A A A A A ",
+"B B B B B ",
+"C C C C C ",
+"D D D D D ",
+"D D D D D ",
+"E E E E E ",
+"F F F F F ",
+"G G G G G ",
+"G G G G G ",
+"H H H H H ",
+"I I I I I ",
+"I I I I I ",
+"J J J J J ",
+"K K K K K ",
+"L L L L L ",
+"M M M M M ",
+"N N N N N ",
+"O O O O O ",
+"P P P P P ",
+"P P P P P ",
+"Q Q Q Q Q ",
+"R R R R R ",
+"S S S S S ",
+"S S S S S ",
+"T T T T T ",
+"U U U U U ",
+"V V V V V ",
+"V V V V V ",
+"W W W W W ",
+"X X X X X ",
+"Y Y Y Y Y ",
+"Y Y Y Y Y ",
+"Z Z Z Z Z ",
+"` ` ` ` ` ",
+" . . . . .",
+"..........",
+"+.+.+.+.+.",
+"@.@.@.@.@.",
+"#.#.#.#.#.",
+"#.#.#.#.#.",
+"$.$.$.$.$.",
+"%.%.%.%.%.",
+"&.&.&.&.&.",
+"&.&.&.&.&.",
+"*.*.*.*.*.",
+"=.=.=.=.=.",
+"-.-.-.-.-.",
+";.;.;.;.;.",
+";.;.;.;.;.",
+">.>.>.>.>.",
+",.,.,.,.,.",
+"'.'.'.'.'.",
+").).).).).",
+"!.!.!.!.!.",
+"~.~.~.~.~.",
+"{.{.{.{.{.",
+"].].].].].",
+"^.^.^.^.^.",
+"/././././.",
+"(.(.(.(.(.",
+"_._._._._.",
+":.:.:.:.:.",
+"<.<.<.<.<.",
+"[.[.[.[.[.",
+"}.}.}.}.}.",
+"|.|.|.|.|.",
+"1.1.1.1.1.",
+"2.2.2.2.2.",
+"3.3.3.3.3.",
+"4.4.4.4.4.",
+"5.5.5.5.5.",
+"6.6.6.6.6.",
+"7.7.7.7.7.",
+"8.8.8.8.8.",
+"9.9.9.9.9.",
+"0.0.0.0.0.",
+"a.a.a.a.a.",
+"b.b.b.b.b.",
+"c.c.c.c.c.",
+"d.d.d.d.d.",
+"e.e.e.e.e.",
+"f.f.f.f.f.",
+"g.g.g.g.g.",
+"h.h.h.h.h.",
+"i.i.i.i.i.",
+"j.j.j.j.j.",
+"k.k.k.k.k.",
+"l.l.l.l.l.",
+"m.m.m.m.m.",
+"n.n.n.n.n.",
+"o.o.o.o.o.",
+"p.p.p.p.p.",
+"q.q.q.q.q.",
+"r.r.r.r.r.",
+"s.s.s.s.s.",
+"t.t.t.t.t.",
+"u.u.u.u.u.",
+"v.v.v.v.v.",
+"w.w.w.w.w.",
+"x.x.x.x.x.",
+"y.y.y.y.y.",
+"z.z.z.z.z.",
+"A.A.A.A.A.",
+"B.B.B.B.B.",
+"C.C.C.C.C.",
+"D.D.D.D.D.",
+"E.E.E.E.E.",
+"F.F.F.F.F.",
+"G.G.G.G.G.",
+"H.H.H.H.H.",
+"I.I.I.I.I.",
+"J.J.J.J.J.",
+"K.K.K.K.K.",
+"L.L.L.L.L.",
+"M.M.M.M.M.",
+"N.N.N.N.N.",
+"O.O.O.O.O.",
+"P.P.P.P.P.",
+"Q.Q.Q.Q.Q.",
+"R.R.R.R.R.",
+"S.S.S.S.S.",
+"T.T.T.T.T.",
+"U.U.U.U.U.",
+"V.V.V.V.V.",
+"W.W.W.W.W.",
+"X.X.X.X.X.",
+"Y.Y.Y.Y.Y.",
+"Z.Z.Z.Z.Z.",
+"`.`.`.`.`.",
+" + + + + +",
+".+.+.+.+.+",
+"++++++++++",
+"@+@+@+@+@+",
+"#+#+#+#+#+",
+"$+$+$+$+$+",
+"%+%+%+%+%+",
+"&+&+&+&+&+",
+"*+*+*+*+*+",
+"=+=+=+=+=+",
+"-+-+-+-+-+",
+";+;+;+;+;+",
+">+>+>+>+>+",
+",+,+,+,+,+",
+"'+'+'+'+'+",
+")+)+)+)+)+",
+"!+!+!+!+!+",
+"~+~+~+~+~+",
+"{+{+{+{+{+",
+"]+]+]+]+]+",
+"^+^+^+^+^+",
+"/+/+/+/+/+",
+"(+(+(+(+(+",
+"_+_+_+_+_+",
+":+:+:+:+:+",
+"<+<+<+<+<+",
+"[+[+[+[+[+",
+"}+}+}+}+}+",
+"|+|+|+|+|+",
+"1+1+1+1+1+",
+"2+2+2+2+2+",
+"3+3+3+3+3+",
+"4+4+4+4+4+",
+"5+5+5+5+5+",
+"6+6+6+6+6+",
+"7+7+7+7+7+",
+"8+8+8+8+8+",
+"9+9+9+9+9+",
+"0+0+0+0+0+",
+"a+a+a+a+a+",
+"b+b+b+b+b+",
+"c+c+c+c+c+",
+"d+d+d+d+d+",
+"e+e+e+e+e+",
+"f+f+f+f+f+",
+"g+g+g+g+g+"};
+
+static const char* channel_setup_names[] = {
+ "mono",
+ "stereo",
+ "3 channels",
+ "4 channels",
+ "5 channels",
+ "8 channels",
+ "manual setup",
+ 0
+};
+
+vector<string> channel_combo_strings;
+
+ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
+
+ : Gtkmmext::UI ("ardour", argcp, argvp, rcfile),
+
+ primary_clock (X_("TransportClockDisplay"), true, false, true),
+ secondary_clock (X_("SecondaryClockDisplay"), true, false, true),
+ preroll_clock (X_("PreRollClock"), true, true),
+ postroll_clock (X_("PostRollClock"), true, true),
+
+ /* adjuster table */
+
+ adjuster_table (3, 3),
+
+ /* preroll stuff */
+
+ preroll_button (_("pre\nroll")),
+ postroll_button (_("post\nroll")),
+
+ /* big clock */
+
+ big_clock ("BigClockDisplay", true),
+
+ /* transport */
+
+ shuttle_units_button (_("% ")),
+ shuttle_style_button (_("spring")),
+
+ punch_in_button (_("punch\nin")),
+ punch_out_button (_("punch\nout")),
+ auto_return_button (_("auto\nreturn")),
+ auto_play_button (_("auto\nplay")),
+ auto_input_button (_("auto\ninput")),
+ click_button (_("click")),
+ follow_button (_("follow\nPH")),
+ auditioning_alert_button (_("AUDITIONING")),
+ solo_alert_button (_("SOLO")),
+
+ session_selector (1, 0),
+
+ shown_flag (false)
+
+{
+ using namespace Gtk::Menu_Helpers;
+
+ Gtkmmext::init();
+
+ /* actually, its already loaded, but ... */
+
+ cerr << "Loading UI configuration file " << rcfile << endl;
+
+ about = 0;
+
+ if (theArdourUI == 0) {
+ theArdourUI = this;
+ }
+
+ editor = 0;
+ mixer = 0;
+ session = 0;
+ _session_is_new = false;
+ big_clock_window = 0;
+ session_selector_window = 0;
+ last_key_press_time = 0;
+ connection_editor = 0;
+ add_route_dialog = 0;
+ route_params = 0;
+ meter_bridge = 0;
+ option_editor = 0;
+ location_ui = 0;
+ sfdb_window = 0;
+ new_session_window = 0;
+ open_session_selector = 0;
+ have_configure_timeout = false;
+ have_disk_overrun_displayed = false;
+ have_disk_underrun_displayed = false;
+ _will_create_new_session_automatically = false;
+ session_loaded = false;
+
+ last_configure_time.tv_sec = 0;
+ last_configure_time.tv_usec = 0;
+
+ shuttle_grabbed = false;
+ shuttle_fract = 0.0;
+
+ set_shuttle_units (Percentage);
+ set_shuttle_behaviour (Sprung);
+
+ shuttle_unit_menu.items().push_back (MenuElem (_("Percentage"), bind (slot (*this, &ARDOUR_UI::set_shuttle_units),
+ Percentage)));
+ shuttle_unit_menu.items().push_back (MenuElem (_("Semitones"), bind (slot (*this, &ARDOUR_UI::set_shuttle_units),
+ Semitones)));
+
+ shuttle_style_menu.items().push_back (MenuElem (_("Sprung"), bind (slot (*this, &ARDOUR_UI::set_shuttle_behaviour),
+ Sprung)));
+ shuttle_style_menu.items().push_back (MenuElem (_("Wheel"), bind (slot (*this, &ARDOUR_UI::set_shuttle_behaviour),
+ Wheel)));
+
+ gettimeofday (&last_peak_grab, 0);
+ gettimeofday (&last_shuttle_request, 0);
+
+ ARDOUR::DiskStream::CannotRecordNoInput.connect (slot (*this, &ARDOUR_UI::cannot_record_no_input));
+ ARDOUR::DiskStream::DeleteSources.connect (slot (*this, &ARDOUR_UI::delete_sources_in_the_right_thread));
+ ARDOUR::DiskStream::DiskOverrun.connect (slot (*this, &ARDOUR_UI::disk_overrun_handler));
+ ARDOUR::DiskStream::DiskUnderrun.connect (slot (*this, &ARDOUR_UI::disk_underrun_handler));
+
+ /* handle pending state with a dialog */
+
+ ARDOUR::Session::AskAboutPendingState.connect (slot (*this, &ARDOUR_UI::pending_state_dialog));
+
+ channel_combo_strings = internationalize (channel_setup_names);
+
+ /* have to wait for AudioEngine and Configuration before proceeding */
+}
+
+void
+ARDOUR_UI::cannot_record_no_input (DiskStream* ds)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &ARDOUR_UI::cannot_record_no_input), ds));
+
+ string msg = compose (_("\
+You cannot record-enable\n\
+track %1\n\
+because it has no input connections.\n\
+You would be wasting space recording silence."),
+ ds->name());
+
+ ArdourMessage message (editor, X_("cannotrecord"), msg);
+}
+
+void
+ARDOUR_UI::set_engine (AudioEngine& e)
+{
+ engine = &e;
+
+ engine->Stopped.connect (slot (*this, &ARDOUR_UI::engine_stopped));
+ engine->Running.connect (slot (*this, &ARDOUR_UI::engine_running));
+ engine->Halted.connect (slot (*this, &ARDOUR_UI::engine_halted));
+ engine->SampleRateChanged.connect (slot (*this, &ARDOUR_UI::update_sample_rate));
+
+ _tooltips.enable();
+
+ keyboard = new Keyboard;
+ install_keybindings ();
+
+ FastMeter::set_vertical_xpm (v_meter_strip_xpm);
+ FastMeter::set_horizontal_xpm (h_meter_strip_xpm);
+
+ if (setup_windows ()) {
+ throw failed_constructor ();
+ }
+
+ if (GTK_ARDOUR::show_key_actions) {
+ KeyboardTarget::show_all_actions ();
+ exit (0);
+ }
+
+ /* start with timecode, metering enabled
+ */
+
+ blink_timeout_tag = -1;
+
+ /* this being a GUI and all, we want peakfiles */
+
+ FileSource::set_build_peakfiles (true);
+ FileSource::set_build_missing_peakfiles (true);
+
+ if (Source::start_peak_thread ()) {
+ throw failed_constructor();
+ }
+
+ /* start the time-of-day-clock */
+
+ update_wall_clock ();
+ Main::timeout.connect (slot (*this, &ARDOUR_UI::update_wall_clock), 60000);
+
+ update_disk_space ();
+ update_cpu_load ();
+ update_sample_rate (engine->frame_rate());
+
+ starting.connect (slot (*this, &ARDOUR_UI::startup));
+ stopping.connect (slot (*this, &ARDOUR_UI::shutdown));
+}
+
+ARDOUR_UI::~ARDOUR_UI ()
+{
+ save_ardour_state ();
+
+ if (keyboard) {
+ delete keyboard;
+ }
+
+ if (editor) {
+ delete editor;
+ }
+
+ if (mixer) {
+ delete mixer;
+ }
+
+ if (add_route_dialog) {
+ delete add_route_dialog;
+ }
+
+ Source::stop_peak_thread ();
+}
+
+gint
+ARDOUR_UI::configure_timeout ()
+{
+ struct timeval now;
+ struct timeval diff;
+
+ if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) {
+ /* no configure events yet */
+ return TRUE;
+ }
+
+ gettimeofday (&now, 0);
+ timersub (&now, &last_configure_time, &diff);
+
+ /* force a gap of 0.5 seconds since the last configure event
+ */
+
+ if (diff.tv_sec == 0 && diff.tv_usec < 500000) {
+ return TRUE;
+ } else {
+ have_configure_timeout = false;
+ save_ardour_state ();
+ return FALSE;
+ }
+}
+
+gboolean
+ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
+{
+ if (have_configure_timeout) {
+ gettimeofday (&last_configure_time, 0);
+ } else {
+ TimeoutSig t;
+ t.connect (slot (*this, &ARDOUR_UI::configure_timeout), 100);
+ have_configure_timeout = true;
+ }
+
+ return FALSE;
+}
+
+void
+ARDOUR_UI::save_ardour_state ()
+{
+ if (!keyboard || !mixer || !editor) {
+ return;
+ }
+
+ /* XXX this is all a bit dubious. add_extra_xml() uses
+ a different lifetime model from add_instant_xml().
+ */
+
+ XMLNode* node = new XMLNode (keyboard->get_state());
+ Config->add_extra_xml (*node);
+ Config->save_state();
+
+ XMLNode& enode (static_cast<Stateful*>(editor)->get_state());
+ XMLNode& mnode (mixer->get_state());
+
+ if (session) {
+ session->add_instant_xml(enode, session->path());
+ session->add_instant_xml(mnode, session->path());
+ } else {
+ Config->add_instant_xml(enode, Config->get_user_ardour_path());
+ Config->add_instant_xml(mnode, Config->get_user_ardour_path());
+ }
+}
+
+void
+ARDOUR_UI::startup ()
+{
+ /* Once the UI is up and running, start the audio engine. Doing
+ this before the UI is up and running can cause problems
+ when not running with SCHED_FIFO, because the amount of
+ CPU and disk work needed to get the UI started can interfere
+ with the scheduling of the audio thread.
+ */
+
+ Gtk::Main::idle.connect (slot (*this, &ARDOUR_UI::start_engine));
+}
+
+void
+ARDOUR_UI::finish()
+{
+ if (session && session->dirty()) {
+ switch (ask_about_saving_session(_("quit"))) {
+ case -1:
+ return;
+ break;
+ case 1:
+ /* use the default name */
+ if (save_state_canfail ("")) {
+ /* failed - don't quit */
+ ArdourMessage (editor, X_("badsave dialog"),
+ _("\
+Ardour was unable to save your session.\n\n\
+If you still wish to quit, please use the\n\n\
+\"Just quit\" option."));
+ return;
+ }
+ break;
+ case 0:
+ break;
+ }
+ }
+
+ quit();
+}
+
+int
+ARDOUR_UI::ask_about_saving_session (string what)
+{
+ ArdourDialog window ("saving dialog");
+ Gtk::VBox packer;
+ Gtk::Label prompt_label;
+ Gtk::HBox button_packer;
+
+ string msg;
+
+ msg = compose(_("Save and %1"), what);
+
+ Gtk::Button save_button (msg);
+ save_button.set_name ("EditorGTKButton");
+
+ msg = compose(_("Just %1"), what);
+
+ Gtk::Button nosave_button (msg);
+ nosave_button.set_name ("EditorGTKButton");
+
+ msg = compose(_("Don't %1"), what);
+
+ Gtk::Button noquit_button (msg);
+ noquit_button.set_name ("EditorGTKButton");
+
+ string prompt;
+ string type;
+
+ if (session->snap_name() == session->name()) {
+ type = _("session");
+ } else {
+ type = _("snapshot");
+ }
+ prompt = compose(_("The %1\n\"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"),
+ type, session->snap_name());
+
+ prompt_label.set_text (prompt);
+ prompt_label.set_alignment (0.5, 0.5);
+ prompt_label.set_name (X_("PrompterLabel"));
+
+ save_button.clicked.connect (bind(slot(window,&ArdourDialog::stop), 1));
+ nosave_button.clicked.connect (bind(slot(window,&ArdourDialog::stop), 0));
+ noquit_button.clicked.connect (bind(slot(window,&ArdourDialog::stop), -1));
+
+ button_packer.set_spacing (10);
+ button_packer.pack_start (save_button);
+ button_packer.pack_start (nosave_button);
+ button_packer.pack_start (noquit_button);
+
+ packer.set_spacing (10);
+ packer.set_border_width (10);
+ packer.pack_start (prompt_label);
+ packer.pack_start (button_packer);
+
+ window.set_name (_("Prompter"));
+ window.set_title (_("ardour: save session?"));
+ window.set_position (GTK_WIN_POS_MOUSE);
+ window.set_modal (true);
+ window.add (packer);
+ window.show_all ();
+
+ window.realize();
+ window.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+ window.set_keyboard_input (true);
+
+ save_the_session = 0;
+
+ editor->ensure_float (window);
+
+ window.run ();
+
+ return window.run_status();
+}
+
+gint
+ARDOUR_UI::every_second ()
+{
+ update_cpu_load ();
+ update_buffer_load ();
+ update_disk_space ();
+ // update_disk_rate ();
+ return TRUE;
+}
+
+gint
+ARDOUR_UI::every_point_one_seconds ()
+{
+ struct timeval now;
+ struct timeval diff;
+
+ /* do not attempt to grab peak power more than once per cycle.
+ */
+
+ gettimeofday (&now, 0);
+ timersub (&now, &last_peak_grab, &diff);
+
+ if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) {
+ IO::GrabPeakPower(); /* EMIT_SIGNAL */
+ last_peak_grab = now;
+ }
+
+ update_speed_display ();
+ RapidScreenUpdate(); /* EMIT_SIGNAL */
+ return TRUE;
+}
+
+gint
+ARDOUR_UI::every_point_zero_one_seconds ()
+{
+ SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
+ return TRUE;
+}
+
+void
+ARDOUR_UI::update_sample_rate (jack_nframes_t ignored)
+{
+ char buf[32];
+
+ ENSURE_GUI_THREAD (bind (slot (*this, &ARDOUR_UI::update_sample_rate), ignored));
+
+ if (!engine->connected()) {
+
+ snprintf (buf, sizeof (buf), _("disconnected"));
+
+ } else {
+
+ jack_nframes_t rate = engine->frame_rate();
+
+ if (fmod (rate, 1000.0) != 0.0) {
+ snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"),
+ (float) rate/1000.0f,
+ (engine->frames_per_cycle() / (float) rate) * 1000.0f);
+ } else {
+ snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"),
+ rate/1000,
+ (engine->frames_per_cycle() / (float) rate) * 1000.0f);
+ }
+ }
+
+ sample_rate_label.set_text (buf);
+}
+
+void
+ARDOUR_UI::update_cpu_load ()
+{
+ char buf[32];
+ snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load());
+ cpu_load_label.set_text (buf);
+}
+
+void
+ARDOUR_UI::update_disk_rate ()
+{
+ char buf[64];
+
+ if (session) {
+ snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"),
+ session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f);
+ disk_rate_label.set_text (buf);
+ } else {
+ disk_rate_label.set_text ("");
+ }
+}
+
+void
+ARDOUR_UI::update_buffer_load ()
+{
+ char buf[64];
+
+ if (session) {
+ snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
+ session->playback_load(), session->capture_load());
+ buffer_load_label.set_text (buf);
+ } else {
+ buffer_load_label.set_text ("");
+ }
+}
+
+void
+ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds)
+{
+ if (ds.record_enabled()) {
+ rec_enabled_diskstreams++;
+ }
+}
+
+void
+ARDOUR_UI::update_disk_space()
+{
+ if (session == 0) {
+ return;
+ }
+
+ jack_nframes_t frames = session->available_capture_duration();
+ char buf[64];
+
+ if (frames == max_frames) {
+ strcpy (buf, _("space: 24hrs+"));
+ } else {
+ int hrs;
+ int mins;
+ int secs;
+ jack_nframes_t fr = session->frame_rate();
+
+ if (session->actively_recording()){
+
+ rec_enabled_diskstreams = 0;
+ session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams);
+
+ if (rec_enabled_diskstreams) {
+ frames /= rec_enabled_diskstreams;
+ }
+
+ } else {
+
+ /* hmmm. shall we divide by the route count? or the diskstream count?
+ or what? for now, do nothing ...
+ */
+
+ }
+
+ hrs = frames / (fr * 3600);
+ frames -= hrs * fr * 3600;
+ mins = frames / (fr * 60);
+ frames -= mins * fr * 60;
+ secs = frames / fr;
+
+ snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs);
+ }
+
+ disk_space_label.set_text (buf);
+}
+
+gint
+ARDOUR_UI::update_wall_clock ()
+{
+ time_t now;
+ struct tm *tm_now;
+ char buf[16];
+
+ time (&now);
+ tm_now = localtime (&now);
+
+ sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min);
+ wall_clock_label.set_text (buf);
+
+ return TRUE;
+}
+
+void
+ARDOUR_UI::toggle_recording_plugins ()
+{
+ /* XXX use toggle_some_session_state */
+
+ if (session == 0) {
+ return;
+ }
+
+ session->set_recording_plugins (!session->get_recording_plugins());
+}
+
+void
+ARDOUR_UI::toggle_auto_play ()
+
+{
+ toggle_some_session_state (auto_play_button,
+ &Session::get_auto_play,
+ &Session::set_auto_play);
+}
+
+void
+ARDOUR_UI::toggle_auto_return ()
+
+{
+ toggle_some_session_state (auto_return_button,
+ &Session::get_auto_return,
+ &Session::set_auto_return);
+}
+
+void
+ARDOUR_UI::toggle_click ()
+{
+ toggle_some_session_state (click_button,
+ &Session::get_clicking,
+ &Session::set_clicking);
+}
+
+void
+ARDOUR_UI::follow_changed ()
+{
+ bool x;
+
+ if (!editor) {
+ return;
+ }
+
+ if (follow_button.get_active() != (x = editor->follow_playhead())) {
+ follow_button.set_active (x);
+ }
+}
+
+void
+ARDOUR_UI::toggle_follow ()
+{
+ bool x;
+
+ if (!editor) {
+ return;
+ }
+
+ if (editor->follow_playhead() != (x = follow_button.get_active())) {
+ editor->set_follow_playhead (x);
+ }
+}
+
+void
+ARDOUR_UI::toggle_session_auto_loop ()
+{
+ if (session) {
+ if (session->get_auto_loop()) {
+ if (session->transport_rolling()) {
+ transport_roll();
+ }
+ else {
+ session->request_auto_loop (false);
+ }
+ }
+ else {
+ session->request_auto_loop (true);
+ }
+ }
+}
+
+void
+ARDOUR_UI::toggle_session_punch_in ()
+{
+ if (session) {
+ session->set_punch_in (!session->get_punch_in());
+ }
+}
+
+void
+ARDOUR_UI::toggle_punch_out ()
+{
+ toggle_some_session_state (punch_out_button,
+ &Session::get_punch_out,
+ &Session::set_punch_out);
+}
+
+void
+ARDOUR_UI::toggle_punch_in ()
+{
+ toggle_some_session_state (punch_in_button,
+ &Session::get_punch_in,
+ &Session::set_punch_in);
+}
+
+void
+ARDOUR_UI::map_button_state ()
+
+{
+ map_some_session_state (auto_return_button,
+ &Session::get_auto_return);
+ map_some_session_state (auto_play_button,
+ &Session::get_auto_play);
+ map_some_session_state (auto_input_button,
+ &Session::get_auto_input);
+ map_some_session_state (punch_in_button,
+ &Session::get_punch_in);
+ map_some_session_state (punch_out_button,
+ &Session::get_punch_out);
+ map_some_session_state (click_button,
+ &Session::get_clicking);
+}
+
+void
+ARDOUR_UI::queue_map_control_change (Session::ControlType t)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &ARDOUR_UI::map_control_change), t));
+}
+
+void
+ARDOUR_UI::map_control_change (Session::ControlType t)
+{
+ switch (t) {
+ case Session::AutoPlay:
+ map_some_session_state (auto_play_button, &Session::get_auto_play);
+ break;
+
+ case Session::AutoLoop:
+ break;
+
+ case Session::AutoReturn:
+ map_some_session_state (auto_return_button, &Session::get_auto_return);
+ break;
+
+ case Session::AutoInput:
+ map_some_session_state (auto_input_button, &Session::get_auto_input);
+ break;
+
+ case Session::PunchOut:
+ map_some_session_state (punch_in_button, &Session::get_punch_out);
+ break;
+
+ case Session::PunchIn:
+ map_some_session_state (punch_in_button, &Session::get_punch_in);
+ break;
+
+ case Session::Clicking:
+ map_some_session_state (click_button, &Session::get_clicking);
+ break;
+
+ case Session::SlaveType:
+// map_some_session_state (mtc_slave_button, &Session::get_mtc_slave);
+ break;
+
+ case Session::SendMTC:
+// map_some_session_state (send_mtc_button, &Session::get_send_mtc);
+ break;
+
+ case Session::SendMMC:
+// map_some_session_state (send_mmc_button, &Session::get_send_mmc);
+ break;
+
+ case Session::MMCControl:
+// map_some_session_state (mmc_control_button, &Session::get_mmc_control);
+ break;
+
+ case Session::MidiFeedback:
+// map_some_session_state (mmc_control_button, &Session::get_mmc_control);
+ break;
+ case Session::MidiControl:
+// map_some_session_state (mmc_control_button, &Session::get_mmc_control);
+ break;
+
+ case Session::Live:
+ break;
+
+ case Session::RecordingPlugins:
+ break;
+
+ case Session::CrossFadesActive:
+ break;
+
+ case Session::EditingMode:
+ break;
+
+ case Session::PlayRange:
+ break;
+
+ case Session::AlignChoice:
+ /* don't care, this is handled by the options editor */
+ break;
+ case Session::SeamlessLoop:
+ /* don't care, this is handled by the options editor */
+ break;
+
+ }
+}
+
+void
+ARDOUR_UI::control_methods_adjusted ()
+
+{
+ int which_method;
+
+ which_method = (int) online_control_button->adjustment.get_value();
+ switch (which_method) {
+ case 0:
+ allow_mmc_and_local ();
+ break;
+ case 1:
+ allow_mmc_only ();
+ break;
+ case 2:
+ allow_local_only ();
+ break;
+ default:
+ fatal << _("programming error: impossible control method") << endmsg;
+ }
+}
+
+
+void
+ARDOUR_UI::mmc_device_id_adjusted ()
+
+{
+#if 0
+ if (mmc) {
+ int dev_id = (int) mmc_id_button->adjustment.get_value();
+ mmc->set_device_id (dev_id);
+ }
+#endif
+}
+
+void
+ARDOUR_UI::map_some_session_state (ToggleButton& button,
+ bool (Session::*get)() const)
+
+{
+ bool x;
+
+ if (session == 0) {
+ return;
+ }
+
+ if (button.get_active() != (x = (session->*get)())) {
+ button.set_active (x);
+ }
+}
+
+void
+ARDOUR_UI::toggle_some_session_state (ToggleButton& button,
+ bool (Session::*get)() const,
+ void (Session::*set)(bool))
+
+{
+ bool button_state;
+ bool session_state;
+
+ if (session == 0) {
+ return;
+ }
+
+ button_state = button.get_active ();
+ session_state = (session->*get)();
+
+ if (button_state != session_state) {
+ (session->*set) (button_state);
+#if 0
+
+ /* check that it worked, and reverse
+ the button state if it didn't
+ */
+
+ if ((session->*get)() != button_state) {
+ button->set_active (!button_state);
+ }
+#endif
+
+ }
+}
+
+gint
+ARDOUR_UI::session_menu (GdkEventButton *ev)
+{
+ session_popup_menu->popup (0, 0, 0, 0);
+ return TRUE;
+}
+
+void
+ARDOUR_UI::redisplay_recent_sessions ()
+{
+ using namespace Gtkmmext;
+ using namespace Gtk::CTree_Helpers;
+
+ vector<string *> *sessions;
+ vector<string *>::iterator i;
+ RecentSessionsSorter cmp;
+
+ /* ---------------------------------------- */
+ /* XXX MAKE ME A FUNCTION (no CTree::clear() in gtkmm 1.2) */
+
+ gtk_ctree_remove_node (session_selector.gtkobj(), NULL);
+ /* ---------------------------------------- */
+
+
+ RecentSessions rs;
+ ARDOUR::read_recent_sessions (rs);
+
+ if (rs.empty()) {
+ session_selector.thaw();
+ return;
+ }
+ /* sort them alphabetically */
+ sort(rs.begin(), rs.end(), cmp);
+ sessions = new vector<string*>;
+ for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
+ sessions->push_back (new string ((*i).second));
+ }
+
+ session_selector.freeze();
+
+ for (i = sessions->begin(); i != sessions->end(); ++i) {
+
+ vector<string*>* states;
+ vector<const gchar*> item;
+ string fullpath = *(*i);
+
+ /* remove any trailing / */
+
+ if (fullpath[fullpath.length()-1] == '/') {
+ fullpath = fullpath.substr (0, fullpath.length()-1);
+ }
+
+ /* now get available states for this session */
+
+ if ((states = Session::possible_states(fullpath)) == 0) {
+ /* no state file? */
+ continue;
+ }
+
+ /* OK, try to add entries for this session */
+
+
+ /* add the parent */
+
+ item.clear ();
+ string basen = PBD::basename (fullpath);
+ item.push_back (basen.c_str());
+ session_selector.rows().push_back (Element (item));
+
+ session_selector.rows().back().set_data (new string (fullpath), deferred_delete<string>);
+
+ if (states->size() == 1) {
+
+ /* only 1 state, show it at the top level */
+
+ session_selector.rows().back().set_leaf (true);
+
+ } else {
+
+ session_selector.rows().back().set_leaf (false);
+
+ vector<string *>::iterator i2;
+
+ /* add the children */
+
+ for (i2 = states->begin(); i2 != states->end(); ++i2) {
+
+ string statename = *(*i2);
+
+ item.clear ();
+ item.push_back (statename.c_str());
+
+ session_selector.rows().back().subtree().push_back (Element (item));
+ session_selector.rows().back().subtree().back().set_data (new string (statename),
+ deferred_delete<string>);
+ session_selector.rows().back().subtree().back().set_leaf (true);
+
+ delete *i2;
+ }
+ }
+
+ delete states;
+ }
+
+ session_selector.thaw();
+ delete sessions;
+}
+
+void
+ARDOUR_UI::session_selection (Gtk::CTree_Helpers::Row row, gint column)
+{
+ using namespace Gtk::CTree_Helpers;
+
+ string session_name;
+ string session_path;
+ string session_state;
+
+ if (!row.is_leaf()) {
+ row.expand();
+ return;
+ }
+
+ string *stp = static_cast<string *> (row.get_data());
+
+ if ((*stp)[0] != '/' && (*stp)[0] != '.') {
+
+ /* its a state file node, so get the parent for the session information,
+ and combine with the state file name.
+ */
+
+ string *spp = static_cast<string *> (row.get_parent().get_data());
+
+ session_name = *spp;
+ session_path = *spp;
+ session_state = *stp;
+
+ } else {
+
+ /* its a session directory node, so just get the session path,
+ and use "default" to load the state.
+ */
+
+ string *spp = static_cast<string *> (row.get_data());
+
+ session_name = *spp;
+ session_path = *spp;
+ session_state = PBD::basename (*spp);
+ }
+
+ session_selector_window->hide ();
+ _session_is_new = false;
+ load_session (session_path, session_state);
+}
+
+void
+ARDOUR_UI::build_session_selector ()
+{
+ session_selector_window = new ArdourDialog ("session selector");
+
+ Gtk::VBox *vpacker = new Gtk::VBox;
+ Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow;
+ Gtk::HBox *button_packer = new Gtk::HBox;
+ Gtk::Button *cancel_button = new Gtk::Button (_("cancel"));
+ Gtk::Button *rescan_button = new Gtk::Button (_("rescan"));
+
+ button_packer->pack_start (*rescan_button);
+ button_packer->pack_start (*cancel_button);
+
+ vpacker->pack_start (*scroller);
+ vpacker->pack_start (*button_packer, false, false);
+
+ scroller->add (session_selector);
+ scroller->set_policy(GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ session_selector_window->add (*vpacker);
+ session_selector_window->set_name ("SessionSelectorWindow");
+ session_selector_window->set_usize (200, 400);
+
+ session_selector_window->delete_event.connect (bind (slot (just_hide_it), static_cast<Gtk::Window*>(session_selector_window)));
+ cancel_button->clicked.connect (bind (slot (*this, &ARDOUR_UI::hide_dialog), session_selector_window));
+ session_selector.tree_select_row.connect (slot (*this, &ARDOUR_UI::session_selection));
+}
+
+void
+ARDOUR_UI::fs_cancel_clicked (Gtk::FileSelection* fs)
+{
+ fs->hide_all();
+ fs->get_selection_entry()->set_text("");
+ allow_focus (false);
+}
+
+gint
+ARDOUR_UI::fs_delete_event (GdkEventAny* ev, Gtk::FileSelection* fs)
+{
+ fs_cancel_clicked (fs);
+ return 1;
+}
+
+void
+ARDOUR_UI::open_session ()
+{
+ /* popup selector window */
+
+ if (open_session_selector == 0) {
+ open_session_selector = new Gtk::FileSelection(_("open session"));
+ open_session_selector->get_ok_button()->clicked.connect (slot (*this, &ARDOUR_UI::open_ok_clicked));
+ open_session_selector->get_cancel_button()->clicked.connect (bind (slot (*this, &ARDOUR_UI::fs_cancel_clicked), open_session_selector));
+ open_session_selector->delete_event.connect (bind (slot (*this, &ARDOUR_UI::fs_delete_event), open_session_selector));
+ }
+
+ open_session_selector->show_all ();
+ allow_focus (true);
+
+ /* wait for selection */
+}
+
+void
+ARDOUR_UI::open_ok_clicked ()
+{
+ open_session_selector->hide_all();
+ string session_path = open_session_selector->get_filename();
+ string path, name;
+ bool isnew;
+
+ if (session_path.length() > 0) {
+ if (Session::find_session (session_path, path, name, isnew) == 0) {
+ _session_is_new = isnew;
+ load_session (path, name);
+ }
+ }
+
+ open_session_selector->get_selection_entry()->set_text("");
+
+ /* XXX hack hack hack */
+
+ GtkCList* clist = (GtkCList*) open_session_selector->gtkobj()->file_list;
+ gtk_clist_unselect_all (clist);
+
+ allow_focus(false);
+}
+
+void
+ARDOUR_UI::open_recent_session ()
+{
+ /* popup selector window */
+
+ if (session_selector_window == 0) {
+ build_session_selector ();
+ }
+
+ redisplay_recent_sessions ();
+ session_selector_window->show_all ();
+
+ /* wait for selection */
+}
+
+void
+ARDOUR_UI::session_add_midi_track ()
+{
+ cerr << _("Patience is a virtue.\n");
+}
+
+void
+ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels)
+{
+ Route* route;
+
+ if (session == 0) {
+ warning << _("You cannot add a track without a session already loaded.") << endmsg;
+ return;
+ }
+
+ try {
+ if (disk) {
+ if ((route = session->new_audio_track (input_channels, output_channels)) == 0) {
+ error << _("could not create new audio track") << endmsg;
+ }
+ } else {
+ if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
+ error << _("could not create new audio bus") << endmsg;
+ }
+ }
+
+#if CONTROLOUTS
+ if (need_control_room_outs) {
+ pan_t pans[2];
+
+ pans[0] = 0.5;
+ pans[1] = 0.5;
+
+ route->set_stereo_control_outs (control_lr_channels);
+ route->control_outs()->set_stereo_pan (pans, this);
+ }
+#endif /* CONTROLOUTS */
+ }
+
+ catch (...) {
+ ArdourMessage msg (editor, X_("noport dialog"),
+ _("There are insufficient JACK ports available\n\
+to create a new track or bus.\n\
+You should save Ardour, exit and\n\
+restart JACK with more ports."));
+ }
+}
+
+void
+ARDOUR_UI::diskstream_added (DiskStream* ds)
+{
+ // meter_bridge_dialog_check->set_sensitive (true);
+}
+
+void
+ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
+{
+ jack_nframes_t _preroll;
+
+ if (session) {
+ _preroll = session->convert_to_frames_at (new_position, session->preroll);
+
+ if (new_position > _preroll) {
+ new_position -= _preroll;
+ } else {
+ new_position = 0;
+ }
+
+ session->request_locate (new_position);
+ }
+}
+
+void
+ARDOUR_UI::transport_goto_start ()
+{
+ if (session) {
+ session->request_locate (0);
+
+
+ /* force displayed area in editor to start no matter
+ what "follow playhead" setting is.
+ */
+
+ if (editor) {
+ editor->reposition_x_origin (0);
+ }
+ }
+}
+
+void
+ARDOUR_UI::transport_goto_end ()
+{
+ if (session) {
+ jack_nframes_t frame = session->current_end_frame();
+ session->request_locate (frame);
+
+ /* force displayed area in editor to start no matter
+ what "follow playhead" setting is.
+ */
+
+ if (editor) {
+ editor->reposition_x_origin (frame);
+ }
+ }
+}
+
+gint
+ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev)
+{
+
+
+ if (session) {
+ if (session->transport_stopped()) {
+ session->request_locate (session->last_transport_start());
+ } else {
+ if (session->get_auto_loop()) {
+ session->request_auto_loop (false);
+ }
+
+ Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift);
+ session->request_stop (Keyboard::modifier_state_equals (ev->state, mask));
+ }
+ }
+
+ return TRUE;
+}
+
+gint
+ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev)
+{
+ transport_roll ();
+ return TRUE;
+}
+
+void
+ARDOUR_UI::transport_stop ()
+{
+ if (!session) {
+ return;
+ }
+
+ if (session->is_auditioning()) {
+ session->cancel_audition ();
+ return;
+ }
+
+ if (session->get_auto_loop()) {
+ session->request_auto_loop (false);
+ }
+
+ session->request_stop ();
+}
+
+void
+ARDOUR_UI::transport_stop_and_forget_capture ()
+{
+ if (session) {
+ session->request_stop (true);
+ }
+}
+
+void
+ARDOUR_UI::remove_last_capture()
+{
+ if (editor) {
+ editor->remove_last_capture();
+ }
+}
+
+void
+ARDOUR_UI::transport_record ()
+{
+ if (session) {
+ switch (session->record_status()) {
+ case Session::Disabled:
+ if (session->ntracks() == 0) {
+ string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.");
+ ArdourMessage msg (editor, X_("cannotrecenable"), txt);
+ return;
+ }
+ session->maybe_enable_record ();
+ break;
+ case Session::Recording:
+ case Session::Enabled:
+ session->disable_record ();
+ }
+ }
+}
+
+void
+ARDOUR_UI::transport_roll ()
+{
+ bool rolling;
+
+ if (!session) {
+ return;
+ }
+
+ rolling = session->transport_rolling ();
+
+ if (session->get_auto_loop()) {
+ session->request_auto_loop (false);
+ auto_loop_button.set_active (false);
+ roll_button.set_active (true);
+ } else if (session->get_play_range ()) {
+ session->request_play_range (false);
+ play_selection_button.set_active (false);
+ } else if (rolling) {
+ session->request_locate (session->last_transport_start(), true);
+ }
+
+ session->request_transport_speed (1.0f);
+}
+
+void
+ARDOUR_UI::transport_loop()
+{
+ if (session) {
+ if (session->get_auto_loop()) {
+ if (session->transport_rolling()) {
+ Location * looploc = session->locations()->auto_loop_location();
+ if (looploc) {
+ session->request_locate (looploc->start(), true);
+ }
+ }
+ }
+ else {
+ session->request_auto_loop (true);
+ }
+ }
+}
+
+void
+ARDOUR_UI::transport_play_selection ()
+{
+ if (!session) {
+ return;
+ }
+
+ if (!session->get_play_range()) {
+ session->request_stop ();
+ }
+
+ editor->play_selection ();
+}
+
+void
+ARDOUR_UI::transport_rewind (int option)
+{
+ float current_transport_speed;
+
+ if (session) {
+ current_transport_speed = session->transport_speed();
+
+ if (current_transport_speed >= 0.0f) {
+ switch (option) {
+ case 0:
+ session->request_transport_speed (-1.0f);
+ break;
+ case 1:
+ session->request_transport_speed (-4.0f);
+ break;
+ case -1:
+ session->request_transport_speed (-0.5f);
+ break;
+ }
+ } else {
+ /* speed up */
+ session->request_transport_speed (current_transport_speed * 1.5f);
+ }
+ }
+}
+
+void
+ARDOUR_UI::transport_forward (int option)
+{
+ float current_transport_speed;
+
+ if (session) {
+ current_transport_speed = session->transport_speed();
+
+ if (current_transport_speed <= 0.0f) {
+ switch (option) {
+ case 0:
+ session->request_transport_speed (1.0f);
+ break;
+ case 1:
+ session->request_transport_speed (4.0f);
+ break;
+ case -1:
+ session->request_transport_speed (0.5f);
+ break;
+ }
+ } else {
+ /* speed up */
+ session->request_transport_speed (current_transport_speed * 1.5f);
+ }
+ }
+}
+
+void
+ARDOUR_UI::toggle_monitor_enable (guint32 dstream)
+{
+ if (session == 0) {
+ return;
+ }
+
+ DiskStream *ds;
+
+ if ((ds = session->diskstream_by_id (dstream)) != 0) {
+ Port *port = ds->io()->input (0);
+ port->request_monitor_input (!port->monitoring_input());
+ }
+}
+
+void
+ARDOUR_UI::toggle_record_enable (guint32 dstream)
+{
+ if (session == 0) {
+ return;
+ }
+
+ DiskStream *ds;
+
+ if ((ds = session->diskstream_by_id (dstream)) != 0) {
+ ds->set_record_enabled (!ds->record_enabled(), this);
+ }
+}
+
+void
+ARDOUR_UI::queue_transport_change ()
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &ARDOUR_UI::map_transport_state));
+}
+
+void
+ARDOUR_UI::map_transport_state ()
+{
+ float sp = session->transport_speed();
+
+ if (sp == 1.0f) {
+ transport_rolling ();
+ } else if (sp < 0.0f) {
+ transport_rewinding ();
+ } else if (sp > 0.0f) {
+ transport_forwarding ();
+ } else {
+ transport_stopped ();
+ }
+}
+
+void
+ARDOUR_UI::send_all_midi_feedback ()
+{
+ if (session) {
+ session->send_all_midi_feedback();
+ }
+}
+
+void
+ARDOUR_UI::allow_local_only ()
+{
+
+}
+
+void
+ARDOUR_UI::allow_mmc_only ()
+{
+
+}
+
+void
+ARDOUR_UI::allow_mmc_and_local ()
+{
+
+}
+
+void
+ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
+{
+ snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
+ (int) adj.get_value()].c_str());
+}
+
+void
+ARDOUR_UI::engine_stopped ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::engine_stopped));
+
+ jack_disconnect_item->set_sensitive (false);
+ jack_reconnect_item->set_sensitive (true);
+ jack_bufsize_menu->set_sensitive (false);
+}
+
+
+void
+ARDOUR_UI::engine_running ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::engine_running));
+
+ jack_disconnect_item->set_sensitive (true);
+ jack_reconnect_item->set_sensitive (false);
+ jack_bufsize_menu->set_sensitive (true);
+}
+
+void
+ARDOUR_UI::engine_halted ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::engine_halted));
+
+ jack_disconnect_item->set_sensitive (false);
+ jack_reconnect_item->set_sensitive (true);
+ jack_bufsize_menu->set_sensitive (false);
+
+ update_sample_rate (0);
+
+ ArdourMessage msg (editor, X_("halted"),
+ _("\
+JACK has either been shutdown or it\n\
+disconnected Ardour because Ardour\n\
+was not fast enough. You can save the\n\
+session and/or try to reconnect to JACK ."));
+}
+
+int32_t
+ARDOUR_UI::do_engine_start ()
+{
+ try {
+ engine->start();
+ }
+
+ catch (AudioEngine::PortRegistrationFailure& err) {
+ engine->stop ();
+ error << _("Unable to create all required ports")
+ << endmsg;
+ unload_session ();
+ return -1;
+ }
+
+ catch (...) {
+ engine->stop ();
+ error << _("Unable to start the session running")
+ << endmsg;
+ unload_session ();
+ return -2;
+ }
+
+ return 0;
+}
+
+gint
+ARDOUR_UI::start_engine ()
+{
+ if (do_engine_start () == 0) {
+ if (session && _session_is_new) {
+ /* we need to retain initial visual
+ settings for a new session
+ */
+ session->save_state ("");
+ }
+
+ /* there is too much going on, in too many threads, for us to
+ end up with a clean session. So wait 1 second after loading,
+ and fix it up. its ugly, but until i come across a better
+ solution, its what we have.
+ */
+
+ Main::timeout.connect (slot (*this, &ARDOUR_UI::make_session_clean), 1000);
+ }
+
+ return FALSE;
+}
+
+void
+ARDOUR_UI::update_clocks ()
+{
+ Clock (session->audible_frame()); /* EMIT_SIGNAL */
+}
+
+void
+ARDOUR_UI::start_clocking ()
+{
+ clock_signal_connection = RapidScreenUpdate.connect (slot (*this, &ARDOUR_UI::update_clocks));
+}
+
+void
+ARDOUR_UI::stop_clocking ()
+{
+ clock_signal_connection.disconnect ();
+}
+
+void
+ARDOUR_UI::toggle_clocking ()
+{
+#if 0
+ if (clock_button.get_active()) {
+ start_clocking ();
+ } else {
+ stop_clocking ();
+ }
+#endif
+}
+
+gint
+ARDOUR_UI::_blink (void *arg)
+
+{
+ ((ARDOUR_UI *) arg)->blink ();
+ return TRUE;
+}
+
+void
+ARDOUR_UI::blink ()
+{
+ Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
+}
+
+void
+ARDOUR_UI::start_blinking ()
+{
+ /* Start the blink signal. Everybody with a blinking widget
+ uses Blink to drive the widget's state.
+ */
+
+ if (blink_timeout_tag < 0) {
+ blink_on = false;
+ blink_timeout_tag = gtk_timeout_add (240, _blink, this);
+ }
+}
+
+void
+ARDOUR_UI::stop_blinking ()
+{
+ if (blink_timeout_tag >= 0) {
+ gtk_timeout_remove (blink_timeout_tag);
+ blink_timeout_tag = -1;
+ }
+}
+
+
+void
+ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream)
+{
+ using namespace Gtk;
+ using namespace Menu_Helpers;
+
+ if (dstream.hidden()) {
+ return;
+ }
+
+ MenuList& items = diskstream_menu->items();
+ items.push_back (MenuElem (dstream.name(), bind (slot (*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id())));
+}
+
+void
+ARDOUR_UI::diskstream_selected (gint32 id)
+{
+ selected_dstream = id;
+ Main::quit ();
+}
+
+gint32
+ARDOUR_UI::select_diskstream (GdkEventButton *ev)
+{
+ using namespace Gtk;
+ using namespace Menu_Helpers;
+
+ if (session == 0) {
+ return -1;
+ }
+
+ diskstream_menu = new Menu();
+ diskstream_menu->set_name ("ArdourContextMenu");
+ using namespace Gtk;
+ using namespace Menu_Helpers;
+
+ MenuList& items = diskstream_menu->items();
+ items.push_back (MenuElem (_("No Stream"), (bind (slot (*this, &ARDOUR_UI::diskstream_selected), -1))));
+
+ session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu);
+
+ if (ev) {
+ diskstream_menu->popup (ev->button, ev->time);
+ } else {
+ diskstream_menu->popup (0, 0);
+ }
+
+ selected_dstream = -1;
+
+ Main::run ();
+
+ delete diskstream_menu;
+
+ return selected_dstream;
+}
+
+void
+ARDOUR_UI::name_io_setup (AudioEngine& engine,
+ string& buf,
+ IO& io,
+ bool in)
+{
+ if (in) {
+ if (io.n_inputs() == 0) {
+ buf = _("none");
+ return;
+ }
+
+ /* XXX we're not handling multiple ports yet. */
+
+ const char **connections = io.input(0)->get_connections();
+
+ if (connections == 0 || connections[0] == '\0') {
+ buf = _("off");
+ } else {
+ buf = connections[0];
+ }
+
+ free (connections);
+
+ } else {
+
+ if (io.n_outputs() == 0) {
+ buf = _("none");
+ return;
+ }
+
+ /* XXX we're not handling multiple ports yet. */
+
+ const char **connections = io.output(0)->get_connections();
+
+ if (connections == 0 || connections[0] == '\0') {
+ buf = _("off");
+ } else {
+ buf = connections[0];
+ }
+
+ free (connections);
+ }
+}
+
+void
+ARDOUR_UI::snapshot_session ()
+{
+ ArdourPrompter prompter (true);
+ string now;
+ time_t n;
+
+ time (&n);
+ now = ctime (&n);
+ now = now.substr (0, now.length() - 1);
+
+ prompter.set_name ("Prompter");
+ prompter.set_prompt (_("Name for snapshot"));
+ prompter.set_initial_text (now);
+ prompter.done.connect (Gtk::Main::quit.slot());
+ prompter.show_all ();
+
+ Gtk::Main::run ();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string snapname;
+
+ prompter.get_result (snapname);
+ if (snapname.length()){
+ save_state (snapname);
+ }
+ }
+}
+
+void
+ARDOUR_UI::save_state (string name)
+{
+ (void) save_state_canfail (name);
+}
+
+int
+ARDOUR_UI::save_state_canfail (string name)
+{
+ if (session) {
+ int ret;
+
+ if (name.length() == 0) {
+ name = session->snap_name();
+ }
+
+ if ((ret = session->save_state (name)) != 0) {
+ return ret;
+ }
+ }
+ save_ardour_state (); /* XXX cannot fail? yeah, right ... */
+ return 0;
+}
+
+void
+ARDOUR_UI::restore_state (string name)
+{
+ if (session) {
+ if (name.length() == 0) {
+ name = session->name();
+ }
+ session->restore_state (name);
+ }
+}
+
+void
+ARDOUR_UI::allow_focus (bool yn)
+{
+ if (keyboard) {
+ keyboard->allow_focus (yn);
+ }
+}
+
+void
+ARDOUR_UI::primary_clock_value_changed ()
+{
+ if (session) {
+ session->request_locate (primary_clock.current_time ());
+ }
+}
+
+void
+ARDOUR_UI::secondary_clock_value_changed ()
+{
+ if (session) {
+ session->request_locate (secondary_clock.current_time ());
+ }
+}
+
+void
+ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w)
+{
+ if (session && dstream && dstream->record_enabled()) {
+
+ Session::RecordState rs;
+
+ rs = session->record_status ();
+
+ switch (rs) {
+ case Session::Disabled:
+ case Session::Enabled:
+ if (w->get_state() != GTK_STATE_SELECTED) {
+ w->set_state (GTK_STATE_SELECTED);
+ }
+ break;
+
+ case Session::Recording:
+ if (w->get_state() != GTK_STATE_ACTIVE) {
+ w->set_state (GTK_STATE_ACTIVE);
+ }
+ break;
+ }
+
+ } else {
+ if (w->get_state() != GTK_STATE_NORMAL) {
+ w->set_state (GTK_STATE_NORMAL);
+ }
+ }
+}
+
+void
+ARDOUR_UI::transport_rec_enable_blink (bool onoff)
+{
+ if (session == 0) {
+ return;
+ }
+
+ switch (session->record_status()) {
+ case Session::Enabled:
+ if (onoff) {
+ rec_button.set_state (GTK_STATE_ACTIVE);
+ } else {
+ rec_button.set_state (GTK_STATE_NORMAL);
+ }
+ break;
+
+ case Session::Recording:
+ rec_button.set_state (GTK_STATE_ACTIVE);
+ break;
+
+ default:
+ rec_button.set_active (false);
+ rec_button.set_state (GTK_STATE_NORMAL);
+ break;
+ }
+}
+
+gint
+ARDOUR_UI::generic_focus_in_event (GdkEventFocus *ev)
+{
+ ARDOUR_UI::instance()->allow_focus (true);
+ return FALSE;
+}
+
+gint
+ARDOUR_UI::generic_focus_out_event (GdkEventFocus *ev)
+{
+ ARDOUR_UI::instance()->allow_focus (false);
+ return FALSE;
+}
+
+gint
+ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
+{
+ window->hide();
+ Gtk::Main::quit ();
+ return TRUE;
+}
+
+void
+ARDOUR_UI::start_keyboard_prefix ()
+{
+ keyboard->start_prefix();
+}
+
+void
+ARDOUR_UI::save_template ()
+
+{
+ ArdourPrompter prompter (true);
+ prompter.set_name ("Prompter");
+ prompter.set_prompt (_("Name for mix template:"));
+ prompter.set_initial_text(session->name() + _("-template"));
+
+ prompter.done.connect(Gtk::Main::quit.slot());
+ prompter.show_all();
+
+ Gtk::Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+
+ prompter.get_result (name);
+
+ if (name.length()) {
+ session->save_template (name);
+ }
+ }
+}
+
+void
+ARDOUR_UI::new_session (bool startup, string predetermined_path)
+{
+ if (new_session_window == 0){
+ new_session_window = new NewSessionDialog (*engine, startup, predetermined_path);
+ editor->ensure_float (*new_session_window);
+ }
+
+ new_session_window->run ();
+
+ /* write favorites either way */
+ Session::FavoriteDirs favs;
+ new_session_window->file_selector.get_favorites (favs);
+ Session::write_favorite_dirs (favs);
+
+ if (new_session_window->run_status()) {
+ return;
+ }
+
+ string session_path = new_session_window->file_selector.get_path ();
+ string session_name = PBD::basename (session_path);
+
+ // Check that it doesn't already exist.
+ access(session_path.c_str(), R_OK);
+ if (errno != ENOENT){
+ error << compose(_("Session %1 already exists at %2"), session_name, session_path) << endmsg;
+ return;
+ }
+
+ _session_is_new = true;
+
+ if (session_path[session_path.length()-1] != '/') {
+
+ string template_name = new_session_window->get_template_name ();
+
+ if (template_name.length()) {
+
+ load_session (session_path, session_name, &template_name);
+
+ } else {
+
+ uint32_t cchns;
+ uint32_t mchns;
+ Session::AutoConnectOption iconnect;
+ Session::AutoConnectOption oconnect;
+
+ if (new_session_window->use_control_button.get_active()) {
+ cchns = (uint32_t) channel_combo_get_channel_count (new_session_window->control_out_channel_combo);
+ } else {
+ cchns = 0;
+ }
+ if (new_session_window->use_master_button.get_active()) {
+ mchns = (uint32_t) channel_combo_get_channel_count (new_session_window->master_out_channel_combo);
+ } else {
+ mchns = 0;
+ }
+
+ if (new_session_window->connect_to_physical_inputs_button.get_active()) {
+ iconnect = Session::AutoConnectPhysical;
+ } else {
+ iconnect = Session::AutoConnectOption (0);
+ }
+
+ if (new_session_window->connect_to_master_button.get_active ()) {
+ oconnect = Session::AutoConnectMaster;
+ } else if (new_session_window->connect_to_physical_outputs_button.get_active ()) {
+ oconnect = Session::AutoConnectPhysical;
+ } else {
+ oconnect = Session::AutoConnectOption (0);
+ }
+
+ uint32_t nphysin = (uint32_t) new_session_window->in_count_adjustment.get_value();
+ uint32_t nphysout = (uint32_t) new_session_window->out_count_adjustment.get_value();
+
+ build_session (session_path, session_name, cchns, mchns, iconnect, oconnect, nphysin, nphysout,
+ engine->frame_rate() * 60 * 5);
+ }
+ }
+}
+
+int
+ARDOUR_UI::load_session (string path, string snap_name, string* mix_template)
+{
+ Session *new_session;
+ int x;
+ session_loaded = false;
+ x = unload_session ();
+
+ if (x < 0) {
+ return -1;
+ } else if (x > 0) {
+ return 0;
+ }
+
+ /* if it already exists, we must have write access */
+
+ if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) {
+ ArdourMessage msg (editor, X_("noaccess dialog"), _("\
+You do not have write access to this session.\n\
+This prevents the session from being loaded."));
+ return -1;
+ }
+
+ try {
+ new_session = new Session (*engine, path, snap_name, mix_template);
+ }
+
+ catch (...) {
+
+ error << compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
+ return -1;
+ }
+
+ connect_to_session (new_session);
+
+ //if (engine->running()) {
+ //mixer->show_window();
+ //}
+ session_loaded = true;
+ return 0;
+}
+
+int
+ARDOUR_UI::make_session_clean ()
+{
+ if (session) {
+ session->set_clean ();
+ }
+
+ return FALSE;
+}
+
+int
+ARDOUR_UI::build_session (string path, string snap_name,
+ uint32_t control_channels,
+ uint32_t master_channels,
+ Session::AutoConnectOption input_connect,
+ Session::AutoConnectOption output_connect,
+ uint32_t nphysin,
+ uint32_t nphysout,
+ jack_nframes_t initial_length)
+{
+ Session *new_session;
+ int x;
+
+ session_loaded = false;
+ x = unload_session ();
+ if (x < 0) {
+ return -1;
+ } else if (x > 0) {
+ return 0;
+ }
+
+ _session_is_new = true;
+
+ try {
+ new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
+ control_channels, master_channels, nphysin, nphysout, initial_length);
+ }
+
+ catch (...) {
+
+ error << compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
+ return -1;
+ }
+
+ connect_to_session (new_session);
+
+ //if (engine->running()) {
+ //mixer->show_window();
+ //}
+ session_loaded = true;
+ return 0;
+}
+
+void
+ARDOUR_UI::hide_dialog (ArdourDialog *dialog)
+{
+ dialog->hide_all();
+}
+
+void
+ARDOUR_UI::show ()
+{
+ if (editor) {
+ editor->show_window ();
+ shown_flag = true;
+ }
+
+ if (session && mixer) {
+ mixer->show_window ();
+ }
+
+ if (about) {
+ about->get_window().raise ();
+ }
+}
+
+void
+ARDOUR_UI::show_splash ()
+{
+ if (about == 0) {
+ about = new About(this);
+ about->show_all();
+ about->show_sub (true);
+ about->get_window().raise ();
+ }
+ else {
+ about->get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+ about->show_all ();
+ about->get_window().raise ();
+ }
+}
+
+void
+ARDOUR_UI::hide_splash ()
+{
+ if (about) {
+ // about->hide();
+ }
+}
+
+void
+ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg)
+{
+ size_t removed;
+
+ removed = rep.paths.size();
+
+ if (removed == 0) {
+ ArdourMessage msg (editor, X_("cleanupresults"),
+ _("\
+No audio files were ready for cleanup\n\n\
+If this seems suprising, check for any existing\n\
+snapshots. These may still include regions that\n\
+require some unused files to continue to exist."));
+ return;
+ }
+
+ ArdourDialog results ("cleanup results");
+
+ const gchar* list_titles[] = {
+ list_title,
+ 0
+ };
+
+ Gtk::CList list (internationalize (list_titles));
+ Gtk::ScrolledWindow list_scroller;
+ Gtk::Label txt;
+ Gtk::Button ok_button (_("OK"));
+ Gtk::VBox vpacker;
+ const char* rowtext[1];
+
+ list_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ vpacker.set_border_width (10);
+ vpacker.set_spacing (10);
+
+ if (rep.space < 1048576.0f) {
+ if (removed > 1) {
+ txt.set_text (compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo"));
+ } else {
+ txt.set_text (compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo"));
+ }
+ } else {
+ if (removed > 1) {
+ txt.set_text (compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega"));
+ } else {
+ txt.set_text (compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega"));
+ }
+ }
+
+ vpacker.pack_start (txt, false, false);
+
+ for (vector<string>::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) {
+ rowtext[0] = (*i).c_str();
+ list.rows().push_back (rowtext);
+ }
+
+ list_scroller.add_with_viewport (list);
+ list_scroller.set_usize (-1, 250);
+
+ vpacker.pack_start (list_scroller, true, true);
+ vpacker.pack_start (ok_button, false, false);
+
+ ok_button.clicked.connect (Main::quit.slot ());
+ results.Hiding.connect (Main::quit.slot ());
+
+ results.add (vpacker);
+
+ results.set_position (GTK_WIN_POS_MOUSE);
+ results.set_title (_("ardour: cleanup"));
+ results.set_modal (true);
+ results.run ();
+}
+
+void
+ARDOUR_UI::cleanup ()
+{
+ if (session == 0) {
+ /* shouldn't happen: menu item is insensitive */
+ return;
+ }
+
+ ArdourDialog checker (X_("cleanup confirm dialog"));
+ Gtk::Label label (_("\
+Cleanup is a destructive operation.\n\
+ALL undo/redo information will be lost if you cleanup.\n\
+Unused audio files will be moved to a \"dead sounds\" location."));
+
+ Gtk::Button ok_button (_("Proceed with cleanup"));
+ Gtk::Button cancel_button (_("Cancel"));
+ Gtk::HBox bbox;
+ Gtk::VBox vbox;
+
+ bbox.set_border_width (6);
+ bbox.set_spacing (12);
+ bbox.pack_start (ok_button, true, false);
+ bbox.pack_start (cancel_button, true, false);
+
+ vbox.set_border_width (6);
+ vbox.set_spacing (12);
+ vbox.pack_start (label, false, false);
+ vbox.pack_start (bbox, false, false);
+
+ checker.add (vbox);
+ checker.set_name (_("CleanupDialog"));
+ checker.set_title (_("ardour cleanup"));
+ checker.set_wmclass (_("ardour_cleanup"), "Ardour");
+ checker.set_position (GTK_WIN_POS_MOUSE);
+ checker.realize ();
+ checker.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ ok_button.clicked.connect (bind (slot (checker, &ArdourDialog::stop), 1));
+ cancel_button.clicked.connect (bind (slot (checker, &ArdourDialog::stop), 0));
+
+ checker.run ();
+
+ if (checker.run_status() != 1) {
+ return;
+ }
+
+ Session::cleanup_report rep;
+
+ editor->prepare_for_cleanup ();
+
+ if (session->cleanup_sources (rep)) {
+ return;
+ }
+
+ display_cleanup_results (rep,
+ _("cleaned files"),
+ _("\
+The following %1 %2 were not in use.\n\
+The next time you flush the wastebasket\n\
+it will release an additional %3 %4bytes\n\
+of disk space"
+ ));
+}
+
+void
+ARDOUR_UI::flush_trash ()
+{
+ if (session == 0) {
+ /* shouldn't happen: menu item is insensitive */
+ return;
+ }
+
+ Session::cleanup_report rep;
+
+ if (session->cleanup_trash_sources (rep)) {
+ return;
+ }
+
+ display_cleanup_results (rep,
+ _("deleted file"),
+ _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"));
+}
+
+void
+ARDOUR_UI::add_route ()
+{
+ int count;
+
+ if (!session) {
+ return;
+ }
+
+ if (add_route_dialog == 0) {
+ add_route_dialog = new AddRouteDialog;
+ editor->ensure_float (*add_route_dialog);
+ }
+
+ if (add_route_dialog->is_visible()) {
+ /* we're already doing this */
+ return;
+ }
+
+ add_route_dialog->run ();
+
+ if (add_route_dialog->run_status()) {
+ return;
+ }
+
+ if ((count = add_route_dialog->count()) <= 0) {
+ return;
+ }
+
+ uint32_t input_chan = add_route_dialog->channels ();
+ uint32_t output_chan;
+ string name_template = add_route_dialog->name_template ();
+ bool track = add_route_dialog->track ();
+
+ Session::AutoConnectOption oac = session->get_output_auto_connect();
+
+ if (oac & Session::AutoConnectMaster) {
+ output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
+ } else {
+ output_chan = input_chan;
+ }
+
+ /* XXX do something with name template */
+
+ while (count) {
+ if (track) {
+ session_add_audio_track (input_chan, output_chan);
+ } else {
+ session_add_audio_bus (input_chan, output_chan);
+ }
+ --count;
+
+ while (Main::events_pending()) {
+ Main::iteration ();
+ }
+ }
+}
+
+XMLNode*
+ARDOUR_UI::mixer_settings () const
+{
+ XMLNode* node = 0;
+
+ if (session) {
+ node = session->instant_xml(X_("Mixer"), session->path());
+ } else {
+ node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path());
+ }
+
+ if (!node) {
+ node = new XMLNode (X_("Mixer"));
+ }
+
+ return node;
+}
+
+XMLNode*
+ARDOUR_UI::editor_settings () const
+{
+ XMLNode* node = 0;
+
+ if (session) {
+ node = session->instant_xml(X_("Editor"), session->path());
+ } else {
+ node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path());
+ }
+
+ if (!node) {
+ node = new XMLNode (X_("Editor"));
+ }
+ return node;
+}
+
+XMLNode*
+ARDOUR_UI::keyboard_settings () const
+{
+ XMLNode* node = 0;
+
+ node = Config->extra_xml(X_("Keyboard"));
+
+ if (!node) {
+ node = new XMLNode (X_("Keyboard"));
+ }
+ return node;
+}
+
+void
+ARDOUR_UI::halt_on_xrun_message ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::halt_on_xrun_message));
+
+ ArdourMessage msg (editor, X_("haltonxrun"),
+ _("Recording was stopped because your system could not keep up."));
+}
+
+void
+ARDOUR_UI::delete_sources_in_the_right_thread (list<ARDOUR::Source*>* deletion_list)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
+
+ for (list<Source*>::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
+ delete *i;
+ }
+
+ delete deletion_list;
+}
+
+void
+ARDOUR_UI::disk_overrun_handler ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::disk_underrun_handler));
+
+ if (!have_disk_overrun_displayed) {
+ have_disk_overrun_displayed = true;
+ ArdourMessage msg (editor, X_("diskrate dialog"), _("\
+The disk system on your computer\n\
+was not able to keep up with Ardour.\n\
+\n\
+Specifically, it failed to write data to disk\n\
+quickly enough to keep up with recording.\n"));
+ have_disk_overrun_displayed = false;
+ }
+}
+
+void
+ARDOUR_UI::disk_underrun_handler ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::disk_underrun_handler));
+
+ if (!have_disk_underrun_displayed) {
+ have_disk_underrun_displayed = true;
+ ArdourMessage msg (editor, X_("diskrate2 dialog"),
+ (_("The disk system on your computer\n\
+was not able to keep up with Ardour.\n\
+\n\
+Specifically, it failed to read data from disk\n\
+quickly enough to keep up with playback.\n")));
+ have_disk_underrun_displayed = false;
+ }
+}
+
+void
+ARDOUR_UI::disk_underrun_message_gone ()
+{
+ have_disk_underrun_displayed = false;
+}
+
+void
+ARDOUR_UI::disk_overrun_message_gone ()
+{
+ have_disk_underrun_displayed = false;
+}
+
+int
+ARDOUR_UI::pending_state_dialog ()
+{
+ ArdourDialog dialog ("pending state dialog");
+ Button use_button (_("Recover from crash"));
+ Button cancel_button (_("Ignore crash data"));
+ Label message (_("\
+This session appears to have been in\n\
+middle of recording when ardour or\n\
+the computer was shutdown.\n\
+\n\
+Ardour can recover any captured audio for\n\
+you, or it can ignore it. Please decide\n\
+what you would like to do.\n"));
+ HBox hpacker;
+ VBox vpacker;
+
+ vpacker.set_border_width (12);
+ vpacker.set_spacing (7);
+ vpacker.pack_start (message);
+ vpacker.pack_start (hpacker);
+
+ hpacker.set_spacing (7);
+ hpacker.pack_start (use_button);
+ hpacker.pack_start (cancel_button);
+
+ use_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 0));
+ cancel_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 1));
+
+ dialog.add (vpacker);
+ dialog.set_position (GTK_WIN_POS_CENTER);
+ dialog.show_all ();
+ dialog.realize();
+ dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ dialog.run ();
+
+ if (dialog.run_status () == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+void
+ARDOUR_UI::disconnect_from_jack ()
+{
+ if (engine) {
+ if( engine->disconnect_from_jack ()) {
+ ArdourMessage msg (editor, X_("nojack dialog"),
+ _("Could not disconnect from JACK"));
+ }
+
+ update_sample_rate (0);
+ }
+}
+
+void
+ARDOUR_UI::reconnect_to_jack ()
+{
+ if (engine) {
+ if (engine->reconnect_to_jack ()) {
+ ArdourMessage msg (editor, X_("nojack dialog"),
+ _("Could not reconnect to JACK"));
+ }
+
+ update_sample_rate (0);
+ }
+}
+
+void
+ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes)
+{
+ engine->request_buffer_size (nframes);
+ update_sample_rate (0);
+}
+
+int
+ARDOUR_UI::cmdline_new_session (string path)
+{
+ if (path[0] != '/') {
+ char buf[PATH_MAX+1];
+ string str;
+
+ getcwd (buf, sizeof (buf));
+ str = buf;
+ str += '/';
+ str += path;
+ path = str;
+ }
+
+ new_session (false, path);
+
+ _will_create_new_session_automatically = false; /* done it */
+ return FALSE; /* don't call it again */
+}
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
new file mode 100644
index 0000000000..34f3422e50
--- /dev/null
+++ b/gtk2_ardour/ardour_ui.h
@@ -0,0 +1,728 @@
+/*
+ Copyright (C) 1999-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gui_h__
+#define __ardour_gui_h__
+
+/* need _BSD_SOURCE to get timersub macros */
+
+#ifdef _BSD_SOURCE
+#include <sys/time.h>
+#else
+#define _BSD_SOURCE
+#include <sys/time.h>
+#undef _BSD_SOURCE
+#endif
+
+#include <list>
+
+#include <cmath>
+
+#include <gtk-canvas.h>
+
+#include <pbd/xml++.h>
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/pix.h>
+#include <gtkmmext/spinner.h>
+#include <gtkmmext/pixmap_button.h>
+#include <gtkmmext/popup_selector.h>
+#include <gtkmmext/click_box.h>
+#include <gtkmmext/selector.h>
+#include <ardour/ardour.h>
+#include <ardour/session.h>
+
+#include "audio_clock.h"
+#include "ardour_dialog.h"
+#include "editing.h"
+
+class AudioClock;
+class PublicEditor;
+class Keyboard;
+class MeterBridge;
+class OptionEditor;
+class Mixer_UI;
+class ConnectionEditor;
+class RouteParams_UI;
+class SoundFileSelector;
+class About;
+class AddRouteDialog;
+class NewSessionDialog;
+class LocationUI;
+
+namespace Gtkmmext {
+ class TearOff;
+};
+
+namespace ARDOUR {
+ class AudioEngine;
+ class Route;
+ class Port;
+ class IO;
+};
+
+namespace ALSA {
+ class MultiChannelDevice;
+};
+
+#define FRAME_NAME "BaseFrame"
+
+class ARDOUR_UI : public Gtkmmext::UI
+{
+ public:
+ ARDOUR_UI (int *argcp, char **argvp[], string rcfile);
+ ~ARDOUR_UI();
+
+ void show ();
+ bool shown() { return shown_flag; }
+
+ void show_splash ();
+ void hide_splash ();
+
+ int load_session (string path, string snapshot, string* mix_template = 0);
+ bool session_loaded;
+ int build_session (string path, string snapshot,
+ uint32_t ctl_chns,
+ uint32_t master_chns,
+ ARDOUR::Session::AutoConnectOption input_connect,
+ ARDOUR::Session::AutoConnectOption output_connect,
+ uint32_t nphysin,
+ uint32_t nphysout,
+ jack_nframes_t initial_length);
+ bool session_is_new() const { return _session_is_new; }
+
+ ARDOUR::Session* the_session() { return session; }
+
+ bool will_create_new_session_automatically() const {
+ return _will_create_new_session_automatically;
+ }
+
+ void set_will_create_new_session_automatically (bool yn) {
+ _will_create_new_session_automatically = yn;
+ }
+
+ void new_session (bool startup = false, std::string path = string());
+ gint cmdline_new_session (std::string path);
+ int unload_session ();
+ void close_session() { unload_session(); }
+
+ int save_state_canfail (string state_name = "");
+ void save_state (string state_name = "");
+ void restore_state (string state_name = "");
+
+ static double gain_to_slider_position (ARDOUR::gain_t g);
+ static ARDOUR::gain_t slider_position_to_gain (double pos);
+
+ static ARDOUR_UI *instance () { return theArdourUI; }
+
+ PublicEditor& the_editor(){return *editor;}
+ Mixer_UI* the_mixer() { return mixer; }
+
+ void allow_focus (bool yn);
+
+ static gint generic_focus_in_event (GdkEventFocus *);
+ static gint generic_focus_out_event (GdkEventFocus *);
+
+ void toggle_location_window ();
+ void toggle_big_clock_window ();
+ void toggle_connection_editor ();
+ void toggle_route_params_window ();
+ void toggle_tempo_window ();
+ void toggle_sfdb_window ();
+
+ SoundFileSelector& get_sfdb_window();
+
+ gint32 select_diskstream (GdkEventButton *ev);
+
+ Gtk::Tooltips& tooltips() { return _tooltips; }
+
+ static SigC::Signal1<void,bool> Blink;
+ static SigC::Signal0<void> RapidScreenUpdate;
+ static SigC::Signal0<void> SuperRapidScreenUpdate;
+ static SigC::Signal1<void,jack_nframes_t> Clock;
+
+ /* this is a helper function to centralize the (complex) logic for
+ blinking rec-enable buttons.
+ */
+
+ void rec_enable_button_blink (bool onoff, ARDOUR::DiskStream *, Gtk::Widget *w);
+
+ void name_io_setup (ARDOUR::AudioEngine&, string&, ARDOUR::IO& io, bool in);
+ void choose_io (ARDOUR::IO&, bool input);
+
+ static gint hide_and_quit (GdkEventAny *ev, ArdourDialog *);
+
+ XMLNode* editor_settings() const;
+ XMLNode* mixer_settings () const;
+ XMLNode* keyboard_settings () const;
+
+ void save_ardour_state ();
+ gboolean configure_handler (GdkEventConfigure* conf);
+
+ void do_transport_locate (jack_nframes_t position);
+ void halt_on_xrun_message ();
+
+ AudioClock primary_clock;
+ AudioClock secondary_clock;
+ AudioClock preroll_clock;
+ AudioClock postroll_clock;
+
+ void add_route ();
+
+ void session_add_audio_track (int input_channels, int32_t output_channels) {
+ session_add_audio_route (true, input_channels, output_channels);
+ }
+
+ void session_add_audio_bus (int input_channels, int32_t output_channels) {
+ session_add_audio_route (false, input_channels, output_channels);
+ }
+
+ void session_add_midi_track ();
+
+ void set_engine (ARDOUR::AudioEngine&);
+
+ gint exit_on_main_window_close (GdkEventAny *);
+
+ protected:
+ friend class PublicEditor;
+
+ void toggle_metering ();
+ void toggle_clocking ();
+ void toggle_auto_play ();
+ void toggle_auto_input ();
+ void toggle_punch_in ();
+ void toggle_punch_out ();
+ void toggle_auto_return ();
+ void toggle_click ();
+ void toggle_follow ();
+
+ void toggle_session_auto_loop ();
+ void toggle_session_punch_in ();
+
+ void toggle_options_window ();
+
+ private:
+ struct GlobalClickBox : public Gtk::VBox {
+ Gtkmmext::ClickBox *box;
+ Gtk::Frame frame;
+ Gtk::Label label;
+ vector<string> &strings;
+ Gtk::Adjustment adjustment;
+
+ static void printer (char buf[32], Gtk::Adjustment &adj, void *arg);
+
+ GlobalClickBox (const string &str, vector<string> &vs)
+ : strings (vs),
+ adjustment (0, 0, vs.size() - 1, 1, 1, 0) {
+ box = new Gtkmmext::ClickBox (&adjustment, "ClickButton");
+ label.set_text (str);
+ label.set_name ("GlobalButtonLabel");
+ frame.add (*box);
+ frame.set_shadow_type (GTK_SHADOW_IN);
+ pack_start (label);
+ pack_start (frame);
+ box->set_print_func (printer, this);
+ box->set_wrap (true);
+ };
+ };
+
+ ARDOUR::AudioEngine *engine;
+ ARDOUR::Session *session;
+
+ Gtk::Tooltips _tooltips;
+
+ void goto_editor_window ();
+ void goto_mixer_window ();
+
+ Gtk::Table adjuster_table;
+ Gtk::Frame adjuster_frame;
+ Gtk::Fixed adjuster_base;
+
+ GlobalClickBox *online_control_button;
+ vector<string> online_control_strings;
+
+ GlobalClickBox *crossfade_time_button;
+ vector<string> crossfade_time_strings;
+
+ GlobalClickBox *mmc_id_button;
+ vector<string> mmc_id_strings;
+
+ Gtk::ToggleButton preroll_button;
+ Gtk::ToggleButton postroll_button;
+
+ Gtk::Table transport_table;
+ Gtk::Table option_table;
+
+ static SoundFileSelector* sfdb_window;
+
+ int setup_windows ();
+ void setup_session_menu ();
+ void setup_transport ();
+ void setup_clock ();
+ void setup_session_info ();
+ void setup_adjustables ();
+
+ Gtk::MenuBar* make_menubar ();
+
+ static ARDOUR_UI *theArdourUI;
+
+ void startup ();
+ void shutdown ();
+
+ void finish();
+ int ask_about_saving_session (string why);
+ gint ask_about_save_deleted (GdkEventAny*);
+ void save_session_choice_made (int);
+ int save_the_session;
+
+ void queue_transport_change ();
+ void map_transport_state ();
+ int32_t do_engine_start ();
+ gint start_engine ();
+
+ void engine_halted ();
+ void engine_stopped ();
+ void engine_running ();
+
+ void map_some_session_state (Gtk::ToggleButton& button,
+ bool (ARDOUR::Session::*get)() const);
+
+ void toggle_some_session_state (Gtk::ToggleButton& button,
+ bool (ARDOUR::Session::*get)() const,
+ void (ARDOUR::Session::*set)(bool));
+ void map_button_state ();
+
+ void clear_meters ();
+
+ static gint _blink (void *);
+ void blink ();
+ gint blink_timeout_tag;
+ bool blink_on;
+ void start_blinking ();
+ void stop_blinking ();
+
+ void control_methods_adjusted ();
+ void mmc_device_id_adjusted ();
+
+ private:
+ Gtk::VBox top_packer;
+
+ SigC::Connection clock_signal_connection;
+ void update_clocks ();
+ void start_clocking ();
+ void stop_clocking ();
+
+ class BigClockWindow : public ArdourDialog
+ {
+ public:
+ BigClockWindow () : ArdourDialog ("big clock window") {};
+ };
+
+ AudioClock big_clock;
+ Gtk::Frame big_clock_frame;
+ BigClockWindow* big_clock_window;
+
+ void big_clock_size_event (GtkAllocation *alloc);
+ void big_clock_realize ();
+
+ /* Transport Control */
+
+ void detach_tearoff (Gtk::Box* parent, Gtk::Widget* contents);
+ void reattach_tearoff (Gtk::Box* parent, Gtk::Widget* contents, int32_t order);
+
+ Gtkmmext::TearOff* transport_tearoff;
+ Gtk::Frame transport_frame;
+ Gtk::HBox transport_tearoff_hbox;
+ Gtk::HBox transport_hbox;
+ Gtk::Fixed transport_base;
+ Gtk::Fixed transport_button_base;
+ Gtk::Frame transport_button_frame;
+ Gtk::HBox transport_button_hbox;
+ Gtk::VBox transport_button_vbox;
+ Gtk::HBox transport_option_button_hbox;
+ Gtk::VBox transport_option_button_vbox;
+ Gtk::HBox transport_clock_hbox;
+ Gtk::VBox transport_clock_vbox;
+ Gtk::HBox primary_clock_hbox;
+ Gtk::HBox secondary_clock_hbox;
+
+ Gtk::Button goto_start_button;
+ Gtk::Button goto_end_button;
+ Gtk::Button rewind_button;
+ Gtk::Button forward_button;
+ Gtk::Button stop_button;
+
+ enum ShuttleBehaviour {
+ Sprung,
+ Wheel
+ };
+
+ enum ShuttleUnits {
+ Percentage,
+ Semitones
+ };
+
+ Gtk::DrawingArea shuttle_box;
+ Gtk::EventBox speed_display_box;
+ Gtk::Label speed_display_label;
+ Gtk::Button shuttle_units_button;
+ Gtk::Button shuttle_style_button;
+ Gtk::Menu shuttle_unit_menu;
+ Gtk::Menu shuttle_style_menu;
+ ShuttleBehaviour shuttle_behaviour;
+ ShuttleUnits shuttle_units;
+
+ void shuttle_style_clicked ();
+ void shuttle_unit_clicked ();
+ void set_shuttle_behaviour (ShuttleBehaviour);
+ void set_shuttle_units (ShuttleUnits);
+ void update_speed_display ();
+
+ gint shuttle_box_button_press (GdkEventButton*);
+ gint shuttle_box_button_release (GdkEventButton*);
+ gint shuttle_box_motion (GdkEventMotion*);
+ gint shuttle_box_expose (GdkEventExpose*);
+ gint mouse_shuttle (double x, bool force);
+ void use_shuttle_fract (bool force);
+
+ bool shuttle_grabbed;
+ double shuttle_fract;
+
+ Gtk::ToggleButton auto_loop_button;
+ Gtk::ToggleButton play_selection_button;
+ Gtk::ToggleButton roll_button;
+
+ Gtk::ToggleButton rec_button;
+ Gtk::ToggleButton punch_in_button;
+ Gtk::ToggleButton punch_out_button;
+ Gtk::ToggleButton auto_return_button;
+ Gtk::ToggleButton auto_play_button;
+ Gtk::ToggleButton auto_input_button;
+ Gtk::ToggleButton click_button;
+ Gtk::ToggleButton follow_button;
+ Gtk::ToggleButton auditioning_alert_button;
+ Gtk::ToggleButton solo_alert_button;
+
+ Gtk::VBox alert_box;
+
+ void follow_changed ();
+
+ void solo_blink (bool);
+ void audition_blink (bool);
+
+ void soloing_changed (bool);
+ void auditioning_changed (bool);
+ void _auditioning_changed (bool);
+
+ void solo_alert_toggle ();
+ void audition_alert_toggle ();
+
+ void primary_clock_value_changed ();
+ void secondary_clock_value_changed ();
+
+ /* called by Blink signal */
+
+ void transport_rec_enable_blink (bool onoff);
+
+ /* These change where we accept control from:
+ MMC, X (local) or both.
+ */
+
+ void allow_mmc_only ();
+ void allow_mmc_and_local ();
+ void allow_local_only ();
+
+ static void rate_printer (char buf[32], Gtk::Adjustment &, void *);
+
+ Gtk::Menu* session_popup_menu;
+ Gtk::CTree session_selector;
+ ArdourDialog* session_selector_window;
+
+ Gtk::FileSelection* open_session_selector;
+
+ void build_session_selector();
+ void session_selection (Gtk::CTree::Row, gint col);
+ struct RecentSessionsSorter {
+ bool operator() (std::pair<string,string> a, std::pair<string,string> b) const {
+ return cmp_nocase(a.first, b.first) == -1;
+ }
+ };
+ void redisplay_recent_sessions();
+
+ /* menu bar and associated stuff */
+
+ Gtk::MenuBar menu_bar;
+ Gtk::Fixed menu_bar_base;
+ Gtk::HBox menu_hbox;
+
+ void build_menu_bar ();
+ void pack_toplevel_controls();
+
+ /* handles on the menu bar items that need to
+ be sensitive to whether or not we have
+ a session loaded.
+ */
+
+ Gtk::MenuItem *add_track_item;
+ Gtk::MenuItem *save_item;
+ Gtk::MenuItem *snapshot_item;
+ Gtk::MenuItem *save_as_item;
+ Gtk::MenuItem *save_template_item;
+ Gtk::MenuItem *export_item;
+ Gtk::MenuItem *close_item;
+
+ Gtk::CheckMenuItem *meter_bridge_dialog_check;
+ Gtk::CheckMenuItem *connection_editor_check;
+ Gtk::CheckMenuItem *route_params_check;
+ Gtk::CheckMenuItem *locations_dialog_check;
+ Gtk::CheckMenuItem *big_clock_check;
+ Gtk::CheckMenuItem *tempo_editor_check;
+ Gtk::CheckMenuItem *sfdb_check;
+ Gtk::CheckMenuItem *options_window_check;
+
+ /* <CMT Additions> */
+ Gtk::MenuItem *image_compositor_item ;
+ /* </CMT Additions> */
+
+
+ Gtk::Label wall_clock_label;
+ Gtk::EventBox wall_clock_box;
+ gint update_wall_clock ();
+
+ Gtk::Label disk_space_label;
+ Gtk::EventBox disk_space_box;
+ void update_disk_space ();
+
+ Gtk::Label cpu_load_label;
+ Gtk::EventBox cpu_load_box;
+ void update_cpu_load ();
+
+ Gtk::Label disk_rate_label;
+ Gtk::EventBox disk_rate_box;
+ void update_disk_rate();
+
+ Gtk::Label buffer_load_label;
+ Gtk::EventBox buffer_load_box;
+ void update_buffer_load ();
+
+ Gtk::Label sample_rate_label;
+ Gtk::EventBox sample_rate_box;
+ void update_sample_rate (jack_nframes_t);
+
+ gint every_second ();
+ gint every_point_one_seconds ();
+ gint every_point_zero_one_seconds ();
+
+ SigC::Connection second_connection;
+ SigC::Connection point_one_second_connection;
+ SigC::Connection point_zero_one_second_connection;
+
+ void diskstream_added (ARDOUR::DiskStream*);
+
+ gint session_menu (GdkEventButton *);
+
+ bool _will_create_new_session_automatically;
+
+ NewSessionDialog* new_session_window;
+ string template_name;
+
+ void new_session_ok_clicked ();
+ void new_session_template_choice (Gtkmmext::Selector *, Gtkmmext::SelectionResult*);
+ void hide_dialog (ArdourDialog *dialog);
+
+ void fs_cancel_clicked (Gtk::FileSelection*);
+ gint fs_delete_event (GdkEventAny*, Gtk::FileSelection*);
+
+ void open_session ();
+ void open_recent_session ();
+ void open_ok_clicked ();
+
+ void save_template ();
+
+
+ void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels);
+
+ void add_diskstream_to_menu (ARDOUR::DiskStream&);
+ void diskstream_selected (gint32);
+ Gtk::Menu *diskstream_menu;
+ gint32 selected_dstream;
+
+ gint mouse_transport_goto_start (GdkEventButton *) {
+ transport_goto_start (); return TRUE;
+ }
+ gint mouse_transport_goto_end (GdkEventButton *) {
+ transport_goto_end (); return TRUE;
+ }
+ gint mouse_transport_record (GdkEventButton *) {
+ transport_record (); return TRUE;
+ }
+ gint mouse_transport_forward (GdkEventButton *) {
+ transport_forward (0); return TRUE;
+ }
+ gint mouse_transport_rewind (GdkEventButton *) {
+ transport_rewind (0); return TRUE;
+ }
+ gint mouse_transport_loop (GdkEventButton *) {
+ transport_loop (); return TRUE;
+ }
+ gint mouse_transport_play_selection (GdkEventButton *) {
+ transport_play_selection (); return TRUE;
+ }
+
+ gint mouse_transport_roll (GdkEventButton *);
+ gint mouse_transport_stop (GdkEventButton *);
+
+ void set_transport_sensitivity (bool);
+
+ void remove_last_capture ();
+
+ void transport_goto_start ();
+ void transport_goto_end ();
+ void transport_stop ();
+ void transport_stop_and_forget_capture ();
+ void transport_record ();
+ void transport_roll ();
+ void transport_play_selection();
+ void transport_forward (int option);
+ void transport_rewind (int option);
+ void transport_loop ();
+
+ void transport_locating ();
+ void transport_rolling ();
+ void transport_rewinding ();
+ void transport_forwarding ();
+ void transport_stopped ();
+
+ void send_all_midi_feedback ();
+
+ bool _session_is_new;
+ void connect_to_session (ARDOUR::Session *);
+ void connect_dependents_to_session (ARDOUR::Session *);
+ void we_have_dependents ();
+ void setup_keybindings ();
+
+ guint32 last_key_press_time;
+
+ void snapshot_session ();
+
+ void map_control_change (ARDOUR::Session::ControlType);
+ void queue_map_control_change (ARDOUR::Session::ControlType);
+ void map_record_state ();
+ void queue_map_record_state ();
+
+ Mixer_UI *mixer;
+ int create_mixer ();
+
+ PublicEditor *editor;
+ int create_editor ();
+
+ MeterBridge *meter_bridge;
+ int create_meter_bridge ();
+
+ RouteParams_UI *route_params;
+ int create_route_params ();
+
+ ConnectionEditor *connection_editor;
+ int create_connection_editor ();
+
+ LocationUI *location_ui;
+ int create_location_ui ();
+
+ void meter_bridge_hiding ();
+ void location_ui_hiding ();
+ void big_clock_hiding ();
+ void route_params_hiding ();
+ void connection_editor_hiding ();
+ void sfdb_hiding ();
+ void option_hiding ();
+
+ /* Various options */
+
+ void toggle_recording_plugins ();
+
+ /* Options window */
+
+ OptionEditor *option_editor;
+
+ /* route dialog */
+
+ AddRouteDialog *add_route_dialog;
+ void add_route_dialog_done (int status);
+
+ /* Keyboard Handling */
+
+ Keyboard* keyboard;
+
+ /* Keymap handling */
+
+ void install_keybindings ();
+ void test_binding_action (const char *);
+ void start_keyboard_prefix();
+
+ void toggle_record_enable (guint32);
+ void toggle_monitor_enable (guint32);
+
+ uint32_t rec_enabled_diskstreams;
+ void count_recenabled_diskstreams (ARDOUR::DiskStream&);
+
+ About* about;
+ bool shown_flag;
+ /* cleanup */
+
+ Gtk::MenuItem *cleanup_item;
+
+ void display_cleanup_results (ARDOUR::Session::cleanup_report& rep, const gchar* list_title, string msg);
+ void cleanup ();
+ void flush_trash ();
+
+ bool have_configure_timeout;
+ struct timeval last_configure_time;
+ gint configure_timeout ();
+
+ struct timeval last_peak_grab;
+ struct timeval last_shuttle_request;
+
+ void cannot_record_no_input (ARDOUR::DiskStream*);
+
+ void delete_sources_in_the_right_thread (list<ARDOUR::Source*>*);
+
+ void editor_display_control_changed (Editing::DisplayControl c);
+
+ bool have_disk_overrun_displayed;
+ bool have_disk_underrun_displayed;
+
+ void disk_overrun_message_gone ();
+ void disk_underrun_message_gone ();
+ void disk_overrun_handler ();
+ void disk_underrun_handler ();
+
+ int pending_state_dialog ();
+
+ void disconnect_from_jack ();
+ void reconnect_to_jack ();
+ void set_jack_buffer_size (jack_nframes_t);
+
+ Gtk::MenuItem* jack_disconnect_item;
+ Gtk::MenuItem* jack_reconnect_item;
+ Gtk::Menu* jack_bufsize_menu;
+
+ int make_session_clean ();
+};
+
+#endif /* __ardour_gui_h__ */
diff --git a/gtk2_ardour/ardour_ui.rc b/gtk2_ardour/ardour_ui.rc
new file mode 100644
index 0000000000..7e2edfd19a
--- /dev/null
+++ b/gtk2_ardour/ardour_ui.rc
@@ -0,0 +1,1976 @@
+#
+# This is the GTK style file for Ardour
+#
+#
+
+style "very_small_text"
+{
+ fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*"
+}
+
+style "small_text"
+{
+ fontset="-*-helvetica-medium-r-normal-*-10-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*"
+}
+
+style "small_bold_text"
+{
+ fontset="-*-helvetica-bold-r-normal-*-10-*-*-*-p-*-*-*"
+ font ="-*-helvetica-bold-r-normal-*-*-100-*-*-p-*-*"
+}
+
+style "medium_bold_text"
+{
+ fontset="-*-helvetica-bold-r-normal-*-12-*-*-*-p-*-*-*"
+ font ="-*-helvetica-bold-r-normal-*-*-120-*-*-p-*-*"
+}
+
+style "medium_text"
+{
+ fontset="-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-120-*-*-p-*-*"
+}
+
+style "red_medium_text" = "medium_text"
+{
+ fg[NORMAL] = { 1.0, 0, 0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+ fg[SELECTED] = { 1.0, 0, 0 }
+}
+
+
+style "large_text"
+{
+ fontset="-*-helvetica-bold-r-normal-*-18-*-*-*-p-*-*-*"
+ font ="-*-helvetica-bold-r-normal-*-*-180-*-*-p-*-*"
+}
+
+style "larger_bold_text"
+{
+ fontset="-*-helvetica-bold-r-normal-*-14-*-*-*-p-*-*-*"
+ font ="-*-helvetica-bold-r-normal-*-*-140-*-*-p-*-*"
+}
+
+style "plugin_name_text"
+{
+ fontset="-*-helvetica-bold-o-*-*-25-*-*-*-p-*-*-*"
+ font="-*-helvetica-bold-o-*-*-25-*-*-*-p-*-*-*"
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+}
+
+style "plugin_maker_text"
+{
+ fontset="-*-helvetica-bold-o-*-*-14-*-*-*-p-*-*-*"
+ font="-*-helvetica-bold-o-*-*-14-*-*-*-p-*-*-*"
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+}
+
+style "first_action_message"
+{
+ font="-*-helvetica-medium-r-*-*-34-350-*-*-*-*-*-*"
+ fontset="-*-helvetica-medium-r-*-*-34-350-*-*-*-*-*-*"
+}
+
+style "verbose_canvas_cursor"
+{
+ font="-*-helvetica-medium-r-*-*-*-240-*-*-*-*-*-*"
+ fontset="-*-helvetica-medium-r-*-*-*-240-*-*-*-*-*-*"
+}
+
+style "marker_text"
+{
+ font="-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*"
+ fontset="-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*"
+}
+
+style "time_axis_view_item_name"
+{
+ font="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*-1"
+ fontset="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*-1"
+}
+
+style "default_base" = "medium_text"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ fg[ACTIVE] = { 0.80, 0.80, 0.70 }
+ fg[PRELIGHT] = { 0.98, 0.76, 0.14 }
+ fg[INSENSITIVE] = { 0.80, 0.80, 0.70 }
+ fg[SELECTED] = {0.20, 0.90,.20 }
+
+ bg[NORMAL] = { 0.20, 0.20, 0.20 }
+ bg[ACTIVE] = { 0.20, 0.20, 0.20 }
+ bg[PRELIGHT] = { 0.20, 0.20, 0.20 }
+ bg[INSENSITIVE] = { 0.10, 0.10, 0.10 }
+ bg[SELECTED] = { 0, 0.40, 0.60 }
+
+ text[NORMAL] = { 0.80, 0.80, 0.70 }
+ text[ACTIVE] = { 0.80, 0.80, 0.70 }
+ text[PRELIGHT] = { 0, 0.80, 0 }
+ text[INSENSITIVE] = { 0.80, 0.80, 0.70 }
+ text[SELECTED] = { 0, 1.0, 0 }
+
+ base[NORMAL] = { 0.0, 0.0, 0.0 }
+ base[ACTIVE] = { 0.0, 0.0, 0.0 }
+ base[PRELIGHT] = { 0.0, 0.0, 0.0 }
+ base[INSENSITIVE] = { 0.0, 0.0, 0.0 }
+ base[SELECTED] = { 0.0, 0.0, 0.0 }
+}
+
+style "ardour_frames" = "medium_text"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ fg[ACTIVE] = { 0.80, 0.80, 0.70 }
+ fg[PRELIGHT] = { 0.98, 0.76, 0.14 }
+ fg[INSENSITIVE] = { 0.80, 0.80, 0.70 }
+ fg[SELECTED] = { 0.80, 0.80, 0.70 }
+
+ bg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[ACTIVE] = { 0.80, 0.80, 0.70 }
+ bg[PRELIGHT] = { 0.98, 0.76, 0.14 }
+ bg[INSENSITIVE] = { 0.80, 0.80, 0.70 }
+ bg[SELECTED] = { 0.80, 0.80, 0.70 }
+
+ text[NORMAL] = { 0.80, 0.80, 0.70 }
+ text[ACTIVE] = { 0.80, 0.80, 0.70 }
+ text[PRELIGHT] = { 0.80, 0.80, 0.70 }
+ text[INSENSITIVE] = { 0.80, 0.80, 0.70 }
+ text[SELECTED] = { 0, 0, 0 }
+
+ base[NORMAL] = { 0.00, 0.00, 0.00 }
+ base[ACTIVE] = { 0.00, 0.00, 0.00 }
+ base[PRELIGHT] = { 0.00, 0.00, 0.00 }
+ base[INSENSITIVE] = { 0.00, 0.00, 0.00 }
+ base[SELECTED] = { 0.00, 0.00, 0.00 }
+}
+
+style "base_frame"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[NORMAL] = { 0.40, 0.40, 0.40 }
+}
+
+style "transport_base" = "medium_bold_text"
+{
+ bg[NORMAL] = { 0.10, 0.10, 0.10 }
+ bg[ACTIVE] = { 0, 0, 0 }
+ bg[PRELIGHT] = { 0, 0, 0 }
+ bg[INSENSITIVE] = { 0, 0, 0 }
+ bg[SELECTED] = { 0, 0, 0 }
+}
+
+style "black_mackie_menu_bar" = "medium_bold_text"
+{
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+ bg[NORMAL] = { 0, 0, 0 }
+}
+
+style "default_buttons_menus" = "default_base"
+{
+ fontset="-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-120-*-*-p-*-*"
+
+ fg[ACTIVE] = { 0, 0, 0 }
+
+ bg[NORMAL] = { 0.35, 0.35, 0.35 }
+ bg[ACTIVE] = { 0.98, 0.76, 0.14 }
+ bg[PRELIGHT] = { 0.25, 0.25, 0.25 }
+ bg[INSENSITIVE] = { 0.10, 0.10, 0.10 }
+ bg[SELECTED] = { 0.06, 0.06, 0.06 }
+}
+
+style "very_small_button" = "default_buttons_menus"
+{
+ fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*"
+}
+
+style "small_button" = "default_buttons_menus"
+{
+ fontset="-*-helvetica-medium-r-normal-*-10-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*"
+}
+
+style "very_small_red_active_and_selected_button" = "very_small_button"
+{
+ bg[ACTIVE] = { 1.0, 0, 0}
+ bg[SELECTED] = { 1.0, 0, 0}
+}
+
+style "small_red_active_and_selected_button" = "small_button"
+{
+ fg[ACTIVE] = { 0, 0, 0 }
+ bg[ACTIVE] = { 1.0, 0, 0}
+ bg[SELECTED] = { 1.0, 0, 0}
+}
+
+style "track_rec_enable_button" = "small_button"
+{
+ fg[SELECTED] = { 0.0, 0.0, 0.0 }
+ fg[ACTIVE] = { 0.0, 0.0, 0.0 }
+ fg[PRELIGHT] = { 0.0, 0.0, 0.0 }
+
+ bg[SELECTED] = { 1.0, 0.0, 0.0 }
+ bg[ACTIVE] = { 0.91, 0.68, 0.68}
+ bg[PRELIGHT] = { 1.0, 0.0, 0.0 }
+}
+
+style "mixer_rec_enable_button" = "track_rec_enable_button"
+{
+ fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*"
+}
+
+style "solo_button" = "small_button"
+{
+ bg[PRELIGHT] = { 0, 1.0, 0 }
+ bg[ACTIVE] = { 0.66, 0.97, 0.19 }
+
+ fg[PRELIGHT] = { 0, 0, 0 }
+ fg[ACTIVE] = { 0, 0, 0 }
+}
+
+style "mixer_solo_button" = "solo_button"
+{
+ fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*"
+}
+
+
+style "mute_button" = "small_button"
+{
+ bg[PRELIGHT] = { 1.0, 0.65, 0.13 }
+ bg[ACTIVE] = { 1.0, 0.98, 0.53 }
+
+ fg[PRELIGHT] = { 0, 0, 0 }
+}
+
+style "mixer_mute_button" = "mute_button"
+{
+ fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*"
+}
+
+style "track_loop_button" = "small_button"
+{
+ bg[ACTIVE] = { 1.0, 0.98, 0.53 }
+ bg[PRELIGHT] = { 1.0, 0.98, 0.53 }
+
+}
+
+style "mixer_red_active_button" = "very_small_button"
+{
+ fg[ACTIVE] = { 0, 1.0, 1.0 }
+ bg[ACTIVE] = { 0.7, 0, 0 }
+
+ base[INSENSITIVE] = { 0.21, 0.21, 0.21 }
+ bg[INSENSITIVE] = { 0.21, 0.21, 0.21 }
+}
+
+style "time_button" = "default_buttons_menus"
+{
+ fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*"
+}
+
+style "transport_button" = "very_small_button"
+{
+ bg[ACTIVE] = { 0.66, 0.97, 0.18 }
+ bg[SELECTED] = { 1.0, 0.04, 0.04 }
+}
+
+style "transport_rec_button" = "very_small_button"
+{
+ bg[ACTIVE] = { 0.82, 0.02, 0.02 }
+ bg[SELECTED] = { 1.0, 0.04, 0.04 }
+}
+
+style "shuttle_control" = "very_small_text"
+{
+ fg[NORMAL] = { 0.85, 0.92, 0.98 }
+ fg[ACTIVE] = { 0.85, 0.92, 0.98 }
+ fg[PRELIGHT] = { 0.85, 0.92, 0.98 }
+ fg[SELECTED] = { 0.85, 0.92, 0.98 }
+ fg[INSENSITIVE] = { 0.85, 0.92, 0.98 }
+
+ bg[NORMAL] = { 0.31, 0.31, 0.31 }
+ bg[PRELIGHT] = { 0.31, 0.31, 0.31 }
+ bg[INSENSITIVE] = { 0.31, 0.31, 0.31 }
+ bg[ACTIVE] = { 0.66, 0.97, 0.18 }
+ bg[SELECTED] = { 1.0, 0.04, 0.04 }
+}
+
+style "ardour_adjusters" = "default_buttons_menus"
+{
+ bg[NORMAL] = { 0.60, 0.60, 0.60 }
+ bg[PRELIGHT] = { 0.80, 0.80, 0.70 }
+ bg[ACTIVE] = { 0.18, 0.18, 0.22 }
+}
+
+style "ardour_progressbars" = "default_buttons_menus"
+{
+ bg[NORMAL] = { 0, 0, 0 }
+ bg[PRELIGHT] = { 0.00, 0.36, 0.40 }
+}
+
+style "options_window" = "default_base"
+{
+ fontset="-*-helvetica-bold-r-normal-*-12-*-*-*-p-*-*-*"
+ font ="-*-helvetica-bold-r-normal-*-*-120-*-*-p-*-*"
+ fg[PRELIGHT] = { 0.80, 0.80, 0.70 }
+}
+
+style "option_entry" = "default_base"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ fg[ACTIVE] = { 0.98, 0.76, 0.14 }
+ fg[INSENSITIVE] = { 0.80, 0.80, 0.70 }
+
+ base[INSENSITIVE] = { 0.12, 0.12, 0.12 }
+
+ bg[NORMAL] = { 0.40, 0.40, 0.40 }
+ bg[ACTIVE] = { 0.40, 0.40, 0.40 }
+}
+
+style "red_when_active" = "medium_text"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[NORMAL] = { 0.31, 0.31, 0.31 }
+
+ fg[ACTIVE] = { 0.80, 0.80, 0.70 }
+ bg[ACTIVE] = { 1.0, 0, 0}
+}
+
+style "xrun_warn"
+{
+ font ="-*-helvetica-bold-r-normal-*-*-180-*-*-p-*-*"
+ fontset="-*-helvetica-bold-r-normal-*-18-*-*-*-p-*-*-*"
+
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+ fg[ACTIVE] = { 1.0, 1.0, 1.0 }
+ text[NORMAL] = { 1.0, 1.0, 1.0 }
+ text[ACTIVE] = { 1.0, 1.0, 1.0 }
+ base[NORMAL] = { 0.09, 0.48, 0.46 }
+ base[ACTIVE] = { 0.09, 0.48, 0.46 }
+ bg[NORMAL] = { 1.0, 0.48, 0.46 }
+ bg[ACTIVE] = { 0.09, 1.0, 0.46 }
+}
+
+style "menu_bar_base"
+{
+ bg[NORMAL] = { 0, 0, 0 }
+ bg[ACTIVE] = { 0, 0, 0 }
+ bg[PRELIGHT] = { 0, 0, 0 }
+ bg[INSENSITIVE] = { 0, 0, 0 }
+ bg[SELECTED] = { 0, 0, 0 }
+}
+
+style "fatal_message" = "medium_text"
+{
+ fg[ACTIVE] = { 1.0, 0, 1.0 }
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[ACTIVE] = { 0,0,0 }
+ bg[NORMAL] = { 0,0,0 }
+ base[ACTIVE] = { 0,0,0 }
+ base[NORMAL] = { 0,0,0 }
+}
+
+style "error_message" = "medium_text"
+{
+ fg[ACTIVE] = { 1.0, 0, 0 }
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[ACTIVE] = { 0,0,0 }
+ bg[NORMAL] = { 0,0,0 }
+ base[ACTIVE] = { 0,0,0 }
+ base[NORMAL] = { 0,0,0 }
+}
+
+style "info_message" = "medium_text"
+{
+ fg[ACTIVE] = { 1.0, 0, 0 }
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[ACTIVE] = { 0,0,0 }
+ bg[NORMAL] = { 0,0,0 }
+ base[ACTIVE] = { 0,0,0 }
+ base[NORMAL] = { 0,0,0 }
+}
+
+style "warning_message" = "medium_text"
+{
+ fg[ACTIVE] = { 0.30,0.30, 1.0 }
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[ACTIVE] = { 0, 0, 0 }
+ bg[NORMAL] = { 0, 0, 0 }
+ base[ACTIVE] = { 0, 0, 0 }
+ base[NORMAL] = { 0, 0, 0 }
+}
+
+style "medium_entry" = "medium_text"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ fg[ACTIVE] = { 0.98, 0.76, 0.14 }
+ fg[SELECTED] = { 0.66, 0.97, 0.18 }
+
+ bg[NORMAL] = { 0.40, 0.40, 0.40 }
+
+ base[NORMAL] = { 0, 0, 0 }
+ base[ACTIVE] = { 0, 0, 0 }
+ base[SELECTED] = { 0, 0, 0 }
+}
+
+style "medium_entry_noselection_fg" = "medium_entry"
+{
+ fg[SELECTED] = { 0.98, 0.76, 0.14 }
+}
+
+style "medium_entry_noselection_bg" = "medium_entry"
+{
+ bg[SELECTED] = { 0, 0, 0 }
+}
+
+style "medium_bold_entry" = "medium_bold_text"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ fg[ACTIVE] = { 0.98, 0.76, 0.14 }
+
+ bg[NORMAL] = { 0.40, 0.40, 0.40 }
+
+ base[NORMAL] = { 0, 0, 0 }
+ base[ACTIVE] = { 0, 0, 0 }
+ base[SELECTED] = { 0, 0, 0 }
+}
+
+
+style "small_entry" = "small_text"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ fg[ACTIVE] = { 0.98, 0.76, 0.14 }
+ bg[NORMAL] = { 0.0, 0.0, 0.0 }
+ base[NORMAL] = { 0, 0, 0 }
+ base[ACTIVE] = { 0, 0, 0 }
+ base[SELECTED] = { 0, 0, 0 }
+}
+
+style "red_active_small_entry" = "small_entry"
+{
+ fg[ACTIVE] = { 1.0, 0.0, 0.0 }
+ fg[SELECTED] = { 1.0, 0, 0 }
+}
+
+style "small_bold_entry" = "small_bold_text"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ fg[ACTIVE] = { 0.98, 0.76, 0.14 }
+
+ bg[NORMAL] = { 0.40, 0.40, 0.40 }
+
+ base[NORMAL] = { 0, 0, 0 }
+ base[ACTIVE] = { 0, 0, 0 }
+ base[SELECTED] = { 0, 0, 0 }
+}
+
+style "small_red_on_black_entry" = "small_bold_text"
+{
+ fg[NORMAL] = { 1.0, 0, 0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+ base[NORMAL] = { 0.0, 0.0, 0.0 }
+ base[ACTIVE] = { 0.0, 0.0, 0.0 }
+ bg[NORMAL] = { 0.0, 0.0, 0.0 }
+ bg[ACTIVE] = { 0.0, 0.0, 0.0 }
+}
+
+style "big_clock_display" = "medium_entry"
+{
+ fontset = "-*-courier-bold-r-*-*-34-*-*-*-*-*-*-*"
+ font = "-*-courier-bold-r-*-*-34-*-*-*-*-*-*-*"
+}
+
+style "transport_clock_display"
+{
+ fontset = "-*-helvetica-bold-r-*-*-18-*-*-*-*-*-*-*"
+ font = "-*-helvetica-bold-r-*-*-18-*-*-*-*-*-*-*"
+
+ fg[NORMAL] = { 0.66, 0.97, 0.18 }
+ fg[ACTIVE] = { 1.0, 0, 0.0 }
+ fg[SELECTED] = { 1.0, 0, 0 }
+ fg[PRELIGHT] = { 1.0, 0, 0.0 }
+ fg[INSENSITIVE] = { 1.0, 0, 0.0 }
+
+ base[NORMAL] = { 0.0, 0.0, 0.0 }
+ base[ACTIVE] = { 0.0, 0.0, 0.0 }
+ bg[NORMAL] = { 0.0, 0.0, 0.0 }
+ bg[ACTIVE] = { 0.0, 0.0, 0.0 }
+}
+
+style "tempo_meter_clock_display"
+{
+ fontset = "-*-helvetica-bold-r-*-*-8-*-*-*-*-*-*-*"
+ font = "-*-helvetica-bold-r-*-*-8-*-*-*-*-*-*-*"
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+ fg[ACTIVE] = { 1.0, 1.0, 0.0 }
+ fg[SELECTED] = { 1.0, 0, 0 }
+ base[NORMAL] = { 0.0, 0.48, 1.0 }
+ base[ACTIVE] = { 0.09, 0.98, 0.46 }
+ bg[NORMAL] = { 0.0, 0.48, 1.0 }
+ bg[ACTIVE] = { 0.09, 0.98, 0.46 }
+}
+
+style "default_clock_display" = "medium text"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ fg[ACTIVE] = { 1.0, 0.0, 0.0 }
+ fg[SELECTED] = { 1.0, 0, 0 }
+ base[NORMAL] = { 0, 0, 0 }
+ base[ACTIVE] = { 0, 0, 0 }
+ bg[NORMAL] = { 0, 0, 0 }
+ bg[ACTIVE] = { 0, 0, 0 }
+}
+
+style "editor_time_ruler" = "small_text"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[NORMAL] = { 0.09, 0.09, 0.09 }
+}
+
+style "audio_track_base" = "default_base"
+{
+ font = "-*-courier-medium-r-*-*-*-100-*-*-*-*-*-*"
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[NORMAL] = { 0.18, 0.18, 0.22 }
+ bg[ACTIVE] = { 0.20, 0.20, 0.20 }
+ bg[PRELIGHT] = { 0.20, 0.20, 0.20 }
+ bg[INSENSITIVE] = { 0.20, 0.20, 0.20 }
+ bg[SELECTED] = { 0.20, 0.20, 0.20 }
+}
+
+style "audio_bus_base"
+{
+ font = "-*-courier-medium-r-*-*-*-100-*-*-*-*-*-*"
+ fg[NORMAL] = { 0.7, 0.8, 0.2 }
+ bg[NORMAL] = {0, 0.36, 0.40 }
+}
+
+style "track_name_display"
+{
+ font = "-*-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*"
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ fg[ACTIVE] = { 0.80, 0.80, 0.70 }
+
+ base[NORMAL] = { 0.06, 0.06, 0.06 }
+ base[ACTIVE] = { 0.26, 0.26, 0.26 }
+ bg[NORMAL] = { 0.26, 0.26, 0.26 }
+ bg[ACTIVE] = { 0.26, 0.26, 0.26 }
+}
+
+style "track_separator"
+{
+ bg[NORMAL] = { 0.40, 0.40, 0.40 }
+}
+
+#
+# Track edit groups. These styles define
+# the colors that the "edit" button will
+# use as a track is moved from
+# track edit group to track edit group.
+# There are 8 edit groups. Edit group 0
+# is used for tracks that are not editable,
+# so we leave its style to the default.
+#
+
+style "edit_group_0"
+
+{
+ bg[ACTIVE] = { 1.0, 0.65, 0.13 }
+ bg[NORMAL] = { 0.31, 0.31, 0.31 }
+ fg[NORMAL] = { 0.82, 0.91, 0.99 }
+ fg[ACTIVE] = { 0, 0, 0 }
+}
+
+style "edit_group_1"
+{
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[PRELIGHT] = { 0, 0, 0 }
+ fg[SELECTED] = { 0, 0, 0 }
+ bg[NORMAL] = { 0.93, 0.34, 0.08 }
+ bg[PRELIGHT] = { 0.93, 0.34, 0.08 }
+ bg[SELECTED] = { 0.93, 0.34, 0.08 }
+}
+
+style "edit_group_2"
+{
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[PRELIGHT] = { 0, 0, 0 }
+ fg[SELECTED] = { 0, 0, 0 }
+ bg[NORMAL] = { 0.93, 0.34, 0.08 }
+ bg[PRELIGHT] = { 0.93, 0.34, 0.08 }
+ bg[SELECTED] = { 0.93, 0.34, 0.08 }
+}
+
+style "edit_group_3"
+{
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[PRELIGHT] = { 0, 0, 0 }
+ fg[SELECTED] = { 0, 0, 0 }
+ bg[NORMAL] = { 0.93, 0.34, 0.08 }
+ bg[PRELIGHT] = { 0.93, 0.34, 0.08 }
+ bg[SELECTED] = { 0.93, 0.34, 0.08 }
+}
+
+style "region_list_display" = "small_bold_text"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ fg[ACTIVE] = { 0.80, 0.80, 0.70 }
+ fg[SELECTED] = { 0.98, 0.76, 0.14 }
+ bg[NORMAL] = { 0, 0, 0 }
+ bg[ACTIVE] = { 0, 0, 0 }
+ bg[SELECTED] = { 0, 0, 0 }
+ base[NORMAL] = { 0, 0, 0 }
+ base[ACTIVE] = { 0, 1, 0 }
+ base[INSENSITIVE] = { 0, 0, 0 }
+ base[SELECTED] = { 0.80, 0.80, 0.70 }
+}
+
+style "main_canvas_area"
+{
+ bg[NORMAL] = { 0.38, 0.38, 0.38 }
+ bg[ACTIVE] = { 0.38, 0.38, 0.38 }
+ bg[INSENSITIVE] = { 0.38, 0.38, 0.38 }
+ bg[SELECTED] = { 0.38, 0.38, 0.38 }
+ bg[PRELIGHT] = { 0.38, 0.38, 0.38 }
+}
+
+style "track_controls_inactive"
+{
+ bg[NORMAL] = { 0.60, 0.60, 0.66 }
+ bg[ACTIVE] = { 0.60, 0.60, 0.66 }
+ bg[INSENSITIVE] = { 0.60, 0.60, 0.66 }
+ bg[SELECTED] = { 0.60, 0.60, 0.66 }
+ bg[PRELIGHT] = { 0.60, 0.60, 0.66 }
+
+ font = "-*-courier-medium-r-*-*-*-100-*-*-*-*-*-*"
+ fg[NORMAL] = { 0.7, 0.8, 0.2 }
+}
+
+style "edit_controls_base_selected"
+{
+ bg[NORMAL] = { 0.56, 0.56, 0.56 }
+ bg[ACTIVE] = { 0.56, 0.56, 0.56 }
+ bg[INSENSITIVE] = { 0.56, 0.56, 0.56 }
+ bg[SELECTED] = { 0.56, 0.56, 0.56 }
+ bg[PRELIGHT] = { 0.56, 0.56, 0.56 }
+}
+
+style "automation_track_controls_base"
+{
+ bg[NORMAL] = { 0.22, 0.22, 0.29 }
+ bg[ACTIVE] = { 0.22, 0.22, 0.29 }
+ bg[INSENSITIVE] = { 0.22, 0.22, 0.29 }
+ bg[SELECTED] = { 0.22, 0.22, 0.29 }
+ bg[PRELIGHT] = { 0.22, 0.22, 0.29 }
+}
+
+# Plugin Editors
+style "plugin_slider"
+{
+ fontset="-*-helvetica-medium-r-normal-*-10-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*"
+
+ fg[NORMAL] = { 0.45, 0.45, 0.45 }
+ fg[ACTIVE] = { 0.45, 0.45, 0.45 }
+ fg[INSENSITIVE] = {0.0, 0.0, 0.0 } # matches default_base
+ fg[SELECTED] = { 0.45, 0.45, 0.45 }
+ fg[PRELIGHT] = { 0.45, 0.45, 0.45 }
+
+ text[NORMAL] = { 0.80, 0.80, 0.70 }
+ text[ACTIVE] = { 0.80, 0.80, 0.70 }
+ text[INSENSITIVE] = { 0.80, 0.80, 0.70 }
+ text[SELECTED] = { 0.80, 0.80, 0.70 }
+ text[PRELIGHT] = { 0.80, 0.80, 0.70 }
+}
+
+style "track_list_display" = "small_bold_text"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ fg[ACTIVE] = { 0.80, 0.80, 0.70 }
+ fg[SELECTED] = { 0.98, 0.76, 0.14 }
+ bg[NORMAL] = { 0, 0, 0 }
+ bg[ACTIVE] = { 0, 0, 0 }
+ bg[SELECTED] = { 0, 0, 0 }
+ base[NORMAL] = { 0, 0, 0 }
+ base[ACTIVE] = { 0, 0, 0 }
+ base[INSENSITIVE] = { 0, 0, 0 }
+ base[SELECTED] = { 0, 0, 0 }
+}
+
+style "region_list_display" = "small_bold_text"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ fg[ACTIVE] = { 0.98, 0.76, 0.14 }
+ fg[SELECTED] = { 0.66, 0.97, 0.18 }
+ bg[NORMAL] = { 0, 0, 0 }
+ bg[ACTIVE] = { 0, 0, 0 }
+ bg[SELECTED] = { 0, 0, 0 }
+ base[NORMAL] = { 1, 0, 0 }
+ base[ACTIVE] = { 0, 0, 0 }
+ base[INSENSITIVE] = { 0, 0, 0 }
+ base[SELECTED] = { 0, 0, 0 }
+}
+
+# MixerPanZone:
+#
+# the NORMAL fg color is used for the pan puck
+# the ACTIVE fg color is used for the speaker boxes
+
+style "pan_zone" = "default_base"
+{
+ fg[NORMAL] = { 0.34, 0.95, 0.92 }
+ fg[ACTIVE] = { 0.95, 0.48, 0.11 }
+}
+
+style "wall_clock" = "medium_bold_text"
+{
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+ bg[NORMAL] = { 0, 0, 0 }
+}
+
+style "paler_red_when_active" = "medium_text"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ fg[PRELIGHT] = { 0.80, 0.80, 0.70 }
+ bg[NORMAL] = { 0.31, 0.31, 0.31 }
+ bg[PRELIGHT] = { 0.31, 0.31, 0.31 }
+
+ fg[ACTIVE] = { 0.36, 0.46, 0.28 }
+ bg[ACTIVE] = { 1.00, 0.59, 0.59}
+}
+
+style "peak_display_peaked_entry" = "small_text"
+{
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+ fg[ACTIVE] = { 1.0, 1.0, 1.0 }
+ fg[SELECTED] = { 1.0, 1.0, 1.0 }
+
+ bg[NORMAL] = {0.9, 0.0, 0.0 }
+ bg[ACTIVE] = { 0.9, 0.0, 0.0 }
+ bg[PRELIGHT] = { 0.9, 0.0, 0.0 }
+ bg[INSENSITIVE] = { 0.9, 0.0, 0.0 }
+ bg[SELECTED] = { 0.9, 0.0, 0.0 }
+ base[NORMAL] = { 0.9, 0.0, 0.0 }
+ base[ACTIVE] = { 0.9, 0.0, 0.0 }
+ base[PRELIGHT] = { 0.9, 0.0, 0.0 }
+ base[INSENSITIVE] = { 0.9, 0.0, 0.0 }
+ base[SELECTED] = { 0.9, 0.0, 0.0 }
+}
+
+style "selected_strip_frame"
+{
+ fg[NORMAL] = { 0.74, 0.42, 0.47 }
+ bg[NORMAL] = { 0.79, 0.28, 0.18 }
+}
+
+style "flashing_alert" = "very_small_text"
+{
+ fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[NORMAL] = { 0.31, 0.31, 0.31 }
+
+ fg[ACTIVE] = { 0.80, 0.80, 0.70 }
+ bg[ACTIVE] = { 1.0, 0, 0}
+}
+
+style "selected_io_selector_port_list" = "medium_text"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ fg[SELECTED] = { 0.98, 0.76, 0.14 }
+ base[NORMAL] = { 0, 0, 0 }
+ base[SELECTED] = { 0, 0, 0 }
+}
+
+style "io_selector_port_list" = "medium_text"
+{
+ fg[NORMAL] = {0.80, 0.80, 0.70 }
+ fg[SELECTED] = {0.80, 0.80, 0.70 }
+ base[NORMAL] = { 0.26, 0.26, 0.26 }
+ base[SELECTED] = { 0.26, 0.26, 0.26 }
+}
+
+style "io_selector_notebook" = "default_base"
+{
+ fg[NORMAL] = { 0.98, 0.76, 0.14 }
+ font ="-*-helvetica-bold-r-normal-*-*-140-*-*-p-*-*"
+}
+
+style "tearoff_arrow" = "medium_bold_entry"
+{
+ bg[NORMAL] = { 0.80, 0.80, 0.70 }
+ bg[PRELIGHT] = { 0.98, 0.76, 0.14 }
+}
+
+style "meter_metrics_strip" = "default_base"
+{
+ font = "-*-courier-medium-r-*-*-*-100-*-*-*-*-*-*"
+ fg[NORMAL] = { 0.7, 0.8, 0.2 }
+}
+
+style "no_session_msg"
+{
+ font = "-*-helvetica-medium-r-*-*-34-350-*-*-*-*-*-*"
+}
+
+style "location_row_button" = "default_buttons_menus"
+{
+ fontset="-*-helvetica-medium-r-normal-*-10-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*"
+}
+
+style "location_rows_clock" = "default_clock_display"
+{
+ fontset="-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-120-*-*-p-*-*"
+}
+
+style "pan_slider"
+{
+ fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*"
+ font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*"
+
+ fg[NORMAL] = { 0.67, 0.23, 0.22 }
+ fg[ACTIVE] = { 0.67, 0.23, 0.22 }
+ fg[INSENSITIVE] = {0.32, 0.39, 0.45 } # matches default_base
+ fg[SELECTED] = { 0.67, 0.23, 0.22 }
+ fg[PRELIGHT] = { 0.67, 0.23, 0.22 }
+
+ bg[NORMAL] = { 0, 0, 0 }
+ bg[ACTIVE] = { 0, 0, 0 }
+ bg[INSENSITIVE] = {0.32, 0.39, 0.45 } # matches default_base
+ bg[SELECTED] = { 0, 0, 0 }
+ bg[PRELIGHT] = { 0, 0, 0 }
+
+ text[NORMAL] = { 0.85, 0.92, 0.98 }
+ text[ACTIVE] = { 0.85, 0.92, 0.98 }
+ text[INSENSITIVE] = { 0.85, 0.92, 0.98 }
+ text[SELECTED] = { 0.85, 0.92, 0.98 }
+ text[PRELIGHT] = { 0.85, 0.92, 0.98 }
+}
+
+#---------------------------------------------------------------
+widget "*FirstActionMessage" style "first_action_message"
+widget "*VerboseCanvasCursor" style "verbose_canvas_cursor"
+widget "*MarkerText" style "marker_text"
+widget "*TimeAxisViewItemName" style "time_axis_view_item_name"
+widget "EditorBase" style "default_base"
+widget "*TimebarLabelBase" style "default_base"
+widget "*WipeWindow" style "default_base"
+widget "*TakeWindow" style "default_base"
+widget "*TrackCanvasScroller" style "default_base"
+widget "*TimeCanvasScroller" style "default_base"
+widget "*SendUIWindow" style "default_base"
+widget "*SendUIFrame" style "default_base"
+widget "*MouseModeBase" style "default_base"
+widget "*SelectionModeBase" style "default_base"
+widget "*MeterBridgeWindow" style "default_base"
+widget "*ControlWindow" style "default_base"
+widget "*RegionWindow" style "default_base"
+widget "*ClickWindow" style "default_base"
+widget "*RegionRenameWindow" style "default_base"
+widget "*BackupRecoveryWindow" style "default_base"
+widget "*PluginDisplayWindow" style "default_base"
+widget "*ExportWindow" style "default_base"
+#widget "*ExportProgress" style "default_buttons_menus"
+widget "*ExportFileLabel" style "small_bold_text"
+widget "*ExportFormatLabel" style "medium_bold_text"
+widget "*ExportHeader" style "small_bold_text"
+widget "*ExportFileDisplay" style "medium_entry"
+widget "*ExportFormatDisplay" style "medium_entry"
+widget "*ExportCheckbox" style "small_entry"
+widget "*ExportTrackSelector" style "medium_entry_noselection_bg"
+widget "*MeterScrollBase" style "default_base"
+widget "*MixerWindow" style "default_base"
+widget "*RegionEditorWindow" style "default_base"
+widget "*AudioEngineControl" style "default_base"
+widget "*PeakFileWaitWindow" style "default_base"
+widget "*OptionsWindow" style "default_base"
+widget "*TimeStretchDialog" style "default_base"
+widget "*ChoiceWindow" style "default_base"
+widget "*PluginManagerWindow" style "default_base"
+widget "*CrossfadeEditWindow" style "default_base"
+widget "*ErrorText" style "default_base"
+widget "*LocationWindow" style "default_base"
+widget "*EditControlsBase" style "default_base"
+widget "*ToolBar" style "default_base"
+widget "*EditModeSelector" style "medium_bold_entry"
+widget "*SnapTypeSelector" style "medium_bold_entry"
+widget "*SnapModeSelector" style "medium_bold_entry"
+widget "*ZoomFocusSelector" style "medium_bold_entry"
+widget "*BigClockBase" style "default_base"
+widget "*AboveMeterZone" style "default_base"
+widget "*BelowMeterZone" style "default_base"
+widget "*ButtonTable" style "default_base"
+widget "*AdjusterTable" style "default_base"
+widget "*PluginEditor" style "default_base"
+widget "*PluginNameBox" style "default_base"
+widget "*IOSelectorWindow" style "default_base"
+widget "*ConnectionEditorWindow" style "default_base"
+widget "*RouteParamsWindow" style "default_base"
+widget "*RouteParamsBaseFrame" style "default_base"
+widget "*MetricDialog" style "default_base"
+widget "AddRouteDialog" style "default_base"
+widget "*LocationLocRowsScroller*" style "default_base"
+widget "*LocationRangeRowsScroller*" style "default_base"
+widget "*LocationRangeRows" style "default_base"
+widget "*LocationLocRows" style "default_base"
+widget "*LocationFrameBox" style "default_base"
+widget "*PanScrollerBase" style "default_base"
+widget "*ArdourContextMenu*" style "default_buttons_menus"
+widget "*EditGroupTitleButton*" style "default_buttons_menus"
+widget "*MixerGroupTitleButton*" style "default_buttons_menus"
+widget "*ErrorLogCloseButton" style "default_buttons_menus"
+widget "*EditorGTKButton*" style "default_buttons_menus"
+widget "*ToolbarButton" style "default_buttons_menus"
+widget "*ToolbarButton*" style "default_buttons_menus"
+widget "*CrossfadeEditButton" style "default_buttons_menus"
+widget "*CrossfadeEditButton*" style "default_buttons_menus"
+widget "*TrackHistoryButton*" style "default_buttons_menus"
+widget "*TrackSizeButton*" style "default_buttons_menus"
+widget "*TrackPlaylistButton*" style "default_buttons_menus"
+widget "*TrackAutomationButton*" style "default_buttons_menus"
+widget "*TrackGroupButton*" style "default_buttons_menus"
+widget "*TrackMixButton*" style "default_buttons_menus"
+widget "*TrackVisualButton*" style "default_buttons_menus"
+widget "*TrackRemoveButton*" style "default_buttons_menus"
+widget "*BaseButton" style "default_buttons_menus"
+widget "*TakeButtonLabel" style "default_buttons_menus"
+widget "*MixerWidthButton" style "default_buttons_menus"
+widget "*MixerHideButton" style "default_buttons_menus"
+widget "*MixerSendButton" style "default_buttons_menus"
+widget "*MixerSendButtonLabel" style "default_buttons_menus"
+widget "*MixerSendSwitch" style "default_buttons_menus"
+widget "*MixerInsertButton" style "default_buttons_menus"
+widget "*MixerInsertButtonLabel" style "default_buttons_menus"
+widget "*MixerInsertSwitch" style "default_buttons_menus"
+widget "*MixerMonitorInputButton*" style "very_small_button"
+widget "*MixerMonitorInputButton.*" style "very_small_button"
+widget "*MixerIOButton" style "very_small_button"
+widget "*MixerIOButtonLabel" style "very_small_button"
+widget "*AddRouteDialogSpinner" style "ardour_adjusters"
+widget "*AddRouteDialogRadioButton*" style "options_window"
+widget "*OptionsNotebook" style "options_window"
+widget "*OptionEditorToggleButton*" style "options_window"
+widget "*OptionsLabel" style "options_window"
+widget "*OptionEditorAuditionerLabel" style "options_window"
+widget "*OptionsEntry" style "option_entry"
+widget "*InspectorNotebook" style "options_window"
+widget "*NewSessionDialog" style "options_window"
+widget "*NewSessionDialogButton*" style "options_window"
+widget "*MixerSendSwitch*" style "very_small_red_active_and_selected_button"
+widget "*OptionEditorToggleButton" style "small_red_active_and_selected_button"
+widget "*NewSessionDialogButton" style "small_red_active_and_selected_button"
+widget "*MixerRecordEnableButton" style "mixer_rec_enable_button"
+widget "*MixerRecordEnableButton*" style "mixer_rec_enable_button"
+widget "*TrackRecordEnableButton" style "track_rec_enable_button"
+widget "*TrackRecordEnableButton*" style "track_rec_enable_button"
+widget "*TrackMuteButton*" style "mute_button"
+widget "*TrackLoopButton*" style "track_loop_button"
+widget "*EditorTimeButton*" style "time_button"
+widget "*EditorMixerButton*" style "default_buttons_menus"
+widget "*SoloButton*" style "solo_button"
+widget "*SoloButton.*" style "solo_button"
+widget "*SafeSoloButton*" style "solo_button"
+widget "*SafeSoloButton.*" style "solo_button"
+widget "*MixerPhaseInvertButton*" style "very_small_button"
+widget "*MixerPhaseInvertButton.*" style "very_small_button"
+widget "*MixerAutomationRecordingButton*" style "very_small_button"
+widget "*MixerAutomationRecordingButton.*" style "very_small_button"
+widget "*MixerAutomationModeButton*" style "very_small_button"
+widget "*MixerAutomationModeButton.*" style "very_small_button"
+widget "*MixerAutomationPlaybackButton*" style "very_small_button"
+widget "*MixerAutomationPlaybackButton.*" style "very_small_button"
+widget "*MixerMuteButton*" style "mixer_mute_button"
+widget "*MixerMuteButton.*" style "mixer_mute_button"
+widget "*MixerSoloButton*" style "mixer_solo_button"
+widget "*MixerSoloButton.*" style "mixer_solo_button"
+widget "*MixerNameButton" style "very_small_button"
+widget "*MixerNameButtonLabel" style "very_small_button"
+widget "*MixerGroupButton" style "very_small_button"
+widget "*MixerGroupButtonLabel" style "very_small_button"
+widget "*MixerCommentButton" style "very_small_button"
+widget "*MixerCommentButton*" style "very_small_button"
+widget "*EditGroupButton" style "very_small_button"
+widget "*EditGroupButtonLabel" style "very_small_button"
+widget "*TransportButton" style "transport_button"
+widget "*TransportButton*" style "transport_button"
+widget "*ShuttleButton" style "transport_button"
+widget "*ShuttleButton*" style "transport_button"
+widget "*ShuttleDisplay" style "transport_button"
+widget "*ShuttleDisplay*" style "transport_button"
+widget "*ShuttleControl" style "shuttle_control"
+widget "*TransportRecButton" style "transport_rec_button"
+widget "*TransportRecButton*" style "transport_rec_button"
+widget "*TransportBase" style "default_base"
+widget "*TransportWindow" style "default_base"
+widget "*RecordingXrunWarningWindow" style "xrun_warn"
+widget "*RecordingXrunWarningWindow*" style "xrun_warn"
+widget "*MainMenuBar" style "menu_bar_base"
+widget "*ErrorMessage" style "error_message"
+widget "*FatalMessage" style "fatal_message"
+widget "*InfoMessage" style "info_message"
+widget "*WarningMessage" style "warning_message"
+widget "*BigClockDisplay" style "big_clock_display"
+widget "*TransportClockDisplay" style "transport_clock_display"
+widget "*SecondaryClockDisplay" style "transport_clock_display"
+widget "*BBTTempoLabel" style "tempo_meter_clock_display"
+widget "*BBTMeterLabel" style "tempo_meter_clock_display"
+widget "*SelectionStartClock" style "default_clock_display"
+widget "*SelectionEndClock" style "default_clock_display"
+widget "*EditCursorClock" style "default_clock_display"
+widget "*PreRollClock" style "default_clock_display"
+widget "*PostRollClock" style "default_clock_display"
+widget "*NudgeClock" style "default_clock_display"
+widget "*ZoomRangeClock" style "default_clock_display"
+widget "*SMPTEOffsetClock" style "default_clock_display"
+widget "*TransportLabel" style "small_bold_text"
+widget "*TakeLabel" style "small_bold_text"
+widget "*LocationLabel" style "small_bold_text"
+widget "*WipeLabel" style "small_bold_text"
+widget "*TakeTagLabel" style "small_bold_text"
+widget "*ToolBarLabel" style "small_bold_text"
+widget "*EditorDisplayLabel" style "small_bold_text"
+widget "*NewSessionLabel" style "large_text"
+widget "*GlobalButtonLabel" style "default_buttons_menus"
+widget "*ClickButton" style "medium_entry"
+widget "*RegionNameDisplay" style "medium_entry"
+widget "*PluginDisplay" style "medium_entry"
+widget "*SelectionDisplay" style "medium_entry"
+widget "*HistorySelector" style "medium_entry"
+widget "*LocationSelector" style "medium_entry"
+widget "*TakeSelector" style "medium_entry"
+widget "*RegionSelector" style "medium_entry"
+widget "*SMPTERuler" style "editor_time_ruler"
+widget "*BBTRuler" style "editor_time_ruler"
+widget "*FramesRuler" style "editor_time_ruler"
+widget "*MinSecRuler" style "editor_time_ruler"
+widget "*BaseFrame" style "base_frame"
+widget "*AudioTrackStripBase" style "audio_track_base"
+widget "*TimeAxisViewControlsBaseUnselected" style "audio_track_base"
+widget "*AudioTrackControlsBaseUnselected" style "audio_track_base"
+widget "*AudioTrackFader" style "audio_track_base"
+widget "*AudioBusStripBase" style "audio_bus_base"
+widget "*BusControlsBaseUnselected" style "audio_bus_base"
+widget "*AudioBusFader" style "audio_bus_base"
+widget "*TrackSeparator" style "track_separator"
+widget "*TrackEditIndicator0*" style "edit_group_0"
+widget "*TrackEditIndicator1*" style "edit_group_1"
+widget "*TrackEditIndicator2*" style "edit_group_2"
+widget "*TrackEditIndicator3*" style "edit_group_3"
+widget "*TrackEditIndicator4*" style "edit_group_3"
+widget "*TrackEditIndicator5*" style "edit_group_3"
+widget "*TrackEditIndicator6*" style "edit_group_3"
+widget "*TrackEditIndicator7*" style "edit_group_3"
+widget "*EditorTrackNameDisplay" style "track_name_display"
+widget "*EditorTrackNameDisplay*" style "track_name_display"
+widget "*EditorRegionList" style "region_list_display"
+widget "*CrossfadeEditAuditionButton" style "red_when_active"
+widget "*CrossfadeEditAuditionButton*" style "red_when_active"
+widget "*CrossfadeEditCurveButton" style "red_when_active"
+widget "*CrossfadeEditCurveButton*" style "red_when_active"
+widget "*CrossfadeEditLabel" style "medium_text"
+widget "*CrossfadeEditFrame" style "base_frame"
+widget "*MouseModeButton" style "default_buttons_menus"
+widget "*MouseModeButton*" style "default_buttons_menus"
+widget "*EditorWindow" style "default_base"
+widget "*EditorMainCanvas" style "main_canvas_area"
+widget "*AudioTrackControlsBaseInactiveUnselected" style "track_controls_inactive"
+widget "*BusControlsBaseInactiveUnselected" style "track_controls_inactive"
+widget "*AutomationTrackControlsBaseInactiveUnselected" style "track_controls_inactive"
+widget "*AudioTrackControlsBaseInactiveSelected" style "track_controls_inactive"
+widget "*BusControlsBaseInactiveSelected" style "track_controls_inactive"
+widget "*AutomationTrackControlsBaseInactiveSelected" style "track_controls_inactive"
+widget "*AudioTrackStripBaseInactive" style "track_controls_inactive"
+widget "*AudioBusStripBaseInactive" style "track_controls_inactive"
+widget "*AudioTrackControlsBaseSelected" style "edit_controls_base_selected"
+widget "*BusControlsBaseSelected" style "edit_controls_base_selected"
+widget "*AutomationTrackControlsBase" style "automation_track_controls_base"
+widget "*AutomationTrackControlsBaseSelected" style "edit_controls_base_selected"
+widget "*EditorMenuBar*" style "black_mackie_menu_bar"
+widget "*MainMenuBar*" style "black_mackie_menu_bar"
+widget "*ZoomClickBox" style "medium_bold_entry"
+widget "*PluginParameterLabel" style "medium_text"
+widget "*PluginNameInfo" style "plugin_name_text"
+widget "*PluginMakerInfo" style "plugin_maker_text"
+widget "*PluginParameterInfo" style "medium_text"
+widget "*MotionControllerValue" style "medium_entry"
+widget "*ParameterValueDisplay" style "medium_bold_entry"
+widget "*PluginUIClickBox" style "medium_bold_entry"
+widget "*PluginUIClickBox*" style "medium_bold_entry"
+widget "*PluginSlider" style "plugin_slider"
+widget "*TrackListDisplay" style "track_list_display"
+widget "*TrackListDisplay.*" style "small_bold_text"
+widget "*RegionListDisplay" style "small_bold_entry"
+widget "*RegionListDisplay.*" style "small_bold_text"
+widget "*MixerRedirectSelector" style "small_bold_entry"
+widget "*MixerRedirectSelector.*" style "small_bold_text"
+widget "*MixerTrackNameArea" style "default_base"
+widget "*MixerTrackCommentArea" style "option_entry"
+widget "*MixerPanZone" style "pan_zone"
+widget "*MixerTrackDisplayList" style "track_list_display"
+widget "*MixerSnapshotDisplayList" style "track_list_display"
+widget "*MixerAuxDisplayList" style "track_list_display"
+widget "*MixerGroupList" style "track_list_display"
+widget "*WallClock" style "wall_clock"
+widget "*CPULoad" style "wall_clock"
+widget "*RegionEditorLabel" style "medium_text"
+widget "*RegionEditorSmallLabel" style "small_text"
+widget "*RegionEditorEntry" style "medium_entry"
+widget "*RegionEditorClock" style "default_clock_display"
+widget "*RegionEditorToggleButton" style "paler_red_when_active"
+widget "*RegionEditorToggleButton*" style "paler_red_when_active"
+widget "*MixerStripSpeedBase" style "small_entry"
+widget "*MixerStripSpeedBase*" style "small_entry"
+widget "*MixerStripSpeedBaseNotOne" style "small_red_on_black_entry"
+widget "*MixerStripSpeedBaseNotOne*" style "small_red_on_black_entry"
+widget "*MixerStripGainDisplay" style "small_entry"
+widget "*MixerStripGainUnitButton" style "very_small_button"
+widget "*MixerStripGainUnitButton*" style "very_small_button"
+widget "*MixerStripMeterPreButton" style "very_small_button"
+widget "*MixerStripMeterPreButton*" style "very_small_button"
+widget "*MixerStripPeakDisplay*" style "red_active_small_entry"
+widget "*MixerStripPeakDisplayPeak*" style "peak_display_peaked_entry"
+widget "*MixerStripSelectedFrame" style "selected_strip_frame"
+widget "*MixerStripFrame" style "base_frame"
+widget "*HWMonitorButton" style "red_when_active"
+widget "*HWMonitorButton*" style "red_when_active"
+widget "*BypassButton" style "red_when_active"
+widget "*BypassButton*" style "red_when_active"
+widget "*TransportSoloAlert" style "flashing_alert"
+widget "*TransportSoloAlert.*" style "flashing_alert"
+widget "*TransportAuditioningAlert" style "flashing_alert"
+widget "*TransportAuditioningAlert.*" style "flashing_alert"
+widget "*Prompter" style "default_base"
+widget "*PrompterLabel" style "default_base"
+widget "*CleanupDialog" style "default_base"
+widget "*CleanupDialog*" style "default_base"
+widget "*FadeCurve" style "medium_bold_entry"
+widget "*FadeCurve*" style "medium_bold_entry"
+widget "*IOSelectorButton" style "default_buttons_menus"
+widget "*IOSelectorButton*" style "default_buttons_menus"
+widget "*IOSelectorList" style "medium_entry_noselection_fg"
+widget "*IOSelectorPortList" style "io_selector_port_list"
+widget "*IOSelectorPortListSelected" style "selected_io_selector_port_list"
+widget "*IOSelectorNotebook" style "io_selector_notebook"
+widget "*IOSelectorNotebookTab" style "io_selector_notebook"
+widget "*IOSelectorFrame" style "base_frame"
+widget "*ConnectionEditorButton" style "default_buttons_menus"
+widget "*ConnectionEditorButton*" style "default_buttons_menus"
+widget "*ConnectionEditorList" style "medium_entry_noselection_fg"
+widget "*ConnectionEditorConnectionList" style "medium_entry"
+widget "*ConnectionEditorPortList" style "io_selector_port_list"
+widget "*ConnectionEditorPortListSelected" style "selected_io_selector_port_list"
+widget "*ConnectionEditorNotebook" style "io_selector_notebook"
+widget "*ConnectionEditorNotebookTab" style "io_selector_notebook"
+widget "*ConnectionEditorFrame" style "base_frame"
+widget "*RouteParamsListDisplay" style "track_list_display"
+widget "*RouteParamsPreListDisplay" style "track_list_display"
+widget "*RouteParamsPostListDisplay" style "track_list_display"
+widget "*TearOffArrow" style "tearoff_arrow"
+widget "*RouteParamsTitleButton" style "medium_text"
+widget "*RouteParamsTitleLabel" style "medium_text"
+widget "*PluginAutomateRecordButton" style "small_red_active_and_selected_button"
+widget "*PluginAutomateRecordButton*" style "small_red_active_and_selected_button"
+widget "*PluginAutomatePlayButton" style "small_red_active_and_selected_button"
+widget "*PluginAutomatePlayButton*" style "small_red_active_and_selected_button"
+widget "*PluginAutomateButton" style "small_button"
+widget "*PluginAutomateButton*" style "small_button"
+widget "*PluginSaveButton" style "small_button"
+widget "*PluginSaveButton*" style "small_button"
+widget "*PluginLoadButton" style "small_button"
+widget "*PluginLoadButton*" style "small_button"
+widget "*FaderMetricsStrip" style "meter_metrics_strip"
+widget "*MeterMetricsStrip" style "meter_metrics_strip"
+widget "*NoSessionMessage" style "no_session_msg"
+widget "*MetricDialogFrame" style "base_frame"
+widget "*MetricEntry" style "medium_bold_entry"
+widget "*MetricButton" style "default_buttons_menus"
+widget "*MetricButton.*" style "default_buttons_menus"
+widget "*MetricLabel" style "medium_text"
+widget "*TimeStretchButton" style "default_buttons_menus"
+widget "*TimeStretchButton.*" style "default_buttons_menus"
+widget "*TimeStretchProgress" style "default_buttons_menus"
+widget "*ChoiceWindow" style "default_buttons_menus"
+widget "*ChoicePrompt" style "default_buttons_menus"
+widget "*ChoiceButton" style "default_buttons_menus"
+widget "*ChoiceButton*" style "default_buttons_menus"
+widget "*SelectionModeButton" style "default_buttons_menus"
+widget "*SelectionModeButton*" style "default_buttons_menus"
+widget "*TrackLabel" style "medium_text"
+widget "*TrackPlugName" style "medium_text"
+widget "*TrackParameterName" style "small_text"
+widget "*AddRouteDialog*" style "medium_text"
+widget "*AddRouteDialog.GtkLabel" style "medium_text"
+widget "*AddRouteDialogChannelChoice" style "medium_bold_entry"
+widget "*AddRouteDialogSpinner" style "medium_bold_entry"
+widget "*AddRouteDialogSpinner*" style "medium_bold_entry"
+widget "*AddRouteDialogRadioButton" style "red_when_active"
+widget "*AddRouteDialogButton" style "default_buttons_menus"
+widget "*AddRouteDialogNameTemplateEntry" style "medium_bold_entry"
+widget "*NewSessionIOLabel" style "larger_bold_text"
+widget "*NewSessionSR1Label" style "red_medium_text"
+widget "*NewSessionSR2Label" style "medium_text"
+widget "*NewSessionChannelChoice" style "medium_bold_entry"
+widget "*NewSessionMainButton" style "larger_bold_text"
+widget "*NewSessionMainButton*" style "larger_bold_text"
+widget "*NewSessionMainLabel" style "larger_bold_text"
+widget "*LocationEditRowClock" style "location_rows_clock"
+widget "*LocationEditNameLabel" style "medium_text"
+widget "*LocationEditSetButton" style "location_row_button"
+widget "*LocationEditSetButton*" style "location_row_button"
+widget "*LocationEditGoButton" style "location_row_button"
+widget "*LocationEditGoButton*" style "location_row_button"
+widget "*LocationEditCdButton" style "small_red_active_and_selected_button"
+widget "*LocationEditCdButton*" style "small_red_active_and_selected_button"
+widget "*LocationEditHideButton" style "small_red_active_and_selected_button"
+widget "*LocationEditHideButton*" style "small_red_active_and_selected_button"
+widget "*LocationEditNumberLabel" style "small_text"
+widget "*LocationLocEditorFrame" style "base_frame"
+widget "*LocationRangeEditorFrame" style "base_frame"
+widget "*LocationEditNameEntry" style "option_entry"
+widget "*LocationAddLocationButton" style "default_buttons_menus"
+widget "*LocationAddLocationButton*" style "default_buttons_menus"
+widget "*LocationAddRangeButton" style "default_buttons_menus"
+widget "*LocationAddRangeButton*" style "default_buttons_menus"
+widget "*LocationEditRemoveButton" style "location_row_button"
+widget "*LocationEditRemoveButton*" style "location_row_button"
+widget "*PanSlider" style "pan_slider"
+widget "*PanningLinkButton" style "mixer_red_active_button"
+widget "*PanningLinkButton.*" style "mixer_red_active_button"
+widget "*PanningLinkDirectionButton" style "very_small_button"
+widget "*PanningLinkDirectionButton.*" style "very_small_button"
+widget "*ChannelCountSelector" style "medium_bold_entry"
+widget "*ChannelCountSelector.GtkArrow" style "default_buttons_menus"
+
+class "GtkWidget" style "default_base"
+class "GtkScrollbar" style "ardour_adjusters"
+class "GtkLabel" style "default_buttons_menus"
+class "GtkButton" style "default_buttons_menus"
+class "GtkArrow" style "tearoff_arrow"
+class "GtkProgressBar" style "ardour_progressbars"
+
+
+#
+#----------------------------------------------------------------------
+#
+# Below this point, all styles refer to colors used by canvas items
+# not actual widgets. The "red" value of the active state is used
+# to define the "alpha" value for the RGBA value. Other color values
+# for the active state are ignored.
+#
+
+style "cWaveForm"
+{
+ fg[NORMAL] = { 0.0, 0.0, 0.0 }
+ fg[ACTIVE] = { 0.80, 0, 0 }
+}
+widget "*cWaveForm" style "cWaveForm"
+
+style "cMutedWaveForm"
+{
+ fg[NORMAL] = { 0.35, 0.35, 0.35 }
+ #fg[NORMAL] = { 0.80, 0.80, 0.70 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cMutedWaveForm" style "cMutedWaveForm"
+
+style "cSelectedFrameBase"
+{
+ fg[NORMAL] = { 0.71, 0.57, 0.66 }
+ #fg[NORMAL] = { 0.10, 0.10, 0.10 }
+ fg[ACTIVE] = { 1.0, 0, 0 } # Not used, opacity set by region editor
+}
+widget "*cSelectedFrameBase" style "cSelectedFrameBase"
+
+style "cFrameBase"
+{
+ fg[NORMAL] = { 0.75, 0.75, 0.76 }
+ fg[ACTIVE] = { 1.0, 0, 0 } # Not used, opacity set by region editor
+}
+widget "*cFrameBase" style "cFrameBase"
+
+style "cAudioTrackBase"
+{
+ fg[NORMAL] = { 0.79, 0.80, 0.85 }
+ #fg[NORMAL] = { 0, 0, 0 }
+ fg[ACTIVE] = { 0.41, 0, 0 }
+ #fg[ACTIVE] = { 0.70, 0, 0 }
+}
+widget "*cAudioTrackBase" style "cAudioTrackBase"
+
+style "cAudioTrackOutline"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cAudioTrackOutline" style "cAudioTrackOutline"
+
+style "cAudioBusBase"
+{
+ fg[NORMAL] = { 0.90, 0.82, 0.90 }
+ fg[ACTIVE] = { 0.41, 0, 0 }
+}
+widget "*cAudioBusBase" style "cAudioBusBase"
+
+style "cTempoBar"
+{
+ fg[NORMAL] = { 0.64, 0.64, 0.62 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*TempoBar" style "cTempoBar"
+
+style "cMeterBar"
+{
+ fg[NORMAL] = { 0.75, 0.75, 0.73 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cMeterBar" style "cMeterBar"
+
+style "cMarkerBar"
+{
+ fg[NORMAL] = { 0.54, 0.54, 0.52 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cMarkerBar" style "cMarkerBar"
+
+style "cRangeMarkerBar"
+{
+ fg[NORMAL] = { 0.48, 0.48, 0.46 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cRangeMarkerBar" style "cRangeMarkerBar"
+
+style "cTransportMarkerBar"
+{
+ fg[NORMAL] = { 0.40, 0.40, 0.38 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cTransportMarkerBar" style "cTransportMarkerBar"
+
+style "cTimeStretchFill"
+{
+ fg[NORMAL] = { 0.89, 0.71, 0.71 }
+ fg[ACTIVE] = { 0.59, 0, 0 }
+}
+widget "*cTimeStretchFill" style "cTimeStretchFill"
+
+style "cTimeStretchOutline"
+{
+ fg[NORMAL] = { 0.39, 0.39, 0.39 }
+ fg[ACTIVE] = { 0.59, 0, 0 }
+}
+widget "*cTimeStretchOutline" style "cTimeStretchOutline"
+
+style "cAutomationLine"
+{
+ fg[NORMAL] = { 0.27, 0.74, 0.35 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cAutomationLine" style "cAutomationLine"
+
+style "cLeftPanAutomationLine"
+{
+ fg[NORMAL] = { 0.77, 0.24, 0.01 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cLeftPanAutomationLine" style "cLeftPanAutomationLine"
+
+style "cRightPanAutomationLine"
+{
+ fg[NORMAL] = { 0.03, 0.26, 0.73 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cRightPanAutomationLine" style "cRightPanAutomationLine"
+
+style "cRedirectAutomationLine"
+{
+ fg[NORMAL] = { 0.28, 0.34, 0.74 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cRedirectAutomationLine" style "cRedirectAutomationLine"
+
+style "cControlPointFill"
+{
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cControlPointFill" style "cControlPointFill"
+
+style "cControlPointOutline"
+{
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cControlPointOutline" style "cControlPointOutline"
+
+style "cEnteredControlPointOutline"
+{
+ fg[NORMAL] = { 1.0, 0.21, 0.21 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cEnteredControlPointOutline" style "cEnteredControlPointOutline"
+
+style "cEnteredControlPointSelected"
+{
+ fg[NORMAL] = { 0.00, 1.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cEnteredControlPointSelected" style "cEnteredControlPointSelected"
+
+style "cEnteredControlPoint"
+{
+ fg[NORMAL] = { 1.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cEnteredControlPoint" style "cEnteredControlPoint"
+
+style "cControlPointSelected"
+{
+ fg[NORMAL] = { 0.91, 0.04, 0.04 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cControlPointSelected" style "cControlPointSelected"
+
+style "cControlPoint"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cControlPoint" style "cControlPoint"
+
+style "cAutomationTrackFill"
+{
+ fg[NORMAL] = { 0.63, 0.63, 0.81 }
+ fg[ACTIVE] = { 0.41, 0, 0 }
+}
+widget "*cAutomationTrackFill" style "cAutomationTrackFill"
+
+style "cAutomationTrackOutline"
+{
+ fg[NORMAL] = { 0.16, 0.16, 0.16 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cAutomationTrackOutline" style "cAutomationTrackOutline"
+
+style "cCrossfadeEditorBase"
+{
+ fg[NORMAL] = { 0.16, 0.18, 0.29 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cCrossfadeEditorBase" style "cCrossfadeEditorBase"
+
+style "cCrossfadeEditorLine"
+{
+ fg[NORMAL] = { 1.0, 0.86, 0.86 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cCrossfadeEditorLine" style "cCrossfadeEditorLine"
+
+style "cSelectedCrossfadeEditorLine"
+{
+ fg[NORMAL] = { 0, 0.86, 0.86 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cSelectedCrossfadeEditorLine" style "cSelectedCrossfadeEditorLine"
+
+style "cCrossfadeEditorLineShading"
+{
+ fg[NORMAL] = { 0, 0.63, 0.82 }
+ fg[ACTIVE] = { 0.33, 0, 0 }
+}
+widget "*cCrossfadeEditorLineShading" style "cCrossfadeEditorLineShading"
+
+style "cCrossfadeEditorPointFill"
+{
+ fg[NORMAL] = { 0, 1.0, 0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cCrossfadeEditorPointFill" style "cCrossfadeEditorPointFill"
+
+style "cCrossfadeEditorPointOutline"
+{
+ fg[NORMAL] = { 0, 0, 1.0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cCrossfadeEditorPointOutline" style "cCrossfadeEditorPointOutline"
+
+style "cCrossfadeEditorWave"
+{
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+ fg[ACTIVE] = { 0.36, 0, 0 }
+}
+widget "*cCrossfadeEditorWave" style "cCrossfadeEditorWave"
+
+style "cSelectedCrossfadeEditorWave"
+{
+ fg[NORMAL] = { 0.98, 0.92, 0.08 }
+ fg[ACTIVE] = { 0.63, 0, 0 }
+}
+widget "*cSelectedCrossfadeEditorWave" style "cSelectedCrossfadeEditorWave"
+
+style "cCrossfadeLine"
+{
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cCrossfadeLine" style "cCrossfadeLine"
+
+style "cActiveCrossfade"
+{
+ fg[NORMAL] = { 0.91, 0.93, 0.24 }
+ fg[ACTIVE] = { 0.47, 0, 0 }
+}
+widget "*cActiveCrossfade" style "cActiveCrossfade"
+
+style "cInactiveCrossfade"
+{
+ fg[NORMAL] = { 1.0, 1.0, 1.0 }
+ fg[ACTIVE] = { 0.1, 0, 0 }
+}
+widget "*cInactiveCrossfade" style "cInactiveCrossfade"
+
+style "cLocationMarker"
+{
+ fg[NORMAL] = { 0.77, 0.96, 0.07 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cLocationMarker" style "cLocationMarker"
+
+style "cLocationRange"
+{
+ fg[NORMAL] = { 0.29, 0.48, 0.35 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cLocationRange" style "cLocationRange"
+
+style "cLocationCDMarker"
+{
+ fg[NORMAL] = { 0.12, 0.91, 0.77 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cLocationCDMarker" style "cLocationCDMarker"
+
+style "cLocationLoop"
+{
+ fg[NORMAL] = { 0.21, 0.59, 0.31 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cLocationLoop" style "cLocationLoop"
+
+style "cLocationPunch"
+{
+ fg[NORMAL] = { 0.49, 0.23, 0.23 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cLocationPunch" style "cLocationPunch"
+
+style "cVerboseCanvasCursor"
+{
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[ACTIVE] = {0.74, 0, 0 }
+}
+widget "*cVerboseCanvasCursor" style "cVerboseCanvasCursor"
+
+style "cRangeDragBarRect"
+{
+ fg[NORMAL] = { 0.59, 0.59, 0.59 }
+ fg[ACTIVE] = { 0.78, 0, 0 }
+}
+widget "*cRangeDragBarRect" style "cRangeDragBarRect"
+
+style "cRangeDragBarRectFill"
+{
+ fg[NORMAL] = { 0.78, 0.82, 0.70 }
+ fg[ACTIVE] = { 0.43, 0, 0 }
+}
+widget "*cRangeDragBarRectFill" style "cRangeDragBarRectFill"
+
+style "cRangeDragRect"
+{
+ fg[NORMAL] = { 0.59, 0.59, 0.59 }
+ fg[ACTIVE] = { 0.78, 0, 0 }
+}
+widget "*cRangeDragRect" style "cRangeDragRect"
+
+style "cRangeDragRectFill"
+{
+ fg[NORMAL] = { 0.51, 0.78, 0.59 }
+ fg[ACTIVE] = { 0.78, 0, 0 }
+}
+widget "*cRangeDragRectFill" style "cRangeDragRectFill"
+
+style "cTransportDragRect"
+{
+ fg[NORMAL] = { 0.59, 0.59, 0.59 }
+ fg[ACTIVE] = { 0.78, 0, 0 }
+}
+widget "*cTransportDragRect" style "cTransportDragRect"
+
+style "cTransportDragRectFill"
+{
+ fg[NORMAL] = { 0.78, 0.78, 0.78 }
+ fg[ACTIVE] = { 1.43, 0, 0 }
+}
+widget "*cTransportDragRectFill" style "cTransportDragRectFill"
+
+style "cMarkerDragLine"
+{
+ fg[NORMAL] = { 0, 0.31, 0 }
+ fg[ACTIVE] = { 0.98, 0, 0 }
+}
+widget "*cMarkerDragLine" style "cMarkerDragLine"
+
+style "cTransportLoopRect"
+{
+ fg[NORMAL] = { 0.12, 0.47, 0.16 }
+ fg[ACTIVE] = { 0.98, 0, 0 }
+}
+widget "*cTransportLoopRect" style "cTransportLoopRect"
+
+style "cTransportLoopRectFill"
+{
+ fg[NORMAL] = { 0.12, 0.47, 0.16 }
+ fg[ACTIVE] = { 0.98, 0, 0 }
+}
+widget "*cTransportLoopRectFill" style "cTransportLoopRectFill"
+
+style "cTransportPunchRect"
+{
+ fg[NORMAL] = { 0.43, 0.16, 0.16 }
+ fg[ACTIVE] = { 0.90, 0, 0 }
+}
+widget "*cTransportPunchRect" style "cTransportPunchRect"
+
+style "cTransportPunchRectFill"
+{
+ fg[NORMAL] = { 0.43, 0.16, 0.16 }
+ fg[ACTIVE] = { 0.90, 0, 0 }
+}
+widget "*cTransportPunchRectFill" style "cTransportPunchRectFill"
+
+style "cPunchInLine"
+{
+ fg[NORMAL] = { 0.66, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cPunchInLine" style "cPunchInLine"
+
+style "cPunchOutLine"
+{
+ fg[NORMAL] = { 0.66, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cPunchOutLine" style "cPunchOutLine"
+
+style "cZoomRect"
+{
+ fg[NORMAL] = { 0.59, 0.59, 0.59 }
+ fg[ACTIVE] = { 0.78, 0, 0 }
+}
+widget "*cZoomRect" style "cZoomRect"
+
+style "cZoomRectFill"
+{
+ fg[NORMAL] = { 0.78, 0.82, 0.70 }
+ fg[ACTIVE] = { 0.43, 0, 0 }
+}
+widget "*cZoomRectFill" style "cZoomRectFill"
+
+style "cRubberBandRect"
+{
+ fg[NORMAL] = { 0.08, 1.00, 0.52 }
+ fg[ACTIVE] = { 0.59, 0, 0 }
+}
+widget "*cRubberBandRect" style "cRubberBandRect"
+
+style "cRubberBandRectFill"
+{
+ fg[NORMAL] = { 0.78, 0.78, 0.78 }
+ fg[ACTIVE] = { 0.35, 0, 0 }
+}
+widget "*cRubberBandRectFill" style "cRubberBandRectFill"
+
+style "cFirstActionMessage"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cFirstActionMessage" style "cFirstActionMessage"
+
+style "cEnteredGainLine"
+{
+ fg[NORMAL] = { 0.87, 0.39, 0.39 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cEnteredGainLine" style "cEnteredGainLine"
+
+style "cEnteredAutomationLine"
+{
+ fg[NORMAL] = { 0.87, 0.39, 0.39 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cEnteredAutomationLine" style "cEnteredAutomationLine"
+
+style "cEnteredMarker"
+{
+ fg[NORMAL] = { 0.87, 0.39, 0.39 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cEnteredMarker" style "cEnteredMarker"
+
+style "cMeterMarker"
+{
+ fg[NORMAL] = { 0.95, 0.26, 0.36 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cMeterMarker" style "cMeterMarker"
+
+style "cTempoMarker"
+{
+ fg[NORMAL] = { 0.95, 0.26, 0.36 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cTempoMarker" style "cTempoMarker"
+
+style "cMeasureLineBeat"
+{
+ fg[NORMAL] = { 0.80, 0.59, 0.51 }
+ fg[ACTIVE] = { 0.98, 0, 0 }
+}
+widget "*cMeasureLineBeat" style "cMeasureLineBeat"
+
+style "cMeasureLineBar"
+{
+ fg[NORMAL] = { 0.68, 1.0, 0.59 }
+ fg[ACTIVE] = { 0.94, 0, 0 }
+}
+widget "*cMeasureLineBar" style "cMeasureLineBar"
+
+style "cGhostTrackBaseOutline"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cGhostTrackBaseOutline" style "cGhostTrackBaseOutline"
+
+style "cGhostTrackBaseFill"
+{
+ fg[NORMAL] = { 0.27, 0.00, 0.49 }
+ fg[ACTIVE] = { 0.50, 0, 0 }
+}
+widget "*cGhostTrackBaseFill" style "cGhostTrackBaseFill"
+
+style "cGhostTrackWave"
+{
+ fg[NORMAL] = { 1.0, 0.00, 0.00 }
+ fg[ACTIVE] = { 0.50, 0, 0 }
+}
+widget "*cGhostTrackWave" style "cGhostTrackWave"
+
+style "cImageTrackBase"
+{
+ fg[NORMAL] = { 0.87, 0.87, 0.85 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cImageTrackBase" style "cImageTrackBase"
+
+style "cImageTrackOutline"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cImageTrackOutline" style "cImageTrackOutline"
+
+style "cMarkerTrackBase"
+{
+ fg[NORMAL] = { 0.87, 0.87, 0.85 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cMarkerTrackBase" style "cMarkerTrackBase"
+
+style "cMarkerTrackOutline"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cMarkerTrackOutline" style "cMarkerTrackOutline"
+
+style "cZeroLine"
+{
+ fg[NORMAL] = { 0.71, 0.71, 0.71 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cZeroLine" style "cZeroLine"
+
+style "cGainLine"
+{
+ fg[NORMAL] = { 0.00, 1.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cGainLine" style "cGainLine"
+
+style "cGainLineInactive"
+{
+ fg[NORMAL] = { 0.06, 0.06, 0.06 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cGainLineInactive" style "cGainLineInactive"
+
+style "cRecordingRectFill"
+{
+ fg[NORMAL] = { 0.90, 0.78, 0.78 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cRecordingRectFill" style "cRecordingRectFill"
+
+style "cRecordingRectOutline"
+{
+ fg[NORMAL] = { 0.31, 0.16, 0.16 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cRecordingRectOutline" style "cRecordingRectOutline"
+
+style "cSelectionRectFill"
+{
+ fg[NORMAL] = { 0.91, 0.96, 0.83 }
+ fg[ACTIVE] = { 0.47, 0, 0 }
+}
+widget "*cSelectionRectFill" style "cSelectionRectFill"
+
+style "cSelectionRectOutline"
+{
+ fg[NORMAL] = { 0.39, 0.39, 0.39 }
+ fg[ACTIVE] = { 0.59, 0, 0 }
+}
+widget "*cSelectionRectOutline" style "cSelectionRectOutline"
+
+style "cSelectionEndFill"
+{
+ fg[NORMAL] = { 0.39, 0.39, 0.39 }
+ fg[ACTIVE] = { 0.70, 0, 0 }
+}
+widget "*cSelectionEndFill" style "cSelectionEndFill"
+
+style "cSelectionEndOutline"
+{
+ fg[NORMAL] = { 0.39, 0.39, 0.39 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cSelectionEndOutline" style "cSelectionEndOutline"
+
+style "cSelectionStartFill"
+{
+ fg[NORMAL] = { 0.39, 0.39, 0.39 }
+ fg[ACTIVE] = { 0.70, 0, 0 }
+}
+widget "*cSelectionStartFill" style "cSelectionStartFill"
+
+style "cSelectionStartOutline"
+{
+ fg[NORMAL] = { 0.39, 0.39, 0.39 }
+ fg[ACTIVE] = { 1.0, 0, 0 }
+}
+widget "*cSelectionStartOutline" style "cSelectionStartOutline"
+
+style "cVestigialFrameFill"
+{
+ fg[NORMAL] = { 0.27, 0.00, 0.49 }
+ fg[ACTIVE] = { 0.06, 0, 0 }
+}
+widget "*cVestigialFrameFill" style "cVestigialFrameFill"
+
+style "cVestigialFrameOutline"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cVestigialFrameOutline" style "cVestigialFrameOutline"
+
+style "cTimeAxisFrameFill"
+{
+ fg[NORMAL] = { 0.27, 0.00, 0.49 }
+ fg[ACTIVE] = { 0.06, 0, 0 }
+}
+widget "*cTimeAxisFrameFill" style "cTimeAxisFrameFill"
+
+style "cTimeAxisFrameOutline"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cTimeAxisFrameOutline" style "cTimeAxisFrameOutline"
+
+style "cNameHighlightFill"
+{
+ fg[NORMAL] = { 0.00, 0.00, 1.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cNameHighlightFill" style "cNameHighlightFill"
+
+style "cNameHighlightOutline"
+{
+ fg[NORMAL] = { 0.49, 0.00, 1.00 }
+ fg[ACTIVE] = { 0.59, 0, 0 }
+}
+widget "*cNameHighlightOutline" style "cNameHighlightOutline"
+
+style "cFrameHandleStartFill"
+{
+ fg[NORMAL] = { 0.49, 0.00, 1.00 }
+ fg[ACTIVE] = { 0.59, 0, 0 }
+}
+widget "*cFrameHandleStartFill" style "cFrameHandleStartFill"
+
+style "cFrameHandleStartOutline"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cFrameHandleStartOutline" style "cFrameHandleStartOutline"
+
+style "cFrameHandleEndFill"
+{
+ fg[NORMAL] = { 0.49, 0.00, 1.00 }
+ fg[ACTIVE] = { 0.59, 0, 0 }
+}
+widget "*cFrameHandleEndFill" style "cFrameHandleEndFill"
+
+style "cFrameHandleEndOutline"
+{
+ fg[NORMAL] = { 0.00, 0.00, 0.00 }
+ fg[ACTIVE] = { 1.00, 0, 0 }
+}
+widget "*cFrameHandleEndOutline" style "cFrameHandleEndOutline"
+
+style "cTrimHandleLockedStart"
+{
+ fg[NORMAL] = { 0.92, 0.06, 0.06 }
+ fg[ACTIVE] = { 0.16, 0, 0 }
+}
+widget "*cTrimHandleLockedStart" style "cTrimHandleLockedStart"
+
+style "cTrimHandleLockedEnd"
+{
+ fg[NORMAL] = { 0.92, 0.06, 0.06 }
+ fg[ACTIVE] = { 0.16, 0, 0 }
+}
+widget "*cTrimHandleLockedEnd" style "cTrimHandleLockedEnd"
+
+style "cTrimHandleStart"
+{
+ fg[NORMAL] = { 0.10, 0.00, 1.00 }
+ fg[ACTIVE] = { 0.27, 0, 0 }
+}
+widget "*cTrimHandleStart" style "cTrimHandleStart"
+
+style "cTrimHandleEnd"
+{
+ fg[NORMAL] = { 0.10, 0.00, 1.00 }
+ fg[ACTIVE] = { 0.27, 0, 0 }
+}
+widget "*cTrimHandleEnd" style "cTrimHandleEnd"
diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc
new file mode 100644
index 0000000000..808e306e81
--- /dev/null
+++ b/gtk2_ardour/ardour_ui2.cc
@@ -0,0 +1,785 @@
+/*
+ Copyright (C) 1999 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <cerrno>
+#include <iostream>
+#include <cmath>
+
+#include <gtk--.h>
+#include <pbd/error.h>
+#include <pbd/basename.h>
+#include <pbd/fastlog.h>
+#include <gtkmmext/pix.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/click_box.h>
+#include <gtkmmext/tearoff.h>
+
+#include <ardour/audioengine.h>
+#include <ardour/ardour.h>
+#include <ardour/route.h>
+
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "audio_clock.h"
+#include "extra_bind.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace Gtkmmext;
+using namespace Gtk;
+using namespace SigC;
+
+int
+ARDOUR_UI::setup_windows ()
+{
+ using namespace Menu_Helpers;
+
+ if (create_editor ()) {
+ error << _("UI: cannot setup editor") << endmsg;
+ return -1;
+ }
+
+ if (create_mixer ()) {
+ error << _("UI: cannot setup mixer") << endmsg;
+ return -1;
+ }
+
+ if (create_meter_bridge ()) {
+ error << _("UI: cannot setup meter_bridge") << endmsg;
+ return -1;
+ }
+
+ /* all other dialogs are created conditionally */
+
+ we_have_dependents ();
+
+ setup_clock ();
+ setup_transport();
+ setup_adjustables ();
+ build_menu_bar ();
+
+ top_packer.pack_start (menu_bar_base, false, false);
+ top_packer.pack_start (transport_frame, false, false);
+
+ editor->add_toplevel_controls (top_packer);
+
+ return 0;
+}
+
+
+void
+ARDOUR_UI::setup_adjustables ()
+
+{
+ adjuster_table.set_homogeneous (true);
+
+ online_control_strings.push_back (_("MMC + Local"));
+ online_control_strings.push_back (_("MMC"));
+ online_control_strings.push_back (_("Local"));
+
+ online_control_button = new GlobalClickBox ("CONTROL",
+ online_control_strings);
+
+ online_control_button->adjustment.value_changed.connect(slot (*this,&ARDOUR_UI::control_methods_adjusted));
+
+ mmc_id_strings.push_back ("1");
+ mmc_id_strings.push_back ("2");
+ mmc_id_strings.push_back ("3");
+ mmc_id_strings.push_back ("4");
+ mmc_id_strings.push_back ("5");
+ mmc_id_strings.push_back ("6");
+ mmc_id_strings.push_back ("7");
+ mmc_id_strings.push_back ("8");
+ mmc_id_strings.push_back ("9");
+
+ mmc_id_button = new GlobalClickBox (_("MMC ID"), mmc_id_strings);
+
+ mmc_id_button->adjustment.value_changed.connect (slot (*this,&ARDOUR_UI::mmc_device_id_adjusted));
+
+ adjuster_table.attach (*online_control_button, 0, 2, 1, 2, GTK_FILL|GTK_EXPAND, 0, 5, 5);
+ adjuster_table.attach (*mmc_id_button, 2, 3, 1, 2, 0, 0, 5, 5);
+}
+
+#include "transport_xpms"
+
+void
+ARDOUR_UI::transport_stopped ()
+{
+ roll_button.set_active (false);
+ play_selection_button.set_active (false);
+ auto_loop_button.set_active (false);
+
+ shuttle_fract = 0;
+ shuttle_box.queue_draw ();
+
+ update_disk_space ();
+}
+
+static const double SHUTTLE_FRACT_SPEED1=0.48412291827; /* derived from A1,A2 */
+
+void
+ARDOUR_UI::transport_rolling ()
+{
+ if (session->get_play_range()) {
+
+ play_selection_button.set_active (true);
+ roll_button.set_active (false);
+ auto_loop_button.set_active (false);
+
+ } else if (session->get_auto_loop ()) {
+
+ auto_loop_button.set_active (true);
+ play_selection_button.set_active (false);
+ roll_button.set_active (false);
+
+ } else {
+
+ roll_button.set_active (true);
+ play_selection_button.set_active (false);
+ auto_loop_button.set_active (false);
+ }
+
+ /* reset shuttle controller */
+
+ shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */
+ shuttle_box.queue_draw ();
+}
+
+void
+ARDOUR_UI::transport_rewinding ()
+{
+ roll_button.set_active (true);
+ play_selection_button.set_active (false);
+ auto_loop_button.set_active (false);
+}
+
+void
+ARDOUR_UI::transport_forwarding ()
+{
+ roll_button.set_active (true);
+ play_selection_button.set_active (false);
+ auto_loop_button.set_active (false);
+}
+
+void
+ARDOUR_UI::setup_transport ()
+{
+ transport_tearoff = manage (new TearOff (transport_tearoff_hbox));
+ transport_tearoff->set_name ("TransportBase");
+
+ transport_hbox.pack_start (*transport_tearoff, true, false);
+
+ transport_base.set_name ("TransportBase");
+ transport_base.add (transport_hbox);
+
+ transport_frame.set_shadow_type (GTK_SHADOW_OUT);
+ transport_frame.set_name ("BaseFrame");
+ transport_frame.add (transport_base);
+
+ transport_tearoff->Detach.connect (bind (slot (*this, &ARDOUR_UI::detach_tearoff), static_cast<Gtk::Box*>(&top_packer),
+ static_cast<Gtk::Widget*>(&transport_frame)));
+ transport_tearoff->Attach.connect (bind (slot (*this, &ARDOUR_UI::reattach_tearoff), static_cast<Gtk::Box*> (&top_packer),
+ static_cast<Gtk::Widget*> (&transport_frame), 1));
+
+
+ goto_start_button.add (*(manage (new Gtk::Pixmap (start_xpm))));
+ goto_end_button.add (*(manage (new Gtk::Pixmap (end_xpm))));
+ roll_button.add (*(manage (new Gtk::Pixmap (arrow_xpm))));
+ stop_button.add (*(manage (new Gtk::Pixmap (stop_xpm))));
+ play_selection_button.add (*(manage (new Gtk::Pixmap (play_selection_xpm))));
+ rec_button.add (*(manage (new Gtk::Pixmap (rec_xpm))));
+ auto_loop_button.add (*(manage (new Gtk::Pixmap (loop_xpm))));
+
+ ARDOUR_UI::instance()->tooltips().set_tip (roll_button, _("Play from playhead"));
+ ARDOUR_UI::instance()->tooltips().set_tip (stop_button, _("Stop playback"));
+ ARDOUR_UI::instance()->tooltips().set_tip (play_selection_button, _("Play range/selection"));
+ ARDOUR_UI::instance()->tooltips().set_tip (goto_start_button, _("Go to start of session"));
+ ARDOUR_UI::instance()->tooltips().set_tip (goto_end_button, _("Go to end of session"));
+ ARDOUR_UI::instance()->tooltips().set_tip (auto_loop_button, _("Play loop range"));
+ ARDOUR_UI::instance()->tooltips().set_tip (auto_return_button, _("Return to last playback start when stopped"));
+ ARDOUR_UI::instance()->tooltips().set_tip (auto_play_button, _("Start playback after any locate"));
+ ARDOUR_UI::instance()->tooltips().set_tip (auto_input_button, _("Be sensible about input monitoring"));
+ ARDOUR_UI::instance()->tooltips().set_tip (punch_in_button, _("Start recording at auto-punch start"));
+ ARDOUR_UI::instance()->tooltips().set_tip (punch_out_button, _("Stop recording at auto-punch end"));
+ ARDOUR_UI::instance()->tooltips().set_tip (click_button, _("Enable/Disable audio click"));
+ ARDOUR_UI::instance()->tooltips().set_tip (follow_button, _("Enable/Disable follow playhead"));
+ ARDOUR_UI::instance()->tooltips().set_tip (shuttle_box, _("Shuttle speed control"));
+ ARDOUR_UI::instance()->tooltips().set_tip (shuttle_units_button, _("Select semitones or %%-age for speed display"));
+ ARDOUR_UI::instance()->tooltips().set_tip (shuttle_style_button, _("Select sprung or wheel behaviour"));
+ ARDOUR_UI::instance()->tooltips().set_tip (speed_display_box, _("Current transport speed"));
+
+ shuttle_box.set_flags (GTK_CAN_FOCUS);
+ shuttle_box.set_events (shuttle_box.get_events() | GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK|GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK);
+ shuttle_box.set_usize (100, 15);
+
+ shuttle_box.set_name ("TransportButton");
+ goto_start_button.set_name ("TransportButton");
+ goto_end_button.set_name ("TransportButton");
+ roll_button.set_name ("TransportButton");
+ stop_button.set_name ("TransportButton");
+ play_selection_button.set_name ("TransportButton");
+ rec_button.set_name ("TransportRecButton");
+ auto_loop_button.set_name ("TransportButton");
+ auto_return_button.set_name ("TransportButton");
+ auto_play_button.set_name ("TransportButton");
+ auto_input_button.set_name ("TransportButton");
+ punch_in_button.set_name ("TransportButton");
+ punch_out_button.set_name ("TransportButton");
+ click_button.set_name ("TransportButton");
+ follow_button.set_name ("TransportButton");
+
+ goto_start_button.unset_flags (GTK_CAN_FOCUS);
+ goto_end_button.unset_flags (GTK_CAN_FOCUS);
+ roll_button.unset_flags (GTK_CAN_FOCUS);
+ stop_button.unset_flags (GTK_CAN_FOCUS);
+ play_selection_button.unset_flags (GTK_CAN_FOCUS);
+ rec_button.unset_flags (GTK_CAN_FOCUS);
+ auto_loop_button.unset_flags (GTK_CAN_FOCUS);
+ auto_return_button.unset_flags (GTK_CAN_FOCUS);
+ auto_play_button.unset_flags (GTK_CAN_FOCUS);
+ auto_input_button.unset_flags (GTK_CAN_FOCUS);
+ punch_out_button.unset_flags (GTK_CAN_FOCUS);
+ punch_in_button.unset_flags (GTK_CAN_FOCUS);
+ click_button.unset_flags (GTK_CAN_FOCUS);
+ follow_button.unset_flags (GTK_CAN_FOCUS);
+
+ goto_start_button.set_events (goto_start_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ goto_end_button.set_events (goto_end_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ roll_button.set_events (roll_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ stop_button.set_events (stop_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ play_selection_button.set_events (play_selection_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ rec_button.set_events (rec_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ auto_loop_button.set_events (auto_loop_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ auto_return_button.set_events (auto_return_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ auto_play_button.set_events (auto_play_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ auto_input_button.set_events (auto_input_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ click_button.set_events (click_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ follow_button.set_events (click_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ punch_in_button.set_events (punch_in_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ punch_out_button.set_events (punch_out_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+
+ goto_start_button.clicked.connect (slot (*this,&ARDOUR_UI::transport_goto_start));
+ goto_end_button.clicked.connect (slot (*this,&ARDOUR_UI::transport_goto_end));
+
+ roll_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_roll));
+ play_selection_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_play_selection));
+ auto_loop_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_loop));
+
+ stop_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_stop));
+ rec_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_record));
+
+ shuttle_box.button_press_event.connect (slot (*this, &ARDOUR_UI::shuttle_box_button_press));
+ shuttle_box.button_release_event.connect (slot (*this, &ARDOUR_UI::shuttle_box_button_release));
+ shuttle_box.motion_notify_event.connect (slot (*this, &ARDOUR_UI::shuttle_box_motion));
+ shuttle_box.expose_event.connect (slot (*this, &ARDOUR_UI::shuttle_box_expose));
+
+ /* clocks, etc. */
+
+ ARDOUR_UI::Clock.connect (bind (slot (primary_clock, &AudioClock::set), false));
+ ARDOUR_UI::Clock.connect (bind (slot (secondary_clock, &AudioClock::set), false));
+
+ primary_clock.set_mode (AudioClock::SMPTE);
+ primary_clock.set_name ("TransportClockDisplay");
+ secondary_clock.set_mode (AudioClock::BBT);
+ secondary_clock.set_name ("TransportClockDisplay");
+
+
+ primary_clock.ValueChanged.connect (slot (*this, &ARDOUR_UI::primary_clock_value_changed));
+ secondary_clock.ValueChanged.connect (slot (*this, &ARDOUR_UI::secondary_clock_value_changed));
+
+ ARDOUR_UI::instance()->tooltips().set_tip (primary_clock, _("Primary clock"));
+ ARDOUR_UI::instance()->tooltips().set_tip (secondary_clock, _("secondary clock"));
+
+ /* options */
+
+ auto_return_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_auto_return));
+ auto_play_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_auto_play));
+ auto_input_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_auto_input));
+ click_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_click));
+ follow_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_follow));
+ punch_in_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_punch_in));
+ punch_out_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_punch_out));
+
+ preroll_button.unset_flags (GTK_CAN_FOCUS);
+ preroll_button.set_events (preroll_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ preroll_button.set_name ("TransportButton");
+
+ postroll_button.unset_flags (GTK_CAN_FOCUS);
+ postroll_button.set_events (postroll_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ postroll_button.set_name ("TransportButton");
+
+ preroll_clock.set_mode (AudioClock::MinSec);
+ preroll_clock.set_name ("TransportClockDisplay");
+ postroll_clock.set_mode (AudioClock::MinSec);
+ postroll_clock.set_name ("TransportClockDisplay");
+
+ /* alerts */
+
+ /* CANNOT bind these to clicked or toggled, must use pressed or released */
+
+ solo_alert_button.set_name ("TransportSoloAlert");
+ solo_alert_button.pressed.connect (slot (*this,&ARDOUR_UI::solo_alert_toggle));
+ auditioning_alert_button.set_name ("TransportAuditioningAlert");
+ auditioning_alert_button.pressed.connect (slot (*this,&ARDOUR_UI::audition_alert_toggle));
+
+ alert_box.pack_start (solo_alert_button);
+ alert_box.pack_start (auditioning_alert_button);
+
+ transport_tearoff_hbox.set_border_width (5);
+
+ transport_tearoff_hbox.pack_start (goto_start_button, false, false);
+ transport_tearoff_hbox.pack_start (goto_end_button, false, false);
+
+ Gtk::Frame* sframe = manage (new Frame);
+ Gtk::VBox* svbox = manage (new VBox);
+ Gtk::HBox* shbox = manage (new HBox);
+
+ sframe->set_shadow_type (GTK_SHADOW_IN);
+ sframe->add (shuttle_box);
+
+ shuttle_box.set_name (X_("ShuttleControl"));
+
+ speed_display_box.add (speed_display_label);
+ set_usize_to_display_given_text (speed_display_box, _("stopped"), 2, 2);
+ speed_display_box.set_name (X_("ShuttleDisplay"));
+
+ shuttle_units_button.set_name (X_("ShuttleButton"));
+ shuttle_units_button.clicked.connect (slot (*this, &ARDOUR_UI::shuttle_unit_clicked));
+
+ shuttle_style_button.set_name (X_("ShuttleButton"));
+ shuttle_style_button.clicked.connect (slot (*this, &ARDOUR_UI::shuttle_style_clicked));
+
+ Gtk::Frame* sdframe = manage (new Frame);
+
+ sdframe->set_shadow_type (GTK_SHADOW_IN);
+ sdframe->add (speed_display_box);
+
+ shbox->pack_start (*sdframe, false, false);
+ shbox->pack_start (shuttle_units_button, true, true);
+ shbox->pack_start (shuttle_style_button, false, false);
+
+ svbox->pack_start (*sframe, false, false);
+ svbox->pack_start (*shbox, false, false);
+
+ transport_tearoff_hbox.pack_start (*svbox, false, false, 5);
+
+ transport_tearoff_hbox.pack_start (auto_loop_button, false, false);
+ transport_tearoff_hbox.pack_start (play_selection_button, false, false);
+ transport_tearoff_hbox.pack_start (roll_button, false, false);
+ transport_tearoff_hbox.pack_start (stop_button, false, false);
+ transport_tearoff_hbox.pack_start (rec_button, false, false, 10);
+
+ transport_tearoff_hbox.pack_start (primary_clock, false, false, 5);
+ transport_tearoff_hbox.pack_start (secondary_clock, false, false, 5);
+
+ transport_tearoff_hbox.pack_start (punch_in_button, false, false);
+ transport_tearoff_hbox.pack_start (punch_out_button, false, false);
+ transport_tearoff_hbox.pack_start (auto_input_button, false, false);
+ transport_tearoff_hbox.pack_start (auto_return_button, false, false);
+ transport_tearoff_hbox.pack_start (auto_play_button, false, false);
+ transport_tearoff_hbox.pack_start (click_button, false, false);
+ transport_tearoff_hbox.pack_start (follow_button, false, false);
+
+ /* desensitize */
+
+ set_transport_sensitivity (false);
+
+ /* catch up with editor state */
+
+ follow_changed ();
+
+// transport_tearoff_hbox.pack_start (preroll_button, false, false);
+// transport_tearoff_hbox.pack_start (preroll_clock, false, false);
+
+// transport_tearoff_hbox.pack_start (postroll_button, false, false);
+// transport_tearoff_hbox.pack_start (postroll_clock, false, false);
+
+ transport_tearoff_hbox.pack_start (alert_box, false, false, 5);
+}
+
+void
+ARDOUR_UI::setup_clock ()
+{
+ ARDOUR_UI::Clock.connect (bind (slot (big_clock, &AudioClock::set), false));
+
+ big_clock_window = new BigClockWindow;
+
+ big_clock_window->set_border_width (0);
+ big_clock_window->add (big_clock);
+ big_clock_window->set_title (_("ardour: clock"));
+
+ big_clock_window->delete_event.connect (bind (slot (just_hide_it), static_cast<Gtk::Window*>(big_clock_window)));
+ big_clock_window->realize.connect (slot (*this, &ARDOUR_UI::big_clock_realize));
+ big_clock_window->size_allocate.connect (slot (*this, &ARDOUR_UI::big_clock_size_event));
+
+ big_clock_window->Hiding.connect (slot (*this, &ARDOUR_UI::big_clock_hiding));
+}
+
+void
+ARDOUR_UI::big_clock_size_event (GtkAllocation *alloc)
+{
+ return;
+}
+
+void
+ARDOUR_UI::big_clock_realize ()
+{
+ big_clock_window->get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH|GDK_DECOR_MAXIMIZE|GDK_DECOR_MINIMIZE));
+}
+
+void
+ARDOUR_UI::detach_tearoff (Gtk::Box* b, Gtk::Widget* w)
+{
+ editor->ensure_float (*transport_tearoff->tearoff_window());
+ b->remove (*w);
+}
+
+void
+ARDOUR_UI::reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n)
+{
+ b->pack_start (*w);
+ b->reorder_child (*w, n);
+}
+
+void
+ARDOUR_UI::soloing_changed (bool onoff)
+{
+ if (solo_alert_button.get_active() != onoff) {
+ solo_alert_button.set_active (onoff);
+ }
+}
+
+void
+ARDOUR_UI::_auditioning_changed (bool onoff)
+{
+ if (auditioning_alert_button.get_active() != onoff) {
+ auditioning_alert_button.set_active (onoff);
+ set_transport_sensitivity (!onoff);
+ }
+}
+
+void
+ARDOUR_UI::auditioning_changed (bool onoff)
+{
+ Gtkmmext::UI::instance()->call_slot(bind (slot (*this, &ARDOUR_UI::_auditioning_changed), onoff));
+}
+
+void
+ARDOUR_UI::audition_alert_toggle ()
+{
+ if (session) {
+ session->cancel_audition();
+ }
+}
+
+void
+ARDOUR_UI::solo_alert_toggle ()
+{
+ if (session) {
+ session->set_all_solo (!session->soloing());
+ }
+}
+
+void
+ARDOUR_UI::solo_blink (bool onoff)
+{
+ if (session == 0) {
+ return;
+ }
+
+ if (session->soloing()) {
+ if (onoff) {
+ solo_alert_button.set_state (GTK_STATE_ACTIVE);
+ } else {
+ solo_alert_button.set_state (GTK_STATE_NORMAL);
+ }
+ } else {
+ solo_alert_button.set_active (false);
+ solo_alert_button.set_state (GTK_STATE_NORMAL);
+ }
+}
+
+void
+ARDOUR_UI::audition_blink (bool onoff)
+{
+ if (session == 0) {
+ return;
+ }
+
+ if (session->is_auditioning()) {
+ if (onoff) {
+ auditioning_alert_button.set_state (GTK_STATE_ACTIVE);
+ } else {
+ auditioning_alert_button.set_state (GTK_STATE_NORMAL);
+ }
+ } else {
+ auditioning_alert_button.set_active (false);
+ auditioning_alert_button.set_state (GTK_STATE_NORMAL);
+ }
+}
+
+
+gint
+ARDOUR_UI::shuttle_box_button_press (GdkEventButton* ev)
+{
+ if (!session) {
+ return TRUE;
+ }
+
+ switch (ev->button) {
+ case 1:
+ Gtk::Main::grab_add (shuttle_box);
+ shuttle_grabbed = true;
+ mouse_shuttle (ev->x, true);
+ break;
+
+ case 2:
+ case 3:
+ return TRUE;
+ break;
+
+ case 4:
+ break;
+ case 5:
+ break;
+ }
+
+ return TRUE;
+}
+
+gint
+ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev)
+{
+ if (!session) {
+ return TRUE;
+ }
+
+ switch (ev->button) {
+ case 1:
+ mouse_shuttle (ev->x, true);
+ shuttle_grabbed = false;
+ Gtk::Main::grab_remove (shuttle_box);
+ if (shuttle_behaviour == Sprung) {
+ shuttle_fract = SHUTTLE_FRACT_SPEED1;
+ session->request_transport_speed (1.0);
+ shuttle_box.queue_draw ();
+ }
+ return TRUE;
+
+ case 2:
+ if (session->transport_rolling()) {
+ shuttle_fract = SHUTTLE_FRACT_SPEED1;
+ session->request_transport_speed (1.0);
+ } else {
+ shuttle_fract = 0;
+ }
+ shuttle_box.queue_draw ();
+ return TRUE;
+
+ case 3:
+ return TRUE;
+
+ case 4:
+ shuttle_fract += 0.005;
+ break;
+ case 5:
+ shuttle_fract -= 0.005;
+ break;
+ }
+
+ use_shuttle_fract (true);
+
+ return TRUE;
+}
+
+gint
+ARDOUR_UI::shuttle_box_motion (GdkEventMotion* ev)
+{
+ if (!session || !shuttle_grabbed) {
+ return TRUE;
+ }
+
+ return mouse_shuttle (ev->x, false);
+}
+
+gint
+ARDOUR_UI::mouse_shuttle (double x, bool force)
+{
+ double half_width = shuttle_box.width() / 2.0;
+ double distance = x - half_width;
+
+ if (distance > 0) {
+ distance = min (distance, half_width);
+ } else {
+ distance = max (distance, -half_width);
+ }
+
+ shuttle_fract = distance / half_width;
+ use_shuttle_fract (force);
+ return TRUE;
+}
+
+void
+ARDOUR_UI::use_shuttle_fract (bool force)
+{
+ struct timeval now;
+ struct timeval diff;
+
+ /* do not attempt to submit a motion-driven transport speed request
+ more than once per process cycle.
+ */
+
+ gettimeofday (&now, 0);
+ timersub (&now, &last_shuttle_request, &diff);
+
+ if (!force && (diff.tv_usec + (diff.tv_sec * 1000000)) < engine->usecs_per_cycle()) {
+ return;
+ }
+
+ last_shuttle_request = now;
+
+ bool neg = (shuttle_fract < 0.0);
+
+ double fract = 1 - sqrt (1 - (shuttle_fract * shuttle_fract)); // Formula A1
+
+ if (neg) {
+ fract = -fract;
+ }
+
+ session->request_transport_speed (8.0 * fract); // Formula A2
+ shuttle_box.queue_draw ();
+}
+
+gint
+ARDOUR_UI::shuttle_box_expose (GdkEventExpose* event)
+{
+ gint x;
+ Gdk_Window win (shuttle_box.get_window());
+
+ /* redraw the background */
+
+ win.draw_rectangle (shuttle_box.get_style()->get_bg_gc (shuttle_box.get_state()),
+ true,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+
+ x = (gint) floor ((shuttle_box.width() / 2.0) + (0.5 * (shuttle_box.width() * shuttle_fract)));
+
+ /* draw line */
+
+ win.draw_line (shuttle_box.get_style()->get_fg_gc (shuttle_box.get_state()),
+ x,
+ 0,
+ x,
+ shuttle_box.height());
+ return TRUE;
+}
+
+void
+ARDOUR_UI::shuttle_style_clicked ()
+{
+ shuttle_style_menu.popup (1, 0);
+}
+
+void
+ARDOUR_UI::shuttle_unit_clicked ()
+{
+ shuttle_unit_menu.popup (1, 0);
+}
+
+void
+ARDOUR_UI::set_shuttle_units (ShuttleUnits u)
+{
+ switch ((shuttle_units = u)) {
+ case Percentage:
+ static_cast<Gtk::Label*>(shuttle_units_button.get_child())->set_text ("% ");
+ break;
+ case Semitones:
+ static_cast<Gtk::Label*>(shuttle_units_button.get_child())->set_text (_("st"));
+ break;
+ }
+}
+
+void
+ARDOUR_UI::set_shuttle_behaviour (ShuttleBehaviour b)
+{
+ switch ((shuttle_behaviour = b)) {
+ case Sprung:
+ static_cast<Gtk::Label*>(shuttle_style_button.get_child())->set_text (_("sprung"));
+ shuttle_fract = 0.0;
+ shuttle_box.queue_draw ();
+ if (session) {
+ if (session->transport_rolling()) {
+ shuttle_fract = SHUTTLE_FRACT_SPEED1;
+ session->request_transport_speed (1.0);
+ }
+ }
+ break;
+ case Wheel:
+ static_cast<Gtk::Label*>(shuttle_style_button.get_child())->set_text (_("wheel"));
+ break;
+ }
+}
+
+void
+ARDOUR_UI::update_speed_display ()
+{
+ if (!session) {
+ speed_display_label.set_text (_("stopped"));
+ return;
+ }
+
+ char buf[32];
+ float x = session->transport_speed ();
+
+ if (x != 0) {
+ if (shuttle_units == Percentage) {
+ snprintf (buf, sizeof (buf), "%.4f", x);
+ } else {
+ if (x < 0) {
+ snprintf (buf, sizeof (buf), "< %.1f", 12.0 * fast_log2 (-x));
+ } else {
+ snprintf (buf, sizeof (buf), "> %.1f", 12.0 * fast_log2 (x));
+ }
+ }
+ speed_display_label.set_text (buf);
+ } else {
+ speed_display_label.set_text (_("stopped"));
+ }
+}
+
+void
+ARDOUR_UI::set_transport_sensitivity (bool yn)
+{
+ goto_start_button.set_sensitive (yn);
+ goto_end_button.set_sensitive (yn);
+ roll_button.set_sensitive (yn);
+ stop_button.set_sensitive (yn);
+ play_selection_button.set_sensitive (yn);
+ rec_button.set_sensitive (yn);
+ auto_loop_button.set_sensitive (yn);
+ shuttle_box.set_sensitive (yn);
+}
diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc
new file mode 100644
index 0000000000..7464a67ce2
--- /dev/null
+++ b/gtk2_ardour/ardour_ui_dependents.cc
@@ -0,0 +1,109 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+/* this file exists solely to break compilation dependencies that
+ would connect changes to the mixer or editor objects.
+*/
+
+#include <cstdio>
+#include <pbd/error.h>
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "mixer_ui.h"
+#include "meter_bridge.h"
+#include "keyboard.h"
+#include "route_params_ui.h"
+#include "i18n.h"
+
+using namespace SigC;
+
+
+namespace ARDOUR {
+ class Session;
+ class Route;
+}
+
+void
+ARDOUR_UI::shutdown ()
+{
+ if (session) {
+ delete session;
+ session = 0;
+ }
+
+}
+
+void
+ARDOUR_UI::we_have_dependents ()
+{
+ setup_keybindings ();
+}
+
+void
+ARDOUR_UI::setup_keybindings ()
+{
+ /* install default bindings */
+
+ KeyboardTarget *defaults = new KeyboardTarget (editor->window(), X_("default"));
+
+ XMLNode* keynode = ARDOUR::Config->get_keys();
+
+ if (keynode != 0) {
+ defaults->set_binding_state (*keynode);
+ editor->set_binding_state (*keynode);
+ mixer->set_binding_state (*keynode);
+ meter_bridge->set_binding_state (*keynode);
+ } else {
+ error << _("keyboard_target: error setting binding state: invalid node") << endmsg;
+ }
+
+ /* use the default keyboard target for now */
+
+ keyboard->set_default_target (defaults);
+}
+
+void
+ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s)
+{
+ editor->connect_to_session (s);
+ mixer->connect_to_session (s);
+
+ meter_bridge->set_session (s);
+}
+
+void
+ARDOUR_UI::goto_editor_window ()
+{
+ editor->show_window ();
+ editor->window().get_window().raise ();
+}
+void
+ARDOUR_UI::goto_mixer_window ()
+{
+ mixer->show_window ();
+ mixer->get_window().raise ();
+}
+
+gint
+ARDOUR_UI::exit_on_main_window_close (GdkEventAny *ev)
+{
+ finish();
+ return TRUE;
+}
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
new file mode 100644
index 0000000000..744a9bd031
--- /dev/null
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -0,0 +1,454 @@
+/*
+ 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.
+
+*/
+
+/* This file contains any ARDOUR_UI methods that require knowledge of
+ the various dialog boxes, and exists so that no compilation dependency
+ exists between the main ARDOUR_UI modules and their respective classes.
+ This is to cut down on the compile times. It also helps with my sanity.
+*/
+
+#include <ardour/session.h>
+
+#include "ardour_ui.h"
+#include "mixer_ui.h"
+#include "meter_bridge.h"
+#include "connection_editor.h"
+#include "public_editor.h"
+#include "option_editor.h"
+#include "location_ui.h"
+#include "route_params_ui.h"
+#include "library_ui.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+
+void
+ARDOUR_UI::connect_to_session (Session *s)
+{
+ session = s;
+
+ session->HaltOnXrun.connect (slot (*this, &ARDOUR_UI::halt_on_xrun_message));
+
+ /* sensitize menu bar options that are now valid */
+
+// save_as_item->set_sensitive (true);
+ save_template_item->set_sensitive (true);
+ snapshot_item->set_sensitive (true);
+ save_item->set_sensitive (true);
+ add_track_item->set_sensitive (true);
+ export_item->set_sensitive (true);
+ close_item->set_sensitive (true);
+ locations_dialog_check->set_sensitive (true);
+ route_params_check->set_sensitive (true);
+ connection_editor_check->set_sensitive (true);
+
+ cleanup_item->set_sensitive (true);
+
+ /* sensitize transport bar */
+
+ goto_start_button.set_sensitive (true);
+ goto_end_button.set_sensitive (true);
+ roll_button.set_sensitive (true);
+ stop_button.set_sensitive (true);
+ play_selection_button.set_sensitive (true);
+ rec_button.set_sensitive (true);
+ auto_loop_button.set_sensitive (true);
+ shuttle_box.set_sensitive (true);
+
+ /* <CMT Additions> */
+ if (image_compositor_item) {
+ image_compositor_item->set_sensitive(true) ;
+ }
+ /* </CMT Additions> */
+
+
+ if (session->n_diskstreams()) {
+ // meter_bridge_dialog_check->set_sensitive (true);
+ } else {
+ session->DiskStreamAdded.connect (slot (*this, &ARDOUR_UI::diskstream_added));
+ }
+
+ if (connection_editor) {
+ connection_editor->set_session (s);
+ }
+
+ if (location_ui) {
+ location_ui->set_session(s);
+ }
+
+ if (route_params) {
+ route_params->set_session (s);
+ }
+
+ if (option_editor) {
+ option_editor->set_session (s);
+ }
+
+
+ Blink.connect (slot (*this, &ARDOUR_UI::transport_rec_enable_blink));
+ Blink.connect (slot (*this, &ARDOUR_UI::solo_blink));
+ Blink.connect (slot (*this, &ARDOUR_UI::audition_blink));
+
+ /* these are all need to be handled in an RT-safe and MT way, so don't
+ do any GUI work, just queue it for handling by the GUI thread.
+ */
+
+ session->TransportStateChange.connect (slot (*this, &ARDOUR_UI::queue_transport_change));
+ session->ControlChanged.connect (slot (*this, &ARDOUR_UI::queue_map_control_change));
+
+ /* alert the user to these things happening */
+
+ session->AuditionActive.connect (slot (*this, &ARDOUR_UI::auditioning_changed));
+ session->SoloActive.connect (slot (*this, &ARDOUR_UI::soloing_changed));
+
+ solo_alert_button.set_active (session->soloing());
+
+ /* can't be auditioning here */
+
+ primary_clock.set_session (s);
+ secondary_clock.set_session (s);
+ big_clock.set_session (s);
+ preroll_clock.set_session (s);
+ postroll_clock.set_session (s);
+
+ /* Clocks are on by default after we are connected to a session, so show that here.
+ */
+
+ map_button_state ();
+
+ connect_dependents_to_session (s);
+
+ start_clocking ();
+ start_blinking ();
+
+ if (editor) {
+ editor->window().realize();
+ }
+
+ transport_stopped ();
+
+ second_connection = Main::timeout.connect (slot (*this, &ARDOUR_UI::every_second), 1000);
+ point_one_second_connection = Main::timeout.connect (slot (*this, &ARDOUR_UI::every_point_one_seconds), 100);
+ point_zero_one_second_connection = Main::timeout.connect (slot (*this, &ARDOUR_UI::every_point_zero_one_seconds), 40);
+}
+
+int
+ARDOUR_UI::unload_session ()
+{
+ if (session && session->dirty()) {
+ switch (ask_about_saving_session (_("close session"))) {
+ case -1:
+ return 1;
+
+ case 1:
+ session->save_state ("");
+ break;
+ }
+ }
+
+ second_connection.disconnect ();
+ point_one_second_connection.disconnect ();
+ point_zero_one_second_connection.disconnect();
+
+ /* desensitize menu bar options that are now invalid */
+
+// save_as_item->set_sensitive (false);
+ save_template_item->set_sensitive (false);
+ snapshot_item->set_sensitive (false);
+ save_item->set_sensitive (false);
+ add_track_item->set_sensitive (false);
+ export_item->set_sensitive (false);
+ close_item->set_sensitive (false);
+ // meter_bridge_dialog_check->set_sensitive (false);
+ connection_editor_check->set_sensitive (false);
+ locations_dialog_check->set_sensitive (false);
+ // meter_bridge_dialog_check->set_active(false);
+ connection_editor_check->set_active(false);
+ locations_dialog_check->set_active(false);
+ route_params_check->set_sensitive (false);
+
+ /* desensitize transport bar */
+
+ goto_start_button.set_sensitive (false);
+ goto_end_button.set_sensitive (false);
+ roll_button.set_sensitive (false);
+ stop_button.set_sensitive (false);
+ play_selection_button.set_sensitive (false);
+ rec_button.set_sensitive (false);
+ auto_loop_button.set_sensitive (false);
+ shuttle_box.set_sensitive (false);
+
+ stop_blinking ();
+ stop_clocking ();
+
+ /* drop everything attached to the blink signal */
+
+ Blink.clear ();
+
+ primary_clock.set_session (0);
+ secondary_clock.set_session (0);
+ big_clock.set_session (0);
+ preroll_clock.set_session (0);
+ postroll_clock.set_session (0);
+
+ if (option_editor) {
+ option_editor->set_session (0);
+ }
+
+ if (mixer) {
+ mixer->hide_all ();
+ }
+
+ delete session;
+ session = 0;
+
+ update_buffer_load ();
+ // update_disk_rate ();
+
+ return 0;
+}
+
+int
+ARDOUR_UI::create_meter_bridge ()
+{
+ if (meter_bridge == 0) {
+ meter_bridge = new MeterBridge ();
+ meter_bridge->Hiding.connect (slot (*this, &ARDOUR_UI::meter_bridge_hiding));
+ }
+ return 0;
+}
+
+void
+ARDOUR_UI::meter_bridge_hiding()
+{
+ // meter_bridge_dialog_check->set_active(false);
+}
+
+int
+ARDOUR_UI::create_connection_editor ()
+{
+ if (connection_editor == 0) {
+ connection_editor = new ConnectionEditor ();
+ connection_editor->Hiding.connect (slot (*this, &ARDOUR_UI::connection_editor_hiding));
+ }
+
+ if (session) {
+ connection_editor->set_session (session);
+ }
+
+ return 0;
+}
+
+void
+ARDOUR_UI::toggle_connection_editor ()
+{
+ if (create_connection_editor()) {
+ return;
+ }
+
+ if (connection_editor->within_hiding()) {
+ return;
+ }
+
+
+ if (connection_editor_check->get_active()){
+ connection_editor->show_all();
+ } else {
+ connection_editor->hide_all();
+ }
+}
+
+void
+ARDOUR_UI::connection_editor_hiding()
+{
+ connection_editor_check->set_active(false);
+}
+
+void
+ARDOUR_UI::big_clock_hiding()
+{
+ big_clock_check->set_active(false);
+}
+
+void
+ARDOUR_UI::toggle_big_clock_window ()
+{
+ if (big_clock_window->within_hiding()) {
+ return;
+ }
+
+ if (big_clock_window->is_visible()) {
+ big_clock_window->hide_all ();
+ } else {
+ big_clock_window->show_all ();
+ }
+}
+
+void
+ARDOUR_UI::toggle_options_window ()
+{
+ if (option_editor == 0) {
+ option_editor = new OptionEditor (*this, *editor, *mixer);
+ option_editor->Hiding.connect(slot(*this, &ARDOUR_UI::option_hiding));
+ option_editor->set_session (session);
+ } else if (option_editor->within_hiding()) {
+ return;
+ }
+
+ if (option_editor->is_visible()) {
+ option_editor->hide_all ();
+ } else {
+ option_editor->show_all ();
+ }
+}
+
+void
+ARDOUR_UI::option_hiding ()
+{
+ options_window_check->set_active(false);
+}
+
+void
+ARDOUR_UI::toggle_auto_input ()
+
+{
+ toggle_some_session_state (auto_input_button,
+ &Session::get_auto_input,
+ &Session::set_auto_input);
+
+ meter_bridge->clear_all_meters ();
+}
+
+void
+ARDOUR_UI::toggle_metering ()
+{
+#if 0
+ if (global_meter_button.get_active()) {
+ meter_bridge->toggle_metering ();
+ }
+#endif
+}
+
+int
+ARDOUR_UI::create_location_ui ()
+{
+ if (location_ui == 0) {
+ location_ui = new LocationUI ();
+ location_ui->set_session (session);
+ location_ui->Hiding.connect (slot (*this, &ARDOUR_UI::location_ui_hiding));
+ }
+ return 0;
+}
+
+void
+ARDOUR_UI::toggle_location_window ()
+{
+ if (create_location_ui()) {
+ return;
+ }
+
+ if (location_ui->within_hiding()) {
+ return;
+ }
+
+ if (location_ui->is_visible()) {
+ location_ui->hide_all();
+ } else {
+ location_ui->show_all();
+ }
+}
+
+void
+ARDOUR_UI::location_ui_hiding()
+{
+ locations_dialog_check->set_active(false);
+}
+
+int
+ARDOUR_UI::create_route_params ()
+{
+ if (route_params == 0) {
+ route_params = new RouteParams_UI (*engine);
+ route_params->set_session (session);
+ route_params->Hiding.connect (slot (*this, &ARDOUR_UI::route_params_hiding));
+ }
+ return 0;
+}
+
+void
+ARDOUR_UI::toggle_route_params_window ()
+{
+ if (create_route_params ()) {
+ return;
+ }
+
+ if (route_params->within_hiding()) {
+ return;
+ }
+
+ if (route_params->is_visible ()) {
+ route_params->hide_all ();
+ } else {
+ route_params->show_all ();
+ }
+}
+
+void
+ARDOUR_UI::route_params_hiding ()
+{
+ route_params_check->set_active (false);
+}
+
+SoundFileSelector&
+ARDOUR_UI::get_sfdb_window ()
+{
+ if (sfdb_window == 0) {
+ sfdb_window = new SoundFileSelector ();
+ sfdb_window->Hiding.connect (slot (*this, &ARDOUR_UI::sfdb_hiding));
+ sfdb_window->hide_all ();
+ }
+
+ return *sfdb_window;
+}
+
+void
+ARDOUR_UI::toggle_sfdb_window ()
+{
+ get_sfdb_window ();
+
+ if (sfdb_window->within_hiding()) {
+ return;
+ }
+
+ if (sfdb_window->is_visible ()) {
+ sfdb_window->hide_all ();
+ } else {
+ sfdb_window->show_all ();
+ sfdb_window->hide_import_stuff();
+ }
+}
+
+void
+ARDOUR_UI::sfdb_hiding ()
+{
+ sfdb_check->set_active (false);
+}
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
new file mode 100644
index 0000000000..dab51b6349
--- /dev/null
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -0,0 +1,315 @@
+/*
+ Copyright (C) 20002-2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+/* This file contains any ARDOUR_UI methods that require knowledge of
+ the editor, and exists so that no compilation dependency exists
+ between the main ARDOUR_UI modules and the PublicEditor class. This
+ is to cut down on the nasty compile times for both these classes.
+*/
+
+#include <pbd/pathscanner.h>
+
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "audio_clock.h"
+#include "editor.h"
+
+#include <ardour/session.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+
+int
+ARDOUR_UI::create_editor ()
+
+{
+ try {
+ editor = new Editor (*engine);
+ }
+
+ catch (failed_constructor& err) {
+ return -1;
+ }
+
+ editor->DisplayControlChanged.connect (slot (*this, &ARDOUR_UI::editor_display_control_changed));
+
+ return 0;
+}
+
+void
+ARDOUR_UI::build_menu_bar ()
+
+{
+ using namespace Menu_Helpers;
+
+ menu_bar.set_name ("MainMenuBar");
+
+ MenuList& items = menu_bar.items();
+
+ /* file menu */
+
+ Menu *session_menu = manage (new Menu);
+ MenuList& session_items = session_menu->items();
+ session_menu->set_name ("ArdourContextMenu");
+
+ session_items.push_back (MenuElem (_("New"), bind (slot (*this, &ARDOUR_UI::new_session), false, string ())));
+ session_items.push_back (MenuElem (_("Open"), slot (*this, &ARDOUR_UI::open_session)));
+ session_items.push_back (MenuElem (_("Recent"), slot (*this, &ARDOUR_UI::open_recent_session)));
+ session_items.push_back (MenuElem (_("Close"), slot (*this, &ARDOUR_UI::close_session)));
+ close_item = session_items.back();
+ close_item->set_sensitive (false);
+
+ session_items.push_back (SeparatorElem());
+
+ session_items.push_back (MenuElem (_("Add Track/Bus"), slot (*this, &ARDOUR_UI::add_route)));
+ add_track_item = session_items.back ();
+ add_track_item->set_sensitive (false);
+
+ session_items.push_back (SeparatorElem());
+
+ /* <CMT Additions> */
+
+ PathScanner scanner;
+ vector<string*>* results = scanner (getenv ("PATH"), "AniComp", false, false);
+
+ if (results && !results->empty()) {
+ Menu* image_compositor_menu = manage(new Menu());
+ MenuList& image_compositor_items = image_compositor_menu->items();
+ image_compositor_menu->set_name ("ArdourContextMenu");
+ image_compositor_items.push_back(MenuElem (_("Connect"), (slot (editor, &PublicEditor::connect_to_image_compositor)))) ;
+ session_items.push_back(MenuElem (_("Image Compositor"), *image_compositor_menu)) ;
+ image_compositor_item = session_items.back() ;
+ image_compositor_item->set_sensitive(false) ;
+ session_items.push_back (SeparatorElem());
+ } else {
+ image_compositor_item = 0;
+ }
+
+ if (results) {
+ delete results;
+ }
+
+ /* </CMT Additions> */
+
+ session_items.push_back (MenuElem (_("Save"), bind (slot (*this, &ARDOUR_UI::save_state), string(""))));
+ save_item = session_items.back();
+ save_item->set_sensitive (false);
+
+ session_items.push_back (MenuElem (_("Snapshot"), slot (*this, &ARDOUR_UI::snapshot_session)));
+ snapshot_item = session_items.back();
+ snapshot_item->set_sensitive (false);
+/*
+ session_items.push_back (MenuElem (_("Save as...")));
+ save_as_item = session_items.back();
+ save_as_item->set_sensitive (false);
+*/
+ session_items.push_back (MenuElem (_("Save Template..."), slot (*this, &ARDOUR_UI::save_template)));
+ save_template_item = session_items.back();
+ save_template_item->set_sensitive (false);
+
+ Menu *export_menu = manage (new Menu);
+ MenuList& export_items = export_menu->items();
+ export_menu->set_name ("ArdourContextMenu");
+ export_items.push_back (MenuElem (_("Export session to audiofile..."), slot (*editor, &PublicEditor::export_session)));
+ export_items.push_back (MenuElem (_("Export range to audiofile..."), slot (*editor, &PublicEditor::export_selection)));
+ // export_items.back()->set_sensitive (false);
+
+ session_items.push_back (MenuElem (_("Export"), *export_menu));
+ export_item = session_items.back();
+ export_item->set_sensitive (false);
+
+ session_items.push_back (SeparatorElem());
+
+ Menu *cleanup_menu = manage (new Menu);
+ MenuList& cleanup_items = cleanup_menu->items();
+ cleanup_menu->set_name ("ArdourContextMenu");
+ cleanup_items.push_back (MenuElem (_("Cleanup unused sources"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::cleanup)));
+ cleanup_items.push_back (MenuElem (_("Flush wastebasket"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::flush_trash)));
+
+ session_items.push_back (MenuElem (_("Cleanup"), *cleanup_menu));
+ cleanup_item = session_items.back ();
+ cleanup_item->set_sensitive (false);
+
+ session_items.push_back (SeparatorElem());
+
+ session_items.push_back (MenuElem (_("Quit"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::finish)));
+
+ items.push_back (MenuElem (_("Session"), *session_menu));
+
+ /* edit menu; the editor is responsible for the contents */
+
+ Menu *edit_menu = manage (new Menu);
+ editor->set_edit_menu (*edit_menu);
+ items.push_back (MenuElem (_("Edit"), *edit_menu));
+ edit_menu->set_name ("ArdourContextMenu");
+
+ /* JACK menu for controlling ... JACK */
+
+ Menu* jack_menu = manage (new Menu);
+ MenuList& jack_items = jack_menu->items();
+ jack_menu->set_name ("ArdourContextMenu");
+
+ jack_items.push_back (MenuElem (_("Disconnect"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::disconnect_from_jack)));
+ jack_disconnect_item = jack_items.back();
+ jack_disconnect_item->set_sensitive (false);
+ jack_items.push_back (MenuElem (_("Reconnect"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::reconnect_to_jack)));
+ jack_reconnect_item = jack_items.back();
+ jack_reconnect_item->set_sensitive (false);
+
+ jack_bufsize_menu = manage (new Menu);
+ MenuList& jack_bufsize_items = jack_bufsize_menu->items();
+ jack_bufsize_menu->set_name ("ArdourContextMenu");
+
+ jack_bufsize_items.push_back (MenuElem (X_("32"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 32)));
+ jack_bufsize_items.push_back (MenuElem (X_("64"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 64)));
+ jack_bufsize_items.push_back (MenuElem (X_("128"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 128)));
+ jack_bufsize_items.push_back (MenuElem (X_("256"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 256)));
+ jack_bufsize_items.push_back (MenuElem (X_("512"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 512)));
+ jack_bufsize_items.push_back (MenuElem (X_("1024"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 1024)));
+ jack_bufsize_items.push_back (MenuElem (X_("2048"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 2048)));
+ jack_bufsize_items.push_back (MenuElem (X_("4096"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 4096)));
+ jack_bufsize_items.push_back (MenuElem (X_("8192"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 8192)));
+
+ jack_items.push_back (MenuElem (_("Latency"), *jack_bufsize_menu));
+ jack_bufsize_menu->set_sensitive (false);
+
+ items.push_back (MenuElem (_("JACK"), *jack_menu));
+
+ /* windows menu */
+
+ Menu *window_menu = new Menu();
+ MenuList& window_items = window_menu->items();
+ window_menu->set_name ("ArdourContextMenu");
+
+ window_items.push_back (TearoffMenuElem());
+
+ window_items.push_back (MenuElem (_("Editor"), slot (*this, &ARDOUR_UI::goto_editor_window)));
+ window_items.push_back (MenuElem (_("Mixer"), slot (*this, &ARDOUR_UI::goto_mixer_window)));
+
+ window_items.push_back (SeparatorElem());
+
+ window_items.push_back
+ (CheckMenuElem
+ (_("Options Editor"),
+ slot (*this, &ARDOUR_UI::toggle_options_window)));
+ options_window_check = dynamic_cast<CheckMenuItem*>(window_items.back());
+ // options_window_check->set_sensitive (false);
+
+ window_items.push_back
+ (CheckMenuElem
+ (_("Audio Library"),
+ slot (*this, &ARDOUR_UI::toggle_sfdb_window)));
+ sfdb_check = dynamic_cast<CheckMenuItem*>(window_items.back());
+
+ window_items.push_back
+ (CheckMenuElem
+ (_("Track/Bus Inspector"),
+ slot (*this, &ARDOUR_UI::toggle_route_params_window)));
+ route_params_check = dynamic_cast<CheckMenuItem*>(window_items.back());
+ route_params_check->set_sensitive (false);
+
+ window_items.push_back
+ (CheckMenuElem
+ (_("Connections"),
+ slot (*this, &ARDOUR_UI::toggle_connection_editor)));
+ connection_editor_check = dynamic_cast<CheckMenuItem*>(window_items.back());
+ connection_editor_check->set_sensitive (false);
+
+#if 0
+ window_items.push_back
+ (CheckMenuElem
+ (_("Meter Bridge"),
+ slot (*this, &ARDOUR_UI::toggle_meter_bridge_window)));
+ meter_bridge_dialog_check = dynamic_cast<CheckMenuItem*>(window_items.back());
+ meter_bridge_dialog_check->set_sensitive (false);
+#endif
+
+ window_items.push_back
+ (CheckMenuElem
+ (_("Locations"),
+ slot (*this, &ARDOUR_UI::toggle_location_window)));
+ locations_dialog_check = dynamic_cast<CheckMenuItem*>(window_items.back());
+ locations_dialog_check->set_sensitive (false);
+
+ window_items.push_back
+ (CheckMenuElem
+ (_("Big Clock"),
+ slot (*this, &ARDOUR_UI::toggle_big_clock_window)));
+ big_clock_check = dynamic_cast<CheckMenuItem*>(window_items.back());
+
+ window_items.push_back (SeparatorElem());
+
+ window_items.push_back (MenuElem (_("About"), slot (*this, &ARDOUR_UI::show_splash)));
+
+
+ items.push_back (MenuElem (_("Windows"), *window_menu));
+
+ wall_clock_box.add (wall_clock_label);
+ wall_clock_box.set_name ("WallClock");
+ wall_clock_label.set_name ("WallClock");
+
+ disk_space_box.add (disk_space_label);
+ disk_space_box.set_name ("WallClock");
+ disk_space_label.set_name ("WallClock");
+
+ cpu_load_box.add (cpu_load_label);
+ cpu_load_box.set_name ("CPULoad");
+ cpu_load_label.set_name ("CPULoad");
+
+ buffer_load_box.add (buffer_load_label);
+ buffer_load_box.set_name ("BufferLoad");
+ buffer_load_label.set_name ("BufferLoad");
+
+// disk_rate_box.add (disk_rate_label);
+// disk_rate_box.set_name ("DiskRate");
+// disk_rate_label.set_name ("DiskRate");
+
+ sample_rate_box.add (sample_rate_label);
+ sample_rate_box.set_name ("SampleRate");
+ sample_rate_label.set_name ("SampleRate");
+
+ menu_hbox.pack_start (menu_bar, true, true);
+ menu_hbox.pack_end (wall_clock_box, false, false, 10);
+ menu_hbox.pack_end (disk_space_box, false, false, 10);
+ menu_hbox.pack_end (cpu_load_box, false, false, 10);
+// menu_hbox.pack_end (disk_rate_box, false, false, 10);
+ menu_hbox.pack_end (buffer_load_box, false, false, 10);
+ menu_hbox.pack_end (sample_rate_box, false, false, 10);
+
+ menu_bar_base.set_name ("MainMenuBar");
+ menu_bar_base.add (menu_hbox);
+}
+
+
+void
+ARDOUR_UI::editor_display_control_changed (Editing::DisplayControl c)
+{
+ switch (c) {
+ case Editing::FollowPlayhead:
+ follow_button.set_active (editor->follow_playhead ());
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/gtk2_ardour/ardour_ui_mixer.cc b/gtk2_ardour/ardour_ui_mixer.cc
new file mode 100644
index 0000000000..8d92f70ae2
--- /dev/null
+++ b/gtk2_ardour/ardour_ui_mixer.cc
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+/* This file contains any ARDOUR_UI methods that require knowledge of
+ the mixer, and exists so that no compilation dependency exists
+ between the main ARDOUR_UI modules and the mixer classes. This
+ is to cut down on the nasty compile times for these classes.
+*/
+
+#include "ardour_ui.h"
+#include "mixer_ui.h"
+
+using namespace ARDOUR;
+
+int
+ARDOUR_UI::create_mixer ()
+
+{
+ try {
+ mixer = new Mixer_UI (*engine);
+ }
+
+ catch (failed_constructor& err) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/gtk2_ardour/arprof b/gtk2_ardour/arprof
new file mode 100755
index 0000000000..984866a99b
--- /dev/null
+++ b/gtk2_ardour/arprof
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+if [ gprofhelper.c -nt gprofhelper.so ] ; then
+ echo "Recompiling gprof helper ..."
+ gcc -shared -nostdlib -fPIC gprofhelper.c -o gprofhelper.so -lpthread -ldl || exit 1
+fi
+
+export LD_LIBRARY_PATH=../libs/ardour/.libs
+LDPRELOAD=./gprofhelper.so ./ardour $*
diff --git a/gtk2_ardour/arval b/gtk2_ardour/arval
new file mode 100755
index 0000000000..7c5c03ebd7
--- /dev/null
+++ b/gtk2_ardour/arval
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+export LD_LIBRARY_PATH=../libs/ardour
+exec valgrind --num-callers=12 --tool=memcheck ./ardour.bin --novst $*
diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc
new file mode 100644
index 0000000000..860e80af5d
--- /dev/null
+++ b/gtk2_ardour/audio_clock.cc
@@ -0,0 +1,1698 @@
+/*
+ Copyright (C) 1999 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdio> // for sprintf
+#include <cmath>
+#include <gtkmmext/utils.h>
+
+#include <ardour/ardour.h>
+#include <ardour/session.h>
+#include <ardour/tempo.h>
+
+#include "ardour_ui.h"
+#include "audio_clock.h"
+#include "utils.h"
+#include "keyboard.h"
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+using namespace Gtk;
+
+const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
+ 2, /* SMPTE_Hours */
+ 2, /* SMPTE_Minutes */
+ 2, /* SMPTE_Seconds */
+ 2, /* SMPTE_Frames */
+ 2, /* MS_Hours */
+ 2, /* MS_Minutes */
+ 5, /* MS_Seconds */
+ 3, /* Bars */
+ 2, /* Beats */
+ 4, /* Tick */
+ 10 /* Audio Frame */
+};
+
+AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool with_tempo_and_meter)
+ : is_duration (duration),
+ editable (allow_edit),
+ colon1 (":"),
+ colon2 (":"),
+ colon3 (":"),
+ colon4 (":"),
+ colon5 (":"),
+ b1 ("|"),
+ b2 ("|")
+{
+ session = 0;
+ last_when = 0;
+ key_entry_state = 0;
+ ops_menu = 0;
+ dragging = false;
+
+ audio_frames_ebox.add (audio_frames_label);
+ frames_packer_hbox.set_border_width (2);
+ frames_packer_hbox.pack_start (audio_frames_ebox, false, false);
+
+ hours_ebox.add (hours_label);
+ minutes_ebox.add (minutes_label);
+ seconds_ebox.add (seconds_label);
+ frames_ebox.add (frames_label);
+ bars_ebox.add (bars_label);
+ beats_ebox.add (beats_label);
+ ticks_ebox.add (ticks_label);
+ ms_hours_ebox.add (ms_hours_label);
+ ms_minutes_ebox.add (ms_minutes_label);
+ ms_seconds_ebox.add (ms_seconds_label);
+
+ smpte_packer.set_homogeneous (false);
+ smpte_packer.set_border_width (2);
+ smpte_packer.pack_start (hours_ebox, false, false);
+ smpte_packer.pack_start (colon1, false, false);
+ smpte_packer.pack_start (minutes_ebox, false, false);
+ smpte_packer.pack_start (colon2, false, false);
+ smpte_packer.pack_start (seconds_ebox, false, false);
+ smpte_packer.pack_start (colon3, false, false);
+ smpte_packer.pack_start (frames_ebox, false, false);
+
+ smpte_packer_hbox.pack_start (smpte_packer, true, false);
+
+ bbt_packer.set_homogeneous (false);
+ bbt_packer.set_border_width (2);
+ bbt_packer.pack_start (bars_ebox, false, false);
+ bbt_packer.pack_start (b1, false, false);
+ bbt_packer.pack_start (beats_ebox, false, false);
+ bbt_packer.pack_start (b2, false, false);
+ bbt_packer.pack_start (ticks_ebox, false, false);
+
+ if (with_tempo_and_meter) {
+ meter_label = manage (new Label);
+ tempo_label = manage (new Label);
+
+ meter_label->set_name ("BBTMeterLabel");
+ tempo_label->set_name ("BBTTempoLabel");
+
+ tempo_meter_box.pack_start (*meter_label, false, false);
+ tempo_meter_box.pack_start (*tempo_label, false, false);
+
+ bbt_packer.pack_start (tempo_meter_box, false, false, 5);
+ } else {
+ meter_label = 0;
+ tempo_label = 0;
+ }
+
+ bbt_packer_hbox.pack_start (bbt_packer, true, false);
+
+ minsec_packer.set_homogeneous (false);
+ minsec_packer.set_border_width (2);
+ minsec_packer.pack_start (ms_hours_ebox, false, false);
+ minsec_packer.pack_start (colon4, false, false);
+ minsec_packer.pack_start (ms_minutes_ebox, false, false);
+ minsec_packer.pack_start (colon5, false, false);
+ minsec_packer.pack_start (ms_seconds_ebox, false, false);
+
+ minsec_packer_hbox.pack_start (minsec_packer, true, false);
+
+ set_name (name);
+ clock_base.set_name (name);
+
+ audio_frames_label.set_name (name);
+ hours_label.set_name (name);
+ minutes_label.set_name (name);
+ seconds_label.set_name (name);
+ frames_label.set_name (name);
+ bars_label.set_name (name);
+ beats_label.set_name (name);
+ ticks_label.set_name (name);
+ ms_hours_label.set_name (name);
+ ms_minutes_label.set_name (name);
+ ms_seconds_label.set_name (name);
+ hours_ebox.set_name (name);
+ minutes_ebox.set_name (name);
+ seconds_ebox.set_name (name);
+ frames_ebox.set_name (name);
+ audio_frames_ebox.set_name (name);
+ bars_ebox.set_name (name);
+ beats_ebox.set_name (name);
+ ticks_ebox.set_name (name);
+ ms_hours_ebox.set_name (name);
+ ms_minutes_ebox.set_name (name);
+ ms_seconds_ebox.set_name (name);
+
+ colon1.set_name (name);
+ colon2.set_name (name);
+ colon3.set_name (name);
+ colon4.set_name (name);
+ colon5.set_name (name);
+ b1.set_name (name);
+ b2.set_name (name);
+
+ clock_frame.set_shadow_type (GTK_SHADOW_IN);
+ clock_frame.set_name ("BaseFrame");
+
+ clock_frame.add (clock_base);
+
+ _mode = BBT; /* lie to force mode switch */
+ set_mode (SMPTE);
+
+ pack_start (clock_frame, true, true);
+
+ /* the clock base handles button releases for menu popup regardless of
+ editable status. if the clock is editable, the clock base is where
+ we pass focus to after leaving the last editable "field", which
+ will then shutdown editing till the user starts it up again.
+
+ it does this because the focus out event on the field disables
+ keyboard event handling, and we don't connect anything up to
+ notice focus in on the clock base. hence, keyboard event handling
+ stays disabled.
+ */
+
+ clock_base.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
+ clock_base.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
+
+ if (editable) {
+ setup_events ();
+ }
+
+ set (last_when, true);
+}
+
+void
+AudioClock::setup_events ()
+{
+ clock_base.set_flags (GTK_CAN_FOCUS);
+
+ hours_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ minutes_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ seconds_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ frames_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ bars_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ beats_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ ticks_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ ms_hours_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ ms_minutes_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ ms_seconds_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+ audio_frames_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK);
+
+ hours_ebox.set_flags (GTK_CAN_FOCUS);
+ minutes_ebox.set_flags (GTK_CAN_FOCUS);
+ seconds_ebox.set_flags (GTK_CAN_FOCUS);
+ frames_ebox.set_flags (GTK_CAN_FOCUS);
+ audio_frames_ebox.set_flags (GTK_CAN_FOCUS);
+ bars_ebox.set_flags (GTK_CAN_FOCUS);
+ beats_ebox.set_flags (GTK_CAN_FOCUS);
+ ticks_ebox.set_flags (GTK_CAN_FOCUS);
+ ms_hours_ebox.set_flags (GTK_CAN_FOCUS);
+ ms_minutes_ebox.set_flags (GTK_CAN_FOCUS);
+ ms_seconds_ebox.set_flags (GTK_CAN_FOCUS);
+
+ hours_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
+ minutes_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
+ seconds_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
+ frames_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
+ audio_frames_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), AudioFrames));
+ bars_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Bars));
+ beats_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Beats));
+ ticks_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Ticks));
+ ms_hours_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Hours));
+ ms_minutes_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Minutes));
+ ms_seconds_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Seconds));
+
+ hours_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Hours));
+ minutes_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
+ seconds_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
+ frames_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Frames));
+ audio_frames_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), AudioFrames));
+ bars_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Bars));
+ beats_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Beats));
+ ticks_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Ticks));
+ ms_hours_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Hours));
+ ms_minutes_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Minutes));
+ ms_seconds_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Seconds));
+
+ hours_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
+ minutes_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
+ seconds_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
+ frames_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Frames));
+ audio_frames_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), AudioFrames));
+ bars_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Bars));
+ beats_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Beats));
+ ticks_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Ticks));
+ ms_hours_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Hours));
+ ms_minutes_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Minutes));
+ ms_seconds_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Seconds));
+
+ hours_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Hours));
+ minutes_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
+ seconds_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
+ frames_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Frames));
+ audio_frames_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), AudioFrames));
+ bars_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Bars));
+ beats_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Beats));
+ ticks_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Ticks));
+ ms_hours_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Hours));
+ ms_minutes_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Minutes));
+ ms_seconds_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Seconds));
+
+ hours_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
+ minutes_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
+ seconds_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
+ frames_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
+ audio_frames_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), AudioFrames));
+ bars_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Bars));
+ beats_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Beats));
+ ticks_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Ticks));
+ ms_hours_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Hours));
+ ms_minutes_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Minutes));
+ ms_seconds_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Seconds));
+
+ hours_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
+ minutes_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
+ seconds_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
+ frames_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
+ audio_frames_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), AudioFrames));
+ bars_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Bars));
+ beats_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Beats));
+ ticks_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Ticks));
+ ms_hours_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Hours));
+ ms_minutes_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Minutes));
+ ms_seconds_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Seconds));
+
+ Gtkmmext::set_usize_to_display_given_text (hours_label, "-88", 0, 2);
+ Gtkmmext::set_usize_to_display_given_text (minutes_label, "88", 0, 2);
+ Gtkmmext::set_usize_to_display_given_text (seconds_label, "88", 0, 2);
+ Gtkmmext::set_usize_to_display_given_text (frames_label, "88", 0, 2);
+
+ Gtkmmext::set_usize_to_display_given_text (bars_label, "-888", 0, 2);
+ Gtkmmext::set_usize_to_display_given_text (beats_label, "88", 0, 2);
+ Gtkmmext::set_usize_to_display_given_text (ticks_label, "8888", 0, 2);
+
+ Gtkmmext::set_usize_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
+}
+
+void
+AudioClock::realize_impl ()
+{
+ HBox::realize_impl ();
+}
+
+void
+AudioClock::set (jack_nframes_t when, bool force)
+{
+
+ if ((!force && !is_visible()) || session == 0) {
+ return;
+ }
+
+ if (when == last_when && !force) {
+ return;
+ }
+
+ switch (_mode) {
+ case SMPTE:
+ set_smpte (when, force);
+ break;
+
+ case BBT:
+ set_bbt (when, force);
+ break;
+
+ case MinSec:
+ set_minsec (when, force);
+ break;
+
+ case Frames:
+ set_frames (when, force);
+ break;
+
+ case Off:
+ break;
+ }
+
+ last_when = when;
+}
+
+void
+AudioClock::set_frames (jack_nframes_t when, bool force)
+{
+ char buf[32];
+ snprintf (buf, sizeof (buf), "%u", when);
+ audio_frames_label.set_text (buf);
+}
+
+void
+AudioClock::set_minsec (jack_nframes_t when, bool force)
+{
+ char buf[32];
+ jack_nframes_t left;
+ int hrs;
+ int mins;
+ float secs;
+
+ left = when;
+ hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
+ left -= (jack_nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
+ mins = (int) floor (left / (session->frame_rate() * 60.0f));
+ left -= (jack_nframes_t) floor (mins * session->frame_rate() * 60.0f);
+ secs = left / (float) session->frame_rate();
+
+ if (force || hrs != ms_last_hrs) {
+ sprintf (buf, "%d", hrs);
+ ms_hours_label.set_text (buf);
+ ms_last_hrs = hrs;
+ }
+
+ if (force || mins != ms_last_mins) {
+ sprintf (buf, "%d", mins);
+ ms_minutes_label.set_text (buf);
+ ms_last_mins = mins;
+ }
+
+ if (force || secs != ms_last_secs) {
+ sprintf (buf, "%06.3f", secs);
+ ms_seconds_label.set_text (buf);
+ ms_last_secs = secs;
+ }
+}
+
+void
+AudioClock::set_smpte (jack_nframes_t when, bool force)
+{
+ char buf[32];
+ SMPTE_Time smpte;
+
+ if (is_duration) {
+ session->smpte_duration (when, smpte);
+ } else {
+ session->smpte_time (when, smpte);
+ }
+
+ if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
+ if (smpte.negative) {
+ sprintf (buf, "-%02ld", smpte.hours);
+ } else {
+ sprintf (buf, " %02ld", smpte.hours);
+ }
+ hours_label.set_text (buf);
+ last_hrs = smpte.hours;
+ last_negative = smpte.negative;
+ }
+
+ if (force || smpte.minutes != last_mins) {
+ sprintf (buf, "%02ld", smpte.minutes);
+ minutes_label.set_text (buf);
+ last_mins = smpte.minutes;
+ }
+
+ if (force || smpte.seconds != last_secs) {
+ sprintf (buf, "%02ld", smpte.seconds);
+ seconds_label.set_text (buf);
+ last_secs = smpte.seconds;
+ }
+
+ if (force || smpte.frames != last_frames) {
+ sprintf (buf, "%02ld", smpte.frames);
+ frames_label.set_text (buf);
+ last_frames = smpte.frames;
+ }
+}
+
+void
+AudioClock::set_bbt (jack_nframes_t when, bool force)
+{
+ char buf[16];
+ BBT_Time bbt;
+
+ session->tempo_map().bbt_time (when, bbt);
+ sprintf (buf, "%03" PRIu32, bbt.bars);
+ bars_label.set_text (buf);
+ sprintf (buf, "%02" PRIu32, bbt.beats);
+ beats_label.set_text (buf);
+ sprintf (buf, "%04" PRIu32, bbt.ticks);
+ ticks_label.set_text (buf);
+
+ if (meter_label) {
+ TempoMap::Metric m (session->tempo_map().metric_at (when));
+ sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
+ tempo_label->set_text (buf);
+ sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
+ meter_label->set_text (buf);
+ }
+}
+
+void
+AudioClock::set_session (Session *s)
+{
+ session = s;
+
+ if (s) {
+ set (last_when, true);
+ }
+}
+
+gint
+AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
+{
+ Label *label = 0;
+ string new_text;
+ char new_char = 0;
+ bool move_on = false;
+
+ switch (field) {
+ case SMPTE_Hours:
+ label = &hours_label;
+ break;
+ case SMPTE_Minutes:
+ label = &minutes_label;
+ break;
+ case SMPTE_Seconds:
+ label = &seconds_label;
+ break;
+ case SMPTE_Frames:
+ label = &frames_label;
+ break;
+
+ case AudioFrames:
+ label = &audio_frames_label;
+ break;
+
+ case MS_Hours:
+ label = &ms_hours_label;
+ break;
+ case MS_Minutes:
+ label = &ms_minutes_label;
+ break;
+ case MS_Seconds:
+ label = &ms_seconds_label;
+ break;
+
+ case Bars:
+ label = &bars_label;
+ break;
+ case Beats:
+ label = &beats_label;
+ break;
+ case Ticks:
+ label = &ticks_label;
+ break;
+ default:
+ return FALSE;
+ }
+
+ switch (ev->keyval) {
+ case GDK_0:
+ case GDK_KP_0:
+ new_char = '0';
+ break;
+ case GDK_1:
+ case GDK_KP_1:
+ new_char = '1';
+ break;
+ case GDK_2:
+ case GDK_KP_2:
+ new_char = '2';
+ break;
+ case GDK_3:
+ case GDK_KP_3:
+ new_char = '3';
+ break;
+ case GDK_4:
+ case GDK_KP_4:
+ new_char = '4';
+ break;
+ case GDK_5:
+ case GDK_KP_5:
+ new_char = '5';
+ break;
+ case GDK_6:
+ case GDK_KP_6:
+ new_char = '6';
+ break;
+ case GDK_7:
+ case GDK_KP_7:
+ new_char = '7';
+ break;
+ case GDK_8:
+ case GDK_KP_8:
+ new_char = '8';
+ break;
+ case GDK_9:
+ case GDK_KP_9:
+ new_char = '9';
+ break;
+
+ case GDK_period:
+ case GDK_KP_Decimal:
+ if (_mode == MinSec && field == MS_Seconds) {
+ new_char = '.';
+ } else {
+ return FALSE;
+ }
+ break;
+
+ case GDK_Return:
+ case GDK_KP_Enter:
+ case GDK_Tab:
+ move_on = true;
+ break;
+
+ case GDK_Escape:
+ clock_base.grab_focus ();
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+
+ if (!move_on) {
+
+ if (key_entry_state == 0) {
+
+ /* initialize with a fresh new string */
+
+ if (field != AudioFrames) {
+ for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
+ new_text += '0';
+ }
+ } else {
+ new_text = "";
+ }
+
+ } else {
+
+ string existing = label->get_text();
+ if (existing.length() >= field_length[field]) {
+ new_text = existing.substr (1, field_length[field] - 1);
+ } else {
+ new_text = existing.substr (0, field_length[field] - 1);
+ }
+ }
+
+ new_text += new_char;
+ label->set_text (new_text);
+ key_entry_state++;
+ }
+
+ if (key_entry_state == field_length[field]) {
+ move_on = true;
+ }
+
+ if (move_on) {
+
+ if (key_entry_state) {
+
+ switch (field) {
+ case SMPTE_Hours:
+ case SMPTE_Minutes:
+ case SMPTE_Seconds:
+ case SMPTE_Frames:
+ // Check SMPTE fields for sanity (may also adjust fields)
+ smpte_sanitize_display();
+ break;
+ default:
+ break;
+ }
+
+ ValueChanged(); /* EMIT_SIGNAL */
+ }
+
+ /* move on to the next field.
+ */
+
+ switch (field) {
+
+ /* SMPTE */
+
+ case SMPTE_Hours:
+ minutes_ebox.grab_focus ();
+ break;
+ case SMPTE_Minutes:
+ seconds_ebox.grab_focus ();
+ break;
+ case SMPTE_Seconds:
+ frames_ebox.grab_focus ();
+ break;
+ case SMPTE_Frames:
+ clock_base.grab_focus ();
+ break;
+
+ /* audio frames */
+ case AudioFrames:
+ clock_base.grab_focus ();
+ break;
+
+ /* Min:Sec */
+
+ case MS_Hours:
+ ms_minutes_ebox.grab_focus ();
+ break;
+ case MS_Minutes:
+ ms_seconds_ebox.grab_focus ();
+ break;
+ case MS_Seconds:
+ clock_base.grab_focus ();
+ break;
+
+ /* BBT */
+
+ case Bars:
+ beats_ebox.grab_focus ();
+ break;
+ case Beats:
+ ticks_ebox.grab_focus ();
+ break;
+ case Ticks:
+ clock_base.grab_focus ();
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+ return TRUE;
+}
+
+gint
+AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
+{
+ ARDOUR_UI::instance()->allow_focus (true);
+
+ key_entry_state = 0;
+
+ switch (field) {
+ case SMPTE_Hours:
+ hours_ebox.set_flags (GTK_HAS_FOCUS);
+ hours_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ case SMPTE_Minutes:
+ minutes_ebox.set_flags (GTK_HAS_FOCUS);
+ minutes_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ case SMPTE_Seconds:
+ seconds_ebox.set_flags (GTK_HAS_FOCUS);
+ seconds_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ case SMPTE_Frames:
+ frames_ebox.set_flags (GTK_HAS_FOCUS);
+ frames_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+
+ case AudioFrames:
+ audio_frames_ebox.set_flags (GTK_HAS_FOCUS);
+ audio_frames_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+
+ case MS_Hours:
+ ms_hours_ebox.set_flags (GTK_HAS_FOCUS);
+ ms_hours_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ case MS_Minutes:
+ ms_minutes_ebox.set_flags (GTK_HAS_FOCUS);
+ ms_minutes_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ case MS_Seconds:
+ ms_seconds_ebox.set_flags (GTK_HAS_FOCUS);
+ ms_seconds_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ case Bars:
+ bars_ebox.set_flags (GTK_HAS_FOCUS);
+ bars_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ case Beats:
+ beats_ebox.set_flags (GTK_HAS_FOCUS);
+ beats_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ case Ticks:
+ ticks_ebox.set_flags (GTK_HAS_FOCUS);
+ ticks_ebox.set_state (GTK_STATE_ACTIVE);
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
+{
+ ARDOUR_UI::instance()->allow_focus (false);
+
+ switch (field) {
+
+ case SMPTE_Hours:
+ hours_ebox.unset_flags (GTK_HAS_FOCUS);
+ hours_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+ case SMPTE_Minutes:
+ minutes_ebox.unset_flags (GTK_HAS_FOCUS);
+ minutes_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+ case SMPTE_Seconds:
+ seconds_ebox.unset_flags (GTK_HAS_FOCUS);
+ seconds_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+ case SMPTE_Frames:
+ frames_ebox.unset_flags (GTK_HAS_FOCUS);
+ frames_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+
+ case AudioFrames:
+ audio_frames_ebox.unset_flags (GTK_HAS_FOCUS);
+ audio_frames_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+
+ case MS_Hours:
+ ms_hours_ebox.unset_flags (GTK_HAS_FOCUS);
+ ms_hours_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+ case MS_Minutes:
+ ms_minutes_ebox.unset_flags (GTK_HAS_FOCUS);
+ ms_minutes_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+ case MS_Seconds:
+ ms_seconds_ebox.unset_flags (GTK_HAS_FOCUS);
+ ms_seconds_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+
+ case Bars:
+ bars_ebox.unset_flags (GTK_HAS_FOCUS);
+ bars_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+ case Beats:
+ beats_ebox.unset_flags (GTK_HAS_FOCUS);
+ beats_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+ case Ticks:
+ ticks_ebox.unset_flags (GTK_HAS_FOCUS);
+ ticks_ebox.set_state (GTK_STATE_NORMAL);
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+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)){
+ // we actually dragged so return without setting editing focus, or we shift clicked
+
+ return TRUE;
+ }
+ }
+
+ if (!editable) {
+ if (ops_menu == 0) {
+ build_ops_menu ();
+ }
+ ops_menu->popup (1, ev->time);
+ return TRUE;
+ }
+
+ if (Keyboard::is_context_menu_event (ev)) {
+ if (ops_menu == 0) {
+ build_ops_menu ();
+ }
+ ops_menu->popup (1, ev->time);
+ return TRUE;
+ }
+
+ switch (ev->button) {
+ case 1:
+ switch (field) {
+ case SMPTE_Hours:
+ hours_ebox.grab_focus();
+ break;
+ case SMPTE_Minutes:
+ minutes_ebox.grab_focus();
+ break;
+ case SMPTE_Seconds:
+ seconds_ebox.grab_focus();
+ break;
+ case SMPTE_Frames:
+ frames_ebox.grab_focus();
+ break;
+
+ case AudioFrames:
+ audio_frames_ebox.grab_focus();
+ break;
+
+ case MS_Hours:
+ ms_hours_ebox.grab_focus();
+ break;
+ case MS_Minutes:
+ ms_minutes_ebox.grab_focus();
+ break;
+ case MS_Seconds:
+ ms_seconds_ebox.grab_focus();
+ break;
+
+ case Bars:
+ bars_ebox.grab_focus ();
+ break;
+ case Beats:
+ beats_ebox.grab_focus ();
+ break;
+ case Ticks:
+ ticks_ebox.grab_focus ();
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+gint
+AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
+{
+ if (session == 0) return FALSE;
+
+ jack_nframes_t frames = 0;
+
+ switch (ev->button) {
+ case 1:
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+ set (frames, true);
+ ValueChanged (); /* EMIT_SIGNAL */
+ }
+
+ /* make absolutely sure that the pointer is grabbed */
+ gdk_pointer_grab(ev->window,FALSE ,
+ GdkEventMask( GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |GDK_BUTTON_RELEASE_MASK),
+ NULL,NULL,ev->time);
+ dragging = true;
+ drag_accum = 0;
+ drag_start_y = ev->y;
+ drag_y = ev->y;
+ break;
+
+ case 2:
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+ set (frames, true);
+ ValueChanged (); /* EMIT_SIGNAL */
+ }
+ break;
+
+ case 3:
+ /* used for context sensitive menu */
+ return FALSE;
+ break;
+
+ case 4:
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+ frames = get_frames (field);
+ if (frames != 0) {
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ frames *= 10;
+ }
+ set (current_time() + frames, true);
+ ValueChanged (); /* EMIT_SIGNAL */
+ }
+ }
+ break;
+
+ case 5:
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+ frames = get_frames (field);
+ if (frames != 0) {
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ frames *= 10;
+ }
+
+ if ((double)current_time() - (double)frames < 0.0) {
+ set (0, true);
+ }
+ else {
+ set (current_time() - frames, true);
+ }
+
+ ValueChanged (); /* EMIT_SIGNAL */
+ }
+ }
+ break;
+
+ default:
+ return FALSE;
+ break;
+ }
+
+ return TRUE;
+}
+
+gint
+AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
+{
+ if (session == 0 || !dragging) {
+ return FALSE;
+ }
+
+ float pixel_frame_scale_factor = 0.2f;
+
+/*
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ pixel_frame_scale_factor = 0.1f;
+ }
+
+
+ if (Keyboard::modifier_state_contains (ev->state,
+ Keyboard::Control|Keyboard::Alt)) {
+
+ pixel_frame_scale_factor = 0.025f;
+ }
+*/
+ double y_delta = ev->y - drag_y;
+
+ drag_accum += y_delta*pixel_frame_scale_factor;
+
+ drag_y = ev->y;
+
+ if (trunc(drag_accum) != 0) {
+
+ jack_nframes_t frames;
+ jack_nframes_t pos ;
+ int dir;
+ dir = (drag_accum < 0 ? 1:-1);
+ pos = current_time();
+ frames = get_frames (field,pos,dir);
+
+ if (frames != 0 && frames * drag_accum < current_time()) {
+
+ set ((jack_nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
+
+ } else {
+ set (0 , false);
+
+ }
+
+ drag_accum= 0;
+ ValueChanged(); /* EMIT_SIGNAL */
+
+
+ }
+
+ return TRUE;
+}
+
+jack_nframes_t
+AudioClock::get_frames (Field field,jack_nframes_t pos,int dir)
+{
+
+ jack_nframes_t frames = 0;
+ BBT_Time bbt;
+ switch (field) {
+ case SMPTE_Hours:
+ frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
+ break;
+ case SMPTE_Minutes:
+ frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
+ break;
+ case SMPTE_Seconds:
+ frames = session->frame_rate();
+ break;
+ case SMPTE_Frames:
+ frames = (jack_nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second);
+ break;
+
+ case AudioFrames:
+ frames = 1;
+ break;
+
+ case MS_Hours:
+ frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
+ break;
+ case MS_Minutes:
+ frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
+ break;
+ case MS_Seconds:
+ frames = session->frame_rate();
+ break;
+
+ case Bars:
+ bbt.bars = 1;
+ bbt.beats = 0;
+ bbt.ticks = 0;
+ frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
+ break;
+ case Beats:
+ bbt.bars = 0;
+ bbt.beats = 1;
+ bbt.ticks = 0;
+ frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
+ break;
+ case Ticks:
+ bbt.bars = 0;
+ bbt.beats = 0;
+ bbt.ticks = 1;
+ frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
+ break;
+ }
+
+ return frames;
+}
+
+jack_nframes_t
+AudioClock::current_time (jack_nframes_t pos) const
+{
+ jack_nframes_t ret = 0;
+
+ switch (_mode) {
+ case SMPTE:
+ ret = smpte_frame_from_display ();
+ break;
+ case BBT:
+ ret = bbt_frame_from_display (pos);
+ break;
+
+ case MinSec:
+ ret = minsec_frame_from_display ();
+ break;
+
+ case Frames:
+ ret = audio_frame_from_display ();
+ break;
+
+ case Off:
+ break;
+ }
+
+ return ret;
+}
+
+jack_nframes_t
+AudioClock::current_duration (jack_nframes_t pos) const
+{
+ jack_nframes_t ret = 0;
+
+ switch (_mode) {
+ case SMPTE:
+ ret = smpte_frame_from_display ();
+ break;
+ case BBT:
+ ret = bbt_frame_duration_from_display (pos);
+ break;
+
+ case MinSec:
+ ret = minsec_frame_from_display ();
+ break;
+
+ case Frames:
+ ret = audio_frame_from_display ();
+ break;
+
+ case Off:
+ break;
+ }
+
+ return ret;
+}
+
+void
+AudioClock::smpte_sanitize_display()
+{
+ // Check SMPTE fields for sanity, possibly adjusting values
+ if (atoi(minutes_label.get_text()) > 59) {
+ minutes_label.set_text("59");
+ }
+
+ if (atoi(seconds_label.get_text()) > 59) {
+ seconds_label.set_text("59");
+ }
+
+ switch ((long)rint(session->smpte_frames_per_second)) {
+ case 24:
+ if (atoi(frames_label.get_text()) > 23) {
+ frames_label.set_text("23");
+ }
+ break;
+ case 25:
+ if (atoi(frames_label.get_text()) > 24) {
+ frames_label.set_text("24");
+ }
+ break;
+ case 30:
+ if (atoi(frames_label.get_text()) > 29) {
+ frames_label.set_text("29");
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (session->smpte_drop_frames) {
+ if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
+ frames_label.set_text("02");
+ }
+ }
+}
+
+jack_nframes_t
+AudioClock::smpte_frame_from_display () const
+{
+ if (session == 0) {
+ return 0;
+ }
+
+ SMPTE_Time smpte;
+ jack_nframes_t sample;
+
+ smpte.hours = atoi (hours_label.get_text());
+ smpte.minutes = atoi (minutes_label.get_text());
+ smpte.seconds = atoi (seconds_label.get_text());
+ smpte.frames = atoi (frames_label.get_text());
+
+ session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
+
+
+#if 0
+#define SMPTE_SAMPLE_TEST_1
+#define SMPTE_SAMPLE_TEST_2
+#define SMPTE_SAMPLE_TEST_3
+#define SMPTE_SAMPLE_TEST_4
+#define SMPTE_SAMPLE_TEST_5
+#define SMPTE_SAMPLE_TEST_6
+#define SMPTE_SAMPLE_TEST_7
+
+ // Testcode for smpte<->sample conversions (P.S.)
+ SMPTE_Time smpte1;
+ jack_nframes_t sample1;
+ jack_nframes_t oldsample = 0;
+ SMPTE_Time smpte2;
+ jack_nframes_t sample_increment;
+
+ sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
+
+#ifdef SMPTE_SAMPLE_TEST_1
+ // Test 1: use_offset = false, use_subframes = false
+ cout << "use_offset = false, use_subframes = false" << endl;
+ for (int i = 0; i < 108003; i++) {
+ session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
+ session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
+
+ if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
+ cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
+ cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+
+ if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
+ cout << "ERROR: smpte2 not equal smpte1" << endl;
+ cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+ oldsample = sample1;
+ session->smpte_increment( smpte1 );
+ }
+
+ cout << "sample_increment: " << sample_increment << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+#endif
+
+#ifdef SMPTE_SAMPLE_TEST_2
+ // Test 2: use_offset = true, use_subframes = false
+ cout << "use_offset = true, use_subframes = false" << endl;
+
+ smpte1.hours = 0;
+ smpte1.minutes = 0;
+ smpte1.seconds = 0;
+ smpte1.frames = 0;
+ smpte1.subframes = 0;
+ sample1 = oldsample = 0;
+
+ session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
+ cout << "Starting at sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
+
+ for (int i = 0; i < 108003; i++) {
+ session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
+ session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
+
+// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+// cout << "sample: " << sample1 << endl;
+// cout << "sample: " << sample1 << " -> ";
+// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+
+ if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
+ cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
+ cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+
+ if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
+ cout << "ERROR: smpte2 not equal smpte1" << endl;
+ cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+ oldsample = sample1;
+ session->smpte_increment( smpte1 );
+ }
+
+ cout << "sample_increment: " << sample_increment << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+#endif
+
+#ifdef SMPTE_SAMPLE_TEST_3
+ // Test 3: use_offset = true, use_subframes = false, decrement
+ cout << "use_offset = true, use_subframes = false, decrement" << endl;
+
+ session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
+ cout << "Starting at sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
+
+ for (int i = 0; i < 108003; i++) {
+ session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
+ session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
+
+// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+// cout << "sample: " << sample1 << endl;
+// cout << "sample: " << sample1 << " -> ";
+// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+
+ if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
+ cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
+ cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+
+ if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
+ cout << "ERROR: smpte2 not equal smpte1" << endl;
+ cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+ oldsample = sample1;
+ session->smpte_decrement( smpte1 );
+ }
+
+ cout << "sample_decrement: " << sample_increment << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+#endif
+
+
+#ifdef SMPTE_SAMPLE_TEST_4
+ // Test 4: use_offset = true, use_subframes = true
+ cout << "use_offset = true, use_subframes = true" << endl;
+
+ for (long sub = 5; sub < 80; sub += 5) {
+ smpte1.hours = 0;
+ smpte1.minutes = 0;
+ smpte1.seconds = 0;
+ smpte1.frames = 0;
+ smpte1.subframes = 0;
+ sample1 = oldsample = (sample_increment * sub) / 80;
+
+ session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
+
+ cout << "starting at sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
+
+ for (int i = 0; i < 108003; i++) {
+ session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
+ session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
+
+ if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
+ cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
+ cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ //break;
+ }
+
+ if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
+ cout << "ERROR: smpte2 not equal smpte1" << endl;
+ cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+ oldsample = sample1;
+ session->smpte_increment( smpte1 );
+ }
+
+ cout << "sample_increment: " << sample_increment << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+
+ for (int i = 0; i < 108003; i++) {
+ session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
+ session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
+
+ if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
+ cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
+ cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ //break;
+ }
+
+ if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
+ cout << "ERROR: smpte2 not equal smpte1" << endl;
+ cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+ oldsample = sample1;
+ session->smpte_decrement( smpte1 );
+ }
+
+ cout << "sample_decrement: " << sample_increment << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ }
+#endif
+
+
+#ifdef SMPTE_SAMPLE_TEST_5
+ // Test 5: use_offset = true, use_subframes = false, increment seconds
+ cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
+
+ smpte1.hours = 0;
+ smpte1.minutes = 0;
+ smpte1.seconds = 0;
+ smpte1.frames = 0;
+ smpte1.subframes = 0;
+ sample1 = oldsample = 0;
+ sample_increment = session->frame_rate();
+
+ session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
+ cout << "Starting at sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
+
+ for (int i = 0; i < 3600; i++) {
+ session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
+ session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
+
+// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+// cout << "sample: " << sample1 << endl;
+// cout << "sample: " << sample1 << " -> ";
+// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+
+// if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
+// {
+// cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
+// break;
+// }
+
+ if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
+ cout << "ERROR: smpte2 not equal smpte1" << endl;
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+ oldsample = sample1;
+ session->smpte_increment_seconds( smpte1 );
+ }
+
+ cout << "sample_increment: " << sample_increment << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+#endif
+
+
+#ifdef SMPTE_SAMPLE_TEST_6
+ // Test 6: use_offset = true, use_subframes = false, increment minutes
+ cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
+
+ smpte1.hours = 0;
+ smpte1.minutes = 0;
+ smpte1.seconds = 0;
+ smpte1.frames = 0;
+ smpte1.subframes = 0;
+ sample1 = oldsample = 0;
+ sample_increment = session->frame_rate() * 60;
+
+ session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
+ cout << "Starting at sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
+
+ for (int i = 0; i < 60; i++) {
+ session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
+ session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
+
+// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+// cout << "sample: " << sample1 << endl;
+// cout << "sample: " << sample1 << " -> ";
+// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+
+// if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
+// {
+// cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
+// break;
+// }
+
+ if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
+ cout << "ERROR: smpte2 not equal smpte1" << endl;
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+ oldsample = sample1;
+ session->smpte_increment_minutes( smpte1 );
+ }
+
+ cout << "sample_increment: " << sample_increment << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+#endif
+
+#ifdef SMPTE_SAMPLE_TEST_7
+ // Test 7: use_offset = true, use_subframes = false, increment hours
+ cout << "use_offset = true, use_subframes = false, increment hours" << endl;
+
+ smpte1.hours = 0;
+ smpte1.minutes = 0;
+ smpte1.seconds = 0;
+ smpte1.frames = 0;
+ smpte1.subframes = 0;
+ sample1 = oldsample = 0;
+ sample_increment = session->frame_rate() * 60 * 60;
+
+ session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
+ cout << "Starting at sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
+
+ for (int i = 0; i < 10; i++) {
+ session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
+ session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
+
+// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+// cout << "sample: " << sample1 << endl;
+// cout << "sample: " << sample1 << " -> ";
+// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+
+// if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
+// {
+// cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
+// break;
+// }
+
+ if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
+ cout << "ERROR: smpte2 not equal smpte1" << endl;
+ cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
+ cout << "sample: " << sample1 << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+ break;
+ }
+ oldsample = sample1;
+ session->smpte_increment_hours( smpte1 );
+ }
+
+ cout << "sample_increment: " << sample_increment << endl;
+ cout << "sample: " << sample1 << " -> ";
+ cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
+#endif
+
+#endif
+
+ return sample;
+}
+
+jack_nframes_t
+AudioClock::minsec_frame_from_display () const
+{
+ if (session == 0) {
+ return 0;
+ }
+
+ int hrs = atoi (ms_hours_label.get_text());
+ int mins = atoi (ms_minutes_label.get_text());
+ float secs = atof (ms_seconds_label.get_text());
+
+ jack_nframes_t sr = session->frame_rate();
+
+ return (jack_nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
+}
+
+jack_nframes_t
+AudioClock::bbt_frame_from_display (jack_nframes_t pos) const
+{
+ if (session == 0) {
+ error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
+ return 0;
+ }
+
+ AnyTime any;
+ any.type = AnyTime::BBT;
+
+ any.bbt.bars = atoi (bars_label.get_text());
+ any.bbt.beats = atoi (beats_label.get_text());
+ any.bbt.ticks = atoi (ticks_label.get_text());
+
+ jack_nframes_t ret = session->convert_to_frames_at (pos, any);
+
+ return ret;
+}
+
+
+jack_nframes_t
+AudioClock::bbt_frame_duration_from_display (jack_nframes_t pos) const
+{
+ if (session == 0) {
+ error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
+ return 0;
+ }
+
+ BBT_Time bbt;
+
+
+ bbt.bars = atoi (bars_label.get_text());
+ bbt.beats = atoi (beats_label.get_text());
+ bbt.ticks = atoi (ticks_label.get_text());
+
+ return session->tempo_map().bbt_duration_at(pos,bbt,1);
+}
+
+jack_nframes_t
+AudioClock::audio_frame_from_display () const
+{
+ return (jack_nframes_t) atoi (audio_frames_label.get_text());
+}
+
+void
+AudioClock::build_ops_menu ()
+{
+ using namespace Menu_Helpers;
+ ops_menu = new Menu;
+ MenuList& ops_items = ops_menu->items();
+ ops_menu->set_name ("ArdourContextMenu");
+
+ Menu *mode_menu = manage (new Menu);
+ MenuList& mode_items = mode_menu->items();
+ mode_menu->set_name ("ArdourContextMenu");
+
+ mode_items.push_back (MenuElem (_("SMPTE"), bind (slot (*this, &AudioClock::set_mode), SMPTE)));
+ mode_items.push_back (MenuElem (_("Bars:Beats"), bind (slot (*this, &AudioClock::set_mode), BBT)));
+ mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (slot (*this, &AudioClock::set_mode), MinSec)));
+ mode_items.push_back (MenuElem (_("Audio Frames"), bind (slot (*this, &AudioClock::set_mode), Frames)));
+ mode_items.push_back (MenuElem (_("Off"), bind (slot (*this, &AudioClock::set_mode), Off)));
+
+ ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
+}
+
+void
+AudioClock::set_mode (Mode m)
+{
+ /* slightly tricky: this is called from within the ARDOUR_UI
+ constructor by some of its clock members. at that time
+ the instance pointer is unset, so we have to be careful.
+ the main idea is to drop keyboard focus in case we had
+ started editing the clock and then we switch clock mode.
+ */
+
+ if (ARDOUR_UI::instance()) {
+ ARDOUR_UI::instance()->allow_focus (false);
+ }
+
+ if (_mode == m) {
+ return;
+ }
+ switch (_mode) {
+ case SMPTE:
+ case BBT:
+ case MinSec:
+ case Frames:
+ clock_base.remove ();
+ break;
+ case Off:
+ break;
+ }
+
+ _mode = m;
+
+ switch (_mode) {
+ case SMPTE:
+ clock_base.add (smpte_packer_hbox);
+ break;
+ case BBT:
+ clock_base.add (bbt_packer_hbox);
+ break;
+ case MinSec:
+ clock_base.add (minsec_packer_hbox);
+ break;
+ case Frames:
+ clock_base.add (frames_packer_hbox);
+ case Off:
+ break;
+ }
+
+ set (last_when, true);
+ clock_base.show_all ();
+ key_entry_state = 0;
+}
diff --git a/gtk2_ardour/audio_clock.h b/gtk2_ardour/audio_clock.h
new file mode 100644
index 0000000000..b9c9be095d
--- /dev/null
+++ b/gtk2_ardour/audio_clock.h
@@ -0,0 +1,176 @@
+/*
+ Copyright (C) 1999 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __audio_clock_h__
+#define __audio_clock_h__
+
+#include <gtk--.h>
+#include <ardour/ardour.h>
+
+namespace ARDOUR {
+ class Session;
+};
+
+class AudioClock : public Gtk::HBox
+{
+ public:
+ enum Mode {
+ SMPTE,
+ BBT,
+ MinSec,
+ Frames,
+ Off,
+ };
+
+ AudioClock (const string& name, bool editable, bool is_duration = false, bool with_tempo_meter = false);
+
+ Mode mode() const { return _mode; }
+
+ void set (jack_nframes_t, bool force = false);
+ void set_mode (Mode);
+
+ jack_nframes_t current_time (jack_nframes_t position = 0) const;
+ jack_nframes_t current_duration (jack_nframes_t position = 0) const;
+ void set_session (ARDOUR::Session *s);
+
+ SigC::Signal0<void> ValueChanged;
+
+ private:
+ ARDOUR::Session *session;
+ Mode _mode;
+ uint32_t key_entry_state;
+ bool is_duration;
+ bool editable;
+
+ Gtk::Menu *ops_menu;
+
+ Gtk::HBox smpte_packer_hbox;
+ Gtk::HBox smpte_packer;
+
+ Gtk::HBox minsec_packer_hbox;
+ Gtk::HBox minsec_packer;
+
+ Gtk::HBox bbt_packer_hbox;
+ Gtk::HBox bbt_packer;
+
+ Gtk::HBox frames_packer_hbox;
+
+ enum Field {
+ SMPTE_Hours,
+ SMPTE_Minutes,
+ SMPTE_Seconds,
+ SMPTE_Frames,
+ MS_Hours,
+ MS_Minutes,
+ MS_Seconds,
+ Bars,
+ Beats,
+ Ticks,
+ AudioFrames,
+ };
+
+ Gtk::EventBox audio_frames_ebox;
+ Gtk::Label audio_frames_label;
+
+ Gtk::EventBox hours_ebox;
+ Gtk::EventBox minutes_ebox;
+ Gtk::EventBox seconds_ebox;
+ Gtk::EventBox frames_ebox;
+
+ Gtk::EventBox ms_hours_ebox;
+ Gtk::EventBox ms_minutes_ebox;
+ Gtk::EventBox ms_seconds_ebox;
+
+ Gtk::EventBox bars_ebox;
+ Gtk::EventBox beats_ebox;
+ Gtk::EventBox ticks_ebox;
+
+ Gtk::Label hours_label;
+ Gtk::Label minutes_label;
+ Gtk::Label seconds_label;
+ Gtk::Label frames_label;
+ Gtk::Label colon1, colon2, colon3;
+
+ Gtk::Label ms_hours_label;
+ Gtk::Label ms_minutes_label;
+ Gtk::Label ms_seconds_label;
+ Gtk::Label colon4, colon5;
+
+ Gtk::Label bars_label;
+ Gtk::Label beats_label;
+ Gtk::Label ticks_label;
+ Gtk::Label b1;
+ Gtk::Label b2;
+
+ Gtk::Label* tempo_label;
+ Gtk::Label* meter_label;
+
+ Gtk::VBox tempo_meter_box;
+
+ Gtk::EventBox clock_base;
+ Gtk::Frame clock_frame;
+
+ jack_nframes_t last_when;
+
+ long last_hrs;
+ long last_mins;
+ long last_secs;
+ long last_frames;
+ bool last_negative;
+
+ long ms_last_hrs;
+ long ms_last_mins;
+ float ms_last_secs;
+
+ bool dragging;
+ double drag_start_y;
+ double drag_y;
+ double drag_accum;
+
+ void realize_impl ();
+
+ gint field_motion_notify_event (GdkEventMotion *ev, Field);
+ gint field_button_press_event (GdkEventButton *ev, Field);
+ gint field_button_release_event (GdkEventButton *ev, Field);
+ gint field_key_release_event (GdkEventKey *, Field);
+ gint field_focus_in_event (GdkEventFocus *, Field);
+ gint field_focus_out_event (GdkEventFocus *, Field);
+
+ void set_smpte (jack_nframes_t, bool);
+ void set_bbt (jack_nframes_t, bool);
+ void set_minsec (jack_nframes_t, bool);
+ void set_frames (jack_nframes_t, bool);
+
+ jack_nframes_t get_frames (Field,jack_nframes_t pos = 0,int dir=1);
+
+ void smpte_sanitize_display();
+ jack_nframes_t smpte_frame_from_display () const;
+ jack_nframes_t bbt_frame_from_display (jack_nframes_t) const;
+ jack_nframes_t bbt_frame_duration_from_display (jack_nframes_t) const;
+ jack_nframes_t minsec_frame_from_display () const;
+ jack_nframes_t audio_frame_from_display () const;
+
+ void build_ops_menu ();
+ void setup_events ();
+
+ static const uint32_t field_length[(int)AudioFrames+1];
+};
+
+#endif /* __audio_clock_h__ */
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc
new file mode 100644
index 0000000000..c4bd90d332
--- /dev/null
+++ b/gtk2_ardour/audio_time_axis.cc
@@ -0,0 +1,2001 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <sigc++/bind.h>
+
+#include <pbd/error.h>
+#include <pbd/stl_delete.h>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/bindable_button.h>
+
+#include <ardour/session.h>
+#include <ardour/session_playlist.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/diskstream.h>
+#include <ardour/utils.h>
+#include <ardour/playlist.h>
+#include <ardour/ladspa_plugin.h>
+#include <ardour/insert.h>
+#include <ardour/location.h>
+#include <ardour/panner.h>
+
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "audio_time_axis.h"
+#include "streamview.h"
+#include "canvas-simplerect.h"
+#include "playlist_selector.h"
+#include "plugin_selector.h"
+#include "plugin_ui.h"
+#include "regionview.h"
+#include "automation_gain_line.h"
+#include "automation_pan_line.h"
+#include "automation_time_axis.h"
+#include "redirect_automation_time_axis.h"
+#include "gain_automation_time_axis.h"
+#include "pan_automation_time_axis.h"
+#include "redirect_automation_line.h"
+#include "selection.h"
+#include "point_selection.h"
+#include "enums.h"
+#include "utils.h"
+#include "keyboard.h"
+#include "rgb_macros.h"
+#include "prompter.h"
+#include "crossfade_view.h"
+#include "gui_thread.h"
+
+#include <ardour/audio_track.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+using namespace LADSPA;
+using namespace Gtk;
+using namespace Editing;
+
+static const gchar * small_x_xpm[] = {
+"11 11 2 1",
+" c None",
+". c #000000",
+" ",
+" ",
+" . . ",
+" . . ",
+" . . ",
+" . ",
+" . . ",
+" . . ",
+" . . ",
+" ",
+" "};
+
+AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt, Widget *canvas)
+ : AxisView(sess),
+ RouteUI(rt, sess, _("m"), _("s"), _("r")), // mute, solo, and record
+ TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas),
+ parent_canvas (canvas),
+ button_table (3, 3),
+ edit_group_button (_("g")), // group
+ playlist_button (_("p")),
+ size_button (_("h")), // height
+ automation_button (_("a")),
+ visual_button (_("v")),
+ redirect_window ("redirect window"),
+ redirect_display (1)
+{
+ _has_state = true;
+ subplugin_menu.set_name ("ArdourContextMenu");
+ playlist_menu = 0;
+ playlist_action_menu = 0;
+ automation_action_menu = 0;
+ gain_track = 0;
+ pan_track = 0;
+ view = 0;
+ timestretch_rect = 0;
+ waveform_item = 0;
+ pan_automation_item = 0;
+ gain_automation_item = 0;
+ no_redraw = false;
+
+ view = new StreamView (*this);
+
+ add_gain_automation_child ();
+ add_pan_automation_child ();
+
+ ignore_toggle = false;
+
+ rec_enable_button->set_active (false);
+ mute_button->set_active (false);
+ solo_button->set_active (false);
+
+ rec_enable_button->set_name ("TrackRecordEnableButton");
+ mute_button->set_name ("TrackMuteButton");
+ solo_button->set_name ("SoloButton");
+ edit_group_button.set_name ("TrackGroupButton");
+ playlist_button.set_name ("TrackPlaylistButton");
+ automation_button.set_name ("TrackAutomationButton");
+ size_button.set_name ("TrackSizeButton");
+ visual_button.set_name ("TrackVisualButton");
+ hide_button.set_name ("TrackRemoveButton");
+
+ hide_button.add (*(manage (new Pixmap (small_x_xpm))));
+
+ _route.mute_changed.connect (slot (*this, &RouteUI::mute_changed));
+ _route.solo_changed.connect (slot (*this, &RouteUI::solo_changed));
+ _route.solo_safe_changed.connect (slot (*this, &RouteUI::solo_changed));
+
+ _route.panner().Changed.connect (slot (*this, &AudioTimeAxisView::update_pans));
+
+ solo_button->button_press_event.connect (slot (*this, &RouteUI::solo_press));
+ solo_button->button_release_event.connect (slot (*this, &RouteUI::solo_release));
+ mute_button->button_press_event.connect (slot (*this, &RouteUI::mute_press));
+ mute_button->button_release_event.connect (slot (*this, &RouteUI::mute_release));
+ rec_enable_button->button_press_event.connect (slot (*this, &RouteUI::rec_enable_press));
+ edit_group_button.button_release_event.connect (slot (*this, &AudioTimeAxisView::edit_click));
+ playlist_button.clicked.connect (slot (*this, &AudioTimeAxisView::playlist_click));
+ automation_button.clicked.connect (slot (*this, &AudioTimeAxisView::automation_click));
+ size_button.button_release_event.connect (slot (*this, &AudioTimeAxisView::size_click));
+ visual_button.clicked.connect (slot (*this, &AudioTimeAxisView::visual_click));
+ hide_button.clicked.connect (slot (*this, &AudioTimeAxisView::hide_click));
+
+ name_entry.activate.connect (slot (*this, &AudioTimeAxisView::name_entry_activated));
+ name_entry.focus_out_event.connect (slot (*this, &AudioTimeAxisView::name_entry_focus_out_handler));
+ name_entry.button_press_event.connect (slot (*this, &AudioTimeAxisView::name_entry_button_press_handler));
+ name_entry.button_release_event.connect (slot (*this, &AudioTimeAxisView::name_entry_button_release_handler));
+ name_entry.key_release_event.connect (slot (*this, &AudioTimeAxisView::name_entry_key_release_handler));
+
+ if (is_audio_track()) {
+ controls_table.attach (*rec_enable_button, 6, 7, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
+ }
+ controls_table.attach (*mute_button, 7, 8, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
+ controls_table.attach (*solo_button, 8, 9, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_FILL|GTK_EXPAND, 0, 0);
+
+ controls_table.attach (edit_group_button, 7, 8, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
+
+ ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
+ ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo"));
+ ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute"));
+ ARDOUR_UI::instance()->tooltips().set_tip(edit_group_button,_("Edit Group"));
+ ARDOUR_UI::instance()->tooltips().set_tip(size_button,_("Display Height"));
+ ARDOUR_UI::instance()->tooltips().set_tip(playlist_button,_("Playlist"));
+ ARDOUR_UI::instance()->tooltips().set_tip(automation_button, _("Automation"));
+ ARDOUR_UI::instance()->tooltips().set_tip(visual_button, _("Visual options"));
+ ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("Hide this track"));
+
+ label_view ();
+
+ controls_table.attach (hide_button, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ controls_table.attach (visual_button, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ controls_table.attach (size_button, 2, 3, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ controls_table.attach (automation_button, 3, 4, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+
+ if (is_audio_track()) {
+ controls_table.attach (playlist_button, 6, 7, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+
+ }
+
+ /* remove focus from the buttons */
+
+ automation_button.unset_flags (GTK_CAN_FOCUS);
+ solo_button->unset_flags (GTK_CAN_FOCUS);
+ mute_button->unset_flags (GTK_CAN_FOCUS);
+ edit_group_button.unset_flags (GTK_CAN_FOCUS);
+ size_button.unset_flags (GTK_CAN_FOCUS);
+ playlist_button.unset_flags (GTK_CAN_FOCUS);
+ hide_button.unset_flags (GTK_CAN_FOCUS);
+ visual_button.unset_flags (GTK_CAN_FOCUS);
+
+ /* map current state of the route */
+
+ update_diskstream_display ();
+ solo_changed(0);
+ mute_changed(0);
+ redirects_changed (0);
+ reset_redirect_automation_curves ();
+ edit_group_menu_radio_group = 0;
+ y_position = -1;
+
+ ensure_xml_node ();
+
+ set_state (*xml_node);
+
+ _route.mute_changed.connect (slot (*this, &RouteUI::mute_changed));
+ _route.solo_changed.connect (slot (*this, &RouteUI::solo_changed));
+ _route.redirects_changed.connect (slot (*this, &AudioTimeAxisView::redirects_changed));
+
+ _route.name_changed.connect (slot (*this, &AudioTimeAxisView::route_name_changed));
+
+ if (is_audio_track()) {
+
+ /* track */
+
+ audio_track()->FreezeChange.connect (slot (*this, &AudioTimeAxisView::map_frozen));
+
+ audio_track()->diskstream_changed.connect (slot (*this, &AudioTimeAxisView::diskstream_changed));
+ get_diskstream()->speed_changed.connect (slot (*this, &AudioTimeAxisView::speed_changed));
+
+ controls_ebox.set_name ("AudioTrackControlsBaseUnselected");
+ controls_base_selected_name = "AudioTrackControlsBaseSelected";
+ controls_base_unselected_name = "AudioTrackControlsBaseUnselected";
+
+ /* ask for notifications of any new RegionViews */
+
+ view->AudioRegionViewAdded.connect (slot (*this, &AudioTimeAxisView::region_view_added));
+
+ view->attach ();
+
+ /* pick up the correct freeze state */
+
+ map_frozen ();
+
+ } else {
+
+ /* bus */
+
+ controls_ebox.set_name ("BusControlsBaseUnselected");
+ controls_base_selected_name = "BusControlsBaseSelected";
+ controls_base_unselected_name = "BusControlsBaseUnselected";
+ }
+
+ editor.ZoomChanged.connect (slot (*this, &AudioTimeAxisView::reset_samples_per_unit));
+}
+
+AudioTimeAxisView::~AudioTimeAxisView ()
+{
+ GoingAway (); /* EMIT_SIGNAL */
+
+ if (playlist_menu) {
+ delete playlist_menu;
+ playlist_menu = 0;
+ }
+
+ if (playlist_action_menu) {
+ delete playlist_action_menu;
+ playlist_action_menu = 0;
+ }
+
+ vector_delete (&redirect_automation_curves);
+
+ for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+ delete *i;
+ }
+
+ if (view) {
+ delete view;
+ view = 0;
+ }
+}
+
+guint32
+AudioTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
+{
+ ensure_xml_node ();
+ xml_node->add_property ("shown_editor", "yes");
+
+ return TimeAxisView::show_at (y, nth, parent);
+}
+
+void
+AudioTimeAxisView::hide ()
+{
+ ensure_xml_node ();
+ xml_node->add_property ("shown_editor", "no");
+
+ TimeAxisView::hide ();
+}
+
+void
+AudioTimeAxisView::set_playlist (AudioPlaylist *newplaylist)
+{
+ AudioPlaylist *pl;
+
+ modified_connection.disconnect ();
+ state_changed_connection.disconnect ();
+
+ if ((pl = dynamic_cast<AudioPlaylist*> (playlist())) != 0) {
+ state_changed_connection = pl->StateChanged.connect (slot (*this, &AudioTimeAxisView::playlist_state_changed));
+ modified_connection = pl->Modified.connect (slot (*this, &AudioTimeAxisView::playlist_modified));
+ }
+}
+
+void
+AudioTimeAxisView::playlist_modified ()
+{
+}
+
+gint
+AudioTimeAxisView::edit_click (GdkEventButton *ev)
+{
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ _route.set_edit_group (0, this);
+ return FALSE;
+ }
+
+ using namespace Menu_Helpers;
+
+ MenuList& items = edit_group_menu.items ();
+
+ items.clear ();
+ items.push_back (RadioMenuElem (edit_group_menu_radio_group, _("No group"),
+ bind (slot (*this, &AudioTimeAxisView::set_edit_group_from_menu), (RouteGroup *) 0)));
+
+ if (_route.edit_group() == 0) {
+ static_cast<RadioMenuItem*>(items.back())->set_active ();
+ }
+
+ _session.foreach_edit_group (this, &AudioTimeAxisView::add_edit_group_menu_item);
+ edit_group_menu.popup (ev->button, ev->time);
+
+ return FALSE;
+}
+
+void
+AudioTimeAxisView::add_edit_group_menu_item (RouteGroup *eg)
+{
+ using namespace Menu_Helpers;
+
+ MenuList &items = edit_group_menu.items();
+ items.push_back (RadioMenuElem (edit_group_menu_radio_group,
+ eg->name(), bind (slot (*this, &AudioTimeAxisView::set_edit_group_from_menu), eg)));
+ if (_route.edit_group() == eg) {
+ static_cast<RadioMenuItem*>(items.back())->set_active ();
+ }
+}
+
+void
+AudioTimeAxisView::set_edit_group_from_menu (RouteGroup *eg)
+
+{
+ _route.set_edit_group (eg, this);
+}
+
+void
+AudioTimeAxisView::playlist_state_changed (Change ignored)
+{
+ // ENSURE_GUI_THREAD (bind (slot (*this, &AudioTimeAxisView::playlist_state_changed), ignored));
+ // why are we here ?
+}
+
+void
+AudioTimeAxisView::playlist_changed ()
+
+{
+ label_view ();
+
+ if (is_audio_track()) {
+ set_playlist (get_diskstream()->playlist());
+ }
+}
+
+void
+AudioTimeAxisView::label_view ()
+{
+ string x = _route.name();
+
+ if (x != name_entry.get_text()) {
+ name_entry.set_text (x);
+ }
+
+ ARDOUR_UI::instance()->tooltips().set_tip (name_entry, x);
+}
+
+void
+AudioTimeAxisView::route_name_changed (void *src)
+{
+ editor.route_name_changed (this);
+ label_view ();
+}
+
+void
+AudioTimeAxisView::take_name_changed (void *src)
+
+{
+ if (src != this) {
+ label_view ();
+ }
+}
+
+void
+AudioTimeAxisView::playlist_click ()
+{
+ // always build a new action menu
+
+ if (playlist_action_menu == 0) {
+ playlist_action_menu = new Menu;
+ playlist_action_menu->set_name ("ArdourContextMenu");
+ }
+
+ build_playlist_menu(playlist_action_menu);
+
+ playlist_action_menu->popup (1, 0);
+}
+
+void
+AudioTimeAxisView::automation_click ()
+{
+ if (automation_action_menu == 0) {
+ /* this seems odd, but the automation action
+ menu is built as part of the display menu.
+ */
+ build_display_menu ();
+ }
+ automation_action_menu->popup (1, 0);
+}
+
+void
+AudioTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end)
+{
+ double x1;
+ double x2;
+ double y2;
+
+ TimeAxisView::show_timestretch (start, end);
+
+ hide_timestretch ();
+
+#if 0
+ if (ts.empty()) {
+ return;
+ }
+
+
+ /* check that the time selection was made in our route, or our edit group.
+ remember that edit_group() == 0 implies the route is *not* in a edit group.
+ */
+
+ if (!(ts.track == this || (ts.group != 0 && ts.group == _route.edit_group()))) {
+ /* this doesn't apply to us */
+ return;
+ }
+
+ /* ignore it if our edit group is not active */
+
+ if ((ts.track != this) && _route.edit_group() && !_route.edit_group()->is_active()) {
+ return;
+ }
+#endif
+
+ if (timestretch_rect == 0) {
+ timestretch_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "fill_color_rgba", color_map[cTimeStretchFill],
+ "outline_color_rgba" , color_map[cTimeStretchOutline],
+ NULL);
+ }
+
+ gtk_canvas_item_show (timestretch_rect);
+ gtk_canvas_item_raise_to_top (timestretch_rect);
+
+ x1 = start / editor.get_current_zoom();
+ x2 = (end - 1) / editor.get_current_zoom();
+ y2 = height - 2;
+
+ gtk_object_set (GTK_OBJECT(timestretch_rect),
+ "x1", x1,
+ "y1", 1.0,
+ "x2", x2,
+ "y2", y2,
+ NULL);
+}
+
+void
+AudioTimeAxisView::hide_timestretch ()
+{
+ TimeAxisView::hide_timestretch ();
+
+ if (timestretch_rect) {
+ gtk_canvas_item_hide (timestretch_rect);
+ }
+}
+
+void
+AudioTimeAxisView::show_selection (TimeSelection& ts)
+{
+
+#if 0
+ /* ignore it if our edit group is not active or if the selection was started
+ in some other track or edit group (remember that edit_group() == 0 means
+ that the track is not in an edit group).
+ */
+
+ if (((ts.track != this && !is_child (ts.track)) && _route.edit_group() && !_route.edit_group()->is_active()) ||
+ (!(ts.track == this || is_child (ts.track) || (ts.group != 0 && ts.group == _route.edit_group())))) {
+ hide_selection ();
+ return;
+ }
+#endif
+
+ TimeAxisView::show_selection (ts);
+}
+
+void
+AudioTimeAxisView::set_state (const XMLNode& node)
+{
+ const XMLProperty *prop;
+
+ TimeAxisView::set_state (node);
+
+ if ((prop = node.property ("shown_editor")) != 0) {
+ if (prop->value() == "no") {
+ _marked_for_display = false;
+ } else {
+ _marked_for_display = true;
+ }
+ } else {
+ _marked_for_display = true;
+ }
+
+ XMLNodeList nlist = node.children();
+ XMLNodeConstIterator niter;
+ XMLNode *child_node;
+
+
+ show_gain_automation = false;
+ show_pan_automation = false;
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ child_node = *niter;
+
+ if (child_node->name() == "gain") {
+ XMLProperty *prop=child_node->property ("shown");
+
+ if (prop != 0) {
+ if (prop->value() == "yes") {
+ show_gain_automation = true;
+ }
+ }
+ continue;
+ }
+
+ if (child_node->name() == "pan") {
+ XMLProperty *prop=child_node->property ("shown");
+
+ if (prop != 0) {
+ if (prop->value() == "yes") {
+ show_pan_automation = true;
+ }
+ }
+ continue;
+ }
+ }
+}
+
+void
+AudioTimeAxisView::set_height (TrackHeight h)
+{
+ bool height_changed = (h != (TrackHeight)height);
+
+ TimeAxisView::set_height (h);
+
+ ensure_xml_node ();
+
+ view->set_height ((double) height);
+
+ switch (height) {
+ case Largest:
+ xml_node->add_property ("track_height", "largest");
+ controls_table.show_all ();
+ name_label.hide ();
+ break;
+ case Large:
+ xml_node->add_property ("track_height", "large");
+ controls_table.show_all ();
+ name_label.hide ();
+ break;
+ case Larger:
+ xml_node->add_property ("track_height", "larger");
+ controls_table.show_all ();
+ name_label.hide ();
+ break;
+ case Normal:
+ xml_node->add_property ("track_height", "normal");
+ controls_table.show_all ();
+ name_label.hide ();
+ break;
+ case Smaller:
+ xml_node->add_property ("track_height", "smaller");
+ controls_table.show_all ();
+ name_label.hide ();
+ edit_group_button.hide ();
+ hide_button.hide ();
+ visual_button.hide ();
+ size_button.hide ();
+ automation_button.hide ();
+ playlist_button.hide ();
+ break;
+ case Small:
+ xml_node->add_property ("track_height", "small");
+ controls_table.hide_all ();
+ controls_table.show ();
+ name_label.set_text (_route.name());
+ name_label.show ();
+ name_hbox.show ();
+ break;
+ }
+
+ if (height_changed) {
+ /* only emit the signal if the height really changed */
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+ }
+}
+
+void
+AudioTimeAxisView::select_track_color ()
+{
+ if (RouteUI::choose_color ()) {
+
+ if (view) {
+ view->apply_color (_color, StreamView::RegionColor);
+ }
+ }
+}
+
+void
+AudioTimeAxisView::reset_redirect_automation_curves ()
+{
+ for (vector<RedirectAutomationLine*>::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) {
+ (*i)->reset();
+ }
+}
+
+void
+AudioTimeAxisView::reset_samples_per_unit ()
+{
+ set_samples_per_unit (editor.get_current_zoom());
+}
+
+void
+AudioTimeAxisView::set_samples_per_unit (double spu)
+{
+ double speed = 1.0;
+
+ if (get_diskstream() != 0) {
+ speed = get_diskstream()->speed();
+ }
+
+ if (view) {
+ view->set_samples_per_unit (spu * speed);
+ }
+
+ TimeAxisView::set_samples_per_unit (spu * speed);
+}
+
+void
+AudioTimeAxisView::build_display_menu ()
+{
+ using namespace Menu_Helpers;
+
+ /* get the size menu ready */
+
+ build_size_menu ();
+
+ /* prepare it */
+
+ TimeAxisView::build_display_menu ();
+
+ /* now fill it with our stuff */
+
+ MenuList& items = display_menu->items();
+ display_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Height"), *size_menu));
+ items.push_back (MenuElem (_("Color"), slot (*this, &AudioTimeAxisView::select_track_color)));
+
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Hide all crossfades"), slot (*this, &AudioTimeAxisView::hide_all_xfades)));
+ items.push_back (MenuElem (_("Show all crossfades"), slot (*this, &AudioTimeAxisView::show_all_xfades)));
+ items.push_back (SeparatorElem());
+
+
+ automation_action_menu = manage (new Menu);
+ MenuList& automation_items = automation_action_menu->items();
+ automation_action_menu->set_name ("ArdourContextMenu");
+
+ automation_items.push_back (MenuElem (_("show all automation"),
+ slot (*this, &AudioTimeAxisView::show_all_automation)));
+
+ automation_items.push_back (MenuElem (_("show existing automation"),
+ slot (*this, &AudioTimeAxisView::show_existing_automation)));
+
+ automation_items.push_back (MenuElem (_("hide all automation"),
+ slot (*this, &AudioTimeAxisView::hide_all_automation)));
+
+ automation_items.push_back (SeparatorElem());
+
+ automation_items.push_back (CheckMenuElem (_("gain"),
+ slot (*this, &AudioTimeAxisView::toggle_gain_track)));
+ gain_automation_item = static_cast<CheckMenuItem*> (automation_items.back());
+ gain_automation_item->set_active(show_gain_automation);
+
+ automation_items.push_back (CheckMenuElem (_("pan"),
+ slot (*this, &AudioTimeAxisView::toggle_pan_track)));
+ pan_automation_item = static_cast<CheckMenuItem*> (automation_items.back());
+ pan_automation_item->set_active(show_pan_automation);
+
+ automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu));
+
+ items.push_back (MenuElem (_("Automation"), *automation_action_menu));
+
+ Menu *waveform_menu = manage(new Menu);
+ MenuList& waveform_items = waveform_menu->items();
+ waveform_menu->set_name ("ArdourContextMenu");
+
+ waveform_items.push_back (CheckMenuElem (_("Show waveforms"), slot (*this, &AudioTimeAxisView::toggle_waveforms)));
+ waveform_item = static_cast<CheckMenuItem *> (waveform_items.back());
+ ignore_toggle = true;
+ waveform_item->set_active (editor.show_waveforms());
+ ignore_toggle = false;
+
+ RadioMenuItem::Group group;
+
+ waveform_items.push_back (RadioMenuElem (group, _("Traditional"), bind (slot (*this, &AudioTimeAxisView::set_waveform_shape), Traditional)));
+ traditional_item = static_cast<RadioMenuItem *> (waveform_items.back());
+
+ waveform_items.push_back (RadioMenuElem (group, _("Rectified"), bind (slot (*this, &AudioTimeAxisView::set_waveform_shape), Rectified)));
+ rectified_item = static_cast<RadioMenuItem *> (waveform_items.back());
+
+ items.push_back (MenuElem (_("Waveform"), *waveform_menu));
+
+ if (is_audio_track()) {
+
+ Menu* alignment_menu = manage (new Menu);
+ MenuList& alignment_items = alignment_menu->items();
+ alignment_menu->set_name ("ArdourContextMenu");
+
+ RadioMenuItem::Group align_group;
+
+ alignment_items.push_back (RadioMenuElem (align_group, _("align with existing material"), bind (slot (*this, &AudioTimeAxisView::set_align_style), ExistingMaterial)));
+ align_existing_item = dynamic_cast<RadioMenuItem*>(alignment_items.back());
+ if (get_diskstream()->alignment_style() == ExistingMaterial) {
+ align_existing_item->set_active();
+ }
+ alignment_items.push_back (RadioMenuElem (align_group, _("align with capture time"), bind (slot (*this, &AudioTimeAxisView::set_align_style), CaptureTime)));
+ align_capture_item = dynamic_cast<RadioMenuItem*>(alignment_items.back());
+ if (get_diskstream()->alignment_style() == CaptureTime) {
+ align_capture_item->set_active();
+ }
+
+ items.push_back (MenuElem (_("Alignment"), *alignment_menu));
+
+ get_diskstream()->AlignmentStyleChanged.connect (slot (*this, &AudioTimeAxisView::align_style_changed));
+ }
+
+ items.push_back (SeparatorElem());
+ items.push_back (CheckMenuElem (_("Active"), slot (*this, &RouteUI::toggle_route_active)));
+ route_active_menu_item = dynamic_cast<CheckMenuItem *> (items.back());
+ route_active_menu_item->set_active (_route.active());
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Remove"), slot (*this, &RouteUI::remove_this_route)));
+
+}
+
+void
+AudioTimeAxisView::align_style_changed ()
+{
+ switch (get_diskstream()->alignment_style()) {
+ case ExistingMaterial:
+ if (!align_existing_item->get_active()) {
+ align_existing_item->set_active();
+ }
+ break;
+ case CaptureTime:
+ if (!align_capture_item->get_active()) {
+ align_capture_item->set_active();
+ }
+ break;
+ }
+}
+
+void
+AudioTimeAxisView::set_align_style (AlignStyle style)
+{
+ get_diskstream()->set_align_style (style);
+}
+
+void
+AudioTimeAxisView::rename_current_playlist ()
+{
+ ArdourPrompter prompter (true);
+
+ AudioPlaylist *pl;
+ DiskStream *ds;
+
+ if (((ds = get_diskstream()) == 0) ||((pl = ds->playlist()) == 0)) {
+ return;
+ }
+
+ prompter.set_prompt (_("Name for playlist"));
+ prompter.set_initial_text (pl->name());
+ prompter.done.connect (Main::quit.slot());
+ prompter.show_all ();
+
+ Main::run ();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+ prompter.get_result (name);
+ pl->set_name (name);
+ }
+}
+
+void
+AudioTimeAxisView::playlist_selected (AudioPlaylist *pl)
+{
+ DiskStream *ds;
+
+ if ((ds = get_diskstream()) != 0) {
+ ds->use_playlist (pl);
+ }
+}
+
+void
+AudioTimeAxisView::use_copy_playlist ()
+{
+ AudioPlaylist *pl;
+ DiskStream *ds;
+
+ if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
+ return;
+ }
+
+ ArdourPrompter prompter (true);
+ string new_name = Playlist::bump_name (pl->name(), _session);
+
+ prompter.set_prompt (_("Name for playlist"));
+ prompter.set_initial_text (new_name);
+ prompter.done.connect (Main::quit.slot());
+ prompter.show_all ();
+
+ Main::run ();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+ prompter.get_result (name);
+
+ ds->use_copy_playlist ();
+
+ pl = ds->playlist();
+ pl->set_name (name);
+ }
+}
+
+void
+AudioTimeAxisView::use_new_playlist ()
+{
+ AudioPlaylist *pl;
+ DiskStream *ds;
+
+ if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) {
+ return;
+ }
+
+ ArdourPrompter prompter (true);
+ string new_name = Playlist::bump_name (pl->name(), _session);
+
+ prompter.set_prompt (_("Name for playlist"));
+ prompter.set_initial_text (new_name);
+ prompter.done.connect (Main::quit.slot());
+ prompter.show_all ();
+
+ Main::run ();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+ prompter.get_result (name);
+
+ ds->use_new_playlist ();
+
+ pl = ds->playlist();
+ pl->set_name (name);
+ }
+}
+
+void
+AudioTimeAxisView::clear_playlist ()
+{
+ AudioPlaylist *pl;
+ DiskStream *ds;
+
+ if ((ds = get_diskstream()) != 0) {
+ if ((pl = ds->playlist()) != 0) {
+ editor.clear_playlist (*pl);
+ }
+ }
+}
+
+void
+AudioTimeAxisView::toggle_waveforms ()
+{
+ if (view && waveform_item && !ignore_toggle) {
+ view->set_show_waveforms (waveform_item->is_active());
+ }
+}
+
+void
+AudioTimeAxisView::set_show_waveforms (bool yn)
+{
+ if (waveform_item) {
+ waveform_item->set_active (yn);
+ } else {
+ view->set_show_waveforms (yn);
+ }
+}
+
+void
+AudioTimeAxisView::set_show_waveforms_recording (bool yn)
+{
+ if (view) {
+ view->set_show_waveforms_recording (yn);
+ }
+}
+
+void
+AudioTimeAxisView::set_waveform_shape (WaveformShape shape)
+{
+ if (view) {
+ view->set_waveform_shape (shape);
+ }
+}
+
+void
+AudioTimeAxisView::speed_changed ()
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &AudioTimeAxisView::reset_samples_per_unit));
+}
+
+void
+AudioTimeAxisView::diskstream_changed (void *src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &AudioTimeAxisView::update_diskstream_display));
+}
+
+void
+AudioTimeAxisView::update_diskstream_display ()
+{
+ DiskStream *ds;
+
+ if ((ds = get_diskstream()) != 0) {
+ set_playlist (ds->playlist ());
+ }
+
+ map_frozen ();
+}
+
+void
+AudioTimeAxisView::selection_click (GdkEventButton* ev)
+{
+ PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group());
+
+ if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) {
+ if (editor.get_selection().selected (this)) {
+ editor.get_selection().remove (*tracks);
+ } else {
+ editor.get_selection().add (*tracks);
+ }
+ } else {
+ editor.get_selection().set (*tracks);
+ }
+
+ delete tracks;
+}
+
+void
+AudioTimeAxisView::set_selected_regionviews (AudioRegionSelection& regions)
+{
+ if (view) {
+ view->set_selected_regionviews (regions);
+ }
+}
+
+void
+AudioTimeAxisView::set_selected_points (PointSelection& points)
+{
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->set_selected_points (points);
+ }
+}
+
+void
+AudioTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results)
+{
+ double speed = 1.0;
+
+ if (get_diskstream() != 0) {
+ speed = get_diskstream()->speed();
+ }
+
+ jack_nframes_t start_adjusted = (jack_nframes_t) (start * speed);
+ jack_nframes_t end_adjusted = (jack_nframes_t) (end * speed);
+
+ if (view && touched (top, bot)) {
+ view->get_selectables (start_adjusted, end_adjusted, results);
+ }
+
+ /* pick up visible automation tracks */
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ if (!(*i)->hidden()) {
+ (*i)->get_selectables (start_adjusted, end_adjusted, top, bot, results);
+ }
+ }
+}
+
+void
+AudioTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
+{
+ if (view) {
+ view->get_inverted_selectables (sel, results);
+ }
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ if (!(*i)->hidden()) {
+ (*i)->get_inverted_selectables (sel, results);
+ }
+ }
+
+ return;
+}
+
+RouteGroup*
+AudioTimeAxisView::edit_group() const
+{
+ return _route.edit_group();
+}
+
+string
+AudioTimeAxisView::name() const
+{
+ return _route.name();
+}
+
+Playlist *
+AudioTimeAxisView::playlist () const
+{
+ DiskStream *ds;
+
+ if ((ds = get_diskstream()) != 0) {
+ return ds->playlist();
+ } else {
+ return 0;
+ }
+}
+
+gint
+AudioTimeAxisView::name_entry_button_press_handler (GdkEventButton *ev)
+{
+ if (ev->button == 3) {
+ return stop_signal (name_entry, "button_press_event");
+ }
+ return FALSE;
+}
+
+gint
+AudioTimeAxisView::name_entry_button_release_handler (GdkEventButton *ev)
+{
+ return FALSE;
+}
+
+gint
+AudioTimeAxisView::name_entry_focus_out_handler (GdkEventFocus* ev)
+{
+ name_entry_changed ();
+ return TRUE;
+}
+
+gint
+AudioTimeAxisView::name_entry_key_release_handler (GdkEventKey* ev)
+{
+ switch (ev->keyval) {
+ case GDK_Tab:
+ case GDK_Up:
+ case GDK_Down:
+ name_entry_changed ();
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+void
+AudioTimeAxisView::name_entry_activated ()
+{
+ /* this should drop focus from the entry,
+ and cause a call to name_entry_changed()
+ */
+ controls_ebox.grab_focus();
+}
+
+void
+AudioTimeAxisView::name_entry_changed ()
+{
+ string x;
+
+ ARDOUR_UI::generic_focus_out_event (0);
+
+ x = name_entry.get_text ();
+
+ if (x == _route.name()) {
+ return;
+ }
+
+ if (x.length() == 0) {
+ name_entry.set_text (_route.name());
+ return;
+ }
+
+ strip_whitespace_edges(x);
+
+ if (_session.route_name_unique (x)) {
+ _route.set_name (x, this);
+ } else {
+ ARDOUR_UI::instance()->popup_error (_("a track already exists with that name"));
+ name_entry.set_text (_route.name());
+ }
+}
+
+void
+AudioTimeAxisView::visual_click ()
+{
+ popup_display_menu (0);
+}
+
+void
+AudioTimeAxisView::hide_click ()
+{
+ editor.unselect_strip_in_display (*this);
+}
+
+Region*
+AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
+{
+ DiskStream *stream;
+ AudioPlaylist *playlist;
+
+ if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
+ return playlist->find_next_region (pos, point, dir);
+ }
+
+ return 0;
+}
+
+void
+AudioTimeAxisView::add_gain_automation_child ()
+{
+ XMLProperty* prop;
+ AutomationLine* line;
+
+ gain_track = new GainAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, _("gain"),
+ _route.gain_automation_curve());
+
+
+ line = new AutomationGainLine ("automation gain", _session, *gain_track,
+ gain_track->canvas_display,
+ _route.gain_automation_curve(),
+ PublicEditor::canvas_control_point_event,
+ PublicEditor::canvas_line_event);
+ line->set_line_color (color_map[cAutomationLine]);
+
+
+ gain_track->add_line (*line);
+
+ add_child (gain_track);
+
+ gain_track->Hiding.connect (slot (*this, &AudioTimeAxisView::gain_hidden));
+
+ bool hideit = true;
+
+ XMLNode* node;
+
+ if ((node = gain_track->get_state_node()) != 0) {
+ if ((prop = node->property ("shown")) != 0) {
+ if (prop->value() == "yes") {
+ hideit = false;
+ }
+ }
+ }
+
+ if (hideit) {
+ gain_track->hide ();
+ }
+}
+
+void
+AudioTimeAxisView::add_pan_automation_child ()
+{
+ XMLProperty* prop;
+
+ pan_track = new PanAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, _("pan"));
+
+ update_pans ();
+
+ add_child (pan_track);
+
+ pan_track->Hiding.connect (slot (*this, &AudioTimeAxisView::pan_hidden));
+
+ ensure_xml_node ();
+ bool hideit = true;
+
+ XMLNode* node;
+
+ if ((node = pan_track->get_state_node()) != 0) {
+ if ((prop = node->property ("shown")) != 0) {
+ if (prop->value() == "yes") {
+ hideit = false;
+ }
+ }
+ }
+
+ if (hideit) {
+ pan_track->hide ();
+ }
+}
+
+void
+AudioTimeAxisView::update_pans ()
+{
+ Panner::iterator p;
+
+ pan_track->clear_lines ();
+
+ /* we don't draw lines for "greater than stereo" panning.
+ */
+
+ if (_route.n_outputs() > 2) {
+ return;
+ }
+
+ for (p = _route.panner().begin(); p != _route.panner().end(); ++p) {
+
+ AutomationLine* line;
+
+ line = new AutomationPanLine ("automation pan", _session, *pan_track,
+ pan_track->canvas_display,
+ (*p)->automation(),
+ PublicEditor::canvas_control_point_event,
+ PublicEditor::canvas_line_event);
+
+ if (p == _route.panner().begin()) {
+ /* first line is a nice orange */
+ line->set_line_color (color_map[cLeftPanAutomationLine]);
+ } else {
+ /* second line is a nice blue */
+ line->set_line_color (color_map[cRightPanAutomationLine]);
+ }
+
+ pan_track->add_line (*line);
+ }
+}
+
+void
+AudioTimeAxisView::toggle_gain_track ()
+{
+
+ bool showit = gain_automation_item->get_active();
+
+ if (showit != gain_track->marked_for_display()) {
+ if (showit) {
+ gain_track->set_marked_for_display (true);
+ gtk_canvas_item_show (gain_track->canvas_display);
+ gain_track->get_state_node()->add_property ("shown", X_("yes"));
+ } else {
+ gain_track->set_marked_for_display (false);
+ gain_track->hide ();
+ gain_track->get_state_node()->add_property ("shown", X_("no"));
+ }
+
+ /* now trigger a redisplay */
+
+ if (!no_redraw) {
+ _route.gui_changed (X_("track_height"), (void *) 0); /* EMIT_SIGNAL */
+ }
+ }
+}
+
+void
+AudioTimeAxisView::gain_hidden ()
+{
+ gain_track->get_state_node()->add_property (X_("shown"), X_("no"));
+
+ if (gain_automation_item && !_hidden) {
+ gain_automation_item->set_active (false);
+ }
+
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+AudioTimeAxisView::toggle_pan_track ()
+{
+ bool showit = pan_automation_item->get_active();
+
+ if (showit != pan_track->marked_for_display()) {
+ if (showit) {
+ pan_track->set_marked_for_display (true);
+ gtk_canvas_item_show (pan_track->canvas_display);
+ pan_track->get_state_node()->add_property ("shown", X_("yes"));
+ } else {
+ pan_track->set_marked_for_display (false);
+ pan_track->hide ();
+ pan_track->get_state_node()->add_property ("shown", X_("no"));
+ }
+
+ /* now trigger a redisplay */
+
+ if (!no_redraw) {
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+ }
+ }
+}
+
+void
+AudioTimeAxisView::pan_hidden ()
+{
+ pan_track->get_state_node()->add_property ("shown", "no");
+
+ if (pan_automation_item && !_hidden) {
+ pan_automation_item->set_active (false);
+ }
+
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+AudioTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo ()
+{
+ for (vector<RedirectAutomationNode*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ delete *i;
+ }
+}
+
+
+AudioTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode ()
+{
+ parent.remove_ran (this);
+
+ if (view) {
+ delete view;
+ }
+}
+
+void
+AudioTimeAxisView::remove_ran (RedirectAutomationNode* ran)
+{
+ if (ran->view) {
+ remove_child (ran->view);
+ }
+}
+
+AudioTimeAxisView::RedirectAutomationNode*
+AudioTimeAxisView::find_redirect_automation_node (Redirect *redirect, uint32_t what)
+{
+ for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+
+ if ((*i)->redirect == redirect) {
+
+ for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+ if ((*ii)->what == what) {
+ return *ii;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static string
+legalize_for_xml_node (string str)
+{
+ string::size_type pos;
+ string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:";
+ string legal;
+
+ legal = str;
+ pos = 0;
+
+ while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) {
+ legal.replace (pos, 1, "_");
+ pos += 1;
+ }
+
+ return legal;
+}
+
+
+void
+AudioTimeAxisView::add_redirect_automation_curve (Redirect *redirect, uint32_t what)
+{
+ RedirectAutomationLine* ral;
+ string name;
+ RedirectAutomationNode* ran;
+
+ if ((ran = find_redirect_automation_node (redirect, what)) == 0) {
+ fatal << _("programming error: ")
+ << compose (X_("redirect automation curve for %1:%2 not registered with audio track!"),
+ redirect->name(), what)
+ << endmsg;
+ /*NOTREACHED*/
+ return;
+ }
+
+ if (ran->view) {
+ return;
+ }
+
+ name = redirect->describe_parameter (what);
+
+ /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
+
+ char state_name[256];
+ snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what);
+
+ ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name);
+
+ ral = new RedirectAutomationLine (name,
+ *redirect, what, _session, *ran->view,
+ ran->view->canvas_display, redirect->automation_list (what),
+ PublicEditor::canvas_control_point_event,
+ PublicEditor::canvas_line_event);
+
+ ral->set_line_color (color_map[cRedirectAutomationLine]);
+ ral->queue_reset ();
+
+ ran->view->add_line (*ral);
+
+ ran->view->Hiding.connect (bind (slot (*this, &AudioTimeAxisView::redirect_automation_track_hidden), ran, redirect));
+
+ if (!ran->view->marked_for_display()) {
+ ran->view->hide ();
+ } else {
+ ran->menu_item->set_active (true);
+ }
+
+ add_child (ran->view);
+
+ view->foreach_regionview (bind (slot (*this, &AudioTimeAxisView::add_ghost_to_redirect), ran->view));
+
+ redirect->mark_automation_visible (what, true);
+}
+
+void
+AudioTimeAxisView::redirect_automation_track_hidden (AudioTimeAxisView::RedirectAutomationNode* ran, Redirect* r)
+{
+ if (!_hidden) {
+ ran->menu_item->set_active (false);
+ }
+
+ r->mark_automation_visible (ran->what, false);
+
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+AudioTimeAxisView::add_existing_redirect_automation_curves (Redirect *redirect)
+{
+ set<uint32_t> s;
+ RedirectAutomationLine *ral;
+
+ redirect->what_has_visible_automation (s);
+
+ for (set<uint32_t>::iterator i = s.begin(); i != s.end(); ++i) {
+
+ if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) {
+ ral->queue_reset ();
+ } else {
+ add_redirect_automation_curve (redirect, (*i));
+ }
+ }
+}
+
+void
+AudioTimeAxisView::add_redirect_to_subplugin_menu (Redirect* r)
+{
+ using namespace Menu_Helpers;
+ RedirectAutomationInfo *rai;
+ list<RedirectAutomationInfo*>::iterator x;
+
+ const std::set<uint32_t>& automatable = r->what_can_be_automated ();
+ std::set<uint32_t> has_visible_automation;
+
+ r->what_has_visible_automation(has_visible_automation);
+
+ if (automatable.empty()) {
+ return;
+ }
+
+ for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) {
+ if ((*x)->redirect == r) {
+ break;
+ }
+ }
+
+ if (x == redirect_automation.end()) {
+
+ rai = new RedirectAutomationInfo (r);
+ redirect_automation.push_back (rai);
+
+ } else {
+
+ rai = *x;
+
+ }
+
+ /* any older menu was deleted at the top of redirects_changed()
+ when we cleared the subplugin menu.
+ */
+
+ rai->menu = manage (new Menu);
+ MenuList& items = rai->menu->items();
+ rai->menu->set_name ("ArdourContextMenu");
+
+ items.clear ();
+
+ for (std::set<uint32_t>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
+
+ RedirectAutomationNode* ran;
+ CheckMenuItem* mitem;
+
+ string name = r->describe_parameter (*i);
+
+ items.push_back (CheckMenuElem (name));
+ mitem = dynamic_cast<CheckMenuItem*> (items.back());
+
+ if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
+ mitem->set_active(true);
+ }
+
+ if ((ran = find_redirect_automation_node (r, *i)) == 0) {
+
+ /* new item */
+
+ ran = new RedirectAutomationNode (*i, mitem, *this);
+
+ rai->lines.push_back (ran);
+
+ } else {
+
+ ran->menu_item = mitem;
+
+ }
+
+ mitem->toggled.connect (bind (slot (*this, &AudioTimeAxisView::redirect_menu_item_toggled), rai, ran));
+ }
+
+ /* add the menu for this redirect, because the subplugin
+ menu is always cleared at the top of redirects_changed().
+ this is the result of some poor design in gtkmm and/or
+ GTK+.
+ */
+
+ subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu));
+ rai->valid = true;
+}
+
+void
+AudioTimeAxisView::redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo* rai,
+ AudioTimeAxisView::RedirectAutomationNode* ran)
+{
+ bool showit = ran->menu_item->get_active();
+ bool redraw = false;
+
+ if (ran->view == 0 && showit) {
+ add_redirect_automation_curve (rai->redirect, ran->what);
+ redraw = true;
+ }
+
+ if (showit != ran->view->marked_for_display()) {
+
+ if (showit) {
+ ran->view->set_marked_for_display (true);
+ gtk_canvas_item_show (ran->view->canvas_display);
+ } else {
+ rai->redirect->mark_automation_visible (ran->what, true);
+ ran->view->set_marked_for_display (false);
+ ran->view->hide ();
+ }
+
+ redraw = true;
+
+ }
+
+ if (redraw && !no_redraw) {
+
+ /* now trigger a redisplay */
+
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+
+ }
+}
+
+void
+AudioTimeAxisView::redirects_changed (void *src)
+{
+ using namespace Menu_Helpers;
+
+ for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+ (*i)->valid = false;
+ }
+
+ subplugin_menu.items().clear ();
+
+ _route.foreach_redirect (this, &AudioTimeAxisView::add_redirect_to_subplugin_menu);
+ _route.foreach_redirect (this, &AudioTimeAxisView::add_existing_redirect_automation_curves);
+
+ for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) {
+
+ list<RedirectAutomationInfo*>::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ if (!(*i)->valid) {
+
+ delete *i;
+ redirect_automation.erase (i);
+
+ }
+
+ i = tmp;
+ }
+
+ /* change in visibility was possible */
+
+ _route.gui_changed ("track_height", this);
+}
+
+RedirectAutomationLine *
+AudioTimeAxisView::find_redirect_automation_curve (Redirect *redirect, uint32_t what)
+{
+ RedirectAutomationNode* ran;
+
+ if ((ran = find_redirect_automation_node (redirect, what)) != 0) {
+ if (ran->view) {
+ return dynamic_cast<RedirectAutomationLine*> (ran->view->lines.front());
+ }
+ }
+
+ return 0;
+}
+
+void
+AudioTimeAxisView::show_all_automation ()
+{
+ no_redraw = true;
+
+ pan_automation_item->set_active (true);
+ gain_automation_item->set_active (true);
+
+ for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+ for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+ if ((*ii)->view == 0) {
+ add_redirect_automation_curve ((*i)->redirect, (*ii)->what);
+ }
+
+ (*ii)->menu_item->set_active (true);
+ }
+ }
+
+ no_redraw = false;
+
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+AudioTimeAxisView::show_existing_automation ()
+{
+ no_redraw = true;
+
+ pan_automation_item->set_active (true);
+ gain_automation_item->set_active (true);
+
+ for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+ for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+ if ((*ii)->view != 0) {
+ (*ii)->menu_item->set_active (true);
+ }
+ }
+ }
+
+ no_redraw = false;
+
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+void
+AudioTimeAxisView::hide_all_automation ()
+{
+ no_redraw = true;
+
+ pan_automation_item->set_active (false);
+ gain_automation_item->set_active (false);
+
+ for (list<RedirectAutomationInfo*>::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) {
+ for (vector<RedirectAutomationNode*>::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) {
+ (*ii)->menu_item->set_active (false);
+ }
+ }
+
+ no_redraw = false;
+ _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+}
+
+bool
+AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
+{
+ Playlist* what_we_got;
+ DiskStream* ds = get_diskstream();
+ Playlist* playlist;
+ bool ret = false;
+
+ if (ds == 0) {
+ /* route is a bus, not a track */
+ return false;
+ }
+
+ playlist = ds->playlist();
+
+
+ TimeSelection time (selection.time);
+ float speed = ds->speed();
+ if (speed != 1.0f) {
+ for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) {
+ (*i).start = (jack_nframes_t)floor( (float) (*i).start * speed);
+ (*i).end = (jack_nframes_t)floor( (float) (*i).end * speed);
+ }
+ }
+
+ switch (op) {
+ case Cut:
+ _session.add_undo (playlist->get_memento());
+ if ((what_we_got = playlist->cut (time)) != 0) {
+ editor.get_cut_buffer().add (what_we_got);
+ _session.add_redo_no_execute (playlist->get_memento());
+ ret = true;
+ }
+ break;
+ case Copy:
+ if ((what_we_got = playlist->copy (time)) != 0) {
+ editor.get_cut_buffer().add (what_we_got);
+ }
+ break;
+
+ case Clear:
+ _session.add_undo (playlist->get_memento());
+ if ((what_we_got = playlist->cut (time)) != 0) {
+ _session.add_redo_no_execute (playlist->get_memento());
+ what_we_got->unref ();
+ ret = true;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+bool
+AudioTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection, size_t nth)
+{
+ if (!is_audio_track()) {
+ return false;
+ }
+
+ Playlist* playlist = get_diskstream()->playlist();
+ PlaylistSelection::iterator p;
+
+ for (p = selection.playlists.begin(); p != selection.playlists.end() && nth; ++p, --nth);
+
+ if (p == selection.playlists.end()) {
+ return false;
+ }
+
+ if (get_diskstream()->speed() != 1.0f)
+ pos = (jack_nframes_t) floor( (float) pos * get_diskstream()->speed() );
+
+ _session.add_undo (playlist->get_memento());
+ playlist->paste (**p, pos, times);
+ _session.add_redo_no_execute (playlist->get_memento());
+
+ return true;
+}
+
+void
+AudioTimeAxisView::region_view_added (AudioRegionView* arv)
+{
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ AutomationTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AutomationTimeAxisView*> (*i)) != 0) {
+ arv->add_ghost (*atv);
+ }
+ }
+}
+
+void
+AudioTimeAxisView::add_ghost_to_redirect (AudioRegionView* arv, AutomationTimeAxisView* atv)
+{
+ arv->add_ghost (*atv);
+}
+
+list<TimeAxisView*>
+AudioTimeAxisView::get_child_list()
+{
+
+ list<TimeAxisView*>redirect_children;
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ if (!(*i)->hidden()) {
+ redirect_children.push_back(*i);
+ }
+ }
+ return redirect_children;
+}
+
+
+void
+AudioTimeAxisView::build_playlist_menu (Gtk::Menu * menu)
+{
+ using namespace Menu_Helpers;
+
+ if (!menu || !is_audio_track()) {
+ return;
+ }
+
+ MenuList& playlist_items = menu->items();
+ menu->set_name ("ArdourContextMenu");
+ playlist_items.clear();
+
+ if (playlist_menu) {
+ delete playlist_menu;
+ }
+ playlist_menu = new Menu;
+ playlist_menu->set_name ("ArdourContextMenu");
+
+ playlist_items.push_back (MenuElem (compose (_("Current: %1"), get_diskstream()->playlist()->name())));
+ playlist_items.push_back (SeparatorElem());
+
+ playlist_items.push_back (MenuElem (_("Rename"), slot (*this, &AudioTimeAxisView::rename_current_playlist)));
+ playlist_items.push_back (SeparatorElem());
+
+ playlist_items.push_back (MenuElem (_("New"), slot (*this, &AudioTimeAxisView::use_new_playlist)));
+ playlist_items.push_back (MenuElem (_("New Copy"), slot(*this, &AudioTimeAxisView::use_copy_playlist)));
+ playlist_items.push_back (SeparatorElem());
+ playlist_items.push_back (MenuElem (_("Clear Current"), slot (*this, &AudioTimeAxisView::clear_playlist)));
+ playlist_items.push_back (SeparatorElem());
+ playlist_items.push_back (MenuElem(_("Select"), slot (*this, &AudioTimeAxisView::show_playlist_selector)));
+
+}
+
+void
+AudioTimeAxisView::show_playlist_selector ()
+{
+ editor.playlist_selector().show_for (this);
+}
+
+
+void
+AudioTimeAxisView::map_frozen ()
+{
+ if (!is_audio_track()) {
+ return;
+ }
+
+ ENSURE_GUI_THREAD (slot (*this, &AudioTimeAxisView::map_frozen));
+
+
+ switch (audio_track()->freeze_state()) {
+ case AudioTrack::Frozen:
+ playlist_button.set_sensitive (false);
+ rec_enable_button->set_sensitive (false);
+ break;
+ default:
+ playlist_button.set_sensitive (true);
+ rec_enable_button->set_sensitive (true);
+ break;
+ }
+}
+
+void
+AudioTimeAxisView::show_all_xfades ()
+{
+ if (view) {
+ view->show_all_xfades ();
+ }
+}
+
+void
+AudioTimeAxisView::hide_all_xfades ()
+{
+ if (view) {
+ view->hide_all_xfades ();
+ }
+}
+
+void
+AudioTimeAxisView::hide_dependent_views (TimeAxisViewItem& tavi)
+{
+ AudioRegionView* rv;
+
+ if (view && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) {
+ view->hide_xfades_involving (*rv);
+ }
+}
+
+void
+AudioTimeAxisView::reveal_dependent_views (TimeAxisViewItem& tavi)
+{
+ AudioRegionView* rv;
+
+ if (view && (rv = dynamic_cast<AudioRegionView*>(&tavi)) != 0) {
+ view->reveal_xfades_involving (*rv);
+ }
+}
+
+void
+AudioTimeAxisView::route_active_changed ()
+{
+ RouteUI::route_active_changed ();
+
+ if (is_audio_track()) {
+ if (_route.active()) {
+ controls_ebox.set_name ("AudioTrackControlsBaseUnselected");
+ controls_base_selected_name = "AudioTrackControlsBaseSelected";
+ controls_base_unselected_name = "AudioTrackControlsBaseUnselected";
+ } else {
+ controls_ebox.set_name ("AudioTrackControlsBaseInactiveUnselected");
+ controls_base_selected_name = "AudioTrackControlsBaseInactiveSelected";
+ controls_base_unselected_name = "AudioTrackControlsBaseInactiveUnselected";
+ }
+ } else {
+ if (_route.active()) {
+ controls_ebox.set_name ("BusControlsBaseUnselected");
+ controls_base_selected_name = "BusControlsBaseSelected";
+ controls_base_unselected_name = "BusControlsBaseUnselected";
+ } else {
+ controls_ebox.set_name ("BusControlsBaseInactiveUnselected");
+ controls_base_selected_name = "BusControlsBaseInactiveSelected";
+ controls_base_unselected_name = "BusControlsBaseInactiveUnselected";
+ }
+ }
+}
+
+XMLNode*
+AudioTimeAxisView::get_child_xml_node (std::string childname)
+{
+ return RouteUI::get_child_xml_node (childname);
+}
diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h
new file mode 100644
index 0000000000..678459072b
--- /dev/null
+++ b/gtk2_ardour/audio_time_axis.h
@@ -0,0 +1,331 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_trackview_h__
+#define __ardour_trackview_h__
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/popup_selector.h>
+#include <list>
+
+#include <ardour/types.h>
+#include <ardour/region.h>
+
+#include "ardour_dialog.h"
+#include "route_ui.h"
+#include "enums.h"
+#include "time_axis_view.h"
+
+namespace ALSA {
+ class MultiChannelDevice;
+}
+
+namespace ARDOUR {
+ class Session;
+ class DiskStream;
+ class RouteGroup;
+ class Redirect;
+ class Insert;
+ class Location;
+ class AudioPlaylist;
+}
+
+namespace LADSPA {
+ class Manager;
+ class Plugin;
+}
+
+class PublicEditor;
+class AudioThing;
+class StreamView;
+class Selection;
+class Selectable;
+class AudioRegionView;
+class AutomationLine;
+class AutomationGainLine;
+class AutomationPanLine;
+class RedirectAutomationLine;
+class TimeSelection;
+class AutomationTimeAxisView;
+
+class AudioTimeAxisView : public RouteUI, public TimeAxisView
+{
+ public:
+ AudioTimeAxisView (PublicEditor&, ARDOUR::Session&, ARDOUR::Route&, Gtk::Widget *canvas);
+ virtual ~AudioTimeAxisView ();
+
+ void show_selection (TimeSelection&);
+ void automation_control_point_changed (ARDOUR::AutomationType);
+
+ void set_samples_per_unit (double);
+ void set_height (TimeAxisView::TrackHeight);
+ void set_show_waveforms (bool yn);
+ void set_show_waveforms_recording (bool yn);
+ void show_timestretch (jack_nframes_t start, jack_nframes_t end);
+ void hide_timestretch ();
+ void selection_click (GdkEventButton*);
+ void set_selected_regionviews (AudioRegionSelection&);
+ void set_selected_points (PointSelection&);
+ void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&);
+ void get_inverted_selectables (Selection&, list<Selectable*>&);
+ void show_all_xfades ();
+ void hide_all_xfades ();
+ void hide_dependent_views (TimeAxisViewItem&);
+ void reveal_dependent_views (TimeAxisViewItem&);
+
+ ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir);
+
+ string name() const;
+
+ ARDOUR::RouteGroup* edit_group() const;
+
+ void build_playlist_menu (Gtk::Menu *);
+ ARDOUR::Playlist* playlist() const;
+
+ /* overridden from parent to store display state */
+ guint32 show_at (double y, int& nth, Gtk::VBox *parent);
+ void hide ();
+
+ /* need accessors/mutators */
+
+ StreamView *view;
+
+ /* editing operations */
+
+ bool cut_copy_clear (Selection&, Editing::CutCopyOp);
+ bool paste (jack_nframes_t, float times, Selection&, size_t nth);
+
+ list<TimeAxisView*>get_child_list();
+
+ void set_state (const XMLNode&);
+ XMLNode* get_child_xml_node (std::string childname);
+
+ private:
+ friend class StreamView;
+ friend class AudioRegionView;
+
+ Gtk::Widget* parent_canvas;
+
+ bool no_redraw;
+
+ AutomationTimeAxisView *gain_track;
+ AutomationTimeAxisView *pan_track;
+
+ void update_automation_view (ARDOUR::AutomationType);
+ void reset_redirect_automation_curves ();
+
+ Gtk::HBox other_button_hbox;
+
+ Gtk::Table button_table;
+
+ Gtk::Button redirect_button;
+ Gtk::Button edit_group_button;
+ Gtk::Button playlist_button;
+ Gtk::Button size_button;
+ Gtk::Button automation_button;
+ Gtk::Button hide_button;
+ Gtk::Button visual_button;
+
+ void route_active_changed ();
+
+ void diskstream_changed (void *src);
+ void update_diskstream_display ();
+
+ gint edit_click (GdkEventButton *);
+
+ /* Redirect handling */
+
+ ArdourDialog redirect_window;
+ Gtk::CList redirect_display;
+ Gtk::Button redirect_add_button;
+ Gtk::Button redirect_remove_button;
+ Gtk::Button redirect_up_button;
+ Gtk::Button redirect_down_button;
+ Gtk::Button redirect_edit_button;
+ Gtk::HBox redirect_button_box;
+ Gtk::VBox redirect_vpacker;
+ Gtk::HBox redirect_display_hpacker;
+
+ int redirect_selected_row;
+
+
+ // variables to get the context menu
+ // automation buttons correctly initialized
+ bool show_gain_automation;
+ bool show_pan_automation;
+
+ void build_redirect_window ();
+ void redirect_click ();
+ void redirect_add ();
+ void redirect_remove ();
+ void redirect_edit ();
+ void redirect_relist ();
+ void redirect_row_selected (gint row, gint col, GdkEvent *ev);
+ void add_to_redirect_display (ARDOUR::Redirect *);
+ void redirects_changed (void *);
+
+ SigC::Connection modified_connection;
+ SigC::Connection state_changed_connection;
+
+ void take_name_changed (void *);
+ void route_name_changed (void *);
+ void name_entry_activated ();
+ void name_entry_changed ();
+ gint name_entry_focus_out_handler (GdkEventFocus*);
+ gint name_entry_key_release_handler (GdkEventKey*);
+ gint name_entry_button_release_handler (GdkEventButton*);
+ gint name_entry_button_press_handler (GdkEventButton*);
+ void on_area_realize ();
+
+ virtual void label_view ();
+
+ Gtk::Menu edit_group_menu;
+ Gtk::RadioMenuItem::Group edit_group_menu_radio_group;
+
+ void add_edit_group_menu_item (ARDOUR::RouteGroup *);
+ void set_edit_group_from_menu (ARDOUR::RouteGroup *);
+
+ void reset_samples_per_unit ();
+
+ void select_track_color();
+
+ virtual void build_display_menu ();
+
+ Gtk::CheckMenuItem* waveform_item;
+ Gtk::RadioMenuItem* traditional_item;
+ Gtk::RadioMenuItem* rectified_item;
+
+ Gtk::RadioMenuItem* align_existing_item;
+ Gtk::RadioMenuItem* align_capture_item;
+
+ void align_style_changed ();
+ void set_align_style (ARDOUR::AlignStyle);
+
+ void toggle_show_waveforms ();
+
+ void set_waveform_shape (WaveformShape);
+ void toggle_waveforms ();
+
+ Gtk::Menu *playlist_menu;
+ Gtk::Menu *playlist_action_menu;
+ Gtk::MenuItem *playlist_item;
+
+ /* playlist */
+
+ void set_playlist (ARDOUR::AudioPlaylist *);
+ void playlist_click ();
+ void show_playlist_selector ();
+
+ void playlist_changed ();
+ void playlist_state_changed (ARDOUR::Change);
+ void playlist_modified ();
+
+ void add_playlist_to_playlist_menu (ARDOUR::Playlist*);
+ void playlist_selected (ARDOUR::AudioPlaylist*);
+ void use_new_playlist ();
+ void use_copy_playlist ();
+ void clear_playlist ();
+ void rename_current_playlist ();
+
+ /* automation stuff */
+
+ Gtk::Menu* automation_action_menu;
+ Gtk::CheckMenuItem* gain_automation_item;
+ Gtk::CheckMenuItem* pan_automation_item;
+
+ void automation_click ();
+ void clear_automation ();
+ void hide_all_automation ();
+ void show_all_automation ();
+ void show_existing_automation ();
+
+ struct RedirectAutomationNode {
+ uint32_t what;
+ Gtk::CheckMenuItem* menu_item;
+ AutomationTimeAxisView* view;
+ AudioTimeAxisView& parent;
+
+ RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, AudioTimeAxisView& p)
+ : what (w), menu_item (mitem), view (0), parent (p) {}
+
+ ~RedirectAutomationNode ();
+ };
+
+ struct RedirectAutomationInfo {
+ ARDOUR::Redirect* redirect;
+ bool valid;
+ Gtk::Menu* menu;
+ vector<RedirectAutomationNode*> lines;
+
+ RedirectAutomationInfo (ARDOUR::Redirect* r)
+ : redirect (r), valid (true) {}
+
+ ~RedirectAutomationInfo ();
+ };
+
+ list<RedirectAutomationInfo*> redirect_automation;
+ RedirectAutomationNode* find_redirect_automation_node (ARDOUR::Redirect *redirect, uint32_t what);
+
+ Gtk::Menu subplugin_menu;
+ void add_redirect_to_subplugin_menu (ARDOUR::Redirect *);
+
+ void remove_ran (RedirectAutomationNode* ran);
+
+ void redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo*,
+ AudioTimeAxisView::RedirectAutomationNode*);
+ void redirect_automation_track_hidden (RedirectAutomationNode*, ARDOUR::Redirect*);
+
+ vector<RedirectAutomationLine*> redirect_automation_curves;
+ RedirectAutomationLine *find_redirect_automation_curve (ARDOUR::Redirect*,uint32_t);
+ void add_redirect_automation_curve (ARDOUR::Redirect*, uint32_t);
+ void add_existing_redirect_automation_curves (ARDOUR::Redirect*);
+
+ GtkCanvasItem *timestretch_rect;
+
+ void timestretch (jack_nframes_t start, jack_nframes_t end);
+
+ void visual_click ();
+ void hide_click ();
+ gint when_displayed (GdkEventAny*);
+
+ void speed_changed ();
+
+ void add_gain_automation_child ();
+ void add_pan_automation_child ();
+ void add_parameter_automation_child ();
+
+ void toggle_gain_track ();
+ void toggle_pan_track ();
+
+ void gain_hidden ();
+ void pan_hidden ();
+
+ void update_pans ();
+
+ void region_view_added (AudioRegionView*);
+ void add_ghost_to_redirect (AudioRegionView*, AutomationTimeAxisView*);
+
+ void map_frozen ();
+};
+
+#endif /* __ardour_trackview_h__ */
+
diff --git a/gtk2_ardour/automation_gain_line.cc b/gtk2_ardour/automation_gain_line.cc
new file mode 100644
index 0000000000..8331d983d7
--- /dev/null
+++ b/gtk2_ardour/automation_gain_line.cc
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2000-2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <sigc++/signal_system.h>
+
+#include <ardour/curve.h>
+#include <pbd/fastlog.h>
+
+#include "public_editor.h"
+#include "automation_gain_line.h"
+#include "utils.h"
+
+#include <ardour/session.h>
+
+using namespace std;
+using namespace ARDOUR;
+
+AutomationGainLine::AutomationGainLine (string name, Session& s, TimeAxisView& tv, GtkCanvasItem* parent,
+ Curve& c,
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer))
+ : AutomationLine (name, tv, parent, c, point_callback, line_callback),
+ session (s)
+{
+ set_verbose_cursor_uses_gain_mapping (true);
+}
+
+void
+AutomationGainLine::view_to_model_y (double& y)
+{
+ y = slider_position_to_gain (y);
+ y = max (0.0, y);
+ y = min (2.0, y);
+}
+
+void
+AutomationGainLine::model_to_view_y (double& y)
+{
+ y = gain_to_slider_position (y);
+}
+
+
+
diff --git a/gtk2_ardour/automation_gain_line.h b/gtk2_ardour/automation_gain_line.h
new file mode 100644
index 0000000000..058576336a
--- /dev/null
+++ b/gtk2_ardour/automation_gain_line.h
@@ -0,0 +1,36 @@
+#ifndef __ardour_gtk_automation_gain_line_h__
+#define __ardour_gtk_automation_gain_line_h__
+
+#include <ardour/ardour.h>
+#include <gtk-canvas.h>
+#include <gtk--.h>
+
+#include "automation_line.h"
+
+namespace ARDOUR {
+ class Session;
+}
+
+
+class TimeAxisView;
+
+class AutomationGainLine : public AutomationLine
+{
+ public:
+ AutomationGainLine (string name, ARDOUR::Session&, TimeAxisView&, GtkCanvasItem* parent,
+ ARDOUR::Curve&,
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer));
+
+ void view_to_model_y (double&);
+ void model_to_view_y (double&);
+
+ private:
+ ARDOUR::Session& session;
+
+};
+
+
+#endif /* __ardour_gtk_automation_gain_line_h__ */
+
+
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
new file mode 100644
index 0000000000..1b9309e7e0
--- /dev/null
+++ b/gtk2_ardour/automation_line.cc
@@ -0,0 +1,1293 @@
+/*
+ Copyright (C) 2002-2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <climits>
+#include <vector>
+
+#include <pbd/stl_delete.h>
+
+#include <ardour/automation_event.h>
+#include <ardour/curve.h>
+#include <ardour/dB.h>
+
+#include "canvas-simplerect.h"
+#include "automation_line.h"
+#include "rgb_macros.h"
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "utils.h"
+#include "selection.h"
+#include "time_axis_view.h"
+#include "point_selection.h"
+#include "automation_selectable.h"
+#include "automation_time_axis.h"
+#include "public_editor.h"
+
+#include <ardour/session.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace Editing;
+
+ControlPoint::ControlPoint (AutomationLine& al, gint (*event_handler)(GtkCanvasItem*, GdkEvent*, gpointer))
+ : line (al)
+{
+ model = al.the_list().end();
+ view_index = 0;
+ can_slide = true;
+ _x = 0;
+ _y = 0;
+ _shape = Full;
+ _size = 4.0;
+ selected = false;
+
+ item = gtk_canvas_item_new (line.canvas_group(),
+ gtk_canvas_simplerect_get_type(),
+ "draw", (gboolean) TRUE,
+ "fill", (gboolean) FALSE,
+ "fill_color_rgba", color_map[cControlPointFill],
+ "outline_color_rgba", color_map[cControlPointOutline],
+ "outline_pixels", (gint) 1,
+ NULL);
+
+ gtk_object_set_data (GTK_OBJECT(item), "control_point", this);
+ gtk_signal_connect (GTK_OBJECT(item), "event", (GtkSignalFunc) event_handler, this);
+
+ hide ();
+ set_visible (false);
+}
+
+ControlPoint::ControlPoint (const ControlPoint& other, bool dummy_arg_to_force_special_copy_constructor)
+ : line (other.line)
+{
+ if (&other == this) {
+ return;
+ }
+
+ model = other.model;
+ view_index = other.view_index;
+ can_slide = other.can_slide;
+ _x = other._x;
+ _y = other._y;
+ _shape = other._shape;
+ _size = other._size;
+ selected = false;
+
+ item = gtk_canvas_item_new (line.canvas_group(),
+ gtk_canvas_simplerect_get_type(),
+ "fill", (gboolean) FALSE,
+ "outline_color_rgba", color_map[cEnteredControlPointOutline],
+ "outline_pixels", (gint) 1,
+ NULL);
+
+ /* NOTE: no event handling in copied ControlPoints */
+
+ hide ();
+ set_visible (false);
+}
+
+ControlPoint::~ControlPoint ()
+{
+ gtk_object_destroy (GTK_OBJECT(item));
+}
+
+void
+ControlPoint::hide ()
+{
+ gtk_canvas_item_hide (item);
+}
+
+void
+ControlPoint::show()
+{
+ gtk_canvas_item_show (item);
+}
+
+void
+ControlPoint::set_visible (bool yn)
+{
+ gtk_canvas_item_set (item, "draw", (gboolean) yn, NULL);
+}
+
+void
+ControlPoint::reset (double x, double y, AutomationList::iterator mi, uint32_t vi, ShapeType shape)
+{
+ model = mi;
+ view_index = vi;
+ move_to (x, y, shape);
+}
+
+void
+ControlPoint::show_color (bool entered, bool hide_too)
+{
+ if (entered) {
+ if (selected) {
+ gtk_canvas_item_set (item, "outline_color_rgba", color_map[cEnteredControlPointSelected], NULL);
+ set_visible(true);
+ } else {
+ gtk_canvas_item_set (item, "outline_color_rgba", color_map[cEnteredControlPoint], NULL);
+ if (hide_too) {
+ set_visible(false);
+ }
+ }
+
+ } else {
+ if (selected) {
+ gtk_canvas_item_set (item, "outline_color_rgba", color_map[cControlPointSelected], NULL);
+ set_visible(true);
+ } else {
+ gtk_canvas_item_set (item, "outline_color_rgba", color_map[cControlPoint], NULL);
+ if (hide_too) {
+ set_visible(false);
+ }
+ }
+ }
+}
+
+void
+ControlPoint::set_size (double sz)
+{
+ _size = sz;
+
+#if 0
+ if (_size > 6.0) {
+ gtk_canvas_item_set (item,
+ "fill", (gboolean) TRUE,
+ NULL);
+ } else {
+ gtk_canvas_item_set (item,
+ "fill", (gboolean) FALSE,
+ NULL);
+ }
+#endif
+
+ move_to (_x, _y, _shape);
+}
+
+void
+ControlPoint::move_to (double x, double y, ShapeType shape)
+{
+ double x1 = 0;
+ double x2 = 0;
+ double half_size = rint(_size/2.0);
+
+ switch (shape) {
+ case Full:
+ x1 = x - half_size;
+ x2 = x + half_size;
+ break;
+ case Start:
+ x1 = x;
+ x2 = x + half_size;
+ break;
+ case End:
+ x1 = x - half_size;
+ x2 = x;
+ break;
+ }
+
+ gtk_canvas_item_set (item,
+ "x1", x1,
+ "x2", x2,
+ "y1", y - half_size,
+ "y2", y + half_size,
+ NULL);
+
+ _x = x;
+ _y = y;
+ _shape = shape;
+}
+
+/*****/
+
+AutomationLine::AutomationLine (string name, TimeAxisView& tv, GtkCanvasItem* parent, AutomationList& al,
+ gint (*point_handler)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_handler)(GtkCanvasItem*, GdkEvent*, gpointer))
+ : trackview (tv),
+ _name (name),
+ alist (al)
+{
+ point_coords = 0;
+ points_visible = false;
+ update_pending = false;
+ _vc_uses_gain_mapping = false;
+ no_draw = false;
+ _visible = true;
+ point_callback = point_handler;
+ _parent_group = parent;
+ terminal_points_can_slide = true;
+ _height = 0;
+
+ group = gtk_canvas_item_new (GTK_CANVAS_GROUP(parent),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", 0.0,
+ NULL);
+
+ line = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_line_get_type(),
+ "width_pixels", (guint) 1,
+ NULL);
+
+ // cerr << _name << " line @ " << line << endl;
+
+ gtk_object_set_data (GTK_OBJECT(line), "line", this);
+ gtk_signal_connect (GTK_OBJECT(line), "event", (GtkSignalFunc) line_handler, this);
+
+ alist.StateChanged.connect (slot (*this, &AutomationLine::list_changed));
+}
+
+AutomationLine::~AutomationLine ()
+{
+ if (point_coords) {
+ gtk_canvas_points_unref (point_coords);
+ }
+
+ vector_delete (&control_points);
+
+ gtk_object_destroy (GTK_OBJECT(group));
+}
+
+void
+AutomationLine::queue_reset ()
+{
+ if (!update_pending) {
+ update_pending = true;
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &AutomationLine::reset));
+ }
+}
+
+void
+AutomationLine::set_point_size (double sz)
+{
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ (*i)->set_size (sz);
+ }
+}
+
+void
+AutomationLine::show ()
+{
+ gtk_canvas_item_show (line);
+
+ if (points_visible) {
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ (*i)->show ();
+ }
+ }
+
+ _visible = true;
+}
+
+void
+AutomationLine::hide ()
+{
+ gtk_canvas_item_hide (line);
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ (*i)->hide();
+ }
+ _visible = false;
+}
+
+void
+AutomationLine::set_height (guint32 h)
+{
+ if (h != _height) {
+ _height = h;
+
+ if (_height > (guint32) TimeAxisView::Larger) {
+ set_point_size (8.0);
+ } else if (_height > (guint32) TimeAxisView::Normal) {
+ set_point_size (6.0);
+ } else {
+ set_point_size (4.0);
+ }
+
+ reset ();
+ }
+}
+
+void
+AutomationLine::set_line_color (uint32_t color)
+{
+ _line_color = color;
+ gtk_canvas_item_set (line, "fill_color_rgba", color, NULL);
+}
+
+void
+AutomationLine::set_verbose_cursor_uses_gain_mapping (bool yn)
+{
+ if (yn != _vc_uses_gain_mapping) {
+ _vc_uses_gain_mapping = yn;
+ reset ();
+ }
+}
+
+ControlPoint*
+AutomationLine::nth (uint32_t n)
+{
+ if (n < control_points.size()) {
+ return control_points[n];
+ } else {
+ return 0;
+ }
+}
+
+void
+AutomationLine::modify_view (ControlPoint& cp, double x, double y, bool with_push)
+{
+ modify_view_point (cp, x, y, with_push);
+ update_line ();
+}
+
+void
+AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool with_push)
+{
+ double delta = 0.0;
+ uint32_t last_movable = UINT_MAX;
+ double x_limit = DBL_MAX;
+
+ /* this just changes the current view. it does not alter
+ the model in any way at all.
+ */
+
+ /* clamp y-coord appropriately. y is supposed to be a normalized fraction (0.0-1.0),
+ and needs to be converted to a canvas unit distance.
+ */
+
+ y = max (0.0, y);
+ y = min (1.0, y);
+ y = _height - (y * _height);
+
+ if (cp.can_slide) {
+
+ /* x-coord cannot move beyond adjacent points or the start/end, and is
+ already in frames. it needs to be converted to canvas units.
+ */
+
+ x = trackview.editor.frame_to_unit (x);
+
+ /* clamp x position using view coordinates */
+
+ ControlPoint *before;
+ ControlPoint *after;
+
+ if (cp.view_index) {
+ before = nth (cp.view_index - 1);
+ x = max (x, before->get_x()+1.0);
+ } else {
+ before = &cp;
+ }
+
+
+ if (!with_push) {
+ if (cp.view_index < control_points.size() - 1) {
+
+ after = nth (cp.view_index + 1);
+
+ /*if it is a "spike" leave the x alone */
+
+ if (after->get_x() - before->get_x() < 2) {
+ x = cp.get_x();
+
+ } else {
+ x = min (x, after->get_x()-1.0);
+ }
+ } else {
+ after = &cp;
+ }
+
+ } else {
+
+ ControlPoint* after;
+
+ /* find the first point that can't move */
+
+ for (uint32_t n = cp.view_index + 1; (after = nth (n)) != 0; ++n) {
+ if (!after->can_slide) {
+ x_limit = after->get_x() - 1.0;
+ last_movable = after->view_index;
+ break;
+ }
+ }
+
+ delta = x - cp.get_x();
+ }
+
+ } else {
+
+ /* leave the x-coordinate alone */
+
+ x = trackview.editor.frame_to_unit ((*cp.model)->when);
+
+ }
+
+ if (!with_push) {
+
+ cp.move_to (x, y, ControlPoint::Full);
+ reset_line_coords (cp);
+
+ } else {
+
+ uint32_t limit = min (control_points.size(), (size_t)last_movable);
+
+ /* move the current point to wherever the user told it to go, subject
+ to x_limit.
+ */
+
+ cp.move_to (min (x, x_limit), y, ControlPoint::Full);
+ reset_line_coords (cp);
+
+ /* now move all subsequent control points, to reflect the motion.
+ */
+
+ for (uint32_t i = cp.view_index + 1; i < limit; ++i) {
+ ControlPoint *p = nth (i);
+ double new_x;
+
+ if (p->can_slide) {
+ new_x = min (p->get_x() + delta, x_limit);
+ p->move_to (new_x, p->get_y(), ControlPoint::Full);
+ reset_line_coords (*p);
+ }
+ }
+ }
+}
+
+void
+AutomationLine::reset_line_coords (ControlPoint& cp)
+{
+ if (point_coords) {
+ point_coords->coords[cp.view_index*2] = cp.get_x();
+ point_coords->coords[(cp.view_index*2) + 1] = cp.get_y();
+ }
+}
+
+void
+AutomationLine::update_line ()
+{
+ gtk_canvas_item_set (line, "points", point_coords, NULL);
+}
+
+void
+AutomationLine::sync_model_with_view_line (uint32_t start, uint32_t end)
+{
+
+ ControlPoint *p;
+
+ update_pending = true;
+
+ for (uint32_t i = start; i <= end; ++i) {
+ p = nth(i);
+ sync_model_with_view_point(*p);
+ }
+
+
+}
+
+void
+AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr)
+{
+ /* part one: find out where the visual control point is.
+ initial results are in canvas units. ask the
+ line to convert them to something relevant.
+ */
+
+ mr.xval = (jack_nframes_t) floor (cp.get_x());
+ mr.yval = 1.0 - (cp.get_y() / _height);
+
+
+ /* if xval has not changed, set it directly from the model to avoid rounding errors */
+
+ if (mr.xval == trackview.editor.frame_to_unit((*cp.model)->when)) {
+ mr.xval = (jack_nframes_t) (*cp.model)->when;
+ } else {
+ mr.xval = trackview.editor.unit_to_frame (mr.xval);
+ }
+
+
+ /* virtual call: this will do the right thing
+ for whatever particular type of line we are.
+ */
+
+ view_to_model_y (mr.yval);
+
+ /* part 2: find out where the model point is now
+ */
+
+ mr.xpos = (jack_nframes_t) (*cp.model)->when;
+ mr.ypos = (*cp.model)->value;
+
+ /* part 3: get the position of the visual control
+ points before and after us.
+ */
+
+ ControlPoint* before;
+ ControlPoint* after;
+
+ if (cp.view_index) {
+ before = nth (cp.view_index - 1);
+ } else {
+ before = 0;
+ }
+
+ after = nth (cp.view_index + 1);
+
+ if (before) {
+ mr.xmin = (jack_nframes_t) (*before->model)->when;
+ mr.ymin = (*before->model)->value;
+ mr.start = before->model;
+ ++mr.start;
+ } else {
+ mr.xmin = mr.xpos;
+ mr.ymin = mr.ypos;
+ mr.start = cp.model;
+ }
+
+ if (after) {
+ mr.end = after->model;
+ } else {
+ mr.xmax = mr.xpos;
+ mr.ymax = mr.ypos;
+ mr.end = cp.model;
+ ++mr.end;
+ }
+}
+
+void
+AutomationLine::sync_model_from (ControlPoint& cp)
+{
+ ControlPoint* p;
+ uint32_t lasti;
+
+ sync_model_with_view_point (cp);
+
+ /* we might have moved all points after `cp' by some amount
+ if we pressed the with_push modifyer some of the time during the drag
+ so all subsequent points have to be resynced
+ */
+
+ lasti = control_points.size() - 1;
+ p = nth (lasti);
+
+ update_pending = true;
+
+ while (p != &cp && lasti) {
+ sync_model_with_view_point (*p);
+ --lasti;
+ p = nth (lasti);
+ }
+}
+
+void
+AutomationLine::sync_model_with_view_point (ControlPoint& cp)
+{
+ ModelRepresentation mr;
+ double ydelta;
+
+ model_representation (cp, mr);
+
+ /* part 4: how much are we changing the central point by */
+
+ ydelta = mr.yval - mr.ypos;
+
+ /* IMPORTANT: changing the model when the x-coordinate changes
+ may invalidate the iterators that we are using. this means that we have
+ to change the points before+after the one corresponding to the visual CP
+ first (their x-coordinate doesn't change). then we change the
+ "main" point.
+
+ apply the full change to the central point, and interpolate
+ in each direction to cover all model points represented
+ by the control point.
+ */
+
+ /* part 5: change all points before the primary point */
+
+ for (AutomationList::iterator i = mr.start; i != cp.model; ++i) {
+
+ double delta;
+
+ delta = ydelta * ((*i)->when - mr.xmin) / (mr.xpos - mr.xmin);
+
+ /* x-coordinate (generally time) stays where it is,
+ y-coordinate moves by a certain amount.
+ */
+
+ update_pending = true;
+ change_model (i, (*i)->when, mr.yval + delta);
+ }
+
+ /* part 6: change later points */
+
+ AutomationList::iterator i = cp.model;
+
+ ++i;
+
+ while (i != mr.end) {
+
+ double delta;
+
+ delta = ydelta * (mr.xmax - (*i)->when) / (mr.xmax - mr.xpos);
+
+ /* x-coordinate (generally time) stays where it is,
+ y-coordinate moves by a certain amount.
+ */
+
+ update_pending = true;
+ change_model (i, (*i)->when, (*i)->value + delta);
+
+ ++i;
+ }
+
+ /* part 7: change the primary point */
+
+ update_pending = true;
+ change_model (cp.model, mr.xval, mr.yval);
+}
+
+void
+AutomationLine::determine_visible_control_points (GtkCanvasPoints* points)
+{
+ uint32_t xi, yi, view_index, pi;
+ int n;
+ AutomationList::iterator model;
+ uint32_t npoints = points->num_points;
+ double last_control_point_x = 0.0;
+ double last_control_point_y = 0.0;
+ uint32_t this_rx = 0;
+ uint32_t prev_rx = 0;
+ uint32_t this_ry = 0;
+ uint32_t prev_ry = 0;
+ double* slope;
+
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ (*i)->hide();
+ }
+ gtk_canvas_item_hide (line);
+
+ if (points == 0 || points->num_points == 0) {
+ return;
+ }
+
+ /* compute derivative/slope for the entire line */
+
+ slope = new double[npoints];
+
+ for (n = 0, xi = 2, yi = 3, view_index = 0; n < points->num_points - 1; xi += 2, yi +=2, ++n, ++view_index) {
+ double xdelta;
+ double ydelta;
+ xdelta = points->coords[xi] - points->coords[xi-2];
+ ydelta = points->coords[yi] - points->coords[yi-2];
+ slope[view_index] = ydelta/xdelta;
+ }
+
+ /* read all points and decide which ones to show as control points */
+
+ for (model = alist.begin(), pi = 0, xi = 0, yi = 1, view_index = 0; pi < npoints; ++model, xi += 2, yi +=2, ++pi) {
+
+ /* now ensure that the control_points vector reflects the current curve
+ state, but don't plot control points too close together. also, don't
+ plot a series of points all with the same value.
+
+ always plot the first and last points, of course.
+ */
+
+ if (invalid_point (points, pi)) {
+ /* for some reason, we are supposed to ignore this point,
+ but still keep track of the model index.
+ */
+ continue;
+ }
+
+ if (pi > 0 && pi < npoints - 1) {
+ if (slope[pi] == slope[pi-1]) {
+
+ /* no reason to display this point */
+
+ continue;
+ }
+ }
+
+ /* need to round here. the ultimate coordinates are integer
+ pixels, so tiny deltas in the coords will be eliminated
+ and we end up with "colinear" line segments. since the
+ line rendering code in libart doesn't like this very
+ much, we eliminate them here. don't do this for the first and last
+ points.
+ */
+
+ this_rx = (uint32_t) rint (points->coords[xi]);
+ this_ry = (unsigned long) rint (points->coords[yi]);
+
+ if (view_index && pi != npoints && (this_rx == prev_rx) && (this_ry == prev_ry)) {
+
+ continue;
+ }
+
+ /* ok, we should display this point */
+
+ if (view_index >= control_points.size()) {
+ /* make sure we have enough control points */
+
+ ControlPoint* ncp = new ControlPoint (*this, point_callback);
+
+ if (_height > (guint32) TimeAxisView::Larger) {
+ ncp->set_size (8.0);
+ } else if (_height > (guint32) TimeAxisView::Normal) {
+ ncp->set_size (6.0);
+ } else {
+ ncp->set_size (4.0);
+ }
+
+ control_points.push_back (ncp);
+ }
+
+ ControlPoint::ShapeType shape;
+
+ if (!terminal_points_can_slide) {
+ if (pi == 0) {
+ control_points[view_index]->can_slide = false;
+ if (points->coords[xi] == 0) {
+ shape = ControlPoint::Start;
+ } else {
+ shape = ControlPoint::Full;
+ }
+ } else if (pi == npoints - 1) {
+ control_points[view_index]->can_slide = false;
+ shape = ControlPoint::End;
+ } else {
+ control_points[view_index]->can_slide = true;
+ shape = ControlPoint::Full;
+ }
+ } else {
+ control_points[view_index]->can_slide = true;
+ shape = ControlPoint::Full;
+ }
+
+ control_points[view_index]->reset (points->coords[xi], points->coords[yi], model, view_index, shape);
+
+ last_control_point_x = points->coords[xi];
+ last_control_point_y = points->coords[yi];
+
+ prev_rx = this_rx;
+ prev_ry = this_ry;
+
+ /* finally, control visibility */
+
+ if (_visible && points_visible) {
+ control_points[view_index]->show ();
+ control_points[view_index]->set_visible (true);
+ } else {
+ if (!points_visible) {
+ control_points[view_index]->set_visible (false);
+ }
+ }
+
+ view_index++;
+ }
+
+ /* discard extra CP's to avoid confusing ourselves */
+
+ while (control_points.size() > view_index) {
+ ControlPoint* cp = control_points.back();
+ control_points.pop_back ();
+ delete cp;
+ }
+
+ if (!terminal_points_can_slide) {
+ control_points.back()->can_slide = false;
+ }
+
+ delete [] slope;
+
+ /* Now make sure the "point_coords" array is large enough
+ to represent all the visible points.
+ */
+
+ if (view_index > 1) {
+
+ npoints = view_index;
+
+ if (point_coords) {
+ if (point_coords->num_points < (int) npoints) {
+ gtk_canvas_points_unref (point_coords);
+ point_coords = get_canvas_points ("autoline", npoints);
+ } else {
+ point_coords->num_points = npoints;
+ }
+ } else {
+ point_coords = get_canvas_points ("autoline", npoints);
+ }
+
+ /* reset the line coordinates */
+
+ uint32_t pci;
+
+ for (pci = 0, view_index = 0; view_index < npoints; ++view_index) {
+ point_coords->coords[pci++] = control_points[view_index]->get_x();
+ point_coords->coords[pci++] = control_points[view_index]->get_y();
+ }
+
+ // cerr << "set al2 points, nc = " << point_coords->num_points << endl;
+ gtk_canvas_item_set (line, "points", point_coords, NULL);
+
+ if (_visible) {
+ gtk_canvas_item_show (line);
+ }
+ }
+
+ set_selected_points (trackview.editor.get_selection().points);
+}
+
+string
+AutomationLine::get_verbose_cursor_string (float fraction)
+{
+ char buf[32];
+
+ if (_vc_uses_gain_mapping) {
+ if (fraction == 0.0) {
+ snprintf (buf, sizeof (buf), "-inf dB");
+ } else {
+ snprintf (buf, sizeof (buf), "%.1fdB", coefficient_to_dB (slider_position_to_gain (fraction)));
+ }
+ } else {
+ snprintf (buf, sizeof (buf), "%.2f", fraction);
+ }
+
+ return buf;
+}
+
+bool
+AutomationLine::invalid_point (GtkCanvasPoints* p, uint32_t index)
+{
+ return p->coords[index*2] == max_frames && p->coords[(index*2)+1] == DBL_MAX;
+}
+
+void
+AutomationLine::invalidate_point (GtkCanvasPoints* p, uint32_t index)
+{
+ p->coords[index*2] = max_frames;
+ p->coords[(index*2)+1] = DBL_MAX;
+}
+
+void
+AutomationLine::start_drag (ControlPoint* cp, float fraction)
+{
+ if (trackview.editor.current_session() == 0) { /* how? */
+ return;
+ }
+
+ string str;
+
+ if (cp) {
+ str = _("automation event move");
+ } else {
+ str = _("automation range drag");
+ }
+
+ trackview.editor.current_session()->begin_reversible_command (str);
+ trackview.editor.current_session()->add_undo (get_memento());
+
+ first_drag_fraction = fraction;
+ last_drag_fraction = fraction;
+ drags = 0;
+}
+
+void
+AutomationLine::point_drag (ControlPoint& cp, jack_nframes_t x, float fraction, bool with_push)
+{
+ modify_view (cp, x, fraction, with_push);
+ drags++;
+}
+
+void
+AutomationLine::line_drag (uint32_t i1, uint32_t i2, float fraction, bool with_push)
+{
+ double ydelta = fraction - last_drag_fraction;
+
+ last_drag_fraction = fraction;
+
+ line_drag_cp1 = i1;
+ line_drag_cp2 = i2;
+
+ ControlPoint *cp;
+
+ for (uint32_t i = i1 ; i <= i2; i++) {
+ cp = nth (i);
+ modify_view_point (*cp, trackview.editor.unit_to_frame (cp->get_x()), ((_height - cp->get_y()) /_height) + ydelta, with_push);
+ }
+
+ update_line ();
+
+ drags++;
+}
+
+void
+AutomationLine::end_drag (ControlPoint* cp)
+{
+ if (drags) {
+
+ if (cp) {
+ sync_model_from (*cp);
+ } else {
+ sync_model_with_view_line (line_drag_cp1, line_drag_cp2);
+ }
+
+ update_pending = false;
+
+ trackview.editor.current_session()->add_redo_no_execute (get_memento());
+ trackview.editor.current_session()->commit_reversible_command ();
+ trackview.editor.current_session()->set_dirty ();
+ }
+}
+
+bool
+AutomationLine::control_points_adjacent (double xval, uint32_t & before, uint32_t& after)
+{
+ ControlPoint *bcp = 0;
+ ControlPoint *acp = 0;
+ double unit_xval;
+
+ /* xval is in frames */
+
+ unit_xval = trackview.editor.frame_to_unit (xval);
+
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+
+ if ((*i)->get_x() <= unit_xval) {
+
+ if (!bcp || (*i)->get_x() > bcp->get_x()) {
+ bcp = *i;
+ before = bcp->view_index;
+ }
+
+ } else if ((*i)->get_x() > unit_xval) {
+ acp = *i;
+ after = acp->view_index;
+ break;
+ }
+ }
+
+ return bcp && acp;
+}
+
+bool
+AutomationLine::is_last_point (ControlPoint& cp)
+{
+ ModelRepresentation mr;
+
+ model_representation (cp, mr);
+
+ // If the list is not empty, and the point is the last point in the list
+
+ if (!alist.empty() && mr.end == alist.end()) {
+ return true;
+ }
+
+ return false;
+}
+
+bool
+AutomationLine::is_first_point (ControlPoint& cp)
+{
+ ModelRepresentation mr;
+
+ model_representation (cp, mr);
+
+ // If the list is not empty, and the point is the first point in the list
+
+ if (!alist.empty() && mr.start == alist.begin()) {
+ return true;
+ }
+
+ return false;
+}
+
+// This is copied into AudioRegionGainLine
+void
+AutomationLine::remove_point (ControlPoint& cp)
+{
+ ModelRepresentation mr;
+
+ model_representation (cp, mr);
+
+ trackview.editor.current_session()->begin_reversible_command (_("remove control point"));
+ trackview.editor.current_session()->add_undo (get_memento());
+
+ alist.erase (mr.start, mr.end);
+
+ trackview.editor.current_session()->add_redo_no_execute (get_memento());
+ trackview.editor.current_session()->commit_reversible_command ();
+ trackview.editor.current_session()->set_dirty ();
+}
+
+void
+AutomationLine::get_selectables (jack_nframes_t& start, jack_nframes_t& end,
+ double botfrac, double topfrac, list<Selectable*>& results)
+{
+
+ double top;
+ double bot;
+ jack_nframes_t nstart;
+ jack_nframes_t nend;
+ bool collecting = false;
+
+ /* Curse X11 and its inverted coordinate system! */
+
+ bot = (1.0 - topfrac) * _height;
+ top = (1.0 - botfrac) * _height;
+
+ nstart = max_frames;
+ nend = 0;
+
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+
+ jack_nframes_t when = (jack_nframes_t) (*(*i)->model)->when;
+
+ if (when >= start && when <= end) {
+
+ if ((*i)->get_y() >= bot && (*i)->get_y() <= top) {
+
+ (*i)->show();
+ (*i)->set_visible(true);
+ collecting = true;
+ nstart = min (nstart, when);
+ nend = max (nend, when);
+
+ } else {
+
+ if (collecting) {
+
+ results.push_back (new AutomationSelectable (nstart, nend, botfrac, topfrac, trackview));
+ collecting = false;
+ nstart = max_frames;
+ nend = 0;
+ }
+ }
+ }
+ }
+
+ if (collecting) {
+ results.push_back (new AutomationSelectable (nstart, nend, botfrac, topfrac, trackview));
+ }
+
+}
+
+void
+AutomationLine::get_inverted_selectables (Selection&, list<Selectable*>& results)
+{
+ // hmmm ....
+}
+
+void
+AutomationLine::set_selected_points (PointSelection& points)
+{
+ double top;
+ double bot;
+
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ (*i)->selected = false;
+ }
+
+ if (points.empty()) {
+ goto out;
+ }
+
+ for (PointSelection::iterator r = points.begin(); r != points.end(); ++r) {
+
+ if (&(*r).track != &trackview) {
+ continue;
+ }
+
+ /* Curse X11 and its inverted coordinate system! */
+
+ bot = (1.0 - (*r).high_fract) * _height;
+ top = (1.0 - (*r).low_fract) * _height;
+
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+
+ double rstart, rend;
+
+ rstart = trackview.editor.frame_to_unit ((*r).start);
+ rend = trackview.editor.frame_to_unit ((*r).end);
+
+ if ((*i)->get_x() >= rstart && (*i)->get_x() <= rend) {
+
+ if ((*i)->get_y() >= bot && (*i)->get_y() <= top) {
+
+ (*i)->selected = true;
+ }
+ }
+
+ }
+ }
+
+ out:
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ (*i)->show_color (false, !points_visible);
+ }
+
+}
+
+void
+AutomationLine::show_selection ()
+{
+ TimeSelection& time (trackview.editor.get_selection().time);
+
+ // cerr << "show selection\n";
+
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+
+ (*i)->selected = false;
+
+ for (list<AudioRange>::iterator r = time.begin(); r != time.end(); ++r) {
+ double rstart, rend;
+
+ rstart = trackview.editor.frame_to_unit ((*r).start);
+ rend = trackview.editor.frame_to_unit ((*r).end);
+
+ if ((*i)->get_x() >= rstart && (*i)->get_x() <= rend) {
+ (*i)->selected = true;
+ break;
+ }
+ }
+
+ (*i)->show_color (false, !points_visible);
+ }
+}
+
+void
+AutomationLine::hide_selection ()
+{
+ // cerr << "hide selection\n";
+// show_selection ();
+}
+
+
+// This is copied into AudioRegionGainLine
+UndoAction
+AutomationLine::get_memento ()
+{
+ return alist.get_memento();
+}
+
+void
+AutomationLine::list_changed (Change ignored)
+{
+ queue_reset ();
+}
+
+void
+AutomationLine::reset_callback (const AutomationList& events)
+{
+ GtkCanvasPoints *tmp_points;
+ uint32_t npoints = events.size();
+
+ if (npoints == 0) {
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ delete *i;
+ }
+ control_points.clear ();
+ gtk_canvas_item_hide (line);
+ return;
+ }
+
+ tmp_points = get_canvas_points ("autoline reset", max (npoints, (uint32_t) 2));
+
+ uint32_t xi, yi;
+ AutomationList::const_iterator ai;
+
+ for (ai = events.const_begin(), xi = 0, yi = 1; ai != events.const_end(); xi += 2, yi +=2, ++ai) {
+
+ tmp_points->coords[xi] = trackview.editor.frame_to_unit ((*ai)->when);
+ double translated_y;
+
+ translated_y = (*ai)->value;
+ model_to_view_y (translated_y);
+ tmp_points->coords[yi] = _height - (translated_y * _height);
+ }
+
+ tmp_points->num_points = npoints;
+
+ determine_visible_control_points (tmp_points);
+ gtk_canvas_points_unref (tmp_points);
+}
+
+void
+AutomationLine::reset ()
+{
+ update_pending = false;
+
+ if (no_draw) {
+ return;
+ }
+
+ alist.apply_to_points (*this, &AutomationLine::reset_callback);
+}
+
+void
+AutomationLine::clear ()
+{
+ /* parent must create command */
+ trackview.editor.current_session()->add_undo (get_memento());
+ alist.clear();
+ trackview.editor.current_session()->add_redo_no_execute (get_memento());
+ trackview.editor.current_session()->commit_reversible_command ();
+ trackview.editor.current_session()->set_dirty ();
+}
+
+void
+AutomationLine::change_model (AutomationList::iterator i, double x, double y)
+{
+ alist.modify (i, (jack_nframes_t) x, y);
+}
+
+void
+AutomationLine::change_model_range (AutomationList::iterator start, AutomationList::iterator end, double xdelta, float ydelta)
+{
+ alist.move_range (start, end, xdelta, ydelta);
+}
+
+void
+AutomationLine::show_all_control_points ()
+{
+ points_visible = true;
+
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ (*i)->show ();
+ (*i)->set_visible (true);
+ }
+}
+
+void
+AutomationLine::hide_all_but_selected_control_points ()
+{
+ points_visible = false;
+
+ for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) {
+ if (!(*i)->selected) {
+ (*i)->set_visible (false);
+ }
+ }
+}
diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h
new file mode 100644
index 0000000000..ab3cc2bb43
--- /dev/null
+++ b/gtk2_ardour/automation_line.h
@@ -0,0 +1,223 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_automation_line_h__
+#define __ardour_automation_line_h__
+
+#include <vector>
+#include <list>
+#include <string>
+#include <sys/types.h>
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <sigc++/signal_system.h>
+
+#include <pbd/undo.h>
+
+#include <ardour/automation_event.h>
+
+using std::vector;
+using std::string;
+
+class AutomationLine;
+class ControlPoint;
+class PointSelection;
+class TimeAxisView;
+class AutomationTimeAxisView;
+class Selectable;
+class Selection;
+
+class ControlPoint
+{
+ public:
+ ControlPoint (AutomationLine& al, gint (*event_handler)(GtkCanvasItem*, GdkEvent*, gpointer));
+ ControlPoint (const ControlPoint&, bool dummy_arg_to_force_special_copy_constructor);
+ ~ControlPoint ();
+
+ enum ShapeType {
+ Full,
+ Start,
+ End
+ };
+
+ void move_to (double x, double y, ShapeType);
+ void reset (double x, double y, ARDOUR::AutomationList::iterator, uint32_t, ShapeType);
+ double get_x() const { return _x; }
+ double get_y() const { return _y; }
+
+ void hide ();
+ void show ();
+ void show_color (bool entered, bool hide_too);
+
+ void set_size (double);
+ void set_visible (bool);
+
+ GtkCanvasItem* item;
+ AutomationLine& line;
+ uint32_t view_index;
+ ARDOUR::AutomationList::iterator model;
+ bool can_slide;
+ bool selected;
+
+ private:
+ double _x;
+ double _y;
+ double _size;
+ ShapeType _shape;
+};
+
+class AutomationLine : public SigC::Object
+{
+ public:
+ AutomationLine (string name, TimeAxisView&, GtkCanvasItem *, ARDOUR::AutomationList&,
+ gint (*point_event_handler)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_event_handler)(GtkCanvasItem*, GdkEvent*, gpointer));
+
+ virtual ~AutomationLine ();
+
+ void queue_reset ();
+ void reset ();
+ void clear();
+
+ void set_selected_points (PointSelection&);
+ void get_selectables (jack_nframes_t& start, jack_nframes_t& end,
+ double botfrac, double topfrac,
+ list<Selectable*>& results);
+ void get_inverted_selectables (Selection&, list<Selectable*>& results);
+
+ virtual void remove_point (ControlPoint&);
+ bool control_points_adjacent (double xval, uint32_t& before, uint32_t& after);
+
+ /* dragging API */
+
+ virtual void start_drag (ControlPoint*, float fraction);
+ virtual void point_drag(ControlPoint&, jack_nframes_t x, float, bool with_push);
+ virtual void end_drag (ControlPoint*);
+ virtual void line_drag(uint32_t i1, uint32_t i2, float, bool with_push);
+
+ ControlPoint* nth (uint32_t);
+ uint32_t npoints() const { return control_points.size(); }
+
+ string name() const { return _name; }
+ bool visible() const { return _visible; }
+ guint32 height() const { return _height; }
+
+ void set_line_color (uint32_t);
+ uint32_t get_line_color() const { return _line_color; }
+
+ void show ();
+ void hide ();
+ void set_height (guint32);
+ void set_verbose_cursor_uses_gain_mapping (bool yn);
+
+ TimeAxisView& trackview;
+
+ GtkCanvasGroup* canvas_group() const { return GTK_CANVAS_GROUP(group); }
+ GtkCanvasItem* parent_group() const { return _parent_group; }
+ GtkCanvasItem* grab_item() const { return line; }
+
+ void show_selection();
+ void hide_selection ();
+
+ void set_point_size (double size);
+
+ static void invalidate_point (GtkCanvasPoints*, uint32_t index);
+ static bool invalid_point (GtkCanvasPoints*, uint32_t index);
+
+ virtual string get_verbose_cursor_string (float);
+ virtual void view_to_model_y (double&) = 0;
+ virtual void model_to_view_y (double&) = 0;
+
+ ARDOUR::AutomationList& the_list() const { return alist; }
+
+ void show_all_control_points ();
+ void hide_all_but_selected_control_points ();
+
+ bool is_last_point (ControlPoint &);
+ bool is_first_point (ControlPoint &);
+
+ protected:
+ string _name;
+ guint32 _height;
+ uint32_t _line_color;
+ ARDOUR::AutomationList& alist;
+
+ bool _visible : 1;
+ bool _vc_uses_gain_mapping : 1;
+ bool terminal_points_can_slide : 1;
+ bool update_pending : 1;
+ bool no_draw : 1;
+ bool points_visible : 1;
+
+ GtkCanvasItem* _parent_group;
+ GtkCanvasItem* group;
+ GtkCanvasItem* line; /* line */
+ GtkCanvasPoints* point_coords; /* coordinates for canvas line */
+ vector<ControlPoint*> control_points; /* visible control points */
+
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer);
+
+ void determine_visible_control_points (GtkCanvasPoints*);
+ void sync_model_from (ControlPoint&);
+ void sync_model_with_view_point (ControlPoint&);
+ void sync_model_with_view_line (uint32_t, uint32_t);
+ void modify_view (ControlPoint&, double, double, bool with_push);
+
+ virtual void change_model (ARDOUR::AutomationList::iterator, double x, double y);
+ virtual void change_model_range (ARDOUR::AutomationList::iterator,ARDOUR::AutomationList::iterator, double delta, float ydelta);
+
+ void reset_callback (const ARDOUR::AutomationList&);
+ void list_changed (ARDOUR::Change);
+
+ UndoAction get_memento();
+
+
+ private:
+ uint32_t drags;
+ double first_drag_fraction;
+ double last_drag_fraction;
+ uint32_t line_drag_cp1;
+ uint32_t line_drag_cp2;
+
+ void modify_view_point(ControlPoint&, double, double, bool with_push);
+ void reset_line_coords (ControlPoint&);
+ void update_line ();
+
+ struct ModelRepresentation {
+ ARDOUR::AutomationList::iterator start;
+ ARDOUR::AutomationList::iterator end;
+ jack_nframes_t xpos;
+ double ypos;
+ jack_nframes_t xmin;
+ double ymin;
+ jack_nframes_t xmax;
+ double ymax;
+ jack_nframes_t xval;
+ double yval;
+ };
+
+ void model_representation (ControlPoint&, ModelRepresentation&);
+
+ friend class AudioRegionGainLine;
+};
+
+#endif /* __ardour_automation_line_h__ */
+
diff --git a/gtk2_ardour/automation_pan_line.cc b/gtk2_ardour/automation_pan_line.cc
new file mode 100644
index 0000000000..fab4f0ba96
--- /dev/null
+++ b/gtk2_ardour/automation_pan_line.cc
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 2000-2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <sigc++/signal_system.h>
+
+#include <ardour/curve.h>
+
+#include "public_editor.h"
+#include "automation_pan_line.h"
+#include "utils.h"
+#include <cmath>
+
+#include <ardour/session.h>
+
+using namespace ARDOUR;
+
+AutomationPanLine::AutomationPanLine (string name, Session& s, TimeAxisView& tv, GtkCanvasItem* parent,
+ Curve& c,
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer))
+ : AutomationLine (name, tv, parent, c, point_callback, line_callback),
+ session (s)
+{
+}
+
+void
+AutomationPanLine::view_to_model_y (double& y)
+{
+ // vertical coordinate axis reversal
+ y = 1.0 - y;
+}
+
+void
+AutomationPanLine::model_to_view_y (double& y)
+{
+ // vertical coordinate axis reversal
+ y = 1.0 - y;
+}
+
+
diff --git a/gtk2_ardour/automation_pan_line.h b/gtk2_ardour/automation_pan_line.h
new file mode 100644
index 0000000000..2fc8efbd9f
--- /dev/null
+++ b/gtk2_ardour/automation_pan_line.h
@@ -0,0 +1,35 @@
+#ifndef __ardour_gtk_automation_pan_line_h__
+#define __ardour_gtk_automation_pan_line_h__
+
+#include <ardour/ardour.h>
+#include <gtk-canvas.h>
+#include <gtk--.h>
+
+#include "automation_line.h"
+
+namespace ARDOUR {
+ class Session;
+}
+
+class TimeAxisView;
+
+class AutomationPanLine : public AutomationLine
+{
+ public:
+ AutomationPanLine (string name, ARDOUR::Session&, TimeAxisView&, GtkCanvasItem* parent,
+ ARDOUR::Curve&,
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer));
+
+ void view_to_model_y (double&);
+ void model_to_view_y (double&);
+
+ private:
+ ARDOUR::Session& session;
+ vector<GtkCanvasItem*> lines;
+};
+
+
+#endif /* __ardour_gtk_automation_pan_line_h__ */
+
+
diff --git a/gtk2_ardour/automation_selectable.h b/gtk2_ardour/automation_selectable.h
new file mode 100644
index 0000000000..9b8f78e057
--- /dev/null
+++ b/gtk2_ardour/automation_selectable.h
@@ -0,0 +1,21 @@
+#ifndef __ardour_gtk_automation_selectable_h__
+#define __ardour_gtk_automation_selectable_h__
+
+#include <ardour/types.h>
+#include "selectable.h"
+
+class TimeAxisView;
+
+struct AutomationSelectable : public Selectable
+{
+ jack_nframes_t start;
+ jack_nframes_t end;
+ double low_fract;
+ double high_fract;
+ TimeAxisView& track;
+
+ AutomationSelectable (jack_nframes_t s, jack_nframes_t e, double l, double h, TimeAxisView& atv)
+ : start (s), end (e), low_fract (l), high_fract (h), track (atv) {}
+};
+
+#endif /* __ardour_gtk_automation_selectable_h__ */
diff --git a/gtk2_ardour/automation_selection.h b/gtk2_ardour/automation_selection.h
new file mode 100644
index 0000000000..1fec8b1d86
--- /dev/null
+++ b/gtk2_ardour/automation_selection.h
@@ -0,0 +1,12 @@
+#ifndef __ardour_gtk_automation_selection_h__
+#define __ardour_gtk_automation_selection_h__
+
+#include <list>
+
+namespace ARDOUR {
+ class AutomationList;
+}
+
+struct AutomationSelection : list<ARDOUR::AutomationList*> {};
+
+#endif /* __ardour_gtk_automation_selection_h__ */
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
new file mode 100644
index 0000000000..e90f7e61f9
--- /dev/null
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -0,0 +1,796 @@
+#include <ardour/route.h>
+
+#include "ardour_ui.h"
+#include "automation_time_axis.h"
+#include "automation_line.h"
+#include "public_editor.h"
+#include "canvas-simplerect.h"
+#include "canvas-waveview.h"
+#include "selection.h"
+#include "ghostregion.h"
+#include "rgb_macros.h"
+#include "automation_selectable.h"
+#include "point_selection.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Editing;
+
+static const gchar * small_x_xpm[] = {
+"11 11 2 1",
+" c None",
+". c #000000",
+" ",
+" ",
+" . . ",
+" . . ",
+" . . ",
+" . ",
+" . . ",
+" . . ",
+" . . ",
+" ",
+" "};
+
+AutomationTimeAxisView::AutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& rent, Widget* p, std::string nom, std::string state_name, std::string nomparent)
+
+ : AxisView (s),
+ TimeAxisView (s, e, &rent, p),
+ route (r),
+ _name (nom),
+ _state_name (state_name),
+ height_button (_("h")),
+ clear_button (_("clear")),
+ auto_button (X_("")) /* force addition of a label */
+{
+ automation_menu = 0;
+ in_destructor = false;
+ auto_off_item = 0;
+ auto_touch_item = 0;
+ auto_write_item = 0;
+ auto_play_item = 0;
+ ignore_state_request = false;
+
+ base_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 1000000.0,
+ "outline_color_rgba", color_map[cAutomationTrackOutline],
+ /* outline ends and bottom */
+ "outline_what", (guint32) (0x1|0x2|0x8),
+ "fill_color_rgba", color_map[cAutomationTrackFill],
+ NULL);
+
+ gtk_object_set_data (GTK_OBJECT(base_rect), "trackview", this);
+
+ gtk_signal_connect (GTK_OBJECT(base_rect), "event",
+ (GtkSignalFunc) PublicEditor::canvas_automation_track_event,
+ this);
+
+ hide_button.add (*(manage (new Pixmap (small_x_xpm))));
+
+ height_button.set_name ("TrackSizeButton");
+ auto_button.set_name ("TrackVisualButton");
+ clear_button.set_name ("TrackVisualButton");
+ hide_button.set_name ("TrackRemoveButton");
+
+ ARDOUR_UI::instance()->tooltips().set_tip(height_button, _("track height"));
+ ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state"));
+ ARDOUR_UI::instance()->tooltips().set_tip(clear_button, _("clear track"));
+ ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track"));
+
+ /* rearrange the name display */
+
+ /* we never show these for automation tracks, so make
+ life easier and remove them.
+ */
+
+ name_hbox.remove (name_entry);
+
+ /* move the name label over a bit */
+
+ string shortpname = _name;
+ bool shortened = false;
+
+ if (_name.length()) {
+ if (shortpname.length() > 18) {
+ shortpname = shortpname.substr (0, 16);
+ shortpname += "...";
+ shortened = true;
+ }
+ }
+ name_label.set_text (shortpname);
+ name_label.set_alignment (1.0, 0.5);
+
+ if (nomparent.length()) {
+
+ /* limit the plug name string */
+
+ string pname = nomparent;
+
+ if (pname.length() > 14) {
+ pname = pname.substr (0, 11);
+ pname += "...";
+ shortened = true;
+ }
+
+ plugname = new Label (pname);
+ plugname->set_name (X_("TrackPlugName"));
+ plugname->set_alignment (1.0, 0.5);
+ name_label.set_name (X_("TrackParameterName"));
+ controls_table.remove (name_hbox);
+ controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ plugname_packed = true;
+ controls_table.attach (name_hbox, 1, 6, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ } else {
+ plugname = 0;
+ plugname_packed = false;
+ }
+
+ if (shortened) {
+ string tipname = nomparent;
+ if (!tipname.empty()) {
+ tipname += ": ";
+ }
+ tipname += _name;
+ ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname);
+ }
+
+ /* add the buttons */
+ controls_table.attach (hide_button, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ controls_table.attach (height_button, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+
+ controls_table.attach (auto_button, 7, 9, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ controls_table.attach (clear_button, 7, 9, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+
+ controls_table.show_all ();
+
+ height_button.clicked.connect (slot (*this, &AutomationTimeAxisView::height_clicked));
+ clear_button.clicked.connect (slot (*this, &AutomationTimeAxisView::clear_clicked));
+ hide_button.clicked.connect (slot (*this, &AutomationTimeAxisView::hide_clicked));
+ auto_button.clicked.connect (slot (*this, &AutomationTimeAxisView::auto_clicked));
+
+ controls_base_selected_name = X_("AutomationTrackControlsBaseSelected");
+ controls_base_unselected_name = X_("AutomationTrackControlsBase");
+ controls_ebox.set_name (controls_base_unselected_name);
+
+ controls_frame.set_shadow_type (GTK_SHADOW_ETCHED_OUT);
+
+ XMLNode* xml_node = get_parent_with_state()->get_child_xml_node (_state_name);
+ set_state (*xml_node);
+
+ /* make sure labels etc. are correct */
+
+ automation_state_changed ();
+}
+
+AutomationTimeAxisView::~AutomationTimeAxisView ()
+{
+ in_destructor = true;
+
+ for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+ delete *i;
+ }
+}
+
+void
+AutomationTimeAxisView::auto_clicked ()
+{
+ using namespace Menu_Helpers;
+
+ if (automation_menu == 0) {
+ automation_menu = manage (new Menu);
+ automation_menu->set_name ("ArdourContextMenu");
+ MenuList& items (automation_menu->items());
+
+ items.push_back (MenuElem (_("off"),
+ bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
+ items.push_back (MenuElem (_("play"),
+ bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
+ items.push_back (MenuElem (_("write"),
+ bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
+ items.push_back (MenuElem (_("touch"),
+ bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
+ }
+
+ automation_menu->popup (1, 0);
+}
+
+
+void
+AutomationTimeAxisView::automation_state_changed ()
+{
+ AutoState state;
+
+ /* update button label */
+
+ if (lines.empty()) {
+ state = Off;
+ } else {
+ state = lines.front()->the_list().automation_state ();
+ }
+
+ switch (state & (Off|Play|Touch|Write)) {
+ case Off:
+ static_cast<Gtk::Label*>(auto_button.get_child())->set_text (_("off"));
+ if (auto_off_item) {
+ ignore_state_request = true;
+ auto_off_item->set_active (true);
+ auto_play_item->set_active (false);
+ auto_touch_item->set_active (false);
+ auto_write_item->set_active (false);
+ ignore_state_request = false;
+ }
+ break;
+ case Play:
+ static_cast<Gtk::Label*>(auto_button.get_child())->set_text (_("play"));
+ if (auto_play_item) {
+ ignore_state_request = true;
+ auto_play_item->set_active (true);
+ auto_off_item->set_active (false);
+ auto_touch_item->set_active (false);
+ auto_write_item->set_active (false);
+ ignore_state_request = false;
+ }
+ break;
+ case Write:
+ static_cast<Gtk::Label*>(auto_button.get_child())->set_text (_("write"));
+ if (auto_write_item) {
+ ignore_state_request = true;
+ auto_write_item->set_active (true);
+ auto_off_item->set_active (false);
+ auto_play_item->set_active (false);
+ auto_touch_item->set_active (false);
+ ignore_state_request = false;
+ }
+ break;
+ case Touch:
+ static_cast<Gtk::Label*>(auto_button.get_child())->set_text (_("touch"));
+ if (auto_touch_item) {
+ ignore_state_request = true;
+ auto_touch_item->set_active (true);
+ auto_off_item->set_active (false);
+ auto_play_item->set_active (false);
+ auto_write_item->set_active (false);
+ ignore_state_request = false;
+ }
+ break;
+ default:
+ static_cast<Gtk::Label*>(auto_button.get_child())->set_text (_("???"));
+ break;
+ }
+}
+
+void
+AutomationTimeAxisView::height_clicked ()
+{
+ popup_size_menu (0);
+}
+
+void
+AutomationTimeAxisView::clear_clicked ()
+{
+ _session.begin_reversible_command (_("clear automation"));
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ (*i)->clear ();
+ }
+ _session.commit_reversible_command ();
+}
+
+void
+AutomationTimeAxisView::set_height (TrackHeight h)
+{
+ bool changed = (height != (uint32_t) h);
+
+ TimeAxisView* state_parent = get_parent_with_state ();
+ XMLNode* xml_node = state_parent->get_child_xml_node (_state_name);
+
+ controls_table.show_all ();
+
+ TimeAxisView::set_height (h);
+ gtk_object_set (GTK_OBJECT(base_rect), "y2", (double) h, NULL);
+
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ (*i)->set_height (h);
+ }
+
+ for (list<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+ (*i)->set_height ();
+ }
+
+ switch (height) {
+ case Largest:
+ xml_node->add_property ("track_height", "largest");
+ controls_table.remove (name_hbox);
+ if (plugname) {
+ if (plugname_packed) {
+ controls_table.remove (*plugname);
+ plugname_packed = false;
+ }
+ controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ plugname_packed = true;
+ controls_table.attach (name_hbox, 1, 6, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ } else {
+ controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ }
+ controls_table.show_all ();
+ name_label.show ();
+ break;
+
+ case Large:
+ xml_node->add_property ("track_height", "large");
+ controls_table.remove (name_hbox);
+ if (plugname) {
+ if (plugname_packed) {
+ controls_table.remove (*plugname);
+ plugname_packed = false;
+ }
+ controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ plugname_packed = true;
+ } else {
+ controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ }
+ controls_table.show_all ();
+ name_label.show ();
+ break;
+
+ case Larger:
+ xml_node->add_property ("track_height", "larger");
+ controls_table.remove (name_hbox);
+ if (plugname) {
+ if (plugname_packed) {
+ controls_table.remove (*plugname);
+ plugname_packed = false;
+ }
+ controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ plugname_packed = true;
+ } else {
+ controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ }
+ controls_table.show_all ();
+ name_label.show ();
+ break;
+
+ case Normal:
+ xml_node->add_property ("track_height", "normal");
+ controls_table.remove (name_hbox);
+ if (plugname) {
+ if (plugname_packed) {
+ controls_table.remove (*plugname);
+ plugname_packed = false;
+ }
+ controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ plugname_packed = true;
+ controls_table.attach (name_hbox, 1, 6, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ } else {
+ controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ }
+ controls_table.show_all ();
+ name_label.show ();
+ break;
+
+ case Smaller:
+ xml_node->add_property ("track_height", "smaller");
+ controls_table.remove (name_hbox);
+ if (plugname) {
+ if (plugname_packed) {
+ controls_table.remove (*plugname);
+ plugname_packed = false;
+ }
+ }
+ controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ controls_table.hide_all ();
+ name_hbox.show_all ();
+ controls_table.show ();
+ break;
+
+ case Small:
+ xml_node->add_property ("track_height", "small");
+ controls_table.remove (name_hbox);
+ if (plugname) {
+ if (plugname_packed) {
+ controls_table.remove (*plugname);
+ plugname_packed = false;
+ }
+ }
+ controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+ controls_table.hide_all ();
+ name_hbox.show_all ();
+ controls_table.show ();
+ break;
+ }
+
+ if (changed) {
+ /* only emit the signal if the height really changed */
+ route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+ }
+}
+
+void
+AutomationTimeAxisView::set_samples_per_unit (double spu)
+{
+ TimeAxisView::set_samples_per_unit (editor.get_current_zoom());
+
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ (*i)->reset ();
+ }
+}
+
+void
+AutomationTimeAxisView::hide_clicked ()
+{
+ set_marked_for_display (false);
+ hide ();
+}
+
+
+void
+AutomationTimeAxisView::build_display_menu ()
+{
+ using namespace Menu_Helpers;
+
+ /* get the size menu ready */
+
+ build_size_menu ();
+
+ /* prepare it */
+
+ TimeAxisView::build_display_menu ();
+
+ /* now fill it with our stuff */
+
+ MenuList& items = display_menu->items();
+
+ items.push_back (MenuElem (_("Height"), *size_menu));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Hide"), slot (*this, &AutomationTimeAxisView::hide_clicked)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Clear"), slot (*this, &AutomationTimeAxisView::clear_clicked)));
+ items.push_back (SeparatorElem());
+
+ Menu* auto_state_menu = manage (new Menu);
+ auto_state_menu->set_name ("ArdourContextMenu");
+ MenuList& as_items = auto_state_menu->items();
+
+ as_items.push_back (CheckMenuElem (_("off"),
+ bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off)));
+ auto_off_item = dynamic_cast<CheckMenuItem*>(as_items.back());
+
+ as_items.push_back (CheckMenuElem (_("play"),
+ bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play)));
+ auto_play_item = dynamic_cast<CheckMenuItem*>(as_items.back());
+
+ as_items.push_back (CheckMenuElem (_("write"),
+ bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write)));
+ auto_write_item = dynamic_cast<CheckMenuItem*>(as_items.back());
+
+ as_items.push_back (CheckMenuElem (_("touch"),
+ bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch)));
+ auto_touch_item = dynamic_cast<CheckMenuItem*>(as_items.back());
+
+ items.push_back (MenuElem (_("State"), *auto_state_menu));
+
+ /* make sure the automation menu state is correct */
+
+ automation_state_changed ();
+}
+
+bool
+AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
+{
+ bool ret = false;
+
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ ret = cut_copy_clear_one ((**i), selection, op);
+ }
+
+ return ret;
+}
+
+bool
+AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op)
+{
+ AutomationList* what_we_got = 0;
+ AutomationList& alist (line.the_list());
+ bool ret = false;
+
+ _session.add_undo (alist.get_memento());
+
+ switch (op) {
+ case Cut:
+ if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) {
+ editor.get_cut_buffer().add (what_we_got);
+ _session.add_redo_no_execute (alist.get_memento());
+ ret = true;
+ }
+ break;
+ case Copy:
+ if ((what_we_got = alist.copy (selection.time.front().start, selection.time.front().end)) != 0) {
+ editor.get_cut_buffer().add (what_we_got);
+ }
+ break;
+
+ case Clear:
+ if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) {
+ _session.add_redo_no_execute (alist.get_memento());
+ delete what_we_got;
+ what_we_got = 0;
+ ret = true;
+ }
+ break;
+ }
+
+ if (what_we_got) {
+ for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
+ double foo = (*x)->value;
+ line.model_to_view_y (foo);
+ (*x)->value = foo;
+ }
+ }
+
+ return ret;
+}
+
+bool
+AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op)
+{
+ bool ret = false;
+
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ ret = cut_copy_clear_objects_one ((**i), selection, op);
+ }
+
+ return ret;
+}
+
+bool
+AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op)
+{
+ AutomationList* what_we_got = 0;
+ AutomationList& alist (line.the_list());
+ bool ret = false;
+
+ _session.add_undo (alist.get_memento());
+
+ for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
+
+ if (&(*i).track != this) {
+ continue;
+ }
+
+ switch (op) {
+ case Cut:
+ if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
+ editor.get_cut_buffer().add (what_we_got);
+ _session.add_redo_no_execute (alist.get_memento());
+ ret = true;
+ }
+ break;
+ case Copy:
+ if ((what_we_got = alist.copy ((*i).start, (*i).end)) != 0) {
+ editor.get_cut_buffer().add (what_we_got);
+ }
+ break;
+
+ case Clear:
+ if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
+ _session.add_redo_no_execute (alist.get_memento());
+ delete what_we_got;
+ what_we_got = 0;
+ ret = true;
+ }
+ break;
+ }
+ }
+
+ if (what_we_got) {
+ for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
+ double foo = (*x)->value;
+ line.model_to_view_y (foo);
+ (*x)->value = foo;
+ }
+ }
+
+ return ret;
+}
+
+bool
+AutomationTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection, size_t nth)
+{
+ bool ret = true;
+
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ ret = paste_one (**i, pos, times, selection, nth);
+ }
+
+ return ret;
+}
+
+bool
+AutomationTimeAxisView::paste_one (AutomationLine& line, jack_nframes_t pos, float times, Selection& selection, size_t nth)
+{
+ AutomationSelection::iterator p;
+ AutomationList& alist (line.the_list());
+
+ for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth);
+
+ if (p == selection.lines.end()) {
+ return false;
+ }
+
+ /* Make a copy of the list because we have to scale the
+ values from view coordinates to model coordinates, and we're
+ not supposed to modify the points in the selection.
+ */
+
+ AutomationList copy (**p);
+
+ for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) {
+ double foo = (*x)->value;
+ line.view_to_model_y (foo);
+ (*x)->value = foo;
+ }
+
+ _session.add_undo (alist.get_memento());
+ alist.paste (copy, pos, times);
+ _session.add_redo_no_execute (alist.get_memento());
+
+ return true;
+}
+
+void
+AutomationTimeAxisView::add_ghost (GhostRegion* gr)
+{
+ ghosts.push_back (gr);
+ gr->GoingAway.connect (slot (*this, &AutomationTimeAxisView::remove_ghost));
+}
+
+void
+AutomationTimeAxisView::remove_ghost (GhostRegion* gr)
+{
+ if (in_destructor) {
+ return;
+ }
+
+ list<GhostRegion*>::iterator i;
+
+ for (i = ghosts.begin(); i != ghosts.end(); ++i) {
+ if ((*i) == gr) {
+ ghosts.erase (i);
+ break;
+ }
+ }
+}
+
+void
+AutomationTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results)
+{
+ if (!lines.empty() && touched (top, bot)) {
+ double topfrac;
+ double botfrac;
+
+ /* remember: this is X Window - coordinate space starts in upper left and moves down.
+ y_position is the "origin" or "top" of the track.
+ */
+
+ double mybot = y_position + height; // XXX need to include Editor::track_spacing;
+
+ if (y_position >= top && mybot <= bot) {
+
+ /* y_position is below top, mybot is above bot, so we're fully
+ covered vertically.
+ */
+
+ topfrac = 1.0;
+ botfrac = 0.0;
+
+ } else {
+
+ /* top and bot are within y_position .. mybot */
+
+ topfrac = 1.0 - ((top - y_position) / height);
+ botfrac = 1.0 - ((bot - y_position) / height);
+ }
+
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ (*i)->get_selectables (start, end, botfrac, topfrac, results);
+ }
+ }
+}
+
+void
+AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
+{
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ (*i)->get_inverted_selectables (sel, result);
+ }
+}
+
+void
+AutomationTimeAxisView::set_selected_points (PointSelection& points)
+{
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ (*i)->set_selected_points (points);
+ }
+}
+
+void
+AutomationTimeAxisView::clear_lines ()
+{
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ delete *i;
+ }
+
+ lines.clear ();
+ automation_connection.disconnect ();
+}
+
+void
+AutomationTimeAxisView::add_line (AutomationLine& line)
+{
+ bool get = false;
+
+ if (lines.empty()) {
+ /* first line is the Model for automation state */
+ automation_connection = line.the_list().automation_state_changed.connect
+ (slot (*this, &AutomationTimeAxisView::automation_state_changed));
+ get = true;
+ }
+
+ lines.push_back (&line);
+ line.set_height (height);
+
+ if (get) {
+ /* pick up the current state */
+ automation_state_changed ();
+ }
+}
+
+void
+AutomationTimeAxisView::show_all_control_points ()
+{
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ (*i)->show_all_control_points ();
+ }
+}
+
+void
+AutomationTimeAxisView::hide_all_but_selected_control_points ()
+{
+ for (vector<AutomationLine*>::iterator i = lines.begin(); i != lines.end(); ++i) {
+ (*i)->hide_all_but_selected_control_points ();
+ }
+}
+
+void
+AutomationTimeAxisView::entered()
+{
+ show_all_control_points ();
+}
+
+void
+AutomationTimeAxisView::exited ()
+{
+ hide_all_but_selected_control_points ();
+}
+
+void
+AutomationTimeAxisView::set_state (const XMLNode& node)
+{
+ TimeAxisView::set_state (node);
+}
+
+XMLNode*
+AutomationTimeAxisView::get_state_node ()
+{
+ TimeAxisView* state_parent = get_parent_with_state ();
+
+ if (state_parent) {
+ return state_parent->get_child_xml_node (_state_name);
+ } else {
+ return 0;
+ }
+}
diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h
new file mode 100644
index 0000000000..55f402aa1c
--- /dev/null
+++ b/gtk2_ardour/automation_time_axis.h
@@ -0,0 +1,121 @@
+#ifndef __ardour_gtk_automation_time_axis_h__
+#define __ardour_gtk_automation_time_axis_h__
+
+#include <vector>
+#include <list>
+#include <string>
+#include <ardour/types.h>
+
+#include "time_axis_view.h"
+
+using std::vector;
+using std::list;
+using std::string;
+
+namespace ARDOUR {
+ class Session;
+ class Route;
+}
+
+namespace Gtk {
+ class Widget;
+}
+
+class PublicEditor;
+class TimeSelection;
+class AudioRegionSelection;
+class PointSelection;
+class AutomationLine;
+class GhostRegion;
+class Selection;
+class Selectable;
+
+class AutomationTimeAxisView : public TimeAxisView {
+ public:
+ AutomationTimeAxisView (ARDOUR::Session&,
+ ARDOUR::Route&,
+ PublicEditor&,
+ TimeAxisView& parent,
+ Gtk::Widget* parent,
+ std::string name, /* translatable */
+ std::string state_name, /* not translatable */
+ std::string plug_name = "");
+
+ ~AutomationTimeAxisView();
+
+ void set_height (TimeAxisView::TrackHeight);
+ void set_samples_per_unit (double);
+ std::string name() const { return _name; }
+
+ virtual void add_automation_event (GtkCanvasItem *item, GdkEvent *event, jack_nframes_t, double) = 0;
+
+ void clear_lines ();
+ void add_line (AutomationLine&);
+
+ vector<AutomationLine*> lines;
+
+ void set_selected_points (PointSelection&);
+ void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable *>&);
+ void get_inverted_selectables (Selection&, list<Selectable*>& results);
+
+ void show_timestretch (jack_nframes_t start, jack_nframes_t end) {}
+ void hide_timestretch () {}
+
+ /* editing operations */
+
+ bool cut_copy_clear (Selection&, Editing::CutCopyOp);
+ bool cut_copy_clear_objects (PointSelection&, Editing::CutCopyOp);
+ bool paste (jack_nframes_t, float times, Selection&, size_t nth);
+
+ void add_ghost (GhostRegion*);
+ void remove_ghost (GhostRegion*);
+
+ void show_all_control_points ();
+ void hide_all_but_selected_control_points ();
+ void set_state (const XMLNode&);
+ XMLNode* get_state_node ();
+
+ protected:
+ ARDOUR::Route& route;
+ GtkCanvasItem* base_rect;
+ string _name;
+ string _state_name;
+ bool in_destructor;
+
+ Gtk::Button hide_button;
+ Gtk::Button height_button;
+ Gtk::Button clear_button;
+ Gtk::Button auto_button;
+ Gtk::Menu* automation_menu;
+ Gtk::Label* plugname;
+ bool plugname_packed;
+
+ Gtk::CheckMenuItem* auto_off_item;
+ Gtk::CheckMenuItem* auto_play_item;
+ Gtk::CheckMenuItem* auto_touch_item;
+ Gtk::CheckMenuItem* auto_write_item;
+
+ void clear_clicked ();
+ void height_clicked ();
+ void hide_clicked ();
+ void auto_clicked ();
+
+ virtual void build_display_menu ();
+
+ list<GhostRegion*> ghosts;
+
+ bool cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp);
+ bool cut_copy_clear_objects_one (AutomationLine&, PointSelection&, Editing::CutCopyOp);
+ bool paste_one (AutomationLine&, jack_nframes_t, float times, Selection&, size_t nth);
+
+ virtual void set_automation_state (ARDOUR::AutoState) = 0;
+ bool ignore_state_request;
+
+ void automation_state_changed ();
+ SigC::Connection automation_connection;
+
+ void entered ();
+ void exited ();
+};
+
+#endif /* __ardour_gtk_automation_time_axis_h__ */
diff --git a/gtk2_ardour/axis_view.cc b/gtk2_ardour/axis_view.cc
new file mode 100644
index 0000000000..419877e75a
--- /dev/null
+++ b/gtk2_ardour/axis_view.cc
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+
+#include <algorithm>
+#include <string>
+
+#include <list>
+
+#include <pbd/error.h>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include <ardour/session.h>
+#include <ardour/utils.h>
+
+#include "public_editor.h"
+#include "axis_view.h"
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace Gtkmmext;
+
+
+list<GdkColor> AxisView::used_colors;
+
+AxisView::AxisView (ARDOUR::Session& sess) : _session(sess)
+{
+ _selected = false;
+}
+
+AxisView::~AxisView()
+{
+
+}
+
+GdkColor
+AxisView::unique_random_color()
+{
+ GdkColor newcolor;
+
+ while (1) {
+
+ /* avoid neon/glowing tones by limiting them to the
+ "inner section" (paler) of a color wheel/circle.
+ */
+
+ const int32_t max_saturation = 48000; // 65535 would open up the whole color wheel
+
+ newcolor.red = random() % max_saturation;
+ newcolor.blue = random() % max_saturation;
+ newcolor.green = random() % max_saturation;
+
+ if (used_colors.size() == 0) {
+ used_colors.push_back (newcolor);
+ return newcolor;
+ }
+
+ for (list<GdkColor>::iterator i = used_colors.begin(); i != used_colors.end(); ++i) {
+ GdkColor c = *i;
+ float rdelta, bdelta, gdelta;
+
+ rdelta = newcolor.red - c.red;
+ bdelta = newcolor.blue - c.blue;
+ gdelta = newcolor.green - c.green;
+
+ if (sqrt (rdelta*rdelta + bdelta*bdelta + gdelta*gdelta) > 25.0) {
+ used_colors.push_back (newcolor);
+ return newcolor;
+ }
+ }
+
+ /* XXX need throttle here to make sure we don't spin for ever */
+ }
+}
diff --git a/gtk2_ardour/axis_view.h b/gtk2_ardour/axis_view.h
new file mode 100644
index 0000000000..5fc6917b74
--- /dev/null
+++ b/gtk2_ardour/axis_view.h
@@ -0,0 +1,97 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_axis_view_h__
+#define __ardour_gtk_axis_view_h__
+
+#include <list>
+#include <gtk--.h>
+#include <pbd/xml++.h>
+#include "prompter.h"
+
+namespace ARDOUR {
+ class Session;
+}
+
+/**
+ * AxisView defines the abstract base class for time-axis trackviews and routes.
+ *
+ */
+class AxisView : public SigC::Object
+{
+ public:
+ /**
+ * Returns the current 'Track' Color
+ *
+ * @return the current Track Color
+ */
+ Gdk_Color color() const { return _color; }
+
+ ARDOUR::Session& session() const { return _session; }
+
+ virtual string name() const = 0;
+
+ virtual void set_selected (bool yn) {
+ if (yn != _selected) {
+ _selected = yn;
+ }
+ }
+
+ virtual bool marked_for_display() const { return _marked_for_display; }
+
+ virtual void set_marked_for_display (bool yn) {
+ if (yn != _marked_for_display) {
+ _marked_for_display = yn;
+ }
+ }
+
+ virtual bool selected() const { return _selected; }
+ SigC::Signal0<void> Hiding;
+ SigC::Signal0<void> GoingAway;
+
+ protected:
+
+ AxisView (ARDOUR::Session& sess);
+ virtual ~AxisView();
+
+
+ /**
+ * Generate a new random TrackView color, unique from those colors already used.
+ *
+ * @return the unique random color.
+ */
+ static GdkColor unique_random_color();
+
+
+ ARDOUR::Session& _session;
+ Gdk_Color _color;
+
+ static list<GdkColor> used_colors;
+
+ Gtk::Label name_label;
+
+ bool _selected;
+
+ bool _marked_for_display;
+
+}; /* class AxisView */
+
+#endif /* __ardour_gtk_axis_view_h__ */
+
diff --git a/gtk2_ardour/canvas-curve.h b/gtk2_ardour/canvas-curve.h
new file mode 100644
index 0000000000..4727c3d1d3
--- /dev/null
+++ b/gtk2_ardour/canvas-curve.h
@@ -0,0 +1,66 @@
+/* gtk-canvas-curve.h: GtkCanvas item for constrained spline curves
+ *
+ * Copyright (C) 2003 Paul Davis <pbd@op.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GTK_CANVAS_CURVE_H__
+#define __GTK_CANVAS_CURVE_H__
+
+#include <gtk-canvas/gtk-canvas-defs.h>
+#include "gtk-canvas/gtk-canvas.h"
+
+BEGIN_GTK_CANVAS_DECLS
+
+/* Wave viewer item for canvas.
+ */
+
+#define GTK_CANVAS_TYPE_CANVAS_CURVE (gtk_canvas_curve_get_type ())
+#define GTK_CANVAS_CURVE(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_CURVE, GtkCanvasCurve))
+#define GTK_CANVAS_CURVE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_CURVE, GtkCanvasCurveClass))
+#define GTK_CANVAS_IS_CANVAS_CURVE(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_CURVE))
+#define GTK_CANVAS_IS_CANVAS_CURVE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_CURVE))
+
+typedef struct _GtkCanvasCurve GtkCanvasCurve;
+typedef struct _GtkCanvasCurveClass GtkCanvasCurveClass;
+
+struct _GtkCanvasCurve
+{
+ GtkCanvasItem item;
+ double x1, y1, x2, y2;
+ void* curve_arg;
+ float* vector;
+ size_t veclen;
+ uint32_t color;
+
+ /* cached values set during update/used during render */
+
+ unsigned char r, b, g, a;
+ guint32 bbox_ulx, bbox_uly;
+ guint32 bbox_lrx, bbox_lry;
+};
+
+struct _GtkCanvasCurveClass {
+ GtkCanvasItemClass parent_class;
+};
+
+GtkType gtk_canvas_curve_get_type (void);
+
+END_GTK_CANVAS_DECLS
+
+#endif /* __GTK_CANVAS_CURVE_H__ */
diff --git a/gtk2_ardour/canvas-imageframe.c b/gtk2_ardour/canvas-imageframe.c
new file mode 100644
index 0000000000..d186e86f50
--- /dev/null
+++ b/gtk2_ardour/canvas-imageframe.c
@@ -0,0 +1,586 @@
+/* Image item type for GtkCanvas widget
+ *
+ * GtkCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is
+ * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
+ *
+ * Copyright (C) 1998 The Free Software Foundation
+ *
+ * Author: Federico Mena <federico@nuclecu.unam.mx>
+ */
+
+
+#include <string.h> /* for memcpy() */
+#include <math.h>
+#include <stdio.h>
+#include "libart_lgpl/art_misc.h"
+#include "libart_lgpl/art_affine.h"
+#include "libart_lgpl/art_pixbuf.h"
+#include "libart_lgpl/art_rgb_pixbuf_affine.h"
+#include "canvas-imageframe.h"
+#include <gtk-canvas/gtk-canvas-util.h>
+#include <gtk-canvas/gtk-canvastypebuiltins.h>
+
+
+enum {
+ ARG_0,
+ ARG_PIXBUF,
+ ARG_X,
+ ARG_Y,
+ ARG_WIDTH,
+ ARG_HEIGHT,
+ ARG_DRAWWIDTH,
+ ARG_ANCHOR
+};
+
+
+static void gtk_canvas_imageframe_class_init(GtkCanvasImageFrameClass* class) ;
+static void gtk_canvas_imageframe_init(GtkCanvasImageFrame* image) ;
+static void gtk_canvas_imageframe_destroy(GtkObject* object) ;
+static void gtk_canvas_imageframe_set_arg(GtkObject* object, GtkArg* arg, guint arg_id) ;
+static void gtk_canvas_imageframe_get_arg(GtkObject* object, GtkArg* arg, guint arg_id) ;
+
+static void gtk_canvas_imageframe_update(GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) ;
+static void gtk_canvas_imageframe_realize(GtkCanvasItem *item) ;
+static void gtk_canvas_imageframe_unrealize(GtkCanvasItem *item) ;
+static void gtk_canvas_imageframe_draw(GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) ;
+static double gtk_canvas_imageframe_point(GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item) ;
+static void gtk_canvas_imageframe_translate(GtkCanvasItem *item, double dx, double dy) ;
+static void gtk_canvas_imageframe_bounds(GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) ;
+static void gtk_canvas_imageframe_render(GtkCanvasItem *item, GtkCanvasBuf *buf) ;
+
+static GtkCanvasItemClass *parent_class;
+
+
+GtkType
+gtk_canvas_imageframe_get_type (void)
+{
+ static GtkType imageframe_type = 0;
+
+ if (!imageframe_type) {
+ GtkTypeInfo imageframe_info = {
+ "GtkCanvasImageFrame",
+ sizeof (GtkCanvasImageFrame),
+ sizeof (GtkCanvasImageFrameClass),
+ (GtkClassInitFunc) gtk_canvas_imageframe_class_init,
+ (GtkObjectInitFunc) gtk_canvas_imageframe_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ imageframe_type = gtk_type_unique (gtk_canvas_item_get_type (), &imageframe_info);
+ }
+
+ return imageframe_type;
+}
+
+static void
+gtk_canvas_imageframe_class_init (GtkCanvasImageFrameClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkCanvasItemClass *item_class;
+
+ object_class = (GtkObjectClass *) class;
+ item_class = (GtkCanvasItemClass *) class;
+
+ parent_class = gtk_type_class (gtk_canvas_item_get_type ());
+
+ gtk_object_add_arg_type ("GtkCanvasImageFrame::pixbuf", GTK_TYPE_BOXED, GTK_ARG_WRITABLE, ARG_PIXBUF);
+ gtk_object_add_arg_type ("GtkCanvasImageFrame::x", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X);
+ gtk_object_add_arg_type ("GtkCanvasImageFrame::y", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y);
+ gtk_object_add_arg_type ("GtkCanvasImageFrame::width", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH);
+ gtk_object_add_arg_type ("GtkCanvasImageFrame::drawwidth", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_DRAWWIDTH);
+ gtk_object_add_arg_type ("GtkCanvasImageFrame::height", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEIGHT);
+ gtk_object_add_arg_type ("GtkCanvasImageFrame::anchor", GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, ARG_ANCHOR);
+
+ object_class->destroy = gtk_canvas_imageframe_destroy;
+ object_class->set_arg = gtk_canvas_imageframe_set_arg;
+ object_class->get_arg = gtk_canvas_imageframe_get_arg;
+
+ item_class->update = gtk_canvas_imageframe_update;
+ item_class->realize = gtk_canvas_imageframe_realize;
+ item_class->unrealize = gtk_canvas_imageframe_unrealize;
+ item_class->draw = gtk_canvas_imageframe_draw;
+ item_class->point = gtk_canvas_imageframe_point;
+ item_class->translate = gtk_canvas_imageframe_translate;
+ item_class->bounds = gtk_canvas_imageframe_bounds;
+ item_class->render = gtk_canvas_imageframe_render;
+}
+
+static void
+gtk_canvas_imageframe_init (GtkCanvasImageFrame *image)
+{
+ image->x = 0.0;
+ image->y = 0.0;
+ image->width = 0.0;
+ image->height = 0.0;
+ image->drawwidth = 0.0;
+ image->anchor = GTK_ANCHOR_CENTER;
+ GTK_CANVAS_ITEM(image)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW;
+}
+
+static void
+gtk_canvas_imageframe_destroy (GtkObject *object)
+{
+ GtkCanvasImageFrame *image;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_CANVAS_IS_CANVAS_IMAGEFRAME (object));
+
+ image = GTK_CANVAS_IMAGEFRAME (object);
+
+ image->cwidth = 0;
+ image->cheight = 0;
+
+ if (image->pixbuf)
+ {
+ art_pixbuf_free (image->pixbuf);
+ image->pixbuf = NULL;
+ }
+
+ if(GTK_OBJECT_CLASS (parent_class)->destroy)
+ {
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ }
+}
+
+/* Get's the image bounds expressed as item-relative coordinates. */
+static void
+get_bounds_item_relative (GtkCanvasImageFrame *image, double *px1, double *py1, double *px2, double *py2)
+{
+ GtkCanvasItem *item;
+ double x, y;
+
+ item = GTK_CANVAS_ITEM (image);
+
+ /* Get item coordinates */
+
+ x = image->x;
+ y = image->y;
+
+ /* Anchor image */
+
+ switch (image->anchor) {
+ case GTK_ANCHOR_NW:
+ case GTK_ANCHOR_W:
+ case GTK_ANCHOR_SW:
+ break;
+
+ case GTK_ANCHOR_N:
+ case GTK_ANCHOR_CENTER:
+ case GTK_ANCHOR_S:
+ x -= image->width / 2;
+ break;
+
+ case GTK_ANCHOR_NE:
+ case GTK_ANCHOR_E:
+ case GTK_ANCHOR_SE:
+ x -= image->width;
+ break;
+ }
+
+ switch (image->anchor) {
+ case GTK_ANCHOR_NW:
+ case GTK_ANCHOR_N:
+ case GTK_ANCHOR_NE:
+ break;
+
+ case GTK_ANCHOR_W:
+ case GTK_ANCHOR_CENTER:
+ case GTK_ANCHOR_E:
+ y -= image->height / 2;
+ break;
+
+ case GTK_ANCHOR_SW:
+ case GTK_ANCHOR_S:
+ case GTK_ANCHOR_SE:
+ y -= image->height;
+ break;
+ }
+
+ /* Bounds */
+
+ *px1 = x;
+ *py1 = y;
+ *px2 = x + image->width;
+ *py2 = y + image->height;
+}
+
+static void
+get_bounds (GtkCanvasImageFrame *image, double *px1, double *py1, double *px2, double *py2)
+{
+ GtkCanvasItem *item;
+ double i2c[6];
+ ArtDRect i_bbox, c_bbox;
+
+ item = GTK_CANVAS_ITEM (image);
+
+ gtk_canvas_item_i2c_affine (item, i2c);
+
+ get_bounds_item_relative (image, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1);
+ art_drect_affine_transform (&c_bbox, &i_bbox, i2c);
+
+ /* add a fudge factor */
+ *px1 = c_bbox.x0 - 1;
+ *py1 = c_bbox.y0 - 1;
+ *px2 = c_bbox.x1 + 1;
+ *py2 = c_bbox.y1 + 1;
+}
+
+/* deprecated */
+static void
+recalc_bounds (GtkCanvasImageFrame *image)
+{
+ GtkCanvasItem *item;
+
+ item = GTK_CANVAS_ITEM (image);
+
+ get_bounds (image, &item->x1, &item->y1, &item->x2, &item->y2);
+
+ item->x1 = image->cx;
+ item->y1 = image->cy;
+ item->x2 = image->cx + image->cwidth;
+ item->y2 = image->cy + image->cheight;
+
+ gtk_canvas_group_child_bounds (GTK_CANVAS_GROUP (item->parent), item);
+}
+
+static void
+gtk_canvas_imageframe_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasItem *item;
+ GtkCanvasImageFrame *image;
+ int update;
+ int calc_bounds;
+
+ item = GTK_CANVAS_ITEM (object);
+ image = GTK_CANVAS_IMAGEFRAME (object);
+
+ update = FALSE;
+ calc_bounds = FALSE;
+
+ switch (arg_id) {
+ case ARG_PIXBUF:
+ if (item->canvas->aa && GTK_VALUE_BOXED (*arg)) {
+ if (image->pixbuf != NULL)
+ art_pixbuf_free (image->pixbuf);
+ image->pixbuf = GTK_VALUE_BOXED (*arg);
+ }
+ update = TRUE;
+ break;
+
+ case ARG_X:
+ image->x = GTK_VALUE_DOUBLE (*arg);
+ update = TRUE;
+ break;
+
+ case ARG_Y:
+ image->y = GTK_VALUE_DOUBLE (*arg);
+ update = TRUE;
+ break;
+
+ case ARG_WIDTH:
+ image->width = fabs (GTK_VALUE_DOUBLE (*arg));
+ update = TRUE;
+ break;
+
+ case ARG_HEIGHT:
+ image->height = fabs (GTK_VALUE_DOUBLE (*arg));
+ update = TRUE;
+ break;
+
+ case ARG_DRAWWIDTH:
+ image->drawwidth = fabs (GTK_VALUE_DOUBLE (*arg));
+ update = TRUE;
+ break;
+
+ case ARG_ANCHOR:
+ image->anchor = GTK_VALUE_ENUM (*arg);
+ update = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+#ifdef OLD_XFORM
+ if (update)
+ (* GTK_CANVAS_ITEM_CLASS (item->object.klass)->update) (item, NULL, NULL, 0);
+
+ if (calc_bounds)
+ recalc_bounds (image);
+#else
+ if (update)
+ gtk_canvas_item_request_update (item);
+#endif
+}
+
+static void
+gtk_canvas_imageframe_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasImageFrame *image;
+
+ image = GTK_CANVAS_IMAGEFRAME (object);
+
+ switch (arg_id) {
+
+ case ARG_X:
+ GTK_VALUE_DOUBLE (*arg) = image->x;
+ break;
+
+ case ARG_Y:
+ GTK_VALUE_DOUBLE (*arg) = image->y;
+ break;
+
+ case ARG_WIDTH:
+ GTK_VALUE_DOUBLE (*arg) = image->width;
+ break;
+
+ case ARG_HEIGHT:
+ GTK_VALUE_DOUBLE (*arg) = image->height;
+ break;
+
+ case ARG_DRAWWIDTH:
+ GTK_VALUE_DOUBLE (*arg) = image->drawwidth;
+ break;
+
+ case ARG_ANCHOR:
+ GTK_VALUE_ENUM (*arg) = image->anchor;
+ break;
+
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+gtk_canvas_imageframe_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ GtkCanvasImageFrame *image;
+ ArtDRect i_bbox, c_bbox;
+ int w = 0;
+ int h = 0;
+
+ image = GTK_CANVAS_IMAGEFRAME (item);
+
+ if (parent_class->update)
+ (* parent_class->update) (item, affine, clip_path, flags);
+
+ /* only works for non-rotated, non-skewed transforms */
+ image->cwidth = (int) (image->width * affine[0] + 0.5);
+ image->cheight = (int) (image->height * affine[3] + 0.5);
+
+ if (image->pixbuf) {
+ image->need_recalc = TRUE ;
+ }
+
+#ifdef OLD_XFORM
+ recalc_bounds (image);
+#else
+ get_bounds_item_relative (image, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1);
+ art_drect_affine_transform (&c_bbox, &i_bbox, affine);
+
+ /* these values only make sense in the non-rotated, non-skewed case */
+ image->cx = c_bbox.x0;
+ image->cy = c_bbox.y0;
+
+ /* add a fudge factor */
+ c_bbox.x0--;
+ c_bbox.y0--;
+ c_bbox.x1++;
+ c_bbox.y1++;
+
+ gtk_canvas_update_bbox (item, c_bbox.x0, c_bbox.y0, c_bbox.x1, c_bbox.y1);
+
+ if (image->pixbuf) {
+ w = image->pixbuf->width;
+ h = image->pixbuf->height;
+ }
+
+ image->affine[0] = (affine[0] * image->width) / w;
+ image->affine[1] = (affine[1] * image->height) / h;
+ image->affine[2] = (affine[2] * image->width) / w;
+ image->affine[3] = (affine[3] * image->height) / h;
+ image->affine[4] = i_bbox.x0 * affine[0] + i_bbox.y0 * affine[2] + affine[4];
+ image->affine[5] = i_bbox.x0 * affine[1] + i_bbox.y0 * affine[3] + affine[5];
+
+#endif
+}
+
+static void
+gtk_canvas_imageframe_realize (GtkCanvasItem *item)
+{
+ GtkCanvasImageFrame *image;
+
+ image = GTK_CANVAS_IMAGEFRAME (item);
+
+ if (parent_class->realize)
+ (* parent_class->realize) (item);
+
+}
+
+static void
+gtk_canvas_imageframe_unrealize (GtkCanvasItem *item)
+{
+ GtkCanvasImageFrame *image;
+
+ image = GTK_CANVAS_IMAGEFRAME(item);
+
+ if (parent_class->unrealize)
+ (* parent_class->unrealize) (item);
+}
+
+static void
+recalc_if_needed (GtkCanvasImageFrame *image)
+{}
+
+static void
+gtk_canvas_imageframe_draw (GtkCanvasItem *item, GdkDrawable *drawable,
+ int x, int y, int width, int height)
+{
+ fprintf(stderr, "please don't use the CanvasImageFrame item in a non-aa Canvas\n") ;
+ abort() ;
+}
+
+static double
+gtk_canvas_imageframe_point (GtkCanvasItem *item, double x, double y,
+ int cx, int cy, GtkCanvasItem **actual_item)
+{
+ GtkCanvasImageFrame *image;
+ int x1, y1, x2, y2;
+ int dx, dy;
+
+ image = GTK_CANVAS_IMAGEFRAME (item);
+
+ *actual_item = item;
+
+ recalc_if_needed (image);
+
+ x1 = image->cx - item->canvas->close_enough;
+ y1 = image->cy - item->canvas->close_enough;
+ x2 = image->cx + image->cwidth - 1 + item->canvas->close_enough;
+ y2 = image->cy + image->cheight - 1 + item->canvas->close_enough;
+
+ /* Hard case: is point inside image's gravity region? */
+
+ //if ((cx >= x1) && (cy >= y1) && (cx <= x2) && (cy <= y2))
+ //return dist_to_mask (image, cx, cy) / item->canvas->pixels_per_unit;
+
+ /* Point is outside image */
+
+ x1 += item->canvas->close_enough;
+ y1 += item->canvas->close_enough;
+ x2 -= item->canvas->close_enough;
+ y2 -= item->canvas->close_enough;
+
+ if (cx < x1)
+ dx = x1 - cx;
+ else if (cx > x2)
+ dx = cx - x2;
+ else
+ dx = 0;
+
+ if (cy < y1)
+ dy = y1 - cy;
+ else if (cy > y2)
+ dy = cy - y2;
+ else
+ dy = 0;
+
+ return sqrt (dx * dx + dy * dy) / item->canvas->pixels_per_unit;
+}
+
+static void
+gtk_canvas_imageframe_translate (GtkCanvasItem *item, double dx, double dy)
+{
+#ifdef OLD_XFORM
+ GtkCanvasImageFrame *image;
+
+ image = GTK_CANVAS_IMAGEFRAME (item);
+
+ image->x += dx;
+ image->y += dy;
+
+ recalc_bounds (image);
+#endif
+}
+
+static void
+gtk_canvas_imageframe_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
+{
+ GtkCanvasImageFrame *image;
+
+ image = GTK_CANVAS_IMAGEFRAME (item);
+
+ *x1 = image->x;
+ *y1 = image->y;
+
+ switch (image->anchor) {
+ case GTK_ANCHOR_NW:
+ case GTK_ANCHOR_W:
+ case GTK_ANCHOR_SW:
+ break;
+
+ case GTK_ANCHOR_N:
+ case GTK_ANCHOR_CENTER:
+ case GTK_ANCHOR_S:
+ *x1 -= image->width / 2.0;
+ break;
+
+ case GTK_ANCHOR_NE:
+ case GTK_ANCHOR_E:
+ case GTK_ANCHOR_SE:
+ *x1 -= image->width;
+ break;
+ }
+
+ switch (image->anchor) {
+ case GTK_ANCHOR_NW:
+ case GTK_ANCHOR_N:
+ case GTK_ANCHOR_NE:
+ break;
+
+ case GTK_ANCHOR_W:
+ case GTK_ANCHOR_CENTER:
+ case GTK_ANCHOR_E:
+ *y1 -= image->height / 2.0;
+ break;
+
+ case GTK_ANCHOR_SW:
+ case GTK_ANCHOR_S:
+ case GTK_ANCHOR_SE:
+ *y1 -= image->height;
+ break;
+ }
+
+ *x2 = *x1 + image->width;
+ *y2 = *y1 + image->height;
+}
+
+static void
+gtk_canvas_imageframe_render (GtkCanvasItem *item, GtkCanvasBuf *buf)
+{
+ GtkCanvasImageFrame *image;
+
+ image = GTK_CANVAS_IMAGEFRAME (item);
+
+ gtk_canvas_buf_ensure_buf (buf);
+
+#ifdef VERBOSE
+ {
+ char str[128];
+ art_affine_to_string (str, image->affine);
+ g_print ("gtk_canvas_imageframe_render %s\n", str);
+ }
+#endif
+
+ art_rgb_pixbuf_affine (buf->buf,
+ buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1,
+ buf->buf_rowstride,
+ image->pixbuf,
+ image->affine,
+ ART_FILTER_NEAREST, NULL);
+
+ buf->is_bg = 0;
+}
diff --git a/gtk2_ardour/canvas-imageframe.h b/gtk2_ardour/canvas-imageframe.h
new file mode 100644
index 0000000000..408814b8fc
--- /dev/null
+++ b/gtk2_ardour/canvas-imageframe.h
@@ -0,0 +1,80 @@
+/* Image item type for GtkCanvas widget
+ *
+ * GtkCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is
+ * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
+ *
+ * Copyright (C) 1998 The Free Software Foundation
+ *
+ * Author: Federico Mena <federico@nuclecu.unam.mx>
+ */
+
+
+#ifndef __GTK_CANVAS_IMAGEFRAME_H__
+#define __GTK_CANVAS_IMAGEFRAME_H__
+
+#include <stdint.h>
+
+#include <gtk-canvas/gtk-canvas-defs.h>
+#include <gtk/gtkpacker.h> /* why the hell is GtkAnchorType here and not in gtkenums.h? */
+#include <libart_lgpl/art_misc.h>
+#include <libart_lgpl/art_pixbuf.h>
+#include "gtk-canvas/gtk-canvas.h"
+
+
+BEGIN_GTK_CANVAS_DECLS
+
+
+/* Image item for the canvas. Images are positioned by anchoring them to a point.
+ * The following arguments are available:
+ *
+ * name type read/write description
+ * ------------------------------------------------------------------------------------------
+ * pixbuf ArtPixBuf* W Pointer to an ArtPixBuf (aa-mode)
+ * x double RW X coordinate of anchor point
+ * y double RW Y coordinate of anchor point
+ * width double RW Width to scale image to, in canvas units
+ * height double RW Height to scale image to, in canvas units
+ * drawwidth double RW Width to scale image to, in canvas units
+ * anchor GtkAnchorType RW Anchor side for the image
+ */
+
+
+#define GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME (gtk_canvas_imageframe_get_type ())
+#define GTK_CANVAS_IMAGEFRAME(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME, GtkCanvasImageFrame))
+#define GTK_CANVAS_IMAGEFRAME_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME, GtkCanvasImageFrameClass))
+#define GTK_CANVAS_IS_CANVAS_IMAGEFRAME(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME))
+#define GTK_CANVAS_IS_CANVAS_IMAGEFRAME_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME))
+
+
+typedef struct _GtkCanvasImageFrame GtkCanvasImageFrame;
+typedef struct _GtkCanvasImageFrameClass GtkCanvasImageFrameClass;
+
+struct _GtkCanvasImageFrame {
+ GtkCanvasItem item;
+
+ double x, y; /* Position at anchor, item relative */
+ double width, height; /* Size of image, item relative */
+ double drawwidth ; /* the amount of the image we draw width-wise (0-drawwidth)*/
+ GtkAnchorType anchor; /* Anchor side for image */
+
+ int cx, cy; /* Top-left canvas coordinates for display */
+ int cwidth, cheight; /* Rendered size in pixels */
+
+ uint32_t need_recalc : 1; /* Do we need to rescale the image? */
+
+ ArtPixBuf *pixbuf; /* A pixbuf, for aa rendering */
+ double affine[6]; /* The item -> canvas affine */
+};
+
+struct _GtkCanvasImageFrameClass {
+ GtkCanvasItemClass parent_class;
+};
+
+
+/* Standard Gtk function */
+GtkType gtk_canvas_imageframe_get_type (void);
+
+
+END_GTK_CANVAS_DECLS
+
+#endif
diff --git a/gtk2_ardour/canvas-ruler.c b/gtk2_ardour/canvas-ruler.c
new file mode 100644
index 0000000000..07b7553431
--- /dev/null
+++ b/gtk2_ardour/canvas-ruler.c
@@ -0,0 +1,381 @@
+#include <stdio.h>
+#include <math.h>
+#include <gtk-canvas.h>
+
+#include "canvas-ruler.h"
+#include "rgb_macros.h"
+
+enum {
+ ARG_0,
+ ARG_X1,
+ ARG_Y1,
+ ARG_X2,
+ ARG_Y2,
+ ARG_FRAMES_PER_UNIT,
+ ARG_FILL_COLOR,
+ ARG_TICK_COLOR
+
+};
+
+static void gtk_canvas_ruler_class_init (GtkCanvasRulerClass *class);
+static void gtk_canvas_ruler_init (GtkCanvasRuler *ruler);
+static void gtk_canvas_ruler_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_canvas_ruler_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+
+static void gtk_canvas_ruler_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
+static void gtk_canvas_ruler_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
+static double gtk_canvas_ruler_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item);
+static void gtk_canvas_ruler_render (GtkCanvasItem *item, GtkCanvasBuf *buf);
+static void gtk_canvas_ruler_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
+
+static GtkCanvasItemClass *parent_class;
+
+
+GtkType
+gtk_canvas_ruler_get_type (void)
+{
+ static GtkType ruler_type = 0;
+
+ if (!ruler_type) {
+ GtkTypeInfo ruler_info = {
+ "GtkCanvasRuler",
+ sizeof (GtkCanvasRuler),
+ sizeof (GtkCanvasRulerClass),
+ (GtkClassInitFunc) gtk_canvas_ruler_class_init,
+ (GtkObjectInitFunc) gtk_canvas_ruler_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ ruler_type = gtk_type_unique (gtk_canvas_item_get_type (), &ruler_info);
+ }
+
+ return ruler_type;
+}
+
+static void
+gtk_canvas_ruler_class_init (GtkCanvasRulerClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkCanvasItemClass *item_class;
+
+ object_class = (GtkObjectClass *) class;
+ item_class = (GtkCanvasItemClass *) class;
+
+ parent_class = gtk_type_class (gtk_canvas_item_get_type ());
+
+ gtk_object_add_arg_type ("GtkCanvasRuler::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1);
+ gtk_object_add_arg_type ("GtkCanvasRuler::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1);
+ gtk_object_add_arg_type ("GtkCanvasRuler::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2);
+ gtk_object_add_arg_type ("GtkCanvasRuler::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2);
+ gtk_object_add_arg_type ("GtkCanvasRuler::frames_per_unit", GTK_TYPE_LONG, GTK_ARG_READWRITE, ARG_FRAMES_PER_UNIT);
+ gtk_object_add_arg_type ("GtkCanvasRuler::fill_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR);
+ gtk_object_add_arg_type ("GtkCanvasRuler::tick_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_TICK_COLOR);
+
+ object_class->set_arg = gtk_canvas_ruler_set_arg;
+ object_class->get_arg = gtk_canvas_ruler_get_arg;
+
+ item_class->update = gtk_canvas_ruler_update;
+ item_class->bounds = gtk_canvas_ruler_bounds;
+ item_class->point = gtk_canvas_ruler_point;
+ item_class->render = gtk_canvas_ruler_render;
+ item_class->draw = gtk_canvas_ruler_draw;
+}
+
+static void
+gtk_canvas_ruler_init (GtkCanvasRuler *ruler)
+{
+ ruler->x1 = 0.0;
+ ruler->y1 = 0.0;
+ ruler->x2 = 0.0;
+ ruler->y2 = 0.0;
+ ruler->frames_per_unit = 1;
+ ruler->fill_color = 0;
+ ruler->tick_color = 0;
+
+ GTK_CANVAS_ITEM(ruler)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW;
+}
+
+static void
+gtk_canvas_ruler_reset_bounds (GtkCanvasItem *item)
+
+{
+ double x1, x2, y1, y2;
+ ArtPoint i1, i2;
+ ArtPoint w1, w2;
+ int Ix1, Ix2, Iy1, Iy2;
+ double i2w[6];
+
+ gtk_canvas_ruler_bounds (item, &x1, &y1, &x2, &y2);
+
+ i1.x = x1;
+ i1.y = y1;
+ i2.x = x2;
+ i2.y = y2;
+
+ gtk_canvas_item_i2w_affine (item, i2w);
+ art_affine_point (&w1, &i1, i2w);
+ art_affine_point (&w2, &i2, i2w);
+
+ Ix1 = (int) rint(w1.x);
+ Ix2 = (int) rint(w2.x);
+ Iy1 = (int) rint(w1.y);
+ Iy2 = (int) rint(w2.y);
+
+ gtk_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2);
+}
+
+/*
+ * CANVAS CALLBACKS
+ */
+
+static void
+gtk_canvas_ruler_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasItem *item;
+ GtkCanvasRuler *ruler;
+ int redraw;
+ int calc_bounds;
+
+ item = GTK_CANVAS_ITEM (object);
+ ruler = GTK_CANVAS_RULER (object);
+
+ redraw = FALSE;
+ calc_bounds = FALSE;
+
+ switch (arg_id) {
+ case ARG_X1:
+ if (ruler->x1 != GTK_VALUE_DOUBLE (*arg)) {
+ ruler->x1 = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_Y1:
+ if (ruler->y1 != GTK_VALUE_DOUBLE (*arg)) {
+ ruler->y1 = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_X2:
+ if (ruler->x2 != GTK_VALUE_DOUBLE (*arg)) {
+ ruler->x2 = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_Y2:
+ if (ruler->y2 != GTK_VALUE_DOUBLE (*arg)) {
+ ruler->y2 = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_FRAMES_PER_UNIT:
+ if (ruler->frames_per_unit != GTK_VALUE_LONG(*arg)) {
+ ruler->frames_per_unit = GTK_VALUE_LONG(*arg);
+ redraw = TRUE;
+ }
+ break;
+
+ case ARG_FILL_COLOR:
+ if (ruler->fill_color != GTK_VALUE_INT(*arg)) {
+ ruler->fill_color = GTK_VALUE_INT(*arg);
+ redraw = TRUE;
+ }
+ break;
+
+ case ARG_TICK_COLOR:
+ if (ruler->tick_color != GTK_VALUE_INT(*arg)) {
+ ruler->tick_color = GTK_VALUE_INT(*arg);
+ redraw = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (calc_bounds) {
+ gtk_canvas_ruler_reset_bounds (item);
+ }
+
+ if (redraw) {
+ gtk_canvas_item_request_update (item);
+ }
+
+}
+
+static void
+gtk_canvas_ruler_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasRuler *ruler;
+
+ ruler = GTK_CANVAS_RULER (object);
+
+ switch (arg_id) {
+ case ARG_X1:
+ GTK_VALUE_DOUBLE (*arg) = ruler->x1;
+ break;
+ case ARG_Y1:
+ GTK_VALUE_DOUBLE (*arg) = ruler->y1;
+ break;
+ case ARG_X2:
+ GTK_VALUE_DOUBLE (*arg) = ruler->x2;
+ break;
+ case ARG_Y2:
+ GTK_VALUE_DOUBLE (*arg) = ruler->y2;
+ break;
+ case ARG_FRAMES_PER_UNIT:
+ GTK_VALUE_LONG (*arg) = ruler->frames_per_unit;
+ break;
+ case ARG_FILL_COLOR:
+ GTK_VALUE_INT (*arg) = ruler->fill_color;
+ break;
+ case ARG_TICK_COLOR:
+ GTK_VALUE_INT (*arg) = ruler->tick_color;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+gtk_canvas_ruler_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ GtkCanvasRuler *ruler;
+ double x;
+ double y;
+
+ ruler = GTK_CANVAS_RULER (item);
+
+ if (parent_class->update)
+ (* parent_class->update) (item, affine, clip_path, flags);
+
+ gtk_canvas_ruler_reset_bounds (item);
+
+ x = ruler->x1;
+ y = ruler->y1;
+
+ gtk_canvas_item_i2w (item, &x, &y);
+ gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &ruler->bbox_ulx, &ruler->bbox_uly);
+
+ x = ruler->x2;
+ y = ruler->y2;
+
+ gtk_canvas_item_i2w (item, &x, &y);
+ gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &ruler->bbox_lrx, &ruler->bbox_lry);
+
+ UINT_TO_RGB (ruler->tick_color, &ruler->tick_r, &ruler->tick_g, &ruler->tick_b);
+ UINT_TO_RGB (ruler->fill_color, &ruler->fill_r, &ruler->fill_g, &ruler->fill_b);
+}
+
+static void
+gtk_canvas_ruler_render (GtkCanvasItem *item,
+ GtkCanvasBuf *buf)
+{
+ GtkCanvasRuler *ruler;
+ int end, begin;
+
+ ruler = GTK_CANVAS_RULER (item);
+
+ if (parent_class->render) {
+ (*parent_class->render) (item, buf);
+ }
+
+ if (buf->is_bg) {
+ gtk_canvas_buf_ensure_buf (buf);
+ buf->is_bg = FALSE;
+ }
+
+ begin = MAX(ruler->bbox_ulx,buf->rect.x0);
+
+ if (ruler->bbox_lrx >= 0) {
+ end = MIN(ruler->bbox_lrx,buf->rect.x1);
+ } else {
+ end = buf->rect.x1;
+ }
+
+ if (begin == end) {
+ return;
+ }
+
+ PAINT_BOX (buf, ruler->fill_r, ruler->fill_g, ruler->fill_b, 255, begin, ruler->bbox_uly, end, ruler->bbox_lry - 1);
+ PAINT_HORIZ (buf, ruler->tick_r, ruler->tick_g, ruler->tick_b, begin, end, ruler->bbox_lry - 1);
+}
+
+static void
+gtk_canvas_ruler_draw (GtkCanvasItem *item,
+ GdkDrawable *drawable,
+ int x, int y,
+ int width, int height)
+{
+ GtkCanvasRuler *ruler;
+
+ ruler = GTK_CANVAS_RULER (item);
+
+ if (parent_class->draw) {
+ (* parent_class->draw) (item, drawable, x, y, width, height);
+ }
+
+ fprintf (stderr, "please don't use the CanvasRuler item in a non-aa Canvas\n");
+ abort ();
+}
+
+static void
+gtk_canvas_ruler_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
+{
+ GtkCanvasRuler *ruler = GTK_CANVAS_RULER (item);
+
+ *x1 = ruler->x1;
+ *y1 = ruler->y1;
+ *x2 = ruler->x2;
+ *y2 = ruler->y2;
+}
+
+static double
+gtk_canvas_ruler_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item)
+{
+ GtkCanvasRuler *ruler;
+ double x1, y1, x2, y2;
+ double dx, dy;
+
+ ruler = GTK_CANVAS_RULER (item);
+
+ *actual_item = item;
+
+ /* Find the bounds for the rectangle plus its outline width */
+
+ gtk_canvas_ruler_bounds (item, &x1, &y1, &x2, &y2);
+
+ /* Is point inside rectangle */
+
+ if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
+ return 0.0;
+ }
+
+ /* Point is outside rectangle */
+
+ if (x < x1)
+ dx = x1 - x;
+ else if (x > x2)
+ dx = x - x2;
+ else
+ dx = 0.0;
+
+ if (y < y1)
+ dy = y1 - y;
+ else if (y > y2)
+ dy = y - y2;
+ else
+ dy = 0.0;
+
+ return sqrt (dx * dx + dy * dy);
+}
diff --git a/gtk2_ardour/canvas-ruler.h b/gtk2_ardour/canvas-ruler.h
new file mode 100644
index 0000000000..db9937000a
--- /dev/null
+++ b/gtk2_ardour/canvas-ruler.h
@@ -0,0 +1,68 @@
+/* gtk-canvas-ruler.h: GtkCanvas item for simple rects
+ *
+ * Copyright (C) 2001 Paul Davis <pbd@op.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GTK_CANVAS_RULER_H__
+#define __GTK_CANVAS_RULER_H__
+
+#include <stdint.h>
+
+#include <gtk-canvas/gtk-canvas-defs.h>
+#include "gtk-canvas/gtk-canvas.h"
+
+BEGIN_GTK_CANVAS_DECLS
+
+/* Wave viewer item for canvas.
+ */
+
+#define GTK_CANVAS_TYPE_CANVAS_RULER (gtk_canvas_ruler_get_type ())
+#define GTK_CANVAS_RULER(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_RULER, GtkCanvasRuler))
+#define GTK_CANVAS_RULER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_RULER, GtkCanvasRulerClass))
+#define GTK_CANVAS_IS_CANVAS_RULER(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_RULER))
+#define GTK_CANVAS_IS_CANVAS_RULER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_RULER))
+
+typedef struct _GtkCanvasRuler GtkCanvasRuler;
+typedef struct _GtkCanvasRulerClass GtkCanvasRulerClass;
+
+struct _GtkCanvasRuler
+{
+ GtkCanvasItem item;
+ double x1, y1, x2, y2;
+ uint32_t fill_color;
+ uint32_t tick_color;
+ uint32_t frames_per_unit;
+
+ /* cached values set during update/used during render */
+
+ unsigned char fill_r, fill_b, fill_g, fill_a;
+ unsigned char tick_r, tick_b, tick_g;
+ guint32 bbox_ulx, bbox_uly;
+ guint32 bbox_lrx, bbox_lry;
+};
+
+struct _GtkCanvasRulerClass {
+ GtkCanvasItemClass parent_class;
+};
+
+GtkType gtk_canvas_ruler_get_type (void);
+
+END_GTK_CANVAS_DECLS
+
+#endif /* __GTK_CANVAS_RULER_H__ */
diff --git a/gtk2_ardour/canvas-simpleline.c b/gtk2_ardour/canvas-simpleline.c
new file mode 100644
index 0000000000..9823975eee
--- /dev/null
+++ b/gtk2_ardour/canvas-simpleline.c
@@ -0,0 +1,371 @@
+#include <stdio.h>
+#include <math.h>
+#include <gtk-canvas.h>
+
+#include "canvas-simpleline.h"
+#include "rgb_macros.h"
+
+enum {
+ ARG_0,
+ ARG_X1,
+ ARG_Y1,
+ ARG_X2,
+ ARG_Y2,
+ ARG_COLOR_RGBA
+};
+
+static void gtk_canvas_simpleline_class_init (GtkCanvasSimpleLineClass *class);
+static void gtk_canvas_simpleline_init (GtkCanvasSimpleLine *simpleline);
+static void gtk_canvas_simpleline_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_canvas_simpleline_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+
+static void gtk_canvas_simpleline_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
+static void gtk_canvas_simpleline_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
+static double gtk_canvas_simpleline_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item);
+static void gtk_canvas_simpleline_render (GtkCanvasItem *item, GtkCanvasBuf *buf);
+static void gtk_canvas_simpleline_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
+
+static GtkCanvasItemClass *parent_class;
+
+
+GtkType
+gtk_canvas_simpleline_get_type (void)
+{
+ static GtkType simpleline_type = 0;
+
+ if (!simpleline_type) {
+ GtkTypeInfo simpleline_info = {
+ "GtkCanvasSimpleLine",
+ sizeof (GtkCanvasSimpleLine),
+ sizeof (GtkCanvasSimpleLineClass),
+ (GtkClassInitFunc) gtk_canvas_simpleline_class_init,
+ (GtkObjectInitFunc) gtk_canvas_simpleline_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ simpleline_type = gtk_type_unique (gtk_canvas_item_get_type (), &simpleline_info);
+ }
+
+ return simpleline_type;
+}
+
+static void
+gtk_canvas_simpleline_class_init (GtkCanvasSimpleLineClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkCanvasItemClass *item_class;
+
+ object_class = (GtkObjectClass *) class;
+ item_class = (GtkCanvasItemClass *) class;
+
+ parent_class = gtk_type_class (gtk_canvas_item_get_type ());
+
+ gtk_object_add_arg_type ("GtkCanvasSimpleLine::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1);
+ gtk_object_add_arg_type ("GtkCanvasSimpleLine::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1);
+ gtk_object_add_arg_type ("GtkCanvasSimpleLine::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2);
+ gtk_object_add_arg_type ("GtkCanvasSimpleLine::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2);
+ gtk_object_add_arg_type ("GtkCanvasSimpleLine::color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_COLOR_RGBA);
+
+ object_class->set_arg = gtk_canvas_simpleline_set_arg;
+ object_class->get_arg = gtk_canvas_simpleline_get_arg;
+
+ item_class->update = gtk_canvas_simpleline_update;
+ item_class->bounds = gtk_canvas_simpleline_bounds;
+ item_class->point = gtk_canvas_simpleline_point;
+ item_class->render = gtk_canvas_simpleline_render;
+ item_class->draw = gtk_canvas_simpleline_draw;
+}
+
+static void
+gtk_canvas_simpleline_init (GtkCanvasSimpleLine *simpleline)
+{
+ simpleline->x1 = 0.0;
+ simpleline->y1 = 0.0;
+ simpleline->x2 = 0.0;
+ simpleline->y2 = 0.0;
+ simpleline->color = RGBA_TO_UINT(98,123,174,241);
+ simpleline->horizontal = TRUE; /* reset in the _update() method */
+ GTK_CANVAS_ITEM(simpleline)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW;
+}
+
+static void
+gtk_canvas_simpleline_bounds_world (GtkCanvasItem *item, int* ix1, int* iy1, int* ix2, int* iy2)
+{
+ double x1, x2, y1, y2;
+ ArtPoint i1, i2;
+ ArtPoint w1, w2;
+ double i2w[6];
+ GtkCanvasSimpleLine *simpleline = GTK_CANVAS_SIMPLELINE(item);
+
+ gtk_canvas_simpleline_bounds (item, &x1, &y1, &x2, &y2);
+
+ i1.x = x1;
+ i1.y = y1;
+ i2.x = x2;
+ i2.y = y2;
+
+ gtk_canvas_item_i2w_affine (item, i2w);
+ art_affine_point (&w1, &i1, i2w);
+ art_affine_point (&w2, &i2, i2w);
+
+ *ix1 = (int) rint(w1.x);
+ *ix2 = (int) rint(w2.x);
+ *iy1 = (int) rint(w1.y);
+ *iy2 = (int) rint(w2.y);
+
+ /* the update rect has to be of non-zero width and height */
+
+ if (x1 == x2) {
+ simpleline->horizontal = FALSE;
+ *ix2 += 1;
+ } else {
+ simpleline->horizontal = TRUE;
+ *iy2 += 1;
+ }
+}
+
+static void
+gtk_canvas_simpleline_reset_bounds (GtkCanvasItem *item)
+{
+ int Ix1, Ix2, Iy1, Iy2;
+
+ gtk_canvas_simpleline_bounds_world (item, &Ix1, &Iy1, &Ix2, &Iy2);
+ gtk_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2);
+}
+
+/*
+ * CANVAS CALLBACKS
+ */
+
+static void
+gtk_canvas_simpleline_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasItem *item;
+ GtkCanvasSimpleLine *simpleline;
+ int redraw;
+ int calc_bounds;
+
+ item = GTK_CANVAS_ITEM (object);
+ simpleline = GTK_CANVAS_SIMPLELINE (object);
+
+ redraw = FALSE;
+ calc_bounds = FALSE;
+
+ switch (arg_id) {
+ case ARG_X1:
+ if (simpleline->x1 != GTK_VALUE_DOUBLE (*arg)) {
+ simpleline->x1 = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_Y1:
+ if (simpleline->y1 != GTK_VALUE_DOUBLE (*arg)) {
+ simpleline->y1 = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_X2:
+ if (simpleline->x2 != GTK_VALUE_DOUBLE (*arg)) {
+ simpleline->x2 = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_Y2:
+ if (simpleline->y2 != GTK_VALUE_DOUBLE (*arg)) {
+ simpleline->y2 = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_COLOR_RGBA:
+ if (simpleline->color != GTK_VALUE_INT(*arg)) {
+ simpleline->color = GTK_VALUE_INT(*arg);
+ UINT_TO_RGBA (simpleline->color, &simpleline->r, &simpleline->g, &simpleline->b, &simpleline->a);
+ redraw = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (calc_bounds) {
+
+ gtk_canvas_item_request_update (item);
+
+ } else if (redraw) {
+
+ int Ix1, Ix2, Iy1, Iy2;
+ gtk_canvas_simpleline_bounds_world (item, &Ix1, &Iy1, &Ix2, &Iy2);
+ gtk_canvas_request_redraw (item->canvas, Ix1, Iy1, Ix2, Iy2);
+ }
+}
+
+static void
+gtk_canvas_simpleline_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasSimpleLine *simpleline;
+
+ simpleline = GTK_CANVAS_SIMPLELINE (object);
+
+ switch (arg_id) {
+ case ARG_X1:
+ GTK_VALUE_DOUBLE (*arg) = simpleline->x1;
+ break;
+ case ARG_Y1:
+ GTK_VALUE_DOUBLE (*arg) = simpleline->y1;
+ break;
+ case ARG_X2:
+ GTK_VALUE_DOUBLE (*arg) = simpleline->x2;
+ break;
+ case ARG_Y2:
+ GTK_VALUE_DOUBLE (*arg) = simpleline->y2;
+ break;
+ case ARG_COLOR_RGBA:
+ GTK_VALUE_INT (*arg) = simpleline->color;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+gtk_canvas_simpleline_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ GtkCanvasSimpleLine *simpleline;
+ double x;
+ double y;
+
+ simpleline = GTK_CANVAS_SIMPLELINE (item);
+
+ if (parent_class->update)
+ (* parent_class->update) (item, affine, clip_path, flags);
+
+ gtk_canvas_simpleline_reset_bounds (item);
+
+ x = simpleline->x1;
+ y = simpleline->y1;
+
+ gtk_canvas_item_i2w (item, &x, &y);
+ gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &simpleline->bbox_ulx, &simpleline->bbox_uly);
+
+ x = simpleline->x2;
+ y = simpleline->y2;
+
+ gtk_canvas_item_i2w (item, &x, &y);
+ gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &simpleline->bbox_lrx, &simpleline->bbox_lry);
+}
+
+static void
+gtk_canvas_simpleline_render (GtkCanvasItem *item,
+ GtkCanvasBuf *buf)
+{
+ GtkCanvasSimpleLine *simpleline;
+ int end, begin;
+
+ simpleline = GTK_CANVAS_SIMPLELINE (item);
+
+ if (parent_class->render) {
+ (*parent_class->render) (item, buf);
+ }
+
+ if (buf->is_bg) {
+ gtk_canvas_buf_ensure_buf (buf);
+ buf->is_bg = FALSE;
+ }
+
+ // begin = MAX(simpleline->bbox_ulx,buf->rect.x0);
+ // end = MIN(simpleline->bbox_lrx,buf->rect.x1);
+
+ begin = simpleline->bbox_ulx;
+ end = simpleline->bbox_lrx;
+
+ if (simpleline->color != 0) {
+ if (simpleline->horizontal) {
+ PAINT_HORIZA(buf, simpleline->r, simpleline->g, simpleline->b, simpleline->a,
+ begin, end, simpleline->bbox_uly);
+ } else {
+ PAINT_VERTA(buf, simpleline->r, simpleline->g, simpleline->b, simpleline->a,
+ begin, simpleline->bbox_uly, simpleline->bbox_lry);
+ }
+ }
+}
+
+static void
+gtk_canvas_simpleline_draw (GtkCanvasItem *item,
+ GdkDrawable *drawable,
+ int x, int y,
+ int width, int height)
+{
+ GtkCanvasSimpleLine *simpleline;
+
+ simpleline = GTK_CANVAS_SIMPLELINE (item);
+
+ if (parent_class->draw) {
+ (* parent_class->draw) (item, drawable, x, y, width, height);
+ }
+
+ fprintf (stderr, "please don't use the CanvasSimpleLine item in a non-aa Canvas\n");
+ abort ();
+}
+
+static void
+gtk_canvas_simpleline_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
+{
+ GtkCanvasSimpleLine *simpleline = GTK_CANVAS_SIMPLELINE (item);
+
+ *x1 = simpleline->x1;
+ *y1 = simpleline->y1;
+ *x2 = simpleline->x2;
+ *y2 = simpleline->y2;
+}
+
+static double
+gtk_canvas_simpleline_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item)
+{
+ GtkCanvasSimpleLine *simpleline;
+ double x1, y1, x2, y2;
+ double dx, dy;
+
+ simpleline = GTK_CANVAS_SIMPLELINE (item);
+
+ *actual_item = item;
+
+ /* Find the bounds for the rectangle plus its outline width */
+
+ gtk_canvas_simpleline_bounds (item, &x1, &y1, &x2, &y2);
+
+ /* Is point inside rectangle */
+
+ if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
+ return 0.0;
+ }
+
+ /* Point is outside rectangle */
+
+ if (x < x1)
+ dx = x1 - x;
+ else if (x > x2)
+ dx = x - x2;
+ else
+ dx = 0.0;
+
+ if (y < y1)
+ dy = y1 - y;
+ else if (y > y2)
+ dy = y - y2;
+ else
+ dy = 0.0;
+
+ return sqrt (dx * dx + dy * dy);
+}
diff --git a/gtk2_ardour/canvas-simpleline.h b/gtk2_ardour/canvas-simpleline.h
new file mode 100644
index 0000000000..f46f54d828
--- /dev/null
+++ b/gtk2_ardour/canvas-simpleline.h
@@ -0,0 +1,66 @@
+/* gtk-canvas-simpleline.h: GtkCanvas item for simple rects
+ *
+ * Copyright (C) 2001 Paul Davis <pbd@op.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GTK_CANVAS_SIMPLELINE_H__
+#define __GTK_CANVAS_SIMPLELINE_H__
+
+#include <stdint.h>
+
+#include <gtk-canvas/gtk-canvas-defs.h>
+#include "gtk-canvas/gtk-canvas.h"
+
+BEGIN_GTK_CANVAS_DECLS
+
+/* Wave viewer item for canvas.
+ */
+
+#define GTK_CANVAS_TYPE_CANVAS_SIMPLELINE (gtk_canvas_simpleline_get_type ())
+#define GTK_CANVAS_SIMPLELINE(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_SIMPLELINE, GtkCanvasSimpleLine))
+#define GTK_CANVAS_SIMPLELINE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_SIMPLELINE, GtkCanvasSimpleLineClass))
+#define GTK_CANVAS_IS_CANVAS_SIMPLELINE(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_SIMPLELINE))
+#define GTK_CANVAS_IS_CANVAS_SIMPLELINE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_SIMPLELINE))
+
+typedef struct _GtkCanvasSimpleLine GtkCanvasSimpleLine;
+typedef struct _GtkCanvasSimpleLineClass GtkCanvasSimpleLineClass;
+
+struct _GtkCanvasSimpleLine
+{
+ GtkCanvasItem item;
+ double x1, y1, x2, y2;
+ uint32_t color;
+ gboolean horizontal;
+
+ /* cached values set during update/used during render */
+
+ unsigned char r, b, g, a;
+ guint32 bbox_ulx, bbox_uly;
+ guint32 bbox_lrx, bbox_lry;
+};
+
+struct _GtkCanvasSimpleLineClass {
+ GtkCanvasItemClass parent_class;
+};
+
+GtkType gtk_canvas_simpleline_get_type (void);
+
+END_GTK_CANVAS_DECLS
+
+#endif /* __GTK_CANVAS_SIMPLELINE_H__ */
diff --git a/gtk2_ardour/canvas-simplerect.c b/gtk2_ardour/canvas-simplerect.c
new file mode 100644
index 0000000000..4ee4985a2c
--- /dev/null
+++ b/gtk2_ardour/canvas-simplerect.c
@@ -0,0 +1,587 @@
+#include <stdio.h>
+#include <math.h>
+#include <gtk-canvas.h>
+
+#include "canvas-simplerect.h"
+#include "rgb_macros.h"
+
+enum {
+ ARG_0,
+ ARG_X1,
+ ARG_Y1,
+ ARG_X2,
+ ARG_Y2,
+ ARG_OUTLINE_PIXELS,
+ ARG_OUTLINE_WHAT,
+ ARG_FILL,
+ ARG_FILL_COLOR_RGBA,
+ ARG_OUTLINE_COLOR_RGBA,
+ ARG_DRAW
+
+};
+
+static void gtk_canvas_simplerect_class_init (GtkCanvasSimpleRectClass *class);
+static void gtk_canvas_simplerect_init (GtkCanvasSimpleRect *simplerect);
+static void gtk_canvas_simplerect_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_canvas_simplerect_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+
+static void gtk_canvas_simplerect_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
+static void gtk_canvas_simplerect_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
+static double gtk_canvas_simplerect_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item);
+static void gtk_canvas_simplerect_render (GtkCanvasItem *item, GtkCanvasBuf *buf);
+static void gtk_canvas_simplerect_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
+
+static GtkCanvasItemClass *parent_class;
+
+
+GtkType
+gtk_canvas_simplerect_get_type (void)
+{
+ static GtkType simplerect_type = 0;
+
+ if (!simplerect_type) {
+ GtkTypeInfo simplerect_info = {
+ "GtkCanvasSimpleRect",
+ sizeof (GtkCanvasSimpleRect),
+ sizeof (GtkCanvasSimpleRectClass),
+ (GtkClassInitFunc) gtk_canvas_simplerect_class_init,
+ (GtkObjectInitFunc) gtk_canvas_simplerect_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ simplerect_type = gtk_type_unique (gtk_canvas_item_get_type (), &simplerect_info);
+ }
+
+ return simplerect_type;
+}
+
+static void
+gtk_canvas_simplerect_class_init (GtkCanvasSimpleRectClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkCanvasItemClass *item_class;
+
+ object_class = (GtkObjectClass *) class;
+ item_class = (GtkCanvasItemClass *) class;
+
+ parent_class = gtk_type_class (gtk_canvas_item_get_type ());
+
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_FILL);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::draw", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DRAW);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::fill_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_COLOR_RGBA);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_pixels", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_PIXELS);
+ gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_what", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_WHAT);
+
+ object_class->set_arg = gtk_canvas_simplerect_set_arg;
+ object_class->get_arg = gtk_canvas_simplerect_get_arg;
+
+ item_class->update = gtk_canvas_simplerect_update;
+ item_class->bounds = gtk_canvas_simplerect_bounds;
+ item_class->point = gtk_canvas_simplerect_point;
+ item_class->render = gtk_canvas_simplerect_render;
+ item_class->draw = gtk_canvas_simplerect_draw;
+}
+
+static void
+gtk_canvas_simplerect_init (GtkCanvasSimpleRect *simplerect)
+{
+ simplerect->x1 = 0.0;
+ simplerect->y1 = 0.0;
+ simplerect->x2 = 0.0;
+ simplerect->y2 = 0.0;
+ simplerect->fill = TRUE;
+ simplerect->draw = TRUE;
+ simplerect->full_draw_on_update = TRUE;
+ simplerect->fill_color = 0;
+ simplerect->outline_color = 0;
+ simplerect->outline_pixels = 1;
+ simplerect->outline_what = 0xf;
+
+ GTK_CANVAS_ITEM(simplerect)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW;
+}
+
+static void
+gtk_canvas_simplerect_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
+{
+ GtkCanvasSimpleRect *simplerect = GTK_CANVAS_SIMPLERECT (item);
+
+ *x1 = simplerect->x1;
+ *y1 = simplerect->y1;
+ *x2 = simplerect->x2 + 1;
+ *y2 = simplerect->y2 + 1;
+
+}
+
+static void
+gtk_canvas_simplerect_reset_bounds (GtkCanvasItem *item)
+{
+ GtkCanvasSimpleRect* simplerect;
+ double x1, x2, y1, y2;
+ double old_x1, old_x2, old_y1, old_y2;
+ double a, b;
+
+ old_x1 = item->x1;
+ old_y1 = item->y1;
+ old_x2 = item->x2;
+ old_y2 = item->y2;
+
+ gtk_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
+ gtk_canvas_item_i2w (item, &x1, &y1);
+ gtk_canvas_item_i2w (item, &x2, &y2);
+
+ item->x1 = x1;
+ item->y1 = y1;
+ item->x2 = x2;
+ item->y2 = y2;
+
+ /* now compute bounding box in canvas units */
+
+ simplerect = GTK_CANVAS_SIMPLERECT (item);
+
+ gtk_canvas_w2c (GTK_CANVAS(item->canvas), x1, y1, &simplerect->bbox_ulx, &simplerect->bbox_uly);
+ gtk_canvas_w2c (GTK_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry);
+
+ /* now queue redraws for changed areas */
+
+ if (item->x1 != old_x1) {
+
+ /* left edge changed. redraw the area that altered */
+
+ a = MIN(item->x1, old_x1);
+ b = MAX(item->x1, old_x1);
+ gtk_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
+ }
+
+ if (item->x2 != old_x2) {
+
+ /* right edge changed. redraw the area that altered */
+
+ a = MIN(item->x2, old_x2);
+ b = MAX(item->x2, old_x2);
+ gtk_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2);
+ }
+
+ if (item->y1 != old_y1) {
+
+ /* top edge changed. redraw the area that altered */
+
+ a = MIN(item->y1, old_y1);
+ b = MAX(item->y1, old_y1);
+ gtk_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
+ }
+
+ if (item->y2 != old_y2) {
+
+ /* lower edge changed. redraw the area that altered */
+
+ a = MIN(item->y2, old_y2);
+ b = MAX(item->y2, old_y2);
+ gtk_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1);
+ }
+}
+
+/*
+ * CANVAS CALLBACKS
+ */
+
+static void
+gtk_canvas_simplerect_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasItem *item;
+ GtkCanvasSimpleRect *simplerect;
+ int update;
+ int bounds_changed;
+
+ item = GTK_CANVAS_ITEM (object);
+ simplerect = GTK_CANVAS_SIMPLERECT (object);
+
+ update = FALSE;
+ bounds_changed = FALSE;
+
+ switch (arg_id) {
+ case ARG_X1:
+ if (simplerect->x1 != GTK_VALUE_DOUBLE (*arg)) {
+ simplerect->x1 = GTK_VALUE_DOUBLE (*arg);
+ bounds_changed = TRUE;
+ }
+ break;
+
+ case ARG_Y1:
+ if (simplerect->y1 != GTK_VALUE_DOUBLE (*arg)) {
+ simplerect->y1 = GTK_VALUE_DOUBLE (*arg);
+ bounds_changed = TRUE;
+ }
+ break;
+
+ case ARG_X2:
+ if (simplerect->x2 != GTK_VALUE_DOUBLE (*arg)) {
+ simplerect->x2 = GTK_VALUE_DOUBLE (*arg);
+ bounds_changed = TRUE;
+ }
+ break;
+
+ case ARG_Y2:
+ if (simplerect->y2 != GTK_VALUE_DOUBLE (*arg)) {
+ simplerect->y2 = GTK_VALUE_DOUBLE (*arg);
+ bounds_changed = TRUE;
+ }
+ break;
+
+ case ARG_DRAW:
+ if (simplerect->draw != GTK_VALUE_BOOL (*arg)) {
+ simplerect->draw = GTK_VALUE_BOOL (*arg);
+ update = TRUE;
+ }
+ break;
+
+
+ case ARG_FILL:
+ if (simplerect->fill != GTK_VALUE_BOOL (*arg)) {
+ simplerect->fill = GTK_VALUE_BOOL (*arg);
+ update = TRUE;
+ }
+ break;
+
+ case ARG_FILL_COLOR_RGBA:
+ if (simplerect->fill_color != GTK_VALUE_INT(*arg)) {
+ simplerect->fill_color = GTK_VALUE_INT(*arg);
+ update = TRUE;
+ }
+ break;
+
+ case ARG_OUTLINE_COLOR_RGBA:
+ if (simplerect->outline_color != GTK_VALUE_INT(*arg)) {
+ simplerect->outline_color = GTK_VALUE_INT(*arg);
+ update = TRUE;
+ }
+ break;
+
+ case ARG_OUTLINE_PIXELS:
+ if (simplerect->outline_pixels != GTK_VALUE_INT(*arg)) {
+ simplerect->outline_pixels = GTK_VALUE_INT(*arg);
+ update = TRUE;
+ }
+ break;
+
+ case ARG_OUTLINE_WHAT:
+ if (simplerect->outline_what != GTK_VALUE_INT(*arg)) {
+ simplerect->outline_what = GTK_VALUE_INT(*arg);
+ update = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ simplerect->full_draw_on_update = update;
+
+ if (update || bounds_changed) {
+ gtk_canvas_item_request_update (item);
+ }
+}
+
+static void
+gtk_canvas_simplerect_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasSimpleRect *simplerect;
+
+ simplerect = GTK_CANVAS_SIMPLERECT (object);
+
+ switch (arg_id) {
+ case ARG_X1:
+ GTK_VALUE_DOUBLE (*arg) = simplerect->x1;
+ break;
+ case ARG_Y1:
+ GTK_VALUE_DOUBLE (*arg) = simplerect->y1;
+ break;
+ case ARG_X2:
+ GTK_VALUE_DOUBLE (*arg) = simplerect->x2;
+ break;
+ case ARG_Y2:
+ GTK_VALUE_DOUBLE (*arg) = simplerect->y2;
+ break;
+ case ARG_DRAW:
+ GTK_VALUE_BOOL (*arg) = simplerect->draw;
+ break;
+ case ARG_FILL:
+ GTK_VALUE_BOOL (*arg) = simplerect->fill;
+ break;
+ case ARG_FILL_COLOR_RGBA:
+ GTK_VALUE_INT (*arg) = simplerect->fill_color;
+ break;
+ case ARG_OUTLINE_COLOR_RGBA:
+ GTK_VALUE_INT (*arg) = simplerect->outline_color;
+ break;
+ case ARG_OUTLINE_PIXELS:
+ GTK_VALUE_INT (*arg) = simplerect->outline_pixels;
+ break;
+ case ARG_OUTLINE_WHAT:
+ GTK_VALUE_INT (*arg) = simplerect->outline_what;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+gtk_canvas_simplerect_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ GtkCanvasSimpleRect *simplerect;
+ unsigned char foo;
+
+ simplerect = GTK_CANVAS_SIMPLERECT (item);
+
+ if (parent_class->update)
+ (* parent_class->update) (item, affine, clip_path, flags);
+
+ gtk_canvas_simplerect_reset_bounds (item);
+
+ if (simplerect->full_draw_on_update) {
+ gtk_canvas_request_redraw (item->canvas,
+ simplerect->bbox_ulx,
+ simplerect->bbox_uly,
+ simplerect->bbox_lrx+1,
+ simplerect->bbox_lry+1);
+ simplerect->full_draw_on_update = FALSE;
+ }
+
+ UINT_TO_RGBA (simplerect->fill_color, &simplerect->fill_r, &simplerect->fill_g, &simplerect->fill_b, &simplerect->fill_a);
+ UINT_TO_RGBA (simplerect->outline_color, &simplerect->outline_r, &simplerect->outline_g, &simplerect->outline_b, &foo);
+}
+
+#define SIMPLERECT_FAST_RENDERER
+#ifdef SIMPLERECT_FAST_RENDERER
+
+static void
+gtk_canvas_simplerect_render (GtkCanvasItem *item,
+ GtkCanvasBuf *buf)
+{
+ GtkCanvasSimpleRect *simplerect;
+ int end, begin;
+ int ey, sy;
+ unsigned int i;
+ ArtIRect intersection;
+ ArtIRect self;
+
+ simplerect = GTK_CANVAS_SIMPLERECT (item);
+
+ if (parent_class->render) {
+ (*parent_class->render) (item, buf);
+ }
+
+ if (buf->is_bg) {
+
+ // this can be useful for debugging/understanding how the canvas redraws
+ // stuff.
+
+ // gint randr, randg, randb;
+ // randr = random() % 255;
+ // randg = random() % 255;
+ // randb = random() % 255;
+ // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
+
+ gtk_canvas_buf_ensure_buf (buf);
+ buf->is_bg = FALSE;
+ }
+
+ if (!simplerect->draw) {
+ return;
+ }
+
+ self.x0 = simplerect->bbox_ulx;
+ self.y0 = simplerect->bbox_uly;
+ self.x1 = simplerect->bbox_lrx;
+ self.y1 = simplerect->bbox_lry;
+
+ art_irect_intersect (&intersection, &self, &buf->rect);
+
+ begin = MAX(simplerect->bbox_ulx, buf->rect.x0);
+ end = MIN((simplerect->bbox_lrx-1), buf->rect.x1);
+
+ sy = simplerect->bbox_uly;
+ ey = simplerect->bbox_lry-1;
+
+ if (simplerect->fill) {
+
+ // this can be useful for debugging/understanding how the canvas redraws
+ // stuff.
+
+ // gint randr, randg, randb;
+ // randr = random() % 255;
+ // randg = random() % 255;
+ // randb = random() % 255;
+ // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
+
+ FAST_PAINT_BOX (buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a,
+ intersection.x0, intersection.y0,
+ intersection.x1, intersection.y1);
+
+ }
+
+ for (i = 0; i < simplerect->outline_pixels; ++i) {
+
+ if (simplerect->outline_what & 0x1) {
+ if (begin == simplerect->bbox_ulx) {
+ PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
+ }
+ }
+
+ if (simplerect->outline_what & 0x2) {
+ if (end == (simplerect->bbox_lrx - 1)) {
+ PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
+ }
+ }
+
+ if (simplerect->outline_what & 0x4) {
+ PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
+ }
+
+ if (simplerect->outline_what & 0x8) {
+ PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
+ }
+ }
+}
+
+#else /* SIMPLERECT_FAST_RENDERER */
+
+static void
+gtk_canvas_simplerect_render (GtkCanvasItem *item,
+ GtkCanvasBuf *buf)
+{
+ GtkCanvasSimpleRect *simplerect;
+ int end, begin;
+ int ey, sy;
+ unsigned int i;
+
+ simplerect = GTK_CANVAS_SIMPLERECT (item);
+
+ if (parent_class->render) {
+ (*parent_class->render) (item, buf);
+ }
+
+ if (buf->is_bg) {
+
+ // this can be useful for debugging/understanding how the canvas redraws
+ // stuff.
+
+ // gint randr, randg, randb;
+ // randr = random() % 255;
+ // randg = random() % 255;
+ // randb = random() % 255;
+ // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1);
+
+ gtk_canvas_buf_ensure_buf (buf);
+ buf->is_bg = FALSE;
+ }
+
+ if (!simplerect->draw) {
+ return;
+ }
+
+ begin = MAX(simplerect->bbox_ulx,buf->rect.x0);
+ end = MIN((simplerect->bbox_lrx-1),buf->rect.x1);
+
+ sy = simplerect->bbox_uly;
+ ey = simplerect->bbox_lry-1;
+
+ if (simplerect->fill) {
+
+ // this can be useful for debugging/understanding how the canvas redraws
+ // stuff.
+
+ // gint randr, randg, randb;
+ // randr = random() % 255;
+ // randg = random() % 255;
+ // randb = random() % 255;
+ // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey);
+
+ PAINT_BOX(buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, begin, sy, end, ey);
+ }
+
+ for (i = 0; i < simplerect->outline_pixels; ++i) {
+
+ if (simplerect->outline_what & 0x1) {
+ if (begin == simplerect->bbox_ulx) {
+ PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey);
+ }
+ }
+
+ if (simplerect->outline_what & 0x2) {
+ if (end == (simplerect->bbox_lrx - 1)) {
+ PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1);
+ }
+ }
+
+ if (simplerect->outline_what & 0x4) {
+ PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i);
+ }
+
+ if (simplerect->outline_what & 0x8) {
+ PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i);
+ }
+ }
+}
+#endif /* SIMPLERECT_FAST_RENDERER */
+
+static void
+gtk_canvas_simplerect_draw (GtkCanvasItem *item,
+ GdkDrawable *drawable,
+ int x, int y,
+ int width, int height)
+{
+ fprintf (stderr, "please don't use the CanvasSimpleRect item in a non-aa Canvas\n");
+ abort ();
+}
+
+static double
+gtk_canvas_simplerect_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item)
+{
+ GtkCanvasSimpleRect *simplerect;
+ double x1, y1, x2, y2;
+ double dx, dy;
+
+ simplerect = GTK_CANVAS_SIMPLERECT (item);
+
+ *actual_item = item;
+
+ /* Find the bounds for the rectangle plus its outline width */
+
+ gtk_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
+
+ /* Is point inside rectangle */
+
+ if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
+ return 0.0;
+ }
+
+ /* Point is outside rectangle */
+
+ if (x < x1)
+ dx = x1 - x;
+ else if (x > x2)
+ dx = x - x2;
+ else
+ dx = 0.0;
+
+ if (y < y1)
+ dy = y1 - y;
+ else if (y > y2)
+ dy = y - y2;
+ else
+ dy = 0.0;
+
+ return sqrt (dx * dx + dy * dy);
+}
diff --git a/gtk2_ardour/canvas-simplerect.h b/gtk2_ardour/canvas-simplerect.h
new file mode 100644
index 0000000000..f15cb40548
--- /dev/null
+++ b/gtk2_ardour/canvas-simplerect.h
@@ -0,0 +1,72 @@
+/* gtk-canvas-simplerect.h: GtkCanvas item for simple rects
+ *
+ * Copyright (C) 2001 Paul Davis <pbd@op.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GTK_CANVAS_SIMPLERECT_H__
+#define __GTK_CANVAS_SIMPLERECT_H__
+
+#include <stdint.h>
+
+#include <gtk-canvas/gtk-canvas-defs.h>
+#include "gtk-canvas/gtk-canvas.h"
+
+BEGIN_GTK_CANVAS_DECLS
+
+/* Wave viewer item for canvas.
+ */
+
+#define GTK_CANVAS_TYPE_CANVAS_SIMPLERECT (gtk_canvas_simplerect_get_type ())
+#define GTK_CANVAS_SIMPLERECT(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_SIMPLERECT, GtkCanvasSimpleRect))
+#define GTK_CANVAS_SIMPLERECT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_SIMPLERECT, GtkCanvasSimpleRectClass))
+#define GTK_CANVAS_IS_CANVAS_SIMPLERECT(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_SIMPLERECT))
+#define GTK_CANVAS_IS_CANVAS_SIMPLERECT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_SIMPLERECT))
+
+typedef struct _GtkCanvasSimpleRect GtkCanvasSimpleRect;
+typedef struct _GtkCanvasSimpleRectClass GtkCanvasSimpleRectClass;
+
+struct _GtkCanvasSimpleRect
+{
+ GtkCanvasItem item;
+ double x1, y1, x2, y2;
+ gboolean fill;
+ gboolean draw;
+ gboolean full_draw_on_update;
+ uint32_t fill_color;
+ uint32_t outline_color;
+ uint32_t outline_pixels;
+
+ /* cached values set during update/used during render */
+
+ unsigned char fill_r, fill_b, fill_g, fill_a;
+ unsigned char outline_r, outline_b, outline_g;
+ unsigned char outline_what;
+ guint32 bbox_ulx, bbox_uly;
+ guint32 bbox_lrx, bbox_lry;
+};
+
+struct _GtkCanvasSimpleRectClass {
+ GtkCanvasItemClass parent_class;
+};
+
+GtkType gtk_canvas_simplerect_get_type (void);
+
+END_GTK_CANVAS_DECLS
+
+#endif /* __GTK_CANVAS_SIMPLERECT_H__ */
diff --git a/gtk2_ardour/canvas-waveview.c b/gtk2_ardour/canvas-waveview.c
new file mode 100644
index 0000000000..ce46811d2c
--- /dev/null
+++ b/gtk2_ardour/canvas-waveview.c
@@ -0,0 +1,1013 @@
+/*
+ Copyright (C) 2000-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include <gtk-canvas.h>
+#include <string.h>
+#include <limits.h>
+
+#include <ardour/dB.h>
+
+#include "canvas-waveview.h"
+#include "rgb_macros.h"
+
+enum {
+ ARG_0,
+ ARG_DATA_SRC,
+ ARG_CHANNEL,
+ ARG_LENGTH_FUNCTION,
+ ARG_PEAK_FUNCTION,
+ ARG_GAIN_FUNCTION,
+ ARG_GAIN_SRC,
+ ARG_CACHE,
+ ARG_CACHE_UPDATER,
+ ARG_SAMPLES_PER_PIXEL,
+ ARG_AMPLITUDE_ABOVE_AXIS,
+ ARG_X,
+ ARG_Y,
+ ARG_HEIGHT,
+ ARG_WAVE_COLOR,
+ ARG_RECTIFIED,
+ ARG_SOURCEFILE_LENGTH_FUNCTION,
+ ARG_REGION_START
+};
+
+static void gtk_canvas_waveview_class_init (GtkCanvasWaveViewClass *class);
+static void gtk_canvas_waveview_init (GtkCanvasWaveView *waveview);
+static void gtk_canvas_waveview_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_canvas_waveview_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+
+static void gtk_canvas_waveview_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags);
+static void gtk_canvas_waveview_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
+static double gtk_canvas_waveview_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item);
+
+static void gtk_canvas_waveview_render (GtkCanvasItem *item, GtkCanvasBuf *buf);
+static void gtk_canvas_waveview_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h);
+
+static void gtk_canvas_waveview_set_data_src (GtkCanvasWaveView *, void *);
+static void gtk_canvas_waveview_set_channel (GtkCanvasWaveView *, guint32);
+
+static gint32 gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_sample, gulong end_sample);
+
+static GtkCanvasItemClass *parent_class;
+
+GtkType
+gtk_canvas_waveview_get_type (void)
+{
+ static GtkType waveview_type = 0;
+
+ if (!waveview_type) {
+ GtkTypeInfo waveview_info = {
+ "GtkCanvasWaveView",
+ sizeof (GtkCanvasWaveView),
+ sizeof (GtkCanvasWaveViewClass),
+ (GtkClassInitFunc) gtk_canvas_waveview_class_init,
+ (GtkObjectInitFunc) gtk_canvas_waveview_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ waveview_type = gtk_type_unique (gtk_canvas_item_get_type (), &waveview_info);
+ }
+
+ return waveview_type;
+}
+
+static void
+gtk_canvas_waveview_class_init (GtkCanvasWaveViewClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkCanvasItemClass *item_class;
+
+ object_class = (GtkObjectClass *) class;
+ item_class = (GtkCanvasItemClass *) class;
+
+ parent_class = gtk_type_class (gtk_canvas_item_get_type ());
+
+ gtk_object_add_arg_type ("GtkCanvasWaveView::data_src", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_DATA_SRC);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::channel", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CHANNEL);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::length_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_LENGTH_FUNCTION);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::sourcefile_length_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_SOURCEFILE_LENGTH_FUNCTION);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::peak_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_PEAK_FUNCTION);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::gain_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_GAIN_FUNCTION);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::gain_src", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_GAIN_SRC);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::cache", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CACHE);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::cache_updater", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CACHE_UPDATER);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::samples_per_unit", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_SAMPLES_PER_PIXEL);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::amplitude_above_axis", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_AMPLITUDE_ABOVE_AXIS);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::x", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::y", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::height", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEIGHT);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::wave_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_WAVE_COLOR);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::rectified", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_RECTIFIED);
+ gtk_object_add_arg_type ("GtkCanvasWaveView::region_start", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_REGION_START);
+
+ object_class->set_arg = gtk_canvas_waveview_set_arg;
+ object_class->get_arg = gtk_canvas_waveview_get_arg;
+
+ item_class->update = gtk_canvas_waveview_update;
+ item_class->bounds = gtk_canvas_waveview_bounds;
+ item_class->point = gtk_canvas_waveview_point;
+ item_class->render = gtk_canvas_waveview_render;
+ item_class->draw = gtk_canvas_waveview_draw;
+}
+
+GtkCanvasWaveViewCache*
+gtk_canvas_waveview_cache_new ()
+{
+ GtkCanvasWaveViewCache *c;
+
+ c = g_malloc (sizeof (GtkCanvasWaveViewCache));
+
+ c->allocated = 2048;
+ c->data = g_malloc (sizeof (GtkCanvasWaveViewCacheEntry) * c->allocated);
+ c->data_size = 0;
+ c->start = 0;
+ c->end = 0;
+
+ return c;
+}
+
+void
+gtk_canvas_waveview_cache_destroy (GtkCanvasWaveViewCache* cache)
+{
+ g_free (cache->data);
+ g_free (cache);
+}
+
+static void
+gtk_canvas_waveview_init (GtkCanvasWaveView *waveview)
+{
+ waveview->x = 0.0;
+ waveview->y = 0.0;
+ waveview->cache = 0;
+ waveview->cache_updater = FALSE;
+ waveview->data_src = NULL;
+ waveview->channel = 0;
+ waveview->peak_function = NULL;
+ waveview->length_function = NULL;
+ waveview->sourcefile_length_function = NULL;
+ waveview->gain_curve_function = NULL;
+ waveview->gain_src = NULL;
+ waveview->rectified = FALSE;
+ waveview->region_start = 0;
+ waveview->samples_per_unit = 1.0;
+ waveview->amplitude_above_axis = 1.0;
+ waveview->height = 100.0;
+ waveview->screen_width = gdk_screen_width ();
+ waveview->reload_cache_in_render = FALSE;
+
+ waveview->wave_color = RGBA_TO_UINT(44,35,126,255);
+
+ GTK_CANVAS_ITEM(waveview)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW;
+}
+
+#define DEBUG_CACHE 0
+
+static gint32
+gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_sample, gulong end_sample)
+{
+ gulong required_cache_entries;
+ gulong rf1, rf2,rf3, required_frames;
+ gulong new_cache_start, new_cache_end;
+ gulong half_width;
+ gulong npeaks;
+ gulong offset;
+ gulong ostart;
+ gulong present_frames;
+ gulong present_entries;
+ gulong copied;
+ GtkCanvasWaveViewCache *cache;
+ float* gain;
+
+ cache = waveview->cache;
+
+ start_sample = start_sample + waveview->region_start;
+ end_sample = end_sample + waveview->region_start;
+#if DEBUG_CACHE
+ // printf("waveview->region_start == %lu\n",waveview->region_start);
+ printf ("=> 0x%x cache @ 0x%x range: %lu - %lu request: %lu - %lu (%lu frames)\n",
+ waveview, cache,
+ cache->start, cache->end,
+ start_sample, end_sample, end_sample - start_sample);
+#endif
+
+ if (cache->start <= start_sample && cache->end >= end_sample) {
+#if DEBUG_CACHE
+ // printf ("0x%x: cache hit for %lu-%lu (cache holds: %lu-%lu\n",
+ // waveview, start_sample, end_sample, cache->start, cache->end);
+#endif
+ goto out;
+ }
+
+ /* make sure the cache is at least twice as wide as the screen width, and put the start sample
+ in the middle, ensuring that we cover the end_sample.
+ */
+
+ /* Note the assumption that we have a 1:1 units:pixel ratio for the canvas. Its everywhere ... */
+
+ half_width = (gulong) floor ((waveview->screen_width * waveview->samples_per_unit)/2.0 + 0.5);
+
+ if (start_sample < half_width) {
+ new_cache_start = 0;
+ } else {
+ new_cache_start = start_sample - half_width;
+ }
+
+ /* figure out how many frames we want */
+
+ rf1 = end_sample - start_sample + 1;
+ rf2 = (gulong) floor ((waveview->screen_width * waveview->samples_per_unit * 2.0f));
+ required_frames = MAX(rf1,rf2);
+
+ /* but make sure it doesn't extend beyond the end of the source material */
+
+ rf3 = (gulong) (waveview->sourcefile_length_function (waveview->data_src)) + 1;
+ rf3 -= new_cache_start;
+
+#if DEBUG_CACHE
+ fprintf (stderr, "\n\nAVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n",
+ rf3, waveview->sourcefile_length_function (waveview->data_src),
+ waveview->region_start, start_sample, new_cache_start);
+#endif
+
+ required_frames = MIN(required_frames,rf3);
+
+ new_cache_end = new_cache_start + required_frames - 1;
+
+ required_cache_entries = (gulong) floor (required_frames / waveview->samples_per_unit );
+
+#if DEBUG_CACHE
+ fprintf (stderr, "new cache = %lu - %lu\n", new_cache_start, new_cache_end);
+ fprintf(stderr,"required_cach_entries = %lu, samples_per_unit = %f\n",
+ required_cache_entries,waveview->samples_per_unit);
+#endif
+
+ if (required_cache_entries > cache->allocated) {
+ cache->data = g_realloc (cache->data, sizeof (GtkCanvasWaveViewCacheEntry) * required_cache_entries);
+ cache->allocated = required_cache_entries;
+ // cache->start = 0;
+ // cache->end = 0;
+ }
+
+ ostart = new_cache_start;
+
+#undef CACHE_MEMMOVE_OPTIMIZATION
+#ifdef CACHE_MEMMOVE_OPTIMIZATION
+
+ /* data is not entirely in the cache, so go fetch it, making sure to fill the cache */
+
+ /* some of the required cache entries are in the cache, but in the wrong
+ locations. use memmove to fix this.
+ */
+
+ if (cache->start < new_cache_start && new_cache_start < cache->end) {
+
+ /* case one: the common area is at the end of the existing cache. move it
+ to the beginning of the cache, and set up to refill whatever remains.
+
+
+ wv->cache_start wv->cache_end
+ |-------------------------------------------------------| cache
+ |--------------------------------| requested
+ <------------------->
+ "present"
+ new_cache_start new_cache_end
+ */
+
+
+ present_frames = cache->end - new_cache_start;
+ present_entries = (gulong) floor (present_frames / waveview->samples_per_unit);
+
+#if DEBUG_CACHE
+ fprintf (stderr, "existing material at end of current cache, move to start of new cache\n"
+ "\tcopy from %lu to start\n", cache->data_size - present_entries);
+#endif
+
+ memmove (&cache->data[0],
+ &cache->data[cache->data_size - present_entries],
+ present_entries * sizeof (GtkCanvasWaveViewCacheEntry));
+
+#if DEBUG_CACHE
+ fprintf (stderr, "satisfied %lu of %lu frames, offset = %lu, will start at %lu (ptr = 0x%x)\n",
+ present_frames, required_frames, present_entries, new_cache_start + present_entries,
+ cache->data + present_entries);
+#endif
+
+ copied = present_entries;
+ offset = present_entries;
+ new_cache_start += present_frames;
+ required_frames -= present_frames;
+
+ } else if (new_cache_end > cache->start && new_cache_end < cache->end) {
+
+ /* case two: the common area lives at the beginning of the existing cache.
+
+ wv->cache_start wv->cache_end
+ |-----------------------------------------------------|
+ |--------------------------------|
+ <----------------->
+ "present"
+
+ new_cache_start new_cache_end
+ */
+
+ present_frames = new_cache_end - cache->start;
+ present_entries = (gulong) floor (present_frames / waveview->samples_per_unit);
+
+ memmove (&cache->data[cache->data_size - present_entries],
+ &cache->data[0],
+ present_entries * sizeof (GtkCanvasWaveViewCacheEntry));
+
+#if DEBUG_CACHE
+ fprintf (stderr, "existing material at start of current cache, move to start of end cache\n");
+#endif
+
+#if DEBUG_CACHE
+ fprintf (stderr, "satisfied %lu of %lu frames, offset = %lu, will start at %lu (ptr = 0x%x)\n",
+ present_entries, required_frames, present_entries, new_cache_start + present_entries,
+ cache->data + present_entries);
+#endif
+
+ copied = present_entries;
+ offset = 0;
+ required_frames -= present_frames;
+
+
+ } else {
+ copied = 0;
+ offset = 0;
+
+ }
+
+#else
+ copied = 0;
+ offset = 0;
+
+#endif /* CACHE_MEMMOVE_OPTIMIZATION */
+
+// fprintf(stderr,"length == %lu\n",waveview->length_function (waveview->data_src));
+// required_frames = MIN (waveview->length_function (waveview->data_src) - new_cache_start, required_frames);
+ npeaks = (gulong) floor (required_frames / waveview->samples_per_unit);
+ npeaks = MAX (1, npeaks);
+ required_frames = npeaks * waveview->samples_per_unit;
+
+#if DEBUG_CACHE
+
+
+ printf ("requesting %lu/%f to cover %lu-%lu at %f spu (request was %lu-%lu) into cache + %lu\n",
+ required_frames, required_frames/waveview->samples_per_unit, new_cache_start, new_cache_end,
+ waveview->samples_per_unit, start_sample, end_sample, offset);
+#endif
+
+#if DEBUG_CACHE
+// printf ("cache holds %lu entries, requesting %lu to cover %lu-%lu (request was %lu-%lu)\n",
+// cache->data_size, npeaks, new_cache_start, new_cache_end,
+// start_sample, end_sample);
+#endif
+
+ waveview->peak_function (waveview->data_src, npeaks, new_cache_start, required_frames, cache->data + offset, waveview->channel,waveview->samples_per_unit);
+
+ /* take into account any copied peaks */
+
+ npeaks += copied;
+
+ if (npeaks < cache->allocated) {
+#if DEBUG_CACHE
+ fprintf (stderr, "zero fill cache for %lu at %lu\n", cache->allocated - npeaks, npeaks);
+#endif
+ memset (&cache->data[npeaks], 0, sizeof (GtkCanvasWaveViewCacheEntry) * (cache->allocated - npeaks));
+ cache->data_size = npeaks;
+ } else {
+ cache->data_size = cache->allocated;
+ }
+
+ if (waveview->gain_curve_function) {
+ guint32 n;
+
+ gain = (float*) malloc (sizeof (float) * cache->data_size);
+
+ waveview->gain_curve_function (waveview->gain_src, new_cache_start, new_cache_end, gain, cache->data_size);
+
+ for (n = 0; n < cache->data_size; ++n) {
+ cache->data[n].min *= gain[n];
+ cache->data[n].max *= gain[n];
+ }
+
+ free (gain);
+
+ }
+
+ cache->start = ostart;
+ cache->end = new_cache_end;
+
+ out:
+#if DEBUG_CACHE
+ fprintf (stderr, "return cache index = %d\n",
+ (gint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5));
+#endif
+ return (gint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5);
+
+}
+
+void
+gtk_canvas_waveview_set_data_src (GtkCanvasWaveView *waveview, void *data_src)
+{
+
+ if (waveview->cache_updater) {
+ if (waveview->data_src == data_src) {
+ waveview->reload_cache_in_render = TRUE;
+ return;
+ }
+
+ waveview->cache->start = 0;
+ waveview->cache->end = 0;
+ }
+
+ waveview->data_src = data_src;
+}
+
+void
+gtk_canvas_waveview_set_channel (GtkCanvasWaveView *waveview, guint32 chan)
+{
+ if (waveview->channel == chan) {
+ return;
+ }
+
+ waveview->channel = chan;
+}
+
+static void
+gtk_canvas_waveview_reset_bounds (GtkCanvasItem *item)
+
+{
+ double x1, x2, y1, y2;
+ ArtPoint i1, i2;
+ ArtPoint w1, w2;
+ int Ix1, Ix2, Iy1, Iy2;
+ double i2w[6];
+
+ gtk_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2);
+
+ i1.x = x1;
+ i1.y = y1;
+ i2.x = x2;
+ i2.y = y2;
+
+ gtk_canvas_item_i2w_affine (item, i2w);
+ art_affine_point (&w1, &i1, i2w);
+ art_affine_point (&w2, &i2, i2w);
+
+ Ix1 = (int) rint(w1.x);
+ Ix2 = (int) rint(w2.x);
+ Iy1 = (int) rint(w1.y);
+ Iy2 = (int) rint(w2.y);
+
+ gtk_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2);
+}
+
+/*
+ * CANVAS CALLBACKS
+ */
+
+static void
+gtk_canvas_waveview_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasItem *item;
+ GtkCanvasWaveView *waveview;
+ int redraw;
+ int calc_bounds;
+
+ item = GTK_CANVAS_ITEM (object);
+ waveview = GTK_CANVAS_WAVEVIEW (object);
+
+ redraw = FALSE;
+ calc_bounds = FALSE;
+
+ switch (arg_id) {
+ case ARG_DATA_SRC:
+ gtk_canvas_waveview_set_data_src (waveview, GTK_VALUE_POINTER(*arg));
+ redraw = TRUE;
+ break;
+
+ case ARG_CHANNEL:
+ gtk_canvas_waveview_set_channel (waveview, GTK_VALUE_UINT(*arg));
+ redraw = TRUE;
+ break;
+
+ case ARG_LENGTH_FUNCTION:
+ waveview->length_function = GTK_VALUE_POINTER(*arg);
+ redraw = TRUE;
+ break;
+ case ARG_SOURCEFILE_LENGTH_FUNCTION:
+ waveview->sourcefile_length_function = GTK_VALUE_POINTER(*arg);
+ redraw = TRUE;
+ break;
+
+ case ARG_PEAK_FUNCTION:
+ waveview->peak_function = GTK_VALUE_POINTER(*arg);
+ redraw = TRUE;
+ break;
+
+ case ARG_GAIN_FUNCTION:
+ waveview->gain_curve_function = GTK_VALUE_POINTER(*arg);
+ redraw = TRUE;
+ break;
+
+ case ARG_GAIN_SRC:
+ waveview->gain_src = GTK_VALUE_POINTER(*arg);
+ if (waveview->cache_updater) {
+ waveview->cache->start = 0;
+ waveview->cache->end = 0;
+ }
+ redraw = TRUE;
+ calc_bounds = TRUE;
+ break;
+
+ case ARG_CACHE:
+ waveview->cache = GTK_VALUE_POINTER(*arg);
+ redraw = TRUE;
+ break;
+
+
+ case ARG_CACHE_UPDATER:
+ waveview->cache_updater = GTK_VALUE_BOOL(*arg);
+ redraw = TRUE;
+ break;
+
+ case ARG_SAMPLES_PER_PIXEL:
+ if ((waveview->samples_per_unit = GTK_VALUE_DOUBLE(*arg)) < 1.0) {
+ waveview->samples_per_unit = 1.0;
+ }
+ if (waveview->cache_updater) {
+ waveview->cache->start = 0;
+ waveview->cache->end = 0;
+ }
+ redraw = TRUE;
+ calc_bounds = TRUE;
+ break;
+
+ case ARG_AMPLITUDE_ABOVE_AXIS:
+ waveview->amplitude_above_axis = GTK_VALUE_DOUBLE(*arg);
+ redraw = TRUE;
+ break;
+
+ case ARG_X:
+ if (waveview->x != GTK_VALUE_DOUBLE (*arg)) {
+ waveview->x = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_Y:
+ if (waveview->y != GTK_VALUE_DOUBLE (*arg)) {
+ waveview->y = GTK_VALUE_DOUBLE (*arg);
+ calc_bounds = TRUE;
+ }
+ break;
+
+ case ARG_HEIGHT:
+ if (waveview->height != fabs (GTK_VALUE_DOUBLE (*arg))) {
+ waveview->height = fabs (GTK_VALUE_DOUBLE (*arg));
+ redraw = TRUE;
+ }
+ break;
+
+ case ARG_WAVE_COLOR:
+ if (waveview->wave_color != GTK_VALUE_INT(*arg)) {
+ waveview->wave_color = GTK_VALUE_INT(*arg);
+ redraw = TRUE;
+ }
+ break;
+
+ case ARG_RECTIFIED:
+ if (waveview->rectified != GTK_VALUE_BOOL(*arg)) {
+ waveview->rectified = GTK_VALUE_BOOL(*arg);
+ redraw = TRUE;
+ }
+ break;
+ case ARG_REGION_START:
+ waveview->region_start = GTK_VALUE_UINT(*arg);
+ redraw = TRUE;
+ calc_bounds = TRUE;
+ break;
+
+
+ default:
+ break;
+ }
+
+ if (calc_bounds) {
+ gtk_canvas_waveview_reset_bounds (item);
+ }
+
+ if (redraw) {
+ gtk_canvas_item_request_update (item);
+ }
+
+}
+
+static void
+gtk_canvas_waveview_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ GtkCanvasWaveView *waveview;
+
+ waveview = GTK_CANVAS_WAVEVIEW (object);
+
+ switch (arg_id) {
+ case ARG_DATA_SRC:
+ GTK_VALUE_POINTER(*arg) = waveview->data_src;
+ break;
+
+ case ARG_CHANNEL:
+ GTK_VALUE_UINT(*arg) = waveview->channel;
+ break;
+
+ case ARG_LENGTH_FUNCTION:
+ GTK_VALUE_POINTER(*arg) = waveview->length_function;
+ break;
+
+ case ARG_SOURCEFILE_LENGTH_FUNCTION:
+ GTK_VALUE_POINTER(*arg) = waveview->sourcefile_length_function;
+ break;
+
+ case ARG_PEAK_FUNCTION:
+ GTK_VALUE_POINTER(*arg) = waveview->peak_function;
+ break;
+
+ case ARG_GAIN_FUNCTION:
+ GTK_VALUE_POINTER(*arg) = waveview->gain_curve_function;
+ break;
+
+ case ARG_GAIN_SRC:
+ GTK_VALUE_POINTER(*arg) = waveview->gain_src;
+ break;
+
+ case ARG_CACHE:
+ GTK_VALUE_POINTER(*arg) = waveview->cache;
+ break;
+
+ case ARG_CACHE_UPDATER:
+ GTK_VALUE_BOOL(*arg) = waveview->cache_updater;
+ break;
+
+ case ARG_SAMPLES_PER_PIXEL:
+ GTK_VALUE_DOUBLE(*arg) = waveview->samples_per_unit;
+ break;
+
+ case ARG_AMPLITUDE_ABOVE_AXIS:
+ GTK_VALUE_DOUBLE(*arg) = waveview->amplitude_above_axis;
+ break;
+
+ case ARG_X:
+ GTK_VALUE_DOUBLE (*arg) = waveview->x;
+ break;
+
+ case ARG_Y:
+ GTK_VALUE_DOUBLE (*arg) = waveview->y;
+ break;
+
+ case ARG_HEIGHT:
+ GTK_VALUE_DOUBLE (*arg) = waveview->height;
+ break;
+
+ case ARG_WAVE_COLOR:
+ GTK_VALUE_INT (*arg) = waveview->wave_color;
+ break;
+
+ case ARG_RECTIFIED:
+ GTK_VALUE_BOOL (*arg) = waveview->rectified;
+
+ case ARG_REGION_START:
+ GTK_VALUE_UINT (*arg) = waveview->region_start;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+gtk_canvas_waveview_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
+{
+ GtkCanvasWaveView *waveview;
+ double x, y;
+
+ waveview = GTK_CANVAS_WAVEVIEW (item);
+
+// check_cache (waveview, "start of update");
+
+ if (parent_class->update)
+ (* parent_class->update) (item, affine, clip_path, flags);
+
+ gtk_canvas_waveview_reset_bounds (item);
+
+ /* get the canvas coordinates of the view. Do NOT use affines
+ for this, because they do not round to the integer units used
+ by the canvas, resulting in subtle pixel-level errors later.
+ */
+
+ x = waveview->x;
+ y = waveview->y;
+
+ gtk_canvas_item_i2w (item, &x, &y);
+ gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &waveview->bbox_ulx, &waveview->bbox_uly);
+
+ waveview->samples = waveview->length_function (waveview->data_src);
+
+ x = waveview->x + (waveview->samples / waveview->samples_per_unit);
+ y = waveview->y + waveview->height;
+
+ gtk_canvas_item_i2w (item, &x, &y);
+ gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &waveview->bbox_lrx, &waveview->bbox_lry);
+
+ /* cache the half-height and the end point in canvas units */
+
+ waveview->half_height = waveview->height / 2.0;
+
+ /* parse the color */
+
+ UINT_TO_RGBA (waveview->wave_color, &waveview->wave_r, &waveview->wave_g, &waveview->wave_b,
+ &waveview->wave_a);
+
+// check_cache (waveview, "end of update");
+}
+
+static void
+gtk_canvas_waveview_render (GtkCanvasItem *item,
+ GtkCanvasBuf *buf)
+{
+ GtkCanvasWaveView *waveview;
+ gulong s1, s2;
+ int clip_length = 0;
+ int pymin, pymax;
+ int cache_index;
+ double half_height;
+ int x, end, begin;
+
+ waveview = GTK_CANVAS_WAVEVIEW (item);
+
+// check_cache (waveview, "start of render");
+
+ if (parent_class->render) {
+ (*parent_class->render) (item, buf);
+ }
+
+ if (buf->is_bg) {
+ gtk_canvas_buf_ensure_buf (buf);
+ buf->is_bg = FALSE;
+ }
+
+ begin = MAX(waveview->bbox_ulx,buf->rect.x0);
+
+ if (waveview->bbox_lrx >= 0) {
+ end = MIN(waveview->bbox_lrx,buf->rect.x1);
+ } else {
+ end = buf->rect.x1;
+ }
+
+ if (begin == end) {
+ return;
+ }
+
+ s1 = floor ((begin - waveview->bbox_ulx) * waveview->samples_per_unit) ;
+
+ // fprintf (stderr, "0x%x begins at sample %f\n", waveview, waveview->bbox_ulx * waveview->samples_per_unit);
+
+ if (end == waveview->bbox_lrx) {
+ /* This avoids minor rounding errors when we have the
+ entire region visible.
+ */
+ s2 = waveview->samples;
+ } else {
+ s2 = s1 + floor ((end - begin) * waveview->samples_per_unit);
+ }
+
+#if 0
+ printf ("0x%x r (%d..%d)(%d..%d) bbox (%d..%d)(%d..%d)"
+ " b/e %d..%d s= %lu..%lu\n",
+ waveview,
+ buf->rect.x0,
+ buf->rect.x1,
+ buf->rect.y0,
+ buf->rect.y1,
+ waveview->bbox_ulx,
+ waveview->bbox_lrx,
+ waveview->bbox_uly,
+ waveview->bbox_lry,
+ begin, end, s1, s2);
+#endif
+
+ /* now ensure that the cache is full and properly
+ positioned.
+ */
+
+// check_cache (waveview, "pre-ensure");
+
+ if (waveview->cache_updater && waveview->reload_cache_in_render) {
+ waveview->cache->start = 0;
+ waveview->cache->end = 0;
+ waveview->reload_cache_in_render = FALSE;
+ }
+
+ cache_index = gtk_canvas_waveview_ensure_cache (waveview, s1, s2);
+
+// check_cache (waveview, "post-ensure");
+
+ /*
+ Now draw each line, clipping it appropriately. The clipping
+ is done by the macros PAINT_FOO().
+ */
+
+ half_height = waveview->half_height;
+
+/* this makes it slightly easier to comprehend whats going on */
+
+#define origin half_height
+
+ for (x = begin; x < end; x++) {
+
+ double max, min;
+ int clip_max, clip_min;
+
+ clip_max = 0;
+ clip_min = 0;
+
+ max = waveview->cache->data[cache_index].max;
+ min = waveview->cache->data[cache_index].min;
+
+ if (max >= 1.0) {
+ max = 1.0;
+ clip_max = 1;
+ }
+
+ if (min <= -1.0) {
+ min = -1.0;
+ clip_min = 1;
+ }
+
+ /* don't rectify at single-sample zoom */
+
+ if (waveview->rectified && waveview->samples_per_unit > 1) {
+
+ if (fabs (min) > fabs (max)) {
+ max = fabs (min);
+ }
+
+ max = max * waveview->height;
+
+ pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit);
+ pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit);
+
+ } else {
+
+ max = max * half_height;
+ min = min * half_height;
+
+ pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit);
+ pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit);
+ }
+
+ /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax,
+ or, if samples_per_unit == 1, then a dot at each location.
+ */
+
+ if (pymax == pymin) {
+ PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin);
+ } else {
+ PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin);
+ }
+
+ /* show clipped waveforms with small red lines */
+
+ if (clip_max || clip_min) {
+ clip_length = MIN(5,(waveview->height/4));
+ }
+
+ if (clip_max) {
+ PAINT_VERT(buf, 255, 0, 0, x, pymax, pymax+clip_length);
+ }
+
+ if (clip_min) {
+ PAINT_VERT(buf, 255, 0, 0, x, pymin-clip_length, pymin);
+ }
+
+ /* presto, we're done */
+
+ cache_index++;
+ }
+
+#undef origin
+
+}
+
+static void
+gtk_canvas_waveview_draw (GtkCanvasItem *item,
+ GdkDrawable *drawable,
+ int x, int y,
+ int width, int height)
+{
+ GtkCanvasWaveView *waveview;
+
+ waveview = GTK_CANVAS_WAVEVIEW (item);
+
+ if (parent_class->draw) {
+ (* parent_class->draw) (item, drawable, x, y, width, height);
+ }
+
+ fprintf (stderr, "please don't use the CanvasWaveView item in a non-aa Canvas\n");
+ abort ();
+}
+
+static void
+gtk_canvas_waveview_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
+{
+ GtkCanvasWaveView *waveview = GTK_CANVAS_WAVEVIEW (item);
+
+ *x1 = waveview->x;
+ *y1 = waveview->y;
+
+ *x2 = ceil (*x1 + (waveview->length_function (waveview->data_src) / waveview->samples_per_unit));
+ *y2 = *y1 + waveview->height;
+
+#if 0
+ x = 0; y = 0;
+ gtk_canvas_item_i2w (item, &x, &y);
+ gtk_canvas_w2c_d (GTK_CANVAS(item->canvas), x, y, &a, &b);
+ x = *x2;
+ y = *y2;
+ gtk_canvas_item_i2w (item, &x, &y);
+ gtk_canvas_w2c_d (GTK_CANVAS(item->canvas), x, y, &c, &d);
+ printf ("item bounds now (%g,%g),(%g,%g)\n", a, b, c, d);
+#endif
+
+}
+
+static double
+gtk_canvas_waveview_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item)
+{
+ /* XXX for now, point is never inside the wave
+ GtkCanvasWaveView *waveview;
+ double x1, y1, x2, y2;
+ double dx, dy;
+ */
+
+ return DBL_MAX;
+
+#if 0
+ waveview = GTK_CANVAS_WAVEVIEW (item);
+
+ *actual_item = item;
+
+ /* Find the bounds for the rectangle plus its outline width */
+
+ gtk_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2);
+
+ /* Is point inside rectangle */
+
+ if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) {
+ return 0.0;
+ }
+
+ /* Point is outside rectangle */
+
+ if (x < x1)
+ dx = x1 - x;
+ else if (x > x2)
+ dx = x - x2;
+ else
+ dx = 0.0;
+
+ if (y < y1)
+ dy = y1 - y;
+ else if (y > y2)
+ dy = y - y2;
+ else
+ dy = 0.0;
+
+ return sqrt (dx * dx + dy * dy);
+#endif
+}
+
diff --git a/gtk2_ardour/canvas-waveview.h b/gtk2_ardour/canvas-waveview.h
new file mode 100644
index 0000000000..b868abfa61
--- /dev/null
+++ b/gtk2_ardour/canvas-waveview.h
@@ -0,0 +1,128 @@
+/* gtk-canvas-waveview.h: GtkCanvas item for displaying wave data
+ *
+ * Copyright (C) 2001 Paul Davis <pbd@op.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __GTK_CANVAS_WAVEVIEW_H__
+#define __GTK_CANVAS_WAVEVIEW_H__
+
+#include <stdint.h>
+
+#include <gtk-canvas/gtk-canvas-defs.h>
+#include "gtk-canvas/gtk-canvas.h"
+
+BEGIN_GTK_CANVAS_DECLS
+
+/* Wave viewer item for canvas.
+ */
+
+#define GTK_CANVAS_TYPE_CANVAS_WAVEVIEW (gtk_canvas_waveview_get_type ())
+#define GTK_CANVAS_WAVEVIEW(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_WAVEVIEW, GtkCanvasWaveView))
+#define GTK_CANVAS_WAVEVIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_WAVEVIEW, GtkCanvasWaveViewClass))
+#define GTK_CANVAS_IS_CANVAS_WAVEVIEW(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_WAVEVIEW))
+#define GTK_CANVAS_IS_CANVAS_WAVEVIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_WAVEVIEW))
+
+typedef struct _GtkCanvasWaveView GtkCanvasWaveView;
+typedef struct _GtkCanvasWaveViewClass GtkCanvasWaveViewClass;
+typedef struct _GtkCanvasWaveViewChannelInfo GtkCanvasWaveViewChannelInfo;
+typedef struct _GtkCanvasWaveViewCacheEntry GtkCanvasWaveViewCacheEntry;
+typedef struct _GtkCanvasWaveViewCache GtkCanvasWaveViewCache;
+
+/* XXX this needs to be synced with ardour/source.h PeakData */
+
+struct _GtkCanvasWaveViewCacheEntry
+{
+ float min;
+ float max;
+};
+
+struct _GtkCanvasWaveViewCache
+{
+ GtkCanvasWaveViewCacheEntry* data;
+ gint32 allocated;
+ gint32 data_size;
+ gulong start;
+ gulong end;
+};
+
+GtkCanvasWaveViewCache* gtk_canvas_waveview_cache_new ();
+void gtk_canvas_waveview_cache_destroy (GtkCanvasWaveViewCache*);
+
+struct _GtkCanvasWaveView
+{
+ GtkCanvasItem item;
+
+ GtkCanvasWaveViewCache *cache;
+ gboolean cache_updater;
+ gint screen_width;
+
+ void *data_src;
+ guint32 channel;
+ void (*peak_function)(void*,gulong,gulong,gulong,gpointer,guint32,double);
+ gulong (*length_function)(void *);
+ gulong (*sourcefile_length_function)(void*);
+ void (*gain_curve_function)(void *arg, double start, double end, float* vector, guint32 veclen);
+ void *gain_src;
+
+ /* x-axis: samples per canvas unit. */
+ double samples_per_unit;
+
+ /* y-axis: amplitude_above_axis.
+ *
+ * the default is that an (scaled, normalized -1.0 ... +1.0) amplitude of 1.0
+ * corresponds to the top of the area assigned to the waveview.
+ *
+ * larger values will expand the vertical scale, cutting off the peaks/troughs.
+ * smaller values will decrease the vertical scale, moving peaks/troughs toward
+ * the middle of the area assigned to the waveview.
+ */
+
+ double amplitude_above_axis;
+ double x;
+ double y;
+ double height;
+ double half_height;
+ uint32_t wave_color;
+
+ char rectified;
+
+ /* These are updated by the update() routine
+ to optimize the render() routine, which may
+ be called several times after a single update().
+ */
+
+ int32_t bbox_ulx;
+ int32_t bbox_uly;
+ int32_t bbox_lrx;
+ int32_t bbox_lry;
+ unsigned char wave_r, wave_g, wave_b, wave_a;
+ uint32_t samples;
+ uint32_t region_start;
+ int32_t reload_cache_in_render;
+};
+
+struct _GtkCanvasWaveViewClass {
+ GtkCanvasItemClass parent_class;
+};
+
+GtkType gtk_canvas_waveview_get_type (void);
+
+END_GTK_CANVAS_DECLS
+
+#endif /* __GTK_CANVAS_WAVEVIEW_H__ */
diff --git a/gtk2_ardour/check_mark.h b/gtk2_ardour/check_mark.h
new file mode 100644
index 0000000000..78f7424028
--- /dev/null
+++ b/gtk2_ardour/check_mark.h
@@ -0,0 +1,50 @@
+/*
+ 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.
+
+*/
+
+static const gchar* check_xpm[] = {
+"13 10 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" .. ",
+" ++++++++.++.",
+" + .++. ",
+" +. .++.+ ",
+" .+. .++. + ",
+".+++..++. + ",
+" .+++++. + ",
+" +.+++. + ",
+" ++.+.++++++ ",
+" . "};
+
+static const gchar* empty_xpm[] = {
+"13 10 2 1",
+" c None",
+"+ c #FFFFFF",
+" ",
+" +++++++++++ ",
+" + + ",
+" + + ",
+" + + ",
+" + + ",
+" + + ",
+" + + ",
+" +++++++++++ ",
+" ",};
+
diff --git a/gtk2_ardour/connection_editor.cc b/gtk2_ardour/connection_editor.cc
new file mode 100644
index 0000000000..c2dbaaa1fd
--- /dev/null
+++ b/gtk2_ardour/connection_editor.cc
@@ -0,0 +1,692 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+#include <stdint.h>
+
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/utils.h>
+#include <sigc++/bind.h>
+
+#include "connection_editor.h"
+
+#include <ardour/session.h>
+#include <ardour/session_connection.h>
+#include <ardour/audioengine.h>
+#include <ardour/connection.h>
+
+#include "utils.h"
+#include "keyboard.h"
+#include "prompter.h"
+
+#include "i18n.h"
+
+#include <inttypes.h>
+
+using namespace std;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace SigC;
+
+ConnectionEditor::ConnectionEditor ()
+ : ArdourDialog ("connection editor"),
+ input_connection_display (1),
+ output_connection_display (1),
+ input_frame (_("Input Connections")),
+ output_frame (_("Output Connections")),
+ new_input_connection_button (_("New Input")),
+ new_output_connection_button (_("New Output")),
+ delete_connection_button (_("Delete")),
+ clear_button (_("Clear")),
+ add_port_button (_("Add Port")),
+ ok_button (_("Close")),
+ cancel_button (_("Cancel")),
+ rescan_button (_("Rescan"))
+
+{
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ session = 0;
+ selected_port = -1;
+ current_connection = 0;
+ push_at_front = false;
+
+ set_name ("ConnectionEditorWindow");
+
+ ok_button.set_name ("ConnectionEditorButton");
+ cancel_button.set_name ("ConnectionEditorButton");
+ rescan_button.set_name ("ConnectionEditorButton");
+ new_input_connection_button.set_name ("ConnectionEditorButton");
+ new_output_connection_button.set_name ("ConnectionEditorButton");
+ clear_button.set_name ("ConnectionEditorButton");
+
+ button_frame.set_name ("ConnectionEditorFrame");
+ input_frame.set_name ("ConnectionEditorFrame");
+ output_frame.set_name ("ConnectionEditorFrame");
+
+ button_box.set_spacing (15);
+ button_box.set_border_width (5);
+ Gtkmmext::set_usize_to_display_given_text (ok_button, _("OK"), 40, 15);
+ button_box.pack_end (ok_button, false, false);
+ // button_box.pack_end (cancel_button, false, false);
+ cancel_button.hide();
+ button_frame.add (button_box);
+
+ ok_button.clicked.connect (slot (*this, &ConnectionEditor::accept));
+ cancel_button.clicked.connect (slot (*this, &ConnectionEditor::cancel));
+ cancel_button.clicked.connect (slot (*this, &ConnectionEditor::rescan));
+
+ notebook.set_name ("ConnectionEditorNotebook");
+ notebook.set_usize (-1, 125);
+
+ clear_button.set_name ("ConnectionEditorButton");
+ add_port_button.set_name ("ConnectionEditorButton");
+ Gtkmmext::set_usize_to_display_given_text (add_port_button, _("Add Port"), 35, 15);
+
+ selector_frame.set_name ("ConnectionEditorFrame");
+ port_frame.set_name ("ConnectionEditorFrame");
+
+ selector_frame.set_label (_("Available Ports"));
+
+ selector_button_box.set_spacing (5);
+ selector_button_box.set_border_width (5);
+ Gtkmmext::set_usize_to_display_given_text (rescan_button, _("Rescan"), 35, 15);
+ selector_button_box.pack_start (rescan_button, false, false);
+
+ selector_box.set_spacing (5);
+ selector_box.set_border_width (5);
+ selector_box.pack_start (notebook);
+ selector_box.pack_start (selector_button_box);
+
+ selector_frame.add (selector_box);
+
+ port_box.set_spacing (5);
+ port_box.set_border_width (3);
+
+ port_button_box.set_spacing (5);
+ port_button_box.set_border_width (2);
+
+ port_button_box.pack_start (add_port_button, false, false);
+ port_and_button_box.set_border_width (5);
+ port_and_button_box.pack_start (port_button_box, false, false);
+ port_and_button_box.pack_start (port_box);
+
+ port_frame.add (port_and_button_box);
+
+ port_and_selector_box.set_spacing (5);
+ port_and_selector_box.pack_start (port_frame);
+ port_and_selector_box.pack_start (selector_frame);
+
+ right_vbox.set_spacing (5);
+ right_vbox.set_border_width (5);
+ right_vbox.pack_start (port_and_selector_box);
+
+ input_connection_display.set_shadow_type (GTK_SHADOW_IN);
+ input_connection_display.set_selection_mode (GTK_SELECTION_SINGLE);
+ input_connection_display.set_usize (80, -1);
+ input_connection_display.set_name ("ConnectionEditorConnectionList");
+ input_connection_display.select_row.connect (bind (slot (*this, &ConnectionEditor::connection_selected), true));
+
+ output_connection_display.set_shadow_type (GTK_SHADOW_IN);
+ output_connection_display.set_selection_mode (GTK_SELECTION_SINGLE);
+ output_connection_display.set_usize (80, -1);
+ output_connection_display.set_name ("ConnectionEditorConnectionList");
+ output_connection_display.select_row.connect (bind (slot (*this, &ConnectionEditor::connection_selected), false));
+
+ input_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ output_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ input_scroller.add_with_viewport (input_connection_display);
+ output_scroller.add_with_viewport (output_connection_display);
+
+ input_box.set_border_width (5);
+ input_box.set_spacing (5);
+ input_box.pack_start (input_scroller);
+ input_box.pack_start (new_input_connection_button, false, false);
+ input_frame.add (input_box);
+
+ output_box.set_border_width (5);
+ output_box.set_spacing (5);
+ output_box.pack_start (output_scroller);
+ output_box.pack_start (new_output_connection_button, false, false);
+ output_frame.add (output_box);
+
+ connection_box.set_spacing (5);
+ connection_box.pack_start (input_frame);
+ connection_box.pack_start (output_frame);
+
+ left_vbox.set_spacing (5);
+ left_vbox.pack_start (connection_box);
+
+ main_hbox.set_border_width (10);
+ main_hbox.set_spacing (5);
+ main_hbox.pack_start (left_vbox);
+ main_hbox.pack_start (right_vbox);
+
+ main_vbox.set_border_width (10);
+ main_vbox.set_spacing (5);
+ main_vbox.pack_start (main_hbox);
+ main_vbox.pack_start (button_frame, false, false);
+
+ set_title (_("ardour: connections"));
+ add (main_vbox);
+
+ delete_event.connect (bind (slot (just_hide_it), reinterpret_cast<Window *> (this)));
+
+ clear_button.clicked.connect (slot (*this, &ConnectionEditor::clear));
+ add_port_button.clicked.connect (slot (*this, &ConnectionEditor::add_port));
+ new_input_connection_button.clicked.connect (bind (slot (*this, &ConnectionEditor::new_connection), true));
+ new_output_connection_button.clicked.connect (bind (slot (*this, &ConnectionEditor::new_connection), false));
+ delete_connection_button.clicked.connect (slot (*this, &ConnectionEditor::delete_connection));
+}
+
+ConnectionEditor::~ConnectionEditor()
+{
+}
+
+void
+ConnectionEditor::set_session (Session *s)
+{
+ if (s != session) {
+
+ ArdourDialog::set_session (s);
+
+ if (session) {
+ session->ConnectionAdded.connect (slot (*this, &ConnectionEditor::proxy_add_connection_and_select));
+ session->ConnectionRemoved.connect (slot (*this, &ConnectionEditor::proxy_remove_connection));
+ } else {
+ hide ();
+ }
+ }
+}
+
+void
+ConnectionEditor::rescan ()
+{
+ refill_connection_display ();
+ display_ports ();
+}
+
+void
+ConnectionEditor::cancel ()
+{
+ hide ();
+}
+
+void
+ConnectionEditor::accept ()
+{
+ hide ();
+}
+
+void
+ConnectionEditor::clear ()
+{
+ if (current_connection) {
+ current_connection->clear ();
+ }
+}
+
+gint
+ConnectionEditor::map_event_impl (GdkEventAny *ev)
+{
+ refill_connection_display ();
+ return Window::map_event_impl (ev);
+}
+
+void
+ConnectionEditor::add_connection (ARDOUR::Connection *connection)
+{
+ using namespace CList_Helpers;
+ const char *rowtext[1];
+
+ rowtext[0] = connection->name().c_str();
+
+ if (dynamic_cast<InputConnection *> (connection)) {
+ if (push_at_front) {
+ input_connection_display.rows().push_front (rowtext);
+ input_connection_display.rows().front().set_data (connection);
+ } else {
+ input_connection_display.rows().push_back (rowtext);
+ input_connection_display.rows().back().set_data (connection);
+ }
+ } else {
+ if (push_at_front) {
+ output_connection_display.rows().push_front (rowtext);
+ output_connection_display.rows().front().set_data (connection);
+ } else {
+ output_connection_display.rows().push_back (rowtext);
+ output_connection_display.rows().back().set_data (connection);
+ }
+ }
+}
+
+void
+ConnectionEditor::remove_connection (ARDOUR::Connection *connection)
+{
+ using namespace Gtk::CList_Helpers;
+ RowList::iterator i;
+ RowList* rlist;
+
+ if (dynamic_cast<InputConnection *> (connection)) {
+ rlist = &input_connection_display.rows();
+ } else {
+ rlist = &output_connection_display.rows();
+ }
+
+ if ((i = rlist->find_data (connection)) != rlist->end()) {
+ rlist->erase (i);
+ }
+}
+
+void
+ConnectionEditor::proxy_add_connection_and_select (ARDOUR::Connection *connection)
+{
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &ConnectionEditor::add_connection_and_select), connection));
+}
+
+void
+ConnectionEditor::proxy_remove_connection (ARDOUR::Connection *connection)
+{
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &ConnectionEditor::remove_connection), connection));
+}
+
+void
+ConnectionEditor::add_connection_and_select (ARDOUR::Connection *connection)
+{
+ add_connection (connection);
+
+ if (dynamic_cast<InputConnection *> (connection)) {
+ input_connection_display.rows().front().select ();
+ } else {
+ output_connection_display.rows().front().select ();
+ }
+}
+
+void
+ConnectionEditor::refill_connection_display ()
+{
+ input_connection_display.clear();
+ output_connection_display.clear();
+
+ current_connection = 0;
+
+ if (session) {
+ session->foreach_connection (this, &ConnectionEditor::add_connection);
+ }
+}
+
+void
+ConnectionEditor::connection_selected (gint row, gint col, GdkEvent *ev, bool input)
+{
+ ARDOUR::Connection *old_current = current_connection;
+
+
+ if (input) {
+ output_connection_display.unselect_all ();
+ current_connection = reinterpret_cast<ARDOUR::Connection*> (input_connection_display.row(row).get_data());
+ } else {
+ input_connection_display.unselect_all ();
+ current_connection = reinterpret_cast<ARDOUR::Connection*> (output_connection_display.row(row).get_data());
+ }
+
+ if (old_current != current_connection) {
+ config_connection.disconnect ();
+ connect_connection.disconnect ();
+ }
+
+ if (current_connection) {
+ config_connection = current_connection->ConfigurationChanged.connect
+ (bind (slot (*this, &ConnectionEditor::configuration_changed), input));
+ connect_connection = current_connection->ConnectionsChanged.connect
+ (bind (slot (*this, &ConnectionEditor::connections_changed), input));
+ }
+
+ display_connection_state (input);
+ display_ports ();
+}
+
+void
+ConnectionEditor::configuration_changed (bool for_input)
+{
+ display_connection_state (for_input);
+}
+
+void
+ConnectionEditor::connections_changed (int which_port, bool for_input)
+{
+ display_connection_state (for_input);
+}
+
+void
+ConnectionEditor::display_ports ()
+{
+ if (session == 0 || current_connection == 0) {
+ return;
+ }
+
+ using namespace Notebook_Helpers;
+ using namespace CList_Helpers;
+
+ typedef map<string,vector<pair<string,string> > > PortMap;
+ PortMap portmap;
+ const char **ports;
+ PageList& pages = notebook.pages();
+ gint current_page;
+ vector<string> rowdata;
+ bool for_input;
+
+ current_page = notebook.get_current_page_num ();
+ pages.clear ();
+
+ /* get relevant current JACK ports */
+
+ for_input = (dynamic_cast<InputConnection *> (current_connection) != 0);
+
+ ports = session->engine().get_ports ("", JACK_DEFAULT_AUDIO_TYPE, for_input?JackPortIsOutput:JackPortIsInput);
+
+ if (ports == 0) {
+ return;
+ }
+
+ /* find all the client names and group their ports into a list-by-client */
+
+ for (int n = 0; ports[n]; ++n) {
+
+ pair<string,vector<pair<string,string> > > newpair;
+ pair<string,string> strpair;
+ pair<PortMap::iterator,bool> result;
+
+ string str = ports[n];
+ string::size_type pos;
+ string portname;
+
+ pos = str.find (':');
+
+ newpair.first = str.substr (0, pos);
+ portname = str.substr (pos+1);
+
+ result = portmap.insert (newpair);
+
+ strpair.first = portname;
+ strpair.second = str;
+
+ result.first->second.push_back (strpair);
+ }
+
+ PortMap::iterator i;
+
+ for (i = portmap.begin(); i != portmap.end(); ++i) {
+
+ Box *client_box = manage (new VBox);
+ Gtk::CList *client_port_display = manage (new Gtk::CList (1));
+ ScrolledWindow *scroller = manage (new ScrolledWindow);
+
+ scroller->add_with_viewport (*client_port_display);
+ scroller->set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ client_box->pack_start (*scroller);
+
+ client_port_display->set_selection_mode (GTK_SELECTION_BROWSE);
+ client_port_display->set_name ("ConnectionEditorList");
+
+ for (vector<pair<string,string> >::iterator s = i->second.begin(); s != i->second.end(); ++s) {
+
+ rowdata.clear ();
+ rowdata.push_back (s->first);
+ client_port_display->rows().push_back (rowdata);
+ client_port_display->rows().back().set_data (g_strdup (s->second.c_str()), free);
+ }
+
+ client_port_display->columns_autosize ();
+ client_port_display->select_row.connect (bind (slot (*this, &ConnectionEditor::port_selection_handler), client_port_display));
+
+ Label *tab_label = manage (new Label);
+
+ tab_label->set_name ("ConnectionEditorNotebookTab");
+ tab_label->set_text ((*i).first);
+
+ pages.push_back (TabElem (*client_box, *tab_label));
+ }
+
+ notebook.set_page (current_page);
+ notebook.show.connect (bind (slot (notebook, &Notebook::set_page), current_page));
+ selector_box.show_all ();
+}
+
+void
+ConnectionEditor::display_connection_state (bool for_input)
+{
+ LockMonitor lm (port_display_lock, __LINE__, __FILE__);
+ uint32_t limit;
+
+ if (session == 0 || current_connection == 0) {
+ return;
+ }
+
+ string frame_label = _("Connection \"");
+ frame_label += current_connection->name();
+ frame_label += _("\"");
+ port_frame.set_label (frame_label);
+
+ for (slist<ScrolledWindow *>::iterator i = port_displays.begin(); i != port_displays.end(); ) {
+
+ slist<ScrolledWindow *>::iterator tmp;
+
+ tmp = i;
+ tmp++;
+
+ port_box.remove (**i);
+ delete *i;
+ port_displays.erase (i);
+
+ i = tmp;
+ }
+
+ limit = current_connection->nports();
+
+ for (uint32_t n = 0; n < limit; ++n) {
+
+ CList *clist;
+ ScrolledWindow *scroller;
+
+ const gchar *title[1];
+ char buf[32];
+ string really_short_name;
+
+ if (for_input) {
+ snprintf(buf, sizeof(buf)-1, _("in %d"), n+1);
+ } else {
+ snprintf(buf, sizeof(buf)-1, _("out %d"), n+1);
+ }
+
+ title[0] = buf;
+ clist = manage (new CList (1, title));
+ scroller = new ScrolledWindow;
+
+ scroller->add_with_viewport (*clist);
+ scroller->set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ port_displays.insert (port_displays.end(), scroller);
+ port_box.pack_start (*scroller);
+
+ clist->set_data ("port", (gpointer) ((intptr_t) n));
+
+ clist->set_name ("ConnectionEditorPortList");
+ clist->click_column.connect (bind (slot (*this, &ConnectionEditor::port_column_click), clist));
+ clist->set_selection_mode (GTK_SELECTION_SINGLE);
+ clist->set_shadow_type (GTK_SHADOW_IN);
+
+ scroller->set_usize (-1, 75);
+
+ /* now fill the clist with the current connections */
+
+ const ARDOUR::Connection::PortList& connections = current_connection->port_connections (n);
+
+ for (ARDOUR::Connection::PortList::const_iterator i = connections.begin(); i != connections.end(); ++i) {
+ const gchar *data[1];
+
+ data[0] = (*i).c_str();
+ clist->rows().push_back (data);
+ }
+
+ clist->columns_autosize ();
+ clist->button_release_event.connect (bind (slot (*this, &ConnectionEditor::port_button_event), clist));
+ }
+
+ port_box.show_all ();
+}
+
+void
+ConnectionEditor::port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *clist)
+{
+ using namespace CList_Helpers;
+
+ string other_port_name = (char *) clist->rows()[row].get_data();
+
+ if (current_connection && selected_port >= 0) {
+ current_connection->add_connection (selected_port, other_port_name);
+ }
+
+}
+
+void
+ConnectionEditor::add_port ()
+{
+ if (current_connection) {
+ current_connection->add_port ();
+ }
+}
+
+void
+ConnectionEditor::port_column_click (gint col, CList *clist)
+{
+ /* Gack. CList's don't respond visually to a change
+ in their state, so rename them to force a style
+ switch.
+ */
+
+ LockMonitor lm (port_display_lock, __LINE__, __FILE__);
+
+ int which_port = reinterpret_cast<intptr_t> (clist->get_data ("port"));
+
+ if (which_port != selected_port) {
+
+ selected_port = which_port;
+ display_ports ();
+
+ clist->set_name ("ConnectionEditorPortListSelected");
+
+ for (slist<ScrolledWindow *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) {
+
+ Widget *child = (*i)->get_child();
+
+ if (static_cast<CList *> (child) != clist) {
+ child->set_name ("ConnectionEditorPortList");
+ child->queue_draw ();
+ }
+ }
+
+ } else {
+
+ selected_port = -1;
+ clist->set_name ("ConnectionEditorPortList");
+ clist->queue_draw();
+ }
+}
+
+gint
+ConnectionEditor::connection_click (GdkEventButton *ev, CList *clist)
+{
+ gint row, col;
+
+ if (clist->get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) {
+ return FALSE;
+ }
+
+ current_connection = reinterpret_cast<ARDOUR::Connection *> (clist->row(row).get_data ());
+
+ return TRUE;
+}
+
+void
+ConnectionEditor::new_connection (bool for_input)
+{
+ if (session == 0) {
+ return;
+ }
+
+ ArdourPrompter prompter (true);
+ prompter.set_prompt (_("Name for new connection:"));
+ prompter.done.connect (Gtk::Main::quit.slot());
+ prompter.show_all();
+
+ Gtk::Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+ prompter.get_result (name);
+
+ push_at_front = true;
+
+ if (name.length()) {
+ if (for_input) {
+ session->add_connection (new ARDOUR::InputConnection (name));
+ } else {
+ session->add_connection (new ARDOUR::OutputConnection (name));
+ }
+ }
+ push_at_front = false;
+ }
+}
+
+void
+ConnectionEditor::delete_connection ()
+{
+ if (session && current_connection) {
+ session->remove_connection (current_connection);
+ current_connection = 0;
+ }
+}
+
+gint
+ConnectionEditor::port_button_event (GdkEventButton *ev, CList *clist)
+{
+ int row, col;
+
+ if (current_connection == 0) {
+ return FALSE;
+ }
+
+ if (clist->get_selection_info ((int) ev->x, (int) ev->y, &row, &col) == 0) {
+ return FALSE;
+ }
+
+ if (!(Keyboard::is_delete_event (ev))) {
+ return FALSE;
+ }
+
+ string port_name = clist->cell (row, col).get_text ();
+ int which_port = (intptr_t) clist->get_data ("port");
+
+ current_connection->remove_connection (which_port, port_name);
+
+ return TRUE;
+}
+
+
diff --git a/gtk2_ardour/connection_editor.h b/gtk2_ardour/connection_editor.h
new file mode 100644
index 0000000000..a09a4560d1
--- /dev/null
+++ b/gtk2_ardour/connection_editor.h
@@ -0,0 +1,147 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_connection_editor_h__
+#define __ardour_gtk_connection_editor_h__
+
+#if __GNUC__ >= 3
+#include <ext/slist>
+using __gnu_cxx::slist;
+#else
+#include <slist.h>
+#endif
+
+#include <gtk--/box.h>
+#include <gtk--/window.h>
+#include <gtk--/scrolledwindow.h>
+#include <gtk--/button.h>
+#include <gtk--/frame.h>
+#include <gtk--/notebook.h>
+#include <gtk--/clist.h>
+
+#include "ardour_dialog.h"
+
+#include <pbd/lockmonitor.h>
+
+namespace ARDOUR {
+ class Session;
+ class Connection;
+}
+
+class ConnectionEditor : public ArdourDialog {
+ public:
+ ConnectionEditor ();
+ ~ConnectionEditor ();
+
+ void set_session (ARDOUR::Session *);
+
+ protected:
+ gint map_event_impl (GdkEventAny *);
+
+ private:
+ ARDOUR::Connection *current_connection;
+ int selected_port;
+ bool push_at_front;
+
+ Gtk::CList input_connection_display;
+ Gtk::CList output_connection_display;
+ Gtk::ScrolledWindow input_scroller;
+ Gtk::ScrolledWindow output_scroller;
+
+ Gtk::Frame input_frame;
+ Gtk::Frame output_frame;
+ Gtk::VBox input_box;
+ Gtk::VBox output_box;
+ Gtk::VBox connection_box;
+
+ Gtk::HBox main_hbox;
+ Gtk::VBox main_vbox;
+
+ Gtk::VBox left_vbox;
+ Gtk::VBox right_vbox;
+ Gtk::VBox port_and_selector_box;
+
+
+ Gtk::Button new_input_connection_button;
+ Gtk::Button new_output_connection_button;
+ Gtk::Button delete_connection_button;
+
+ /* client/port selection */
+
+ Gtk::Notebook notebook;
+ Gtk::Button clear_client_button;
+ Gtk::Frame selector_frame;
+ Gtk::VBox selector_box;
+ Gtk::HBox selector_button_box;
+
+ /* connection displays */
+
+ Gtk::HBox port_box;
+ Gtk::HBox port_button_box;
+ Gtk::VBox port_and_button_box;
+ Gtk::Frame port_frame;
+ Gtk::Button clear_button;
+ Gtk::Button add_port_button;
+
+ PBD::Lock port_display_lock;
+ slist<Gtk::ScrolledWindow *> port_displays;
+
+ Gtk::Button ok_button;
+ Gtk::Button cancel_button;
+ Gtk::Button rescan_button;
+
+ Gtk::Frame button_frame;
+ Gtk::HBox button_box;
+
+ void new_connection (bool for_input);
+ void delete_connection ();
+
+ void display_ports ();
+ void display_connection_state (bool for_input);
+
+ void add_connection (ARDOUR::Connection *);
+ void add_connection_and_select (ARDOUR::Connection *);
+ void proxy_add_connection_and_select (ARDOUR::Connection *);
+ void proxy_remove_connection (ARDOUR::Connection *);
+ void remove_connection (ARDOUR::Connection *);
+ void refill_connection_display ();
+
+ void rescan ();
+ void clear ();
+ void cancel ();
+ void accept ();
+
+ void port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *);
+
+ void add_port ();
+ void remove_port (int which_port);
+
+ void port_column_click (gint col, Gtk::CList *clist);
+ gint port_button_event (GdkEventButton *, Gtk::CList *clist);
+ gint connection_click (GdkEventButton *ev, Gtk::CList *clist);
+ void connection_selected (gint, gint, GdkEvent *, bool);
+
+ SigC::Connection config_connection;
+ SigC::Connection connect_connection;
+ void configuration_changed (bool);
+ void connections_changed (int, bool);
+};
+
+#endif /* __ardour_gtk_connection_editor_h__ */
diff --git a/gtk2_ardour/crossfade_edit.cc b/gtk2_ardour/crossfade_edit.cc
new file mode 100644
index 0000000000..7667de3134
--- /dev/null
+++ b/gtk2_ardour/crossfade_edit.cc
@@ -0,0 +1,1343 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+
+#include <sigc++/bind.h>
+
+#include <gtk--/frame.h>
+#include <gtk--/pixmap.h>
+#include <gtk--/scrolledwindow.h>
+
+#include <ardour/automation_event.h>
+#include <ardour/curve.h>
+#include <ardour/crossfade.h>
+#include <ardour/session.h>
+#include <ardour/auditioner.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/playlist_templates.h>
+
+#include <gtkmmext/gtk_ui.h>
+
+#include "ardour_ui.h"
+#include "crossfade_edit.h"
+#include "rgb_macros.h"
+#include "canvas-simplerect.h"
+#include "canvas-waveview.h"
+#include "keyboard.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace SigC;
+using namespace Editing;
+
+#include "i18n.h"
+
+const int32_t CrossfadeEditor::Point::size = 7;
+const double CrossfadeEditor::canvas_border = 10;
+CrossfadeEditor::Presets* CrossfadeEditor::fade_in_presets = 0;
+CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0;
+
+#include "crossfade_xpms.h"
+
+CrossfadeEditor::Half::Half ()
+ : line (0),
+ normative_curve (0.0, 1.0, 1.0, true),
+ gain_curve (0.0, 2.0, 1.0, true)
+{
+}
+
+CrossfadeEditor::CrossfadeEditor (Session& s, Crossfade& xf, double my, double mxy)
+ : ArdourDialog (_("crossfade editor")),
+ cancel_button (_("Cancel")),
+ ok_button (_("OK")),
+ xfade (xf),
+ session (s),
+ clear_button (_("Clear")),
+ revert_button (_("Reset")),
+ audition_both_button (_("Fade")),
+ audition_left_dry_button (_("Out (dry)")),
+ audition_left_button (_("Out")),
+ audition_right_dry_button (_("In (dry)")),
+ audition_right_button (_("In")),
+
+ preroll_button (_("With Pre-roll")),
+ postroll_button (_("With Post-roll")),
+
+ miny (my),
+ maxy (mxy),
+
+ fade_in_table (3, 3),
+ fade_out_table (3, 3),
+
+ select_in_button (_("Fade In")),
+ select_out_button (_("Fade Out"))
+{
+ set_wmclass ("ardour_automationedit", "Ardour");
+ set_name ("CrossfadeEditWindow");
+ set_title (_("ardour: x-fade edit"));
+ set_position (GTK_WIN_POS_MOUSE);
+
+ add (vpacker);
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_POINTER_MOTION_MASK);
+
+ select_out_button.set_group (select_in_button.group());
+ select_out_button.set_mode (false);
+ select_in_button.set_mode (false);
+
+ if (fade_in_presets == 0) {
+ build_presets ();
+ }
+
+ point_grabbed = false;
+ toplevel = 0;
+
+ _canvas = gtk_canvas_new_aa ();
+
+ canvas = wrap (_canvas);
+ canvas->size_allocate.connect (slot (*this, &CrossfadeEditor::canvas_allocation));
+ canvas->set_usize (425, 200);
+
+ toplevel = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 10.0,
+ "y2", 10.0,
+ "fill", (gboolean) TRUE,
+ "fill_color_rgba", (guint32) color_map[cCrossfadeEditorBase],
+ "outline_pixels", 0,
+ NULL);
+
+ gtk_signal_connect (GTK_OBJECT(toplevel),
+ "event",
+ (GtkSignalFunc) _canvas_event,
+ this);
+
+ fade[Out].line = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
+ gtk_canvas_line_get_type (),
+ "width_pixels", (guint) 1,
+ "fill_color_rgba", color_map[cCrossfadeEditorLine],
+ NULL);
+
+ fade[Out].shading = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
+ gtk_canvas_polygon_get_type(),
+ "fill_color_rgba", color_map[cCrossfadeEditorLineShading],
+ NULL);
+
+ fade[In].line = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
+ gtk_canvas_line_get_type (),
+ "width_pixels", (guint) 1,
+ "fill_color_rgba", color_map[cCrossfadeEditorLine],
+ NULL);
+
+ fade[In].shading = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
+ gtk_canvas_polygon_get_type(),
+ "fill_color_rgba", color_map[cCrossfadeEditorLineShading],
+ NULL);
+
+ gtk_signal_connect (GTK_OBJECT(fade[In].shading),
+ "event",
+ (GtkSignalFunc) _canvas_event,
+ this);
+
+
+ gtk_signal_connect (GTK_OBJECT(fade[Out].shading),
+ "event",
+ (GtkSignalFunc) _canvas_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(fade[In].line),
+ "event",
+ (GtkSignalFunc) _curve_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(fade[Out].line),
+ "event",
+ (GtkSignalFunc) _curve_event,
+ this);
+
+
+ select_in_button.set_name (X_("CrossfadeEditCurveButton"));
+ select_out_button.set_name (X_("CrossfadeEditCurveButton"));
+
+ select_in_button.clicked.connect (bind (slot (this, &CrossfadeEditor::curve_select_clicked), In));
+ select_out_button.clicked.connect (bind (slot (this, &CrossfadeEditor::curve_select_clicked), Out));
+
+ HBox* acbox = manage (new HBox);
+
+ audition_box.set_border_width (7);
+ audition_box.set_spacing (5);
+ audition_box.set_homogeneous (false);
+ audition_box.pack_start (audition_left_dry_button, false, false);
+ audition_box.pack_start (audition_left_button, false, false);
+ audition_box.pack_start (audition_both_button, false, false);
+ audition_box.pack_start (audition_right_button, false, false);
+ audition_box.pack_start (audition_right_dry_button, false, false);
+
+ Frame* audition_frame = manage (new Frame (_("Audition")));
+
+ audition_frame->set_name (X_("CrossfadeEditFrame"));
+ audition_frame->add (audition_box);
+
+ acbox->pack_start (*audition_frame, true, false);
+
+ Frame* canvas_frame = manage (new Frame);
+ canvas_frame->add (*canvas);
+ canvas_frame->set_shadow_type (GTK_SHADOW_IN);
+
+ fade_in_table.attach (select_in_button, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND);
+ fade_out_table.attach (select_out_button, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND);
+
+ Pixmap *pxmap;
+ Button* pbutton;
+ int row;
+ int col;
+
+ row = 1;
+ col = 0;
+
+ for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
+
+ pxmap = manage (new Pixmap ((*i)->xpm));
+ pbutton = manage (new Button);
+ pbutton->add (*pxmap);
+ pbutton->set_name ("CrossfadeEditButton");
+ pbutton->clicked.connect (bind (slot (*this, &CrossfadeEditor::apply_preset), *i));
+ fade_in_table.attach (*pbutton, col, col+1, row, row+1);
+ fade_in_buttons.push_back (pbutton);
+
+ col++;
+
+ if (col == 2) {
+ col = 0;
+ row++;
+ }
+ }
+
+ row = 1;
+ col = 0;
+
+ for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
+
+ pxmap = manage (new Pixmap ((*i)->xpm));
+ pbutton = manage (new Button);
+ pbutton->add (*pxmap);
+ pbutton->set_name ("CrossfadeEditButton");
+ pbutton->clicked.connect (bind (slot (*this, &CrossfadeEditor::apply_preset), *i));
+ fade_out_table.attach (*pbutton, col, col+1, row, row+1);
+ fade_out_buttons.push_back (pbutton);
+
+ col++;
+
+ if (col == 2) {
+ col = 0;
+ row++;
+ }
+ }
+
+ clear_button.set_name ("CrossfadeEditButton");
+ revert_button.set_name ("CrossfadeEditButton");
+ ok_button.set_name ("CrossfadeEditButton");
+ cancel_button.set_name ("CrossfadeEditButton");
+ preroll_button.set_name ("CrossfadeEditButton");
+ postroll_button.set_name ("CrossfadeEditButton");
+ audition_both_button.set_name ("CrossfadeEditAuditionButton");
+ audition_left_dry_button.set_name ("CrossfadeEditAuditionButton");
+ audition_left_button.set_name ("CrossfadeEditAuditionButton");
+ audition_right_dry_button.set_name ("CrossfadeEditAuditionButton");
+ audition_right_button.set_name ("CrossfadeEditAuditionButton");
+
+ clear_button.clicked.connect (slot (*this, &CrossfadeEditor::clear));
+ revert_button.clicked.connect (slot (*this, &CrossfadeEditor::reset));
+ audition_both_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_toggled));
+ audition_right_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_right_toggled));
+ audition_right_dry_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_right_dry_toggled));
+ audition_left_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_left_toggled));
+ audition_left_dry_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_left_dry_toggled));
+
+ action_box.set_border_width (7);
+ action_box.set_spacing (5);
+ action_box.set_homogeneous (false);
+ action_box.pack_end (cancel_button, false, false);
+ action_box.pack_end (ok_button, false, false);
+ action_box.pack_end (revert_button, false, false);
+ action_box.pack_end (clear_button, false, false);
+
+ Frame* edit_frame = manage (new Frame (_("Edit")));
+ edit_frame->set_name (X_("CrossfadeEditFrame"));
+ edit_frame->add (action_box);
+
+ Gtk::HBox* action_center_box = manage (new HBox);
+ action_center_box->pack_start (*edit_frame, true, false);
+
+ roll_box.pack_start (preroll_button, false, false);
+ roll_box.pack_start (postroll_button, false, false);
+
+ Gtk::HBox* rcenter_box = manage (new HBox);
+ rcenter_box->pack_start (roll_box, true, false);
+
+ VBox* vpacker2 = manage (new (VBox));
+
+ vpacker2->set_border_width (12);
+ vpacker2->set_spacing (7);
+ vpacker2->pack_start (*acbox, false, false);
+ vpacker2->pack_start (*rcenter_box, false, false);
+ vpacker2->pack_start (*action_center_box, false, false);
+
+ curve_button_box.set_spacing (7);
+ curve_button_box.pack_start (fade_out_table, false, false, 12);
+ curve_button_box.pack_start (*vpacker2, false, false, 12);
+ curve_button_box.pack_start (fade_in_table, false, false, 12);
+
+ vpacker.set_border_width (12);
+ vpacker.set_spacing (5);
+ vpacker.pack_start (*canvas_frame, true, true);
+ vpacker.pack_start (curve_button_box, false, false);
+
+ /* button to allow hackers to check the actual curve values */
+
+// Button* foobut = manage (new Button ("dump"));
+// foobut->clicked.connect (slot (*this, &CrossfadeEditor::dump));
+// vpacker.pack_start (*foobut, false, false);
+
+ current = In;
+ set (xfade.fade_in(), In);
+
+ current = Out;
+ set (xfade.fade_out(), Out);
+
+ curve_select_clicked (In);
+
+ xfade.StateChanged.connect (slot (*this, &CrossfadeEditor::xfade_changed));
+
+ session.AuditionActive.connect (slot (*this, &CrossfadeEditor::audition_state_changed));
+}
+
+CrossfadeEditor::~CrossfadeEditor()
+{
+ /* most objects will be destroyed when the toplevel window is. */
+
+ for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
+ delete *i;
+ }
+
+ for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
+ delete *i;
+ }
+}
+
+void
+CrossfadeEditor::dump ()
+{
+ for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) {
+ cerr << (*i)->when << ' ' << (*i)->value << endl;
+ }
+}
+
+void
+CrossfadeEditor::audition_state_changed (bool yn)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &CrossfadeEditor::audition_state_changed), yn));
+
+ if (!yn) {
+ audition_both_button.set_active (false);
+ audition_left_button.set_active (false);
+ audition_right_button.set_active (false);
+ audition_left_dry_button.set_active (false);
+ audition_right_dry_button.set_active (false);
+ }
+}
+
+void
+CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which)
+{
+ double firstx, endx;
+ ARDOUR::Curve::const_iterator the_end;
+
+ for (list<Point*>::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) {
+ delete *i;
+ }
+
+ fade[which].points.clear ();
+ fade[which].gain_curve.clear ();
+ fade[which].normative_curve.clear ();
+
+ if (curve.empty()) {
+ goto out;
+ }
+
+ the_end = curve.const_end();
+ --the_end;
+
+ firstx = (*curve.const_begin())->when;
+ endx = (*the_end)->when;
+
+ for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) {
+
+ double xfract = ((*i)->when - firstx) / (endx - firstx);
+ double yfract = ((*i)->value - miny) / (maxy - miny);
+
+ Point* p = make_point ();
+
+ p->move_to (x_coordinate (xfract), y_coordinate (yfract),
+ xfract, yfract);
+
+ fade[which].points.push_back (p);
+ }
+
+ /* no need to sort because curve is already time-ordered */
+
+ out:
+
+ swap (which, current);
+ redraw ();
+ swap (which, current);
+}
+
+gint
+CrossfadeEditor::_canvas_event (GtkCanvasItem* item, GdkEvent* event, gpointer data)
+{
+ CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
+ return ed->canvas_event (item, event);
+}
+
+gint
+CrossfadeEditor::canvas_event (GtkCanvasItem* item, GdkEvent* event)
+{
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ add_control_point ((event->button.x - canvas_border)/effective_width(),
+ 1.0 - ((event->button.y - canvas_border)/effective_height()));
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+CrossfadeEditor::Point::~Point()
+{
+ gtk_object_destroy (GTK_OBJECT(box));
+}
+
+CrossfadeEditor::Point*
+CrossfadeEditor::make_point ()
+{
+ Point* p = new Point;
+
+ p->box = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
+ gtk_canvas_simplerect_get_type(),
+ "fill", (gboolean) TRUE,
+ "fill_color_rgba", color_map[cCrossfadeEditorPointFill],
+ "outline_color_rgba", color_map[cCrossfadeEditorPointOutline],
+ "outline_pixels", (gint) 1,
+ NULL);
+
+ p->curve = fade[current].line;
+
+ gtk_object_set_data (GTK_OBJECT(p->box), "point", p);
+ gtk_signal_connect (GTK_OBJECT(p->box), "event",
+ (GtkSignalFunc) _point_event,
+ this);
+
+ return p;
+}
+
+void
+CrossfadeEditor::add_control_point (double x, double y)
+{
+ PointSorter cmp;
+
+ /* enforce end point x location */
+
+ if (fade[current].points.empty()) {
+ x = 0.0;
+ } else if (fade[current].points.size() == 1) {
+ x = 1.0;
+ }
+
+ Point* p = make_point ();
+
+ p->move_to (x_coordinate (x), y_coordinate (y), x, y);
+
+ fade[current].points.push_back (p);
+ fade[current].points.sort (cmp);
+
+ redraw ();
+}
+
+void
+CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract)
+{
+ const double half_size = rint(size/2.0);
+ double x1 = nx - half_size;
+ double x2 = nx + half_size;
+
+ gtk_canvas_item_set (box,
+ "x1", x1,
+ "x2", x2,
+ "y1", ny - half_size,
+ "y2", ny + half_size,
+ NULL);
+ x = xfract;
+ y = yfract;
+}
+
+void
+CrossfadeEditor::canvas_allocation (GtkAllocation *alloc)
+{
+ if (toplevel) {
+ gtk_canvas_item_set (toplevel,
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", (double) _canvas->allocation.width + canvas_border,
+ "y2", (double) _canvas->allocation.height + canvas_border,
+ NULL);
+ }
+
+ gtk_canvas_set_scroll_region (GTK_CANVAS(_canvas), 0.0, 0.0,
+ _canvas->allocation.width,
+ _canvas->allocation.height);
+
+ Point* end = make_point ();
+ PointSorter cmp;
+
+ if (fade[In].points.size() > 1) {
+ Point* old_end = fade[In].points.back();
+ fade[In].points.pop_back ();
+ end->move_to (x_coordinate (old_end->x),
+ y_coordinate (old_end->y),
+ old_end->x, old_end->y);
+ delete old_end;
+ } else {
+ double x = 1.0;
+ double y = 0.5;
+ end->move_to (x_coordinate (x), y_coordinate (y), x, y);
+
+ }
+
+ fade[In].points.push_back (end);
+ fade[In].points.sort (cmp);
+
+ for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
+ (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y),
+ (*i)->x, (*i)->y);
+ }
+
+ end = make_point ();
+
+ if (fade[Out].points.size() > 1) {
+ Point* old_end = fade[Out].points.back();
+ fade[Out].points.pop_back ();
+ end->move_to (x_coordinate (old_end->x),
+ y_coordinate (old_end->y),
+ old_end->x, old_end->y);
+ delete old_end;
+ } else {
+ double x = 1.0;
+ double y = 0.5;
+ end->move_to (x_coordinate (x), y_coordinate (y), x, y);
+
+ }
+
+ fade[Out].points.push_back (end);
+ fade[Out].points.sort (cmp);
+
+ for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
+ (*i)->move_to (x_coordinate ((*i)->x),
+ y_coordinate ((*i)->y),
+ (*i)->x, (*i)->y);
+ }
+
+ WhichFade old_current = current;
+ current = In;
+ redraw ();
+ current = Out;
+ redraw ();
+ current = old_current;
+
+ double spu = xfade.length() / (double) effective_width();
+
+ if (fade[In].waves.empty()) {
+ make_waves (xfade.in(), In);
+ }
+
+ if (fade[Out].waves.empty()) {
+ make_waves (xfade.out(), Out);
+ }
+
+ double ht;
+ vector<GtkCanvasItem*>::iterator i;
+ uint32_t n;
+
+ ht = _canvas->allocation.height / xfade.in().n_channels();
+
+ for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) {
+ double yoff;
+
+ yoff = n * ht;
+
+ gtk_canvas_item_set ((*i),
+ "y", yoff,
+ "height", ht,
+ "samples_per_unit", spu,
+ NULL);
+ }
+
+ ht = _canvas->allocation.height / xfade.out().n_channels();
+
+ for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) {
+ double yoff;
+
+ yoff = n * ht;
+
+ gtk_canvas_item_set ((*i),
+ "y", yoff,
+ "height", ht,
+ "samples_per_unit", spu,
+ NULL);
+ }
+
+}
+
+gint
+CrossfadeEditor::_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data)
+{
+ CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
+ return ed->point_event (item, event);
+}
+
+gint
+CrossfadeEditor::point_event (GtkCanvasItem* item, GdkEvent* event)
+{
+ Point* point = static_cast<Point*> (gtk_object_get_data (GTK_OBJECT (item), "point"));
+
+ if (point->curve != fade[current].line) {
+ return FALSE;
+ }
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ point_grabbed = true;
+ break;
+ case GDK_BUTTON_RELEASE:
+ point_grabbed = false;
+
+ if (Keyboard::is_delete_event (&event->button)) {
+ fade[current].points.remove (point);
+ delete point;
+ }
+
+ redraw ();
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ if (point_grabbed) {
+ double new_x, new_y;
+
+ /* can't drag first or last points horizontally */
+
+ if (point == fade[current].points.front() || point == fade[current].points.back()) {
+ new_x = point->x;
+ } else {
+ new_x = (event->motion.x - canvas_border)/effective_width();
+ }
+
+ new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height());
+ point->move_to (x_coordinate (new_x), y_coordinate (new_y),
+ new_x, new_y);
+ redraw ();
+ }
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+gint
+CrossfadeEditor::_curve_event (GtkCanvasItem* item, GdkEvent* event, gpointer data)
+{
+ CrossfadeEditor* ed = static_cast<CrossfadeEditor*> (data);
+ return ed->curve_event (item, event);
+}
+
+gint
+CrossfadeEditor::curve_event (GtkCanvasItem* item, GdkEvent* event)
+{
+ /* treat it like a toplevel event */
+
+ return canvas_event (item, event);
+}
+
+void
+CrossfadeEditor::xfade_changed (Change ignored)
+{
+ set (xfade.fade_in(), In);
+ set (xfade.fade_out(), Out);
+}
+
+void
+CrossfadeEditor::redraw ()
+{
+ if (_canvas->allocation.width < 2) {
+ return;
+ }
+
+ jack_nframes_t len = xfade.length ();
+
+ fade[current].normative_curve.clear ();
+ fade[current].gain_curve.clear ();
+
+ 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);
+ }
+
+ size_t npoints = (size_t) effective_width();
+ float vec[npoints];
+
+ fade[current].normative_curve.get_vector (0, 1.0, vec, npoints);
+
+ GtkCanvasPoints* pts = get_canvas_points ("xfade edit1", npoints);
+ GtkCanvasPoints* spts = get_canvas_points ("xfade edit2", npoints + 3);
+
+ /* the shade coordinates *MUST* be in anti-clockwise order.
+ */
+
+ if (current == In) {
+
+ /* lower left */
+
+ spts->coords[0] = canvas_border;
+ spts->coords[1] = effective_height() + canvas_border;
+
+ /* lower right */
+
+ spts->coords[2] = effective_width() + canvas_border;
+ spts->coords[3] = effective_height() + canvas_border;
+
+ /* upper right */
+
+ spts->coords[4] = effective_width() + canvas_border;
+ spts->coords[5] = canvas_border;
+
+
+ } else {
+
+ /* upper left */
+
+ spts->coords[0] = canvas_border;
+ spts->coords[1] = canvas_border;
+
+ /* lower left */
+
+ spts->coords[2] = canvas_border;
+ spts->coords[3] = effective_height() + canvas_border;
+
+ /* lower right */
+
+ spts->coords[4] = effective_width() + canvas_border;
+ spts->coords[5] = effective_height() + canvas_border;
+
+ }
+
+ size_t last_spt = ((npoints + 3) * 2) - 2;
+
+ for (size_t i = 0; i < npoints; ++i) {
+
+ double y = vec[i];
+
+ pts->coords[i*2] = canvas_border + i;
+ pts->coords[(i*2)+1] = y_coordinate (y);
+
+ spts->coords[last_spt - (i*2)] = canvas_border + i;
+ spts->coords[last_spt - (i*2) + 1] = pts->coords[(i*2)+1];
+ }
+
+ gtk_canvas_item_set (fade[current].line, "points", pts, NULL);
+ gtk_canvas_item_set (fade[current].shading, "points", spts, NULL);
+
+ gtk_canvas_points_unref (pts);
+ gtk_canvas_points_unref (spts);
+
+ for (vector<GtkCanvasItem*>::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) {
+ gtk_canvas_item_set ((*i), "gain_src", &fade[current].gain_curve, NULL);
+ }
+}
+
+void
+CrossfadeEditor::apply_preset (Preset *preset)
+{
+ for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
+ delete *i;
+ }
+
+ fade[current].points.clear ();
+
+ for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) {
+ Point* p = make_point ();
+ p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y),
+ (*i).x, (*i).y);
+ fade[current].points.push_back (p);
+ }
+
+ redraw ();
+}
+
+void
+CrossfadeEditor::apply ()
+{
+ _apply_to (&xfade);
+}
+
+void
+CrossfadeEditor::_apply_to (Crossfade* xf)
+{
+ ARDOUR::Curve& in (xf->fade_in());
+ ARDOUR::Curve& out (xf->fade_out());
+
+ /* IN */
+
+
+ ARDOUR::Curve::const_iterator the_end = in.const_end();
+ --the_end;
+
+ double firstx = (*in.begin())->when;
+ double endx = (*the_end)->when;
+ double miny = in.get_min_y ();
+ double maxy = in.get_max_y ();
+
+ in.freeze ();
+ in.clear ();
+
+ for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
+
+ double when = firstx + ((*i)->x * (endx - firstx));
+ double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
+ in.add (when, value);
+ }
+
+ /* OUT */
+
+ the_end = out.const_end();
+ --the_end;
+
+ firstx = (*out.begin())->when;
+ endx = (*the_end)->when;
+ miny = out.get_min_y ();
+ maxy = out.get_max_y ();
+
+ out.freeze ();
+ out.clear ();
+
+ for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
+
+ double when = firstx + ((*i)->x * (endx - firstx));
+ double value = (*i)->y; // miny + ((*i)->y * (maxy - miny));
+ out.add (when, value);
+ }
+
+ in.thaw ();
+ out.thaw ();
+}
+
+void
+CrossfadeEditor::setup (Crossfade* xfade)
+{
+ _apply_to (xfade);
+ xfade->set_active (true);
+ xfade->fade_in().solve ();
+ xfade->fade_out().solve ();
+}
+
+void
+CrossfadeEditor::clear ()
+{
+ for (list<Point*>::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) {
+ delete *i;
+ }
+
+ fade[current].points.clear ();
+
+ redraw ();
+}
+
+void
+CrossfadeEditor::reset ()
+{
+ set (xfade.fade_in(), In);
+ set (xfade.fade_out(), Out);
+}
+
+void
+CrossfadeEditor::build_presets ()
+{
+ Preset* p;
+
+ fade_in_presets = new Presets;
+ fade_out_presets = new Presets;
+
+ /* FADE OUT */
+
+ p = new Preset (hiin_xpm);
+ p->push_back (PresetPoint (0, 0));
+ p->push_back (PresetPoint (0.0207373, 0.197222));
+ p->push_back (PresetPoint (0.0645161, 0.525));
+ p->push_back (PresetPoint (0.152074, 0.802778));
+ p->push_back (PresetPoint (0.276498, 0.919444));
+ p->push_back (PresetPoint (0.481567, 0.980556));
+ p->push_back (PresetPoint (0.767281, 1));
+ p->push_back (PresetPoint (1, 1));
+ fade_in_presets->push_back (p);
+
+ p = new Preset (loin_xpm);
+ p->push_back (PresetPoint (0, 0));
+ p->push_back (PresetPoint (0.389401, 0.0333333));
+ p->push_back (PresetPoint (0.629032, 0.0861111));
+ p->push_back (PresetPoint (0.829493, 0.233333));
+ p->push_back (PresetPoint (0.9447, 0.483333));
+ p->push_back (PresetPoint (0.976959, 0.697222));
+ p->push_back (PresetPoint (1, 1));
+ fade_in_presets->push_back (p);
+
+ p = new Preset (regin_xpm);
+ p->push_back (PresetPoint (0, 0));
+ p->push_back (PresetPoint (0.0737327, 0.308333));
+ p->push_back (PresetPoint (0.246544, 0.658333));
+ p->push_back (PresetPoint (0.470046, 0.886111));
+ p->push_back (PresetPoint (0.652074, 0.972222));
+ p->push_back (PresetPoint (0.771889, 0.988889));
+ p->push_back (PresetPoint (1, 1));
+ fade_in_presets->push_back (p);
+
+ p = new Preset (regin2_xpm);
+ p->push_back (PresetPoint (0, 0));
+ p->push_back (PresetPoint (0.304147, 0.0694444));
+ p->push_back (PresetPoint (0.529954, 0.152778));
+ p->push_back (PresetPoint (0.725806, 0.333333));
+ p->push_back (PresetPoint (0.847926, 0.558333));
+ p->push_back (PresetPoint (0.919355, 0.730556));
+ p->push_back (PresetPoint (1, 1));
+ fade_in_presets->push_back (p);
+
+ p = new Preset (linin_xpm);
+ p->push_back (PresetPoint (0, 0));
+ p->push_back (PresetPoint (1, 1));
+ fade_in_presets->push_back (p);
+
+ /* FADE OUT */
+
+ p = new Preset (hiout_xpm);
+ p->push_back (PresetPoint (0, 1));
+ p->push_back (PresetPoint (0.305556, 1));
+ p->push_back (PresetPoint (0.548611, 0.991736));
+ p->push_back (PresetPoint (0.759259, 0.931129));
+ p->push_back (PresetPoint (0.918981, 0.68595));
+ p->push_back (PresetPoint (0.976852, 0.22865));
+ p->push_back (PresetPoint (1, 0));
+ fade_out_presets->push_back (p);
+
+ p = new Preset (regout_xpm);
+ p->push_back (PresetPoint (0, 1));
+ p->push_back (PresetPoint (0.228111, 0.988889));
+ p->push_back (PresetPoint (0.347926, 0.972222));
+ p->push_back (PresetPoint (0.529954, 0.886111));
+ p->push_back (PresetPoint (0.753456, 0.658333));
+ p->push_back (PresetPoint (0.9262673, 0.308333));
+ p->push_back (PresetPoint (1, 0));
+ fade_out_presets->push_back (p);
+
+ p = new Preset (loout_xpm);
+ p->push_back (PresetPoint (0, 1));
+ p->push_back (PresetPoint (0.023041, 0.697222));
+ p->push_back (PresetPoint (0.0553, 0.483333));
+ p->push_back (PresetPoint (0.170507, 0.233333));
+ p->push_back (PresetPoint (0.370968, 0.0861111));
+ p->push_back (PresetPoint (0.610599, 0.0333333));
+ p->push_back (PresetPoint (1, 0));
+ fade_out_presets->push_back (p);
+
+ p = new Preset (regout2_xpm);
+ p->push_back (PresetPoint (0, 1));
+ p->push_back (PresetPoint (0.080645, 0.730556));
+ p->push_back (PresetPoint (0.277778, 0.289256));
+ p->push_back (PresetPoint (0.470046, 0.152778));
+ p->push_back (PresetPoint (0.695853, 0.0694444));
+ p->push_back (PresetPoint (1, 0));
+ fade_out_presets->push_back (p);
+
+ p = new Preset (linout_xpm);
+ p->push_back (PresetPoint (0, 1));
+ p->push_back (PresetPoint (1, 0));
+ fade_out_presets->push_back (p);
+}
+
+void
+CrossfadeEditor::curve_select_clicked (WhichFade wf)
+{
+ current = wf;
+
+ if (wf == In) {
+
+ for (vector<GtkCanvasItem*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
+ gtk_canvas_item_set ((*i), "wave_color", color_map[cSelectedCrossfadeEditorWave], NULL);
+ }
+
+ for (vector<GtkCanvasItem*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
+ gtk_canvas_item_set ((*i), "wave_color", color_map[cCrossfadeEditorWave], NULL);
+ }
+
+ gtk_canvas_item_set (fade[In].line, "fill_color_rgba", color_map[cSelectedCrossfadeEditorLine], NULL);
+ gtk_canvas_item_set (fade[Out].line, "fill_color_rgba", color_map[cCrossfadeEditorLine], NULL);
+ gtk_canvas_item_hide (fade[Out].shading);
+ gtk_canvas_item_show (fade[In].shading);
+
+ for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
+ gtk_canvas_item_hide ((*i)->box);
+ }
+
+ for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
+ gtk_canvas_item_show ((*i)->box);
+ }
+
+ for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
+ (*i)->set_sensitive (false);
+ }
+
+ for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
+ (*i)->set_sensitive (true);
+ }
+
+ } else {
+
+ for (vector<GtkCanvasItem*>::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) {
+ gtk_canvas_item_set ((*i), "wave_color", color_map[cCrossfadeEditorWave], NULL);
+ }
+
+ for (vector<GtkCanvasItem*>::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) {
+ gtk_canvas_item_set ((*i), "wave_color", color_map[cSelectedCrossfadeEditorWave], NULL);
+ }
+
+ gtk_canvas_item_set (fade[Out].line, "fill_color_rgba", color_map[cSelectedCrossfadeEditorLine], NULL);
+ gtk_canvas_item_set (fade[In].line, "fill_color_rgba", color_map[cCrossfadeEditorLine], NULL);
+ gtk_canvas_item_hide (fade[In].shading);
+ gtk_canvas_item_show (fade[Out].shading);
+
+ for (list<Point*>::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) {
+ gtk_canvas_item_hide ((*i)->box);
+ }
+
+ for (list<Point*>::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) {
+ gtk_canvas_item_show ((*i)->box);
+ }
+
+ for (vector<Button*>::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) {
+ (*i)->set_sensitive (true);
+ }
+
+ for (vector<Button*>::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) {
+ (*i)->set_sensitive (false);
+ }
+
+ }
+}
+
+double
+CrossfadeEditor::x_coordinate (double& xfract) const
+{
+ xfract = min (1.0, xfract);
+ xfract = max (0.0, xfract);
+
+ return canvas_border + (xfract * effective_width());
+}
+
+double
+CrossfadeEditor::y_coordinate (double& yfract) const
+{
+ yfract = min (1.0, yfract);
+ yfract = max (0.0, yfract);
+
+ return (_canvas->allocation.height - (canvas_border)) - (yfract * effective_height());
+}
+
+void
+CrossfadeEditor::make_waves (AudioRegion& region, WhichFade which)
+{
+ gdouble ht;
+ uint32_t nchans = region.n_channels();
+ guint32 color;
+ double spu;
+
+ if (which == In) {
+ color = color_map[cSelectedCrossfadeEditorWave];
+ } else {
+ color = color_map[cCrossfadeEditorWave];
+ }
+
+ ht = _canvas->allocation.height / (double) nchans;
+ spu = xfade.length() / (double) effective_width();
+
+ for (uint32_t n = 0; n < nchans; ++n) {
+
+ gdouble yoff = n * ht;
+
+ if (region.source(n).peaks_ready (bind (slot (*this, &CrossfadeEditor::peaks_ready), &region, which))) {
+
+ GtkCanvasItem *wave = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)),
+ gtk_canvas_waveview_get_type (),
+ "data_src", (gpointer) &region,
+ "cache_updater", (gboolean) TRUE,
+ "cache", gtk_canvas_waveview_cache_new (),
+ "channel", (guint32) n,
+ "length_function", (gpointer) region_length_from_c,
+ "sourcefile_length_function", (gpointer) sourcefile_length_from_c,
+ "peak_function", (gpointer) region_read_peaks_from_c,
+ "gain_function", (gpointer) curve_get_vector_from_c,
+ "gain_src", &fade[which].gain_curve,
+ "x", (double) canvas_border,
+ "y", yoff,
+ "height", ht,
+ "samples_per_unit", spu,
+ "amplitude_above_axis", 2.0,
+ "wave_color", color,
+ NULL);
+
+ gtk_canvas_item_lower_to_bottom (wave);
+ fade[which].waves.push_back (wave);
+ }
+ }
+
+ gtk_canvas_item_lower_to_bottom (toplevel);
+}
+
+void
+CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which)
+{
+ /* this should never be called, because the peak files for an xfade
+ will be ready by the time we want them. but our API forces us
+ to provide this, so ..
+ */
+
+ make_waves (*r, which);
+}
+
+void
+CrossfadeEditor::audition_both ()
+{
+ AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
+ jack_nframes_t preroll;
+ jack_nframes_t postroll;
+ jack_nframes_t length;
+ jack_nframes_t left_start_offset;
+ jack_nframes_t right_length;
+ jack_nframes_t left_length;
+
+ if (preroll_button.get_active()) {
+ preroll = ARDOUR_UI::instance()->preroll_clock.current_duration ();
+ } else {
+ preroll = 0;
+ }
+
+ if (postroll_button.get_active()) {
+ postroll = ARDOUR_UI::instance()->postroll_clock.current_duration ();
+ } else {
+ postroll = 0;
+ }
+
+ if ((left_start_offset = xfade.out().length() - xfade.length()) >= preroll) {
+ left_start_offset -= preroll;
+ }
+
+ length = 0;
+
+ if ((left_length = xfade.length()) < xfade.out().length() - left_start_offset) {
+ length += postroll;
+ }
+
+ right_length = xfade.length();
+
+ if (xfade.in().length() - right_length < postroll) {
+ right_length += postroll;
+ }
+
+ AudioRegion* left = new AudioRegion (xfade.out(), left_start_offset, left_length, "xfade out",
+ 0, Region::DefaultFlags, false);
+ AudioRegion* right = new AudioRegion (xfade.in(), 0, right_length, "xfade in",
+ 0, Region::DefaultFlags, false);
+
+ pl.add_region (*left, 0);
+ pl.add_region (*right, 1+preroll);
+
+ /* there is only one ... */
+
+ pl.foreach_crossfade (this, &CrossfadeEditor::setup);
+
+ session.audition_playlist ();
+}
+
+void
+CrossfadeEditor::audition_left_dry ()
+{
+ AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
+ 0, Region::DefaultFlags, false);
+
+ session.audition_region (*left);
+}
+
+void
+CrossfadeEditor::audition_left ()
+{
+ AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
+
+ AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left",
+ 0, Region::DefaultFlags, false);
+ AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
+ 0, Region::DefaultFlags, false);
+
+ pl.add_region (*left, 0);
+ pl.add_region (*right, 1);
+
+ right->set_muted (true);
+
+ /* there is only one ... */
+
+ pl.foreach_crossfade (this, &CrossfadeEditor::setup);
+
+ session.audition_playlist ();
+
+ /* memory leak for regions */
+}
+
+void
+CrossfadeEditor::audition_right_dry ()
+{
+ AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in",
+ 0, Region::DefaultFlags, false);
+ session.audition_region (*right);
+}
+
+void
+CrossfadeEditor::audition_right ()
+{
+ AudioPlaylist& pl (session.the_auditioner().prepare_playlist());
+
+ AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out",
+ 0, Region::DefaultFlags, false);
+ AudioRegion* right = new AudioRegion (xfade.out(), 0, xfade.length(), "xfade out",
+ 0, Region::DefaultFlags, false);
+
+ pl.add_region (*left, 0);
+ pl.add_region (*right, 1);
+
+ left->set_muted (true);
+
+ /* there is only one ... */
+
+ pl.foreach_crossfade (this, &CrossfadeEditor::setup);
+
+ session.audition_playlist ();
+}
+
+void
+CrossfadeEditor::cancel_audition ()
+{
+ session.cancel_audition ();
+}
+
+void
+CrossfadeEditor::audition_toggled ()
+{
+ bool x;
+
+ if ((x = audition_both_button.get_active ()) != session.is_auditioning()) {
+
+ if (x) {
+ audition_both ();
+ } else {
+ cancel_audition ();
+ }
+ }
+}
+
+void
+CrossfadeEditor::audition_right_toggled ()
+{
+ bool x;
+
+ if ((x = audition_right_button.get_active ()) != session.is_auditioning()) {
+
+ if (x) {
+ audition_right ();
+ } else {
+ cancel_audition ();
+ }
+ }
+}
+
+void
+CrossfadeEditor::audition_right_dry_toggled ()
+{
+ bool x;
+
+ if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) {
+
+ if (x) {
+ audition_right_dry ();
+ } else {
+ cancel_audition ();
+ }
+ }
+}
+
+void
+CrossfadeEditor::audition_left_toggled ()
+{
+ bool x;
+
+ if ((x = audition_left_button.get_active ()) != session.is_auditioning()) {
+
+ if (x) {
+ audition_left ();
+ } else {
+ cancel_audition ();
+ }
+ }
+}
+
+void
+CrossfadeEditor::audition_left_dry_toggled ()
+{
+ bool x;
+
+ if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) {
+
+ if (x) {
+ audition_left_dry ();
+ } else {
+ cancel_audition ();
+ }
+ }
+}
diff --git a/gtk2_ardour/crossfade_edit.h b/gtk2_ardour/crossfade_edit.h
new file mode 100644
index 0000000000..dbe62dea66
--- /dev/null
+++ b/gtk2_ardour/crossfade_edit.h
@@ -0,0 +1,195 @@
+#ifndef __gtk_ardour_xfade_edit_h__
+#define __gtk_ardour_xfade_edit_h__
+
+#include <list>
+
+#include <gtk--/box.h>
+#include <gtk--/button.h>
+#include <gtk--/radiobutton.h>
+#include <gtk-canvas.h>
+
+#include <ardour/curve.h>
+#include "ardour_dialog.h"
+
+namespace ARDOUR
+{
+ class Session;
+ class Curve;
+ class Crossfade;
+}
+
+class CrossfadeEditor : public ArdourDialog
+{
+ public:
+ CrossfadeEditor (ARDOUR::Session&, ARDOUR::Crossfade&, double miny, double maxy);
+ ~CrossfadeEditor ();
+
+ void apply ();
+
+ static const double canvas_border;
+
+ /* these are public so that a caller/subclass can make them do the right thing.
+ */
+
+ Gtk::Button cancel_button;
+ Gtk::Button ok_button;
+
+ struct PresetPoint {
+ double x;
+ double y;
+
+ PresetPoint (double a, double b)
+ : x (a), y (b) {}
+ };
+
+ struct Preset : public list<PresetPoint> {
+ const gchar** xpm;
+
+ Preset (const gchar** x)
+ : xpm (x) {}
+ };
+
+ typedef list<Preset*> Presets;
+
+ static Presets* fade_in_presets;
+ static Presets* fade_out_presets;
+
+ private:
+ ARDOUR::Crossfade& xfade;
+ ARDOUR::Session& session;
+
+ Gtk::VBox vpacker;
+
+ struct Point {
+ ~Point();
+
+ GtkCanvasItem* box;
+ GtkCanvasItem* curve;
+ double x;
+ double y;
+
+ static const int32_t size;
+
+ void move_to (double x, double y, double xfract, double yfract);
+ };
+
+ struct PointSorter
+ {
+ bool operator() (const CrossfadeEditor::Point* a, const CrossfadeEditor::Point *b) {
+ return a->x < b->x;
+ }
+ };
+
+ GtkWidget* _canvas;
+ GtkCanvasItem* toplevel;
+ Gtk::Widget* canvas;
+
+ struct Half {
+ GtkCanvasItem* line;
+ GtkCanvasItem* shading;
+ list<Point*> points;
+ ARDOUR::Curve normative_curve; /* 0 - 1.0, linear */
+ ARDOUR::Curve gain_curve; /* 0 - 2.0, gain mapping */
+ vector<GtkCanvasItem*> waves;
+
+ Half();
+ };
+
+ enum WhichFade {
+ In = 0,
+ Out = 1
+ };
+
+ Half fade[2];
+ WhichFade current;
+
+ bool point_grabbed;
+ vector<Gtk::Button*> fade_out_buttons;
+ vector<Gtk::Button*> fade_in_buttons;
+
+ Gtk::HBox action_box;
+
+ Gtk::VBox vpacker2;
+
+ Gtk::Button clear_button;
+ Gtk::Button revert_button;
+
+ Gtk::ToggleButton audition_both_button;
+ Gtk::ToggleButton audition_left_dry_button;
+ Gtk::ToggleButton audition_left_button;
+ Gtk::ToggleButton audition_right_dry_button;
+ Gtk::ToggleButton audition_right_button;
+
+ Gtk::ToggleButton preroll_button;
+ Gtk::ToggleButton postroll_button;
+
+ Gtk::HBox roll_box;
+
+ gint event_handler (GdkEvent*);
+
+ static gint _canvas_event (GtkCanvasItem*, GdkEvent* event, gpointer data);
+ static gint _point_event (GtkCanvasItem*, GdkEvent* event, gpointer data);
+ static gint _curve_event (GtkCanvasItem*, GdkEvent* event, gpointer data);
+
+ gint canvas_event (GtkCanvasItem*, GdkEvent* event);
+ gint point_event (GtkCanvasItem*, GdkEvent* event);
+ gint curve_event (GtkCanvasItem*, GdkEvent* event);
+
+ void canvas_allocation (GtkAllocation*);
+ void add_control_point (double x, double y);
+ Point* make_point ();
+ void redraw ();
+
+ double effective_width () const { return _canvas->allocation.width - (2.0 * canvas_border); }
+ double effective_height () const { return _canvas->allocation.height - (2.0 * canvas_border); }
+
+ void clear ();
+ void reset ();
+
+ double miny;
+ double maxy;
+
+ Gtk::Table fade_in_table;
+ Gtk::Table fade_out_table;
+
+ void build_presets ();
+ void apply_preset (Preset*);
+
+ Gtk::RadioButton select_in_button;
+ Gtk::RadioButton select_out_button;
+ Gtk::HBox curve_button_box;
+ Gtk::HBox audition_box;
+
+ void curve_select_clicked (WhichFade);
+
+ double x_coordinate (double& xfract) const;
+ double y_coordinate (double& yfract) const;
+
+ void set (const ARDOUR::Curve& alist, WhichFade);
+
+ void make_waves (ARDOUR::AudioRegion&, WhichFade);
+ void peaks_ready (ARDOUR::AudioRegion* r, WhichFade);
+
+ void _apply_to (ARDOUR::Crossfade* xf);
+ void setup (ARDOUR::Crossfade*);
+ void cancel_audition ();
+ void audition_state_changed (bool);
+
+ void audition_toggled ();
+ void audition_right_toggled ();
+ void audition_right_dry_toggled ();
+ void audition_left_toggled ();
+ void audition_left_dry_toggled ();
+
+ void audition_both ();
+ void audition_left_dry ();
+ void audition_left ();
+ void audition_right_dry ();
+ void audition_right ();
+
+ void xfade_changed (ARDOUR::Change);
+
+ void dump ();
+};
+
+#endif /* __gtk_ardour_xfade_edit_h__ */
diff --git a/gtk2_ardour/crossfade_view.cc b/gtk2_ardour/crossfade_view.cc
new file mode 100644
index 0000000000..e074e7626c
--- /dev/null
+++ b/gtk2_ardour/crossfade_view.cc
@@ -0,0 +1,263 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+
+#include <ardour/region.h>
+#include <gtkmmext/doi.h>
+
+#include "canvas-simplerect.h"
+#include "canvas-curve.h"
+#include "crossfade_view.h"
+#include "rgb_macros.h"
+#include "audio_time_axis.h"
+#include "public_editor.h"
+#include "regionview.h"
+#include "utils.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Editing;
+
+SigC::Signal1<void,CrossfadeView*> CrossfadeView::GoingAway;
+
+CrossfadeView::CrossfadeView (GtkCanvasGroup *parent,
+ AudioTimeAxisView &tv,
+ Crossfade& xf,
+ double spu,
+ GdkColor& basic_color,
+ AudioRegionView& lview,
+ AudioRegionView& rview)
+
+
+ : TimeAxisViewItem ("xf.name()", parent, tv, spu, basic_color, xf.position(),
+ xf.overlap_length(), TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowFrame)),
+ crossfade (xf),
+ left_view (lview),
+ right_view (rview)
+
+{
+ _valid = true;
+ _visible = true;
+
+ fade_in = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_line_get_type(),
+ "fill_color_rgba", color_map[cCrossfadeLine],
+ "width_pixels", (guint) 1,
+ NULL);
+
+ fade_out = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_line_get_type(),
+ "fill_color_rgba", color_map[cCrossfadeLine],
+ "width_pixels", (guint) 1,
+ NULL);
+
+ set_height (get_time_axis_view().height);
+
+ /* no frame around the xfade or overlap rects */
+
+ gtk_canvas_item_set (frame, "outline_what", 0, NULL);
+
+ /* never show the vestigial frame */
+
+ gtk_canvas_item_hide (vestigial_frame);
+ show_vestigial = false;
+
+ gtk_object_set_data (GTK_OBJECT(group), "crossfadeview", this);
+ gtk_signal_connect (GTK_OBJECT(group), "event",
+ (GtkSignalFunc) PublicEditor::canvas_crossfade_view_event,
+ this);
+
+ crossfade_changed (Change (~0));
+
+ crossfade.StateChanged.connect (slot (*this, &CrossfadeView::crossfade_changed));
+}
+
+CrossfadeView::~CrossfadeView ()
+{
+ GoingAway (this) ; /* EMIT_SIGNAL */
+}
+
+std::string
+CrossfadeView::get_item_name ()
+{
+ return "xfade";
+// return crossfade.name();
+}
+
+void
+CrossfadeView::reset_width_dependent_items (double pixel_width)
+{
+ TimeAxisViewItem::reset_width_dependent_items (pixel_width);
+
+ active_changed ();
+
+ if (pixel_width < 5) {
+ gtk_canvas_item_hide (fade_in);
+ gtk_canvas_item_hide (fade_out);
+ }
+}
+
+void
+CrossfadeView::set_height (double height)
+{
+ if (height == TimeAxisView::Smaller ||
+ height == TimeAxisView::Small)
+ TimeAxisViewItem::set_height (height - 3 );
+ else
+ TimeAxisViewItem::set_height (height - NAME_HIGHLIGHT_SIZE - 3 );
+
+ redraw_curves ();
+}
+
+void
+CrossfadeView::crossfade_changed (Change what_changed)
+{
+ bool need_redraw_curves = false;
+
+ if (what_changed & BoundsChanged) {
+ set_position (crossfade.position(), this);
+ set_duration (crossfade.overlap_length(), this);
+ need_redraw_curves = true;
+ }
+
+ if (what_changed & Crossfade::ActiveChanged) {
+ /* calls redraw_curves */
+ active_changed ();
+ } else if (need_redraw_curves) {
+ redraw_curves ();
+ }
+}
+
+void
+CrossfadeView::redraw_curves ()
+{
+ GtkCanvasPoints* points;
+ int32_t npoints;
+ float* vec;
+
+ double h;
+
+ /*
+ At "height - 3.0" the bottom of the crossfade touches the name highlight or the bottom of the track (if the
+ track is either Small or Smaller.
+ */
+ switch(get_time_axis_view().height) {
+ case TimeAxisView::Smaller:
+ case TimeAxisView::Small:
+ h = get_time_axis_view().height - 3.0;
+ break;
+
+ default:
+ h = get_time_axis_view().height - NAME_HIGHLIGHT_SIZE - 3.0;
+ }
+
+ if (h < 0) {
+ /* no space allocated yet */
+ return;
+ }
+
+ npoints = get_time_axis_view().editor.frame_to_pixel (crossfade.length());
+ npoints = std::min (gdk_screen_width(), npoints);
+
+ if (!_visible || !crossfade.active() || npoints < 3) {
+ gtk_canvas_item_hide (fade_in);
+ gtk_canvas_item_hide (fade_out);
+ return;
+ } else {
+ gtk_canvas_item_show (fade_in);
+ gtk_canvas_item_show (fade_out);
+ }
+
+ points = get_canvas_points ("xfade edit redraw", npoints);
+ vec = new float[npoints];
+
+ crossfade.fade_in().get_vector (0, crossfade.length(), vec, npoints);
+ for (int i = 0, pci = 0; i < npoints; ++i) {
+ points->coords[pci++] = i;
+ points->coords[pci++] = 2.0 + h - (h * vec[i]);
+ }
+ gtk_canvas_item_set (fade_in, "points", points, NULL);
+
+ crossfade.fade_out().get_vector (0, crossfade.length(), vec, npoints);
+ for (int i = 0, pci = 0; i < npoints; ++i) {
+ points->coords[pci++] = i;
+ points->coords[pci++] = 2.0 + h - (h * vec[i]);
+ }
+ gtk_canvas_item_set (fade_out, "points", points, NULL);
+
+ delete [] vec;
+
+ gtk_canvas_points_unref (points);
+
+ /* XXX this is ugly, but it will have to wait till Crossfades are reimplented
+ as regions. This puts crossfade views on top of a track, above all regions.
+ */
+
+ gtk_canvas_item_raise_to_top (group);
+}
+
+void
+CrossfadeView::active_changed ()
+{
+ if (crossfade.active()) {
+ gtk_canvas_item_set (frame, "fill_color_rgba", color_map[cActiveCrossfade], NULL);
+ } else {
+ gtk_canvas_item_set (frame, "fill_color_rgba", color_map[cInactiveCrossfade], NULL);
+ }
+
+ redraw_curves ();
+}
+
+void
+CrossfadeView::set_valid (bool yn)
+{
+ _valid = yn;
+}
+
+AudioRegionView&
+CrossfadeView::upper_regionview () const
+{
+ if (left_view.region.layer() > right_view.region.layer()) {
+ return left_view;
+ } else {
+ return right_view;
+ }
+}
+
+void
+CrossfadeView::show ()
+{
+ gtk_canvas_item_show (group);
+ _visible = true;
+}
+
+void
+CrossfadeView::hide ()
+{
+ gtk_canvas_item_hide (group);
+ _visible = false;
+}
+
+void
+CrossfadeView::fake_hide ()
+{
+ gtk_canvas_item_hide (group);
+}
diff --git a/gtk2_ardour/crossfade_view.h b/gtk2_ardour/crossfade_view.h
new file mode 100644
index 0000000000..3825a50acf
--- /dev/null
+++ b/gtk2_ardour/crossfade_view.h
@@ -0,0 +1,84 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_crossfade_view_h__
+#define __gtk_ardour_crossfade_view_h__
+
+#include <vector>
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <sigc++/signal_system.h>
+#include <ardour/crossfade.h>
+
+#include "time_axis_view_item.h"
+
+class AudioTimeAxisView;
+class AudioRegionView;
+
+struct CrossfadeView : public TimeAxisViewItem
+{
+ CrossfadeView (GtkCanvasGroup*,
+ AudioTimeAxisView&,
+ ARDOUR::Crossfade&,
+ double initial_samples_per_unit,
+ GdkColor& basic_color,
+ AudioRegionView& leftview,
+ AudioRegionView& rightview);
+ ~CrossfadeView ();
+
+ ARDOUR::Crossfade& crossfade; // ok, let 'em have it
+ AudioRegionView& left_view; // and these too
+ AudioRegionView& right_view;
+
+ std::string get_item_name();
+ void set_height (double);
+
+ bool valid() const { return _valid; }
+ bool visible() const { return _visible; }
+ void set_valid (bool yn);
+
+ static SigC::Signal1<void,CrossfadeView*> GoingAway;
+
+ AudioRegionView& upper_regionview () const;
+
+ void fake_hide ();
+ void hide ();
+ void show ();
+
+ protected:
+ void reset_width_dependent_items (double pixel_width);
+
+ private:
+ bool _valid;
+ bool _visible;
+
+ double spu;
+
+ GtkCanvasItem *overlap_rect;
+ GtkCanvasItem *fade_in;
+ GtkCanvasItem *fade_out;
+ GtkCanvasItem *active_button;
+
+ void crossfade_changed (ARDOUR::Change);
+ void active_changed ();
+ void redraw_curves ();
+};
+
+#endif /* __gtk_ardour_crossfade_view_h__ */
diff --git a/gtk2_ardour/crossfade_xpms.h b/gtk2_ardour/crossfade_xpms.h
new file mode 100644
index 0000000000..4b5d0efccd
--- /dev/null
+++ b/gtk2_ardour/crossfade_xpms.h
@@ -0,0 +1,316 @@
+#ifndef __ardour_gtk_crossfade_xpms_h_
+#define __ardour_gtk_crossfade_xpms_h_
+
+/* XPM */
+static const gchar * hiout_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #F6F92A",
+"+ c #F6FA2A",
+" ",
+" ",
+" ",
+" ",
+" .+++++++ ",
+" .++++++++ ",
+" ++++++ ",
+" +++++ ",
+" ++++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" ++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" .+. ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * regout2_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #FDFD00",
+"+ c #FEFE00",
+" ",
+" ",
+" .+. ",
+" +++ ",
+" +++ ",
+" +++ ",
+" .++ ",
+" ++ ",
+" ++. ",
+" +++ ",
+" .++ ",
+" +++ ",
+" +++ ",
+" .+++ ",
+" ++++ ",
+" ++++ ",
+" +++++. ",
+" .+++++. ",
+" .++++++. ",
+" .+++++ ",
+" .+. ",
+" ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * regout_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #FDFD00",
+"+ c #FEFE00",
+" ",
+" ",
+" ",
+" ",
+" .++++. ",
+" .++++++. ",
+" .+++++. ",
+" .+++++ ",
+" ++++ ",
+" ++++ ",
+" ++++ ",
+" +++. ",
+" +++ ",
+" ++. ",
+" +++ ",
+" .++. ",
+" +++ ",
+" .++ ",
+" ++ ",
+" ++ ",
+" ++ ",
+" .. ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * regin2_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #FDFD00",
+"+ c #FEFE00",
+" ",
+" ",
+" .+. ",
+" +++ ",
+" +++ ",
+" ++. ",
+" .++ ",
+" +++ ",
+" ++. ",
+" .++ ",
+" +++ ",
+" .++. ",
+" +++ ",
+" +++. ",
+" ++++ ",
+" .++++ ",
+" .+++++ ",
+" .++++++. ",
+" .++++++. ",
+" ++++. ",
+" .. ",
+" ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * regin_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #FDFD00",
+"+ c #FEFE00",
+" ",
+" ",
+" ",
+" ",
+" .++++. ",
+" .++++++. ",
+" .+++++. ",
+" +++++. ",
+" ++++ ",
+" ++++ ",
+" ++++ ",
+" .+++ ",
+" +++ ",
+" .++ ",
+" +++ ",
+" .++. ",
+" +++ ",
+" ++. ",
+" ++ ",
+" ++ ",
+" ++ ",
+" .. ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * linout_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #FDFD00",
+"+ c #FEFE00",
+" ",
+" ",
+" ",
+" .. ",
+" +++ ",
+" .+++ ",
+" ++++ ",
+" ++++ ",
+" +++. ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" .+++ ",
+" ++++ ",
+" ++++ ",
+" ++++ ",
+" ++++ ",
+" .. ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * linin_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #FDFD00",
+"+ c #FEFE00",
+" ",
+" ",
+" ",
+" ",
+" .+. ",
+" +++. ",
+" ++++ ",
+" ++++ ",
+" ++++ ",
+" ++++ ",
+" +++. ",
+" +++ ",
+" +++ ",
+" +++ ",
+" .+++ ",
+" ++++ ",
+" ++++ ",
+" ++++ ",
+" ++++ ",
+" .+++ ",
+" .++ ",
+" + ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * loout_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #F6F92A",
+"+ c #F6FA2A",
+" ",
+" ",
+" .. ",
+" ++ ",
+" ++ ",
+" ++ ",
+" ++ ",
+" ++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" ++++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" ++++ ",
+" +++++ ",
+" ++++++ ",
+" +++++++++. ",
+" ++++++++ ",
+" ++++. ",
+" ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * loin_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #F6F92A",
+"+ c #F6FA2A",
+" ",
+" ",
+" .+. ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" ++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" +++ ",
+" ++++ ",
+" +++++ ",
+" ++++++ ",
+" .++++++++ ",
+" .+++++++ ",
+" ",
+" ",
+" ",
+" ",
+" "};
+/* XPM */
+static const gchar * hiin_xpm[] = {
+"25 25 3 1",
+" c None",
+". c #F6FA2A",
+"+ c #F6F92A",
+" ",
+" ",
+" ",
+" ",
+" .......+ ",
+" ........+ ",
+" ...... ",
+" ..... ",
+" .... ",
+" ... ",
+" ... ",
+" ... ",
+" ... ",
+" ... ",
+" ... ",
+" ... ",
+" .. ",
+" ... ",
+" ... ",
+" ... ",
+" ... ",
+" +.+ ",
+" ",
+" ",
+" "};
+
+
+#endif /* __ardour_gtk_crossfade_xpms_h_ */
diff --git a/gtk2_ardour/curvetest.cc b/gtk2_ardour/curvetest.cc
new file mode 100644
index 0000000000..613835aa4c
--- /dev/null
+++ b/gtk2_ardour/curvetest.cc
@@ -0,0 +1,51 @@
+#include <iostream>
+#include <fstream>
+#include <cfloat>
+#include <unistd.h>
+
+#include <ardour/curve.h>
+
+using namespace std;
+using namespace ARDOUR;
+
+int
+curvetest (string filename)
+{
+ ifstream in (filename.c_str());
+ stringstream line;
+ Curve c (-1.0, +1.0, 0, true);
+ double minx = DBL_MAX;
+ double maxx = DBL_MIN;
+
+ while (in) {
+ double x, y;
+
+ in >> x;
+ in >> y;
+
+ if (!in) {
+ break;
+ }
+
+ if (x < minx) {
+ minx = x;
+ }
+
+ if (x > maxx) {
+ maxx = x;
+ }
+
+ c.add (x, y);
+ }
+
+
+ float foo[1024];
+
+ c.get_vector (minx, maxx, foo, 1024);
+
+ for (int i = 0; i < 1024; ++i) {
+ cout << minx + (((double) i / 1024.0) * (maxx - minx)) << ' ' << foo[i] << endl;
+ }
+
+ return 0;
+}
diff --git a/gtk2_ardour/default_keys.cc b/gtk2_ardour/default_keys.cc
new file mode 100644
index 0000000000..d8b9a2ae9e
--- /dev/null
+++ b/gtk2_ardour/default_keys.cc
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 1999 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gtk--.h>
+#include <sigc++/bind.h>
+#include <pbd/error.h>
+
+#include "ardour_ui.h"
+#include "keyboard_target.h"
+
+using namespace ARDOUR;
+using namespace Gtkmmext;
+using namespace Gtk;
+using namespace SigC;
+
+void
+ARDOUR_UI::install_keybindings ()
+{
+ KeyboardTarget::add_action ("start-prefix", slot (*this, &ARDOUR_UI::start_keyboard_prefix));
+
+ KeyboardTarget::add_action ("toggle-editor-window", slot (*this, &ARDOUR_UI::goto_editor_window));
+ KeyboardTarget::add_action ("toggle-mixer-window", slot (*this, &ARDOUR_UI::goto_mixer_window));
+ KeyboardTarget::add_action ("toggle-locations-window", slot (*this, &ARDOUR_UI::toggle_location_window));
+ KeyboardTarget::add_action ("toggle-big-clock-window", slot (*this, &ARDOUR_UI::toggle_big_clock_window));
+ KeyboardTarget::add_action ("toggle-options-window", slot (*this, &ARDOUR_UI::toggle_options_window));
+ KeyboardTarget::add_action ("toggle-auto-loop", slot (*this, &ARDOUR_UI::toggle_session_auto_loop));
+ KeyboardTarget::add_action ("toggle-punch-in", slot (*this, &ARDOUR_UI::toggle_session_punch_in));
+
+ KeyboardTarget::add_action ("new-session", bind (slot (*this, &ARDOUR_UI::new_session), false, string()));
+ KeyboardTarget::add_action ("add-audio-track", bind (slot (*this, &ARDOUR_UI::session_add_audio_track), 1, 1));
+ KeyboardTarget::add_action ("add-audio-bus", bind (slot (*this, &ARDOUR_UI::session_add_audio_bus), 1, 1));
+
+ KeyboardTarget::add_action ("save-state", bind (slot (*this, &ARDOUR_UI::save_state), string ("")));
+ KeyboardTarget::add_action ("quit", (slot (*this, &ARDOUR_UI::finish)));
+
+ KeyboardTarget::add_action ("remove-last-capture", slot (*this, &ARDOUR_UI::remove_last_capture));
+
+ KeyboardTarget::add_action ("transport-stop", slot (*this, &ARDOUR_UI::transport_stop));
+ KeyboardTarget::add_action ("transport-stop-and-forget-capture", slot (*this, &ARDOUR_UI::transport_stop_and_forget_capture));
+ KeyboardTarget::add_action ("transport-roll", slot (*this, &ARDOUR_UI::transport_roll));
+ KeyboardTarget::add_action ("transport-loop", slot (*this, &ARDOUR_UI::transport_loop));
+ KeyboardTarget::add_action ("transport-record", slot (*this, &ARDOUR_UI::transport_record));
+ KeyboardTarget::add_action ("transport-rewind", bind (slot (*this, &ARDOUR_UI::transport_rewind), 0));
+ KeyboardTarget::add_action ("transport-rewind-slow", bind (slot (*this, &ARDOUR_UI::transport_rewind), -1));
+ KeyboardTarget::add_action ("transport-rewind-fast", bind (slot (*this, &ARDOUR_UI::transport_rewind), 1));
+ KeyboardTarget::add_action ("transport-forward", bind (slot (*this, &ARDOUR_UI::transport_forward), 0));
+ KeyboardTarget::add_action ("transport-forward-slow", bind (slot (*this, &ARDOUR_UI::transport_forward), -1));
+ KeyboardTarget::add_action ("transport-forward-fast", bind (slot (*this, &ARDOUR_UI::transport_forward), 1));
+
+ KeyboardTarget::add_action ("transport-goto-start", slot (*this, &ARDOUR_UI::transport_goto_start));
+ KeyboardTarget::add_action ("transport-goto-end", slot (*this, &ARDOUR_UI::transport_goto_end));
+
+ KeyboardTarget::add_action ("send-all-midi-feedback", slot (*this, &ARDOUR_UI::send_all_midi_feedback));
+
+ KeyboardTarget::add_action ("toggle-record-enable-track1", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 0U));
+ KeyboardTarget::add_action ("toggle-record-enable-track2", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 1U));
+ KeyboardTarget::add_action ("toggle-record-enable-track3", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 2U));
+ KeyboardTarget::add_action ("toggle-record-enable-track4", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 3U));
+ KeyboardTarget::add_action ("toggle-record-enable-track5", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 4U));
+ KeyboardTarget::add_action ("toggle-record-enable-track6", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 5U));
+ KeyboardTarget::add_action ("toggle-record-enable-track7", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 6U));
+ KeyboardTarget::add_action ("toggle-record-enable-track8", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 7U));
+ KeyboardTarget::add_action ("toggle-record-enable-track9", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 8U));
+ KeyboardTarget::add_action ("toggle-record-enable-track10", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 9U));
+ KeyboardTarget::add_action ("toggle-record-enable-track11", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 10U));
+ KeyboardTarget::add_action ("toggle-record-enable-track12", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 11U));
+ KeyboardTarget::add_action ("toggle-record-enable-track13", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 12U));
+ KeyboardTarget::add_action ("toggle-record-enable-track14", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 13U));
+ KeyboardTarget::add_action ("toggle-record-enable-track15", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 14U));
+ KeyboardTarget::add_action ("toggle-record-enable-track16", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 15U));
+ KeyboardTarget::add_action ("toggle-record-enable-track17", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 16U));
+ KeyboardTarget::add_action ("toggle-record-enable-track18", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 17U));
+ KeyboardTarget::add_action ("toggle-record-enable-track19", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 18U));
+ KeyboardTarget::add_action ("toggle-record-enable-track20", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 19U));
+ KeyboardTarget::add_action ("toggle-record-enable-track21", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 20U));
+ KeyboardTarget::add_action ("toggle-record-enable-track22", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 21U));
+ KeyboardTarget::add_action ("toggle-record-enable-track23", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 22U));
+ KeyboardTarget::add_action ("toggle-record-enable-track24", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 23U));
+ KeyboardTarget::add_action ("toggle-record-enable-track25", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 24U));
+ KeyboardTarget::add_action ("toggle-record-enable-track26", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 25U));
+ KeyboardTarget::add_action ("toggle-record-enable-track27", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 26U));
+ KeyboardTarget::add_action ("toggle-record-enable-track28", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 27U));
+ KeyboardTarget::add_action ("toggle-record-enable-track29", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 28U));
+ KeyboardTarget::add_action ("toggle-record-enable-track30", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 29U));
+ KeyboardTarget::add_action ("toggle-record-enable-track31", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 30U));
+ KeyboardTarget::add_action ("toggle-record-enable-track32", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 31U));
+
+#if 0
+ ADD ME TO ARDOUR RC SOMEDAY
+ add_binding ("Shift-F1",, bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 0+12U));
+ add_binding ("Control-F1",, bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 0+24U));
+ add_binding ("Alt-F1",, bind (slot (*this, &ARDOUR_UI::toggle_monitor_enable), 0U));
+ add_binding ("Alt-Shift-F1",, bind (slot (*this, &ARDOUR_UI::toggle_monitor_enable), 0+12U));
+ add_binding ("Alt-Control-F1",, bind (slot (*this, &ARDOUR_UI::toggle_monitor_enable), 0+24U));
+#endif
+}
diff --git a/gtk2_ardour/editing.cc b/gtk2_ardour/editing.cc
new file mode 100644
index 0000000000..672c1ab741
--- /dev/null
+++ b/gtk2_ardour/editing.cc
@@ -0,0 +1,104 @@
+#include <string>
+
+#include "editing.h"
+
+using namespace std;
+
+// This involves some cpp magic. --taybin
+
+#define SNAPTYPE(a) /*empty*/
+#define SNAPMODE(a) /*empty*/
+#define REGIONLISTSORTTYPE(a) /*empty*/
+#define MOUSEMODE(a) /*empty*/
+#define ZOOMFOCUS(a) /*empty*/
+#define DISPLAYCONTROL(a) /*empty*/
+
+namespace Editing {
+
+// SNAPTYPE
+#undef SNAPTYPE
+#define SNAPTYPE(s) if (!strcmp(type, #s)) {return s;}
+SnapType
+str2snaptype (string str) {
+ const char* type = str.c_str();
+ #include "editing_syms.h"
+ return SnapToBar;
+}
+#undef SNAPTYPE
+#define SNAPTYPE(a) /*empty*/
+
+// SNAPMODE
+#undef SNAPMODE
+#define SNAPMODE(s) if (!strcmp(type, #s)) {return s;}
+SnapMode
+str2snapmode (string str) {
+ const char* type = str.c_str();
+ #include "editing_syms.h"
+ return SnapNormal;
+}
+#undef SNAPMODE
+#define SNAPMODE(a) /*empty*/
+
+// REGIONLISTSORTTYPE
+#undef REGIONLISTSORTTYPE
+#define REGIONLISTSORTTYPE(s) if (!strcmp(type, #s)) {return s;}
+RegionListSortType
+str2regionlistsorttype (string str) {
+ const char* type = str.c_str();
+ #include "editing_syms.h"
+ return ByName;
+}
+#undef REGIONLISTSORTTYPE
+#define REGIONLISTSORTTYPE(a) /*empty*/
+
+// MOUSEMODE
+#undef MOUSEMODE
+#define MOUSEMODE(s) if (!strcmp(type, #s)) {return s;}
+MouseMode
+str2mousemode (string str) {
+ const char* type = str.c_str();
+ #include "editing_syms.h"
+ return MouseObject;
+}
+#undef MOUSEMODE
+#define MOUSEMODE(a) /*empty*/
+
+// ZOOMFOCUS
+#undef ZOOMFOCUS
+#define ZOOMFOCUS(s) if (!strcmp(type, #s)) {return s;}
+ZoomFocus
+str2zoomfocus (string str) {
+ const char* type = str.c_str();
+ #include "editing_syms.h"
+ return ZoomFocusPlayhead;
+}
+#undef ZOOMFOCUS
+#define ZOOMFOCUS(a) /*empty*/
+
+// DISPLAYCONTROL
+#undef DISPLAYCONTROL
+#define DISPLAYCONTROL(s) if (!strcmp(type, #s)) {return s;}
+DisplayControl
+str2displaycontrol (string str) {
+ const char* type = str.c_str();
+ #include "editing_syms.h"
+ return FollowPlayhead;
+}
+#undef DISPLAYCONTROL
+#define DISPLAYCONTROL(a) /*empty*/
+
+// COLORID
+#undef COLORID
+#define COLORID(s) if (!strcmp(type, #s)) {return s;}
+ColorID
+str2color_id (string str) {
+ const char* type = str.c_str();
+ #include "editing_syms.h"
+ return cFrameHandleEndOutline;
+}
+#undef COLORID
+#define COLORID(a) /*empty*/
+
+ColorMap color_map;
+
+} // namespace Editing
diff --git a/gtk2_ardour/editing.h b/gtk2_ardour/editing.h
new file mode 100644
index 0000000000..2b95073ef7
--- /dev/null
+++ b/gtk2_ardour/editing.h
@@ -0,0 +1,170 @@
+#ifndef __gtk_ardour_editing_h__
+#define __gtk_ardour_editing_h__
+
+#include <string>
+#include <map>
+
+// This involves some cpp magic. --taybin
+
+#define SNAPTYPE(a) /*empty*/
+#define SNAPMODE(a) /*empty*/
+#define REGIONLISTSORTTYPE(a) /*empty*/
+#define MOUSEMODE(a) /*empty*/
+#define ZOOMFOCUS(a) /*empty*/
+#define DISPLAYCONTROL(a) /*empty*/
+#define COLORID(a) /*empty*/
+
+namespace Editing {
+
+// SNAPTYPE
+#undef SNAPTYPE
+#define SNAPTYPE(a) a,
+enum SnapType {
+ #include "editing_syms.h"
+};
+
+#undef SNAPTYPE
+#define SNAPTYPE(s) #s,
+static const char *snaptypestrs[] = {
+ #include "editing_syms.h"
+};
+inline const char* enum2str(SnapType m) {return snaptypestrs[m];}
+SnapType str2snaptype(std::string);
+
+#undef SNAPTYPE
+#define SNAPTYPE(a) /*empty*/
+
+// SNAPMODE
+#undef SNAPMODE
+#define SNAPMODE(a) a,
+enum SnapMode {
+ #include "editing_syms.h"
+};
+
+#undef SNAPMODE
+#define SNAPMODE(s) #s,
+static const char *snapmodestrs[] = {
+ #include "editing_syms.h"
+};
+inline const char* enum2str(SnapMode m) {return snapmodestrs[m];}
+SnapMode str2snapmode(std::string);
+
+#undef SNAPMODE
+#define SNAPMODE(a) /*empty*/
+
+// REGIONLISTSORTTYPE
+#undef REGIONLISTSORTTYPE
+#define REGIONLISTSORTTYPE(a) a,
+enum RegionListSortType {
+ #include "editing_syms.h"
+};
+
+#undef REGIONLISTSORTTYPE
+#define REGIONLISTSORTTYPE(s) #s,
+static const char *regionlistsorttypestrs[] = {
+ #include "editing_syms.h"
+};
+inline const char* enum2str(RegionListSortType m) {return regionlistsorttypestrs[m];}
+RegionListSortType str2regionlistsorttype(std::string);
+
+#undef REGIONLISTSORTTYPE
+#define REGIONLISTSORTTYPE(a) /*empty*/
+
+// MOUSEMODE
+#undef MOUSEMODE
+#define MOUSEMODE(a) a,
+enum MouseMode {
+ #include "editing_syms.h"
+};
+
+#undef MOUSEMODE
+#define MOUSEMODE(s) #s,
+static const char *mousemodestrs[] = {
+ #include "editing_syms.h"
+};
+inline const char* enum2str(MouseMode m) {return mousemodestrs[m];}
+MouseMode str2mousemode(std::string);
+
+#undef MOUSEMODE
+#define MOUSEMODE(a) /*empty*/
+
+// ZOOMFOCUS
+#undef ZOOMFOCUS
+#define ZOOMFOCUS(a) a,
+enum ZoomFocus {
+ #include "editing_syms.h"
+};
+
+#undef ZOOMFOCUS
+#define ZOOMFOCUS(s) #s,
+static const char *zoomfocusstrs[] = {
+ #include "editing_syms.h"
+};
+inline const char* enum2str(ZoomFocus m) {return zoomfocusstrs[m];}
+ZoomFocus str2zoomfocus(std::string);
+
+#undef ZOOMFOCUS
+#define ZOOMFOCUS(a) /*empty*/
+
+// DISPLAYCONTROL
+#undef DISPLAYCONTROL
+#define DISPLAYCONTROL(a) a,
+enum DisplayControl {
+ #include "editing_syms.h"
+};
+
+#undef DISPLAYCONTROL
+#define DISPLAYCONTROL(s) #s,
+static const char *displaycontrolstrs[] = {
+ #include "editing_syms.h"
+};
+inline const char* enum2str(DisplayControl m) {return displaycontrolstrs[m];}
+DisplayControl str2displaycontrol (std::string);
+
+#undef DISPLAYCONTROL
+#define DISPLAYCONTROL(a) /*empty*/
+
+#undef COLORID
+#define COLORID(a) a,
+enum ColorID {
+ #include "editing_syms.h"
+};
+
+#undef COLORID
+#define COLORID(s) #s,
+static const char *color_id_strs[] = {
+ #include "editing_syms.h"
+};
+inline const char* enum2str(ColorID m) {return color_id_strs[m];}
+ColorID str2color_id (std::string);
+
+#undef COLORID
+#define COLORID(a) /*empty*/
+
+/////////////////////
+// These don't need their state saved. yet...
+enum CutCopyOp {
+ Cut,
+ Copy,
+ Clear
+};
+
+enum XFadeType {
+ Pre,
+ Post,
+ At
+};
+
+struct Color {
+ char r;
+ char g;
+ char b;
+ char a;
+};
+
+typedef std::map<Editing::ColorID,int> ColorMap;
+extern ColorMap color_map;
+
+} // namespace Editing
+
+#endif // __gtk_ardour_editing_h__
diff --git a/gtk2_ardour/editing_syms.h b/gtk2_ardour/editing_syms.h
new file mode 100644
index 0000000000..3037daa3e2
--- /dev/null
+++ b/gtk2_ardour/editing_syms.h
@@ -0,0 +1,157 @@
+/* Changing this order will break the menu */
+SNAPTYPE(SnapToFrame)
+SNAPTYPE(SnapToCDFrame)
+SNAPTYPE(SnapToSMPTEFrame)
+SNAPTYPE(SnapToSMPTESeconds)
+SNAPTYPE(SnapToSMPTEMinutes)
+SNAPTYPE(SnapToSeconds)
+SNAPTYPE(SnapToMinutes)
+SNAPTYPE(SnapToAThirtysecondBeat)
+SNAPTYPE(SnapToASixteenthBeat)
+SNAPTYPE(SnapToAEighthBeat)
+SNAPTYPE(SnapToAQuarterBeat)
+SNAPTYPE(SnapToAThirdBeat)
+SNAPTYPE(SnapToBeat)
+SNAPTYPE(SnapToBar)
+SNAPTYPE(SnapToMark)
+SNAPTYPE(SnapToEditCursor)
+SNAPTYPE(SnapToRegionStart)
+SNAPTYPE(SnapToRegionEnd)
+SNAPTYPE(SnapToRegionSync)
+SNAPTYPE(SnapToRegionBoundary)
+
+/* Changing this order will break the menu */
+SNAPMODE(SnapNormal)
+SNAPMODE(SnapMagnetic)
+
+REGIONLISTSORTTYPE(ByEndInFile)
+REGIONLISTSORTTYPE(ByLength)
+REGIONLISTSORTTYPE(ByName)
+REGIONLISTSORTTYPE(ByPosition)
+REGIONLISTSORTTYPE(BySourceFileCreationDate)
+REGIONLISTSORTTYPE(BySourceFileFS)
+REGIONLISTSORTTYPE(BySourceFileLength)
+REGIONLISTSORTTYPE(BySourceFileName)
+REGIONLISTSORTTYPE(ByStartInFile)
+REGIONLISTSORTTYPE(ByTimestamp)
+
+MOUSEMODE(MouseGain)
+MOUSEMODE(MouseObject)
+MOUSEMODE(MouseRange)
+MOUSEMODE(MouseTimeFX)
+MOUSEMODE(MouseZoom)
+MOUSEMODE(MouseAudition)
+
+/* Changing this order will break the menu */
+ZOOMFOCUS(ZoomFocusLeft)
+ZOOMFOCUS(ZoomFocusRight)
+ZOOMFOCUS(ZoomFocusCenter)
+ZOOMFOCUS(ZoomFocusPlayhead)
+ZOOMFOCUS(ZoomFocusEdit)
+
+DISPLAYCONTROL(FollowPlayhead)
+DISPLAYCONTROL(ShowMeasures)
+DISPLAYCONTROL(ShowWaveforms)
+DISPLAYCONTROL(ShowWaveformsRecording)
+
+COLORID(cWaveForm)
+COLORID(cMutedWaveForm)
+COLORID(cSelectedFrameBase)
+COLORID(cFrameBase)
+COLORID(cAudioTrackBase)
+COLORID(cAudioTrackOutline)
+COLORID(cAudioBusBase)
+COLORID(cTimeStretchFill)
+COLORID(cTimeStretchOutline)
+COLORID(cAutomationLine)
+COLORID(cLeftPanAutomationLine)
+COLORID(cRightPanAutomationLine)
+COLORID(cRedirectAutomationLine)
+COLORID(cControlPointFill)
+COLORID(cControlPointOutline)
+COLORID(cEnteredControlPointOutline)
+COLORID(cEnteredControlPointSelected)
+COLORID(cEnteredControlPoint)
+COLORID(cControlPointSelected)
+COLORID(cControlPoint)
+COLORID(cAutomationTrackFill)
+COLORID(cAutomationTrackOutline)
+COLORID(cCrossfadeEditorBase)
+COLORID(cCrossfadeEditorLine)
+COLORID(cSelectedCrossfadeEditorLine)
+COLORID(cCrossfadeEditorLineShading)
+COLORID(cCrossfadeEditorPointFill)
+COLORID(cCrossfadeEditorPointOutline)
+COLORID(cCrossfadeEditorWave)
+COLORID(cSelectedCrossfadeEditorWave)
+COLORID(cCrossfadeLine)
+COLORID(cActiveCrossfade)
+COLORID(cInactiveCrossfade)
+COLORID(cLocationMarker)
+COLORID(cLocationRange)
+COLORID(cLocationCDMarker)
+COLORID(cLocationLoop)
+COLORID(cLocationPunch)
+COLORID(cVerboseCanvasCursor)
+COLORID(cTempoBar)
+COLORID(cMeterBar)
+COLORID(cMarkerBar)
+COLORID(cRangeMarkerBar)
+COLORID(cTransportMarkerBar)
+COLORID(cRangeDragBarRect)
+COLORID(cRangeDragBarRectFill)
+COLORID(cRangeDragRect)
+COLORID(cRangeDragRectFill)
+COLORID(cTransportDragRect)
+COLORID(cTransportDragRectFill)
+COLORID(cMarkerDragLine)
+COLORID(cTransportLoopRect)
+COLORID(cTransportLoopRectFill)
+COLORID(cTransportPunchRect)
+COLORID(cTransportPunchRectFill)
+COLORID(cPunchInLine)
+COLORID(cPunchOutLine)
+COLORID(cZoomRect)
+COLORID(cZoomRectFill)
+COLORID(cRubberBandRect)
+COLORID(cRubberBandRectFill)
+COLORID(cFirstActionMessage)
+COLORID(cEnteredGainLine)
+COLORID(cEnteredAutomationLine)
+COLORID(cEnteredMarker)
+COLORID(cMeterMarker)
+COLORID(cTempoMarker)
+COLORID(cMeasureLineBeat)
+COLORID(cMeasureLineBar)
+COLORID(cGhostTrackBaseOutline)
+COLORID(cGhostTrackBaseFill)
+COLORID(cGhostTrackWave)
+COLORID(cImageTrackBase)
+COLORID(cImageTrackOutline)
+COLORID(cMarkerTrackBase)
+COLORID(cMarkerTrackOutline)
+COLORID(cZeroLine)
+COLORID(cGainLine)
+COLORID(cGainLineInactive)
+COLORID(cRecordingRectFill)
+COLORID(cRecordingRectOutline)
+COLORID(cSelectionRectFill)
+COLORID(cSelectionRectOutline)
+COLORID(cSelectionEndFill)
+COLORID(cSelectionEndOutline)
+COLORID(cSelectionStartFill)
+COLORID(cSelectionStartOutline)
+COLORID(cVestigialFrameFill)
+COLORID(cVestigialFrameOutline)
+COLORID(cTimeAxisFrameFill)
+COLORID(cTimeAxisFrameOutline)
+COLORID(cNameHighlightFill)
+COLORID(cNameHighlightOutline)
+COLORID(cFrameHandleStartFill)
+COLORID(cFrameHandleStartOutline)
+COLORID(cFrameHandleEndFill)
+COLORID(cFrameHandleEndOutline)
+COLORID(cTrimHandleLockedStart)
+COLORID(cTrimHandleLockedEnd)
+COLORID(cTrimHandleStart)
+COLORID(cTrimHandleEnd)
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
new file mode 100644
index 0000000000..2bd016e8b7
--- /dev/null
+++ b/gtk2_ardour/editor.cc
@@ -0,0 +1,4655 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <unistd.h>
+#include <cstdlib>
+#include <cmath>
+#include <string>
+#include <algorithm>
+
+#include <sigc++/bind.h>
+
+#include <gtk-canvas.h>
+#include <pbd/error.h>
+
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/tearoff.h>
+#include <gtkmmext/utils.h>
+
+#include <ardour/audio_track.h>
+#include <ardour/diskstream.h>
+#include <ardour/plugin_manager.h>
+#include <ardour/location.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/audioregion.h>
+#include <ardour/session.h>
+#include <ardour/session_route.h>
+#include <ardour/tempo.h>
+#include <ardour/utils.h>
+
+#include "ardour_ui.h"
+#include "canvas-ruler.h"
+#include "canvas-simpleline.h"
+#include "canvas-simplerect.h"
+#include "canvas-waveview.h"
+#include "check_mark.h"
+#include "editor.h"
+#include "grouped_buttons.h"
+#include "keyboard.h"
+#include "library_ui.h"
+#include "marker.h"
+#include "playlist_selector.h"
+#include "regionview.h"
+#include "rgb_macros.h"
+#include "selection.h"
+#include "streamview.h"
+#include "time_axis_view.h"
+#include "utils.h"
+#include "crossfade_view.h"
+#include "editing.h"
+#include "public_editor.h"
+#include "crossfade_edit.h"
+#include "extra_bind.h"
+#include "audio_time_axis.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+/* <CMT Additions> */
+#include "imageframe_socket_handler.h"
+/* </CMT Additions> */
+
+using namespace std;
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+using namespace Editing;
+
+/* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */
+
+const double max_canvas_coordinate = 100000000.0;
+const double Editor::timebar_height = 15.0;
+
+#include "editor_xpms"
+
+static const gchar *route_list_titles[] = {
+ N_("Tracks"),
+ 0
+};
+
+static const gchar *edit_group_list_titles[] = {
+ "foo", "bar", 0
+};
+
+static const gchar *region_list_display_titles[] = {
+ N_("Regions/name"),
+ 0
+};
+
+static const gchar *named_selection_display_titles[] = {
+ N_("Chunks"),
+ 0
+};
+
+static const int32_t slide_index = 0;
+static const int32_t splice_index = 1;
+
+static const gchar *edit_mode_strings[] = {
+ N_("Slide"),
+ N_("Splice"),
+ 0
+};
+
+static const gchar *snap_type_strings[] = {
+ N_("None"),
+ N_("CD Frames"),
+ N_("SMPTE Frames"),
+ N_("SMPTE Seconds"),
+ N_("SMPTE Minutes"),
+ N_("Seconds"),
+ N_("Minutes"),
+ N_("Beats/32"),
+ N_("Beats/16"),
+ N_("Beats/8"),
+ N_("Beats/4"),
+ N_("Beats/3"),
+ N_("Beats"),
+ N_("Bars"),
+ N_("Marks"),
+ N_("Edit Cursor"),
+ N_("Region starts"),
+ N_("Region ends"),
+ N_("Region syncs"),
+ N_("Region bounds"),
+ 0
+};
+
+static const gchar *snap_mode_strings[] = {
+ N_("Normal"),
+ N_("Magnetic"),
+ 0
+};
+
+static const gchar *zoom_focus_strings[] = {
+ N_("Left"),
+ N_("Right"),
+ N_("Center"),
+ N_("Playhead"),
+ N_("Edit Cursor"),
+ 0
+};
+
+/* Soundfile drag-n-drop */
+
+enum {
+ TARGET_STRING,
+ TARGET_ROOTWIN,
+ TARGET_URL
+};
+
+static GtkTargetEntry target_table[] = {
+ { "STRING", 0, TARGET_STRING },
+ { "text/plain", 0, TARGET_STRING },
+ { "text/uri-list", 0, TARGET_URL },
+ { "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
+};
+
+static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
+
+GdkCursor* Editor::cross_hair_cursor = 0;
+GdkCursor* Editor::selector_cursor = 0;
+GdkCursor* Editor::trimmer_cursor = 0;
+GdkCursor* Editor::grabber_cursor = 0;
+GdkCursor* Editor::zoom_cursor = 0;
+GdkCursor* Editor::time_fx_cursor = 0;
+GdkCursor* Editor::fader_cursor = 0;
+GdkCursor* Editor::speaker_cursor = 0;
+GdkCursor* Editor::null_cursor = 0;
+GdkCursor* Editor::wait_cursor = 0;
+GdkCursor* Editor::timebar_cursor = 0;
+
+GdkPixmap *Editor::check_pixmap = 0;
+GdkBitmap *Editor::check_mask = 0;
+GdkPixmap *Editor::empty_pixmap = 0;
+GdkBitmap *Editor::empty_mask = 0;
+
+extern gint route_list_compare_func (GtkCList*,gconstpointer,gconstpointer);
+
+Editor::Editor (AudioEngine& eng)
+ : engine (eng),
+
+ /* time display buttons */
+
+ minsec_label (_("Mins:Secs")),
+ bbt_label (_("Bars:Beats")),
+ smpte_label (_("SMPTE")),
+ frame_label (_("Frames")),
+ tempo_label (_("Tempo")),
+ meter_label (_("Meter")),
+ mark_label (_("Location Markers")),
+ range_mark_label (_("Range Markers")),
+ transport_mark_label (_("Loop/Punch Ranges")),
+
+ edit_packer (3, 3, false),
+ edit_hscroll_left_arrow (GTK_ARROW_LEFT, GTK_SHADOW_OUT),
+ edit_hscroll_right_arrow (GTK_ARROW_RIGHT, GTK_SHADOW_OUT),
+
+ region_list_display (internationalize (region_list_display_titles)),
+
+ named_selection_display (internationalize (named_selection_display_titles)),
+
+ /* tool bar related */
+
+ editor_mixer_button (_("editor\nmixer")),
+
+ selection_start_clock (X_("SelectionStartClock"), true),
+ selection_end_clock (X_("SelectionEndClock"), true),
+ edit_cursor_clock (X_("EditCursorClock"), true),
+ zoom_range_clock (X_("ZoomRangeClock"), true, true),
+
+ toolbar_selection_clock_table (2,3),
+
+ mouse_mode_button_table (2, 3),
+
+ mouse_select_button (_("range")),
+ mouse_move_button (_("object")),
+ mouse_gain_button (_("gain")),
+ mouse_zoom_button (_("zoom")),
+ mouse_timefx_button (_("timefx")),
+ mouse_audition_button (_("listen")),
+
+ automation_mode_button (_("mode")),
+ global_automation_button (_("automation")),
+
+ edit_mode_label (_("Edit Mode")),
+ snap_type_label (_("Snap To")),
+ snap_mode_label(_("Snap Mode")),
+ zoom_focus_label (_("Zoom Focus")),
+
+ route_list (internationalize (route_list_titles)),
+ edit_group_list (internationalize (edit_group_list_titles)),
+
+ /* <CMT Additions> */
+ image_socket_listener(0),
+ /* </CMT Additions> */
+
+ /* nudge */
+
+ nudge_label (_("Nudge")),
+ nudge_clock (X_("NudgeClock"), true, true)
+
+{
+ constructed = false;
+
+ /* we are a singleton */
+
+ PublicEditor::_instance = this;
+
+ init_colormap ();
+
+ check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
+ gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gtkobj())),
+ &check_mask, NULL, (gchar **) check_xpm);
+ empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
+ gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gtkobj())),
+ &empty_mask, NULL, (gchar **) empty_xpm);
+
+ session = 0;
+
+ selection = new Selection;
+ cut_buffer = new Selection;
+
+ selection->TimeChanged.connect (slot (*this, &Editor::time_selection_changed));
+ selection->TracksChanged.connect (slot (*this, &Editor::track_selection_changed));
+ selection->RegionsChanged.connect (slot (*this, &Editor::region_selection_changed));
+ selection->PointsChanged.connect (slot (*this, &Editor::point_selection_changed));
+
+ clicked_regionview = 0;
+ clicked_trackview = 0;
+ clicked_audio_trackview = 0;
+ clicked_crossfadeview = 0;
+ clicked_control_point = 0;
+ latest_regionview = 0;
+ region_list_display_drag_region = 0;
+ last_update_frame = 0;
+ drag_info.item = 0;
+ last_audition_region = 0;
+ region_list_button_region = 0;
+ current_mixer_strip = 0;
+ current_bbt_points = 0;
+
+ snap_type = SnapToFrame;
+ set_snap_to (snap_type);
+ snap_mode = SnapNormal;
+ set_snap_mode (snap_mode);
+ snap_threshold = 5.0;
+ bbt_beat_subdivision = 4;
+ canvas_width = 0;
+ canvas_height = 0;
+ autoscroll_timeout_tag = -1;
+ interthread_progress_window = 0;
+ current_interthread_info = 0;
+ _show_measures = true;
+ _show_waveforms = true;
+ _show_waveforms_recording = true;
+ first_action_message = 0;
+ export_dialog = 0;
+ show_gain_after_trim = false;
+ no_zoom_repos_update = false;
+ need_wave_cursor = 0;
+ ignore_route_list_reorder = false;
+ verbose_cursor_on = true;
+ route_removal = false;
+ track_spacing = 0;
+ show_automatic_regions_in_region_list = true;
+ have_pending_keyboard_selection = false;
+ _follow_playhead = true;
+ _xfade_visibility = true;
+ editor_ruler_menu = 0;
+ no_ruler_shown_update = false;
+ edit_group_list_menu = 0;
+ route_list_menu = 0;
+ region_list_menu = 0;
+ marker_menu = 0;
+ marker_menu_item = 0;
+ tm_marker_menu = 0;
+ transport_marker_menu = 0;
+ new_transport_marker_menu = 0;
+ editor_mixer_strip_width = Wide;
+ repos_zoom_queued = false;
+ import_audio_item = 0;
+ embed_audio_item = 0;
+ region_edit_menu_split_item = 0;
+ temp_location = 0;
+ region_edit_menu_split_multichannel_item = 0;
+ edit_hscroll_dragging = false;
+ leftmost_frame = 0;
+ ignore_mouse_mode_toggle = false;
+ current_stepping_trackview = 0;
+ entered_track = 0;
+ entered_regionview = 0;
+ clear_entered_track = false;
+ _new_regionviews_show_envelope = false;
+ current_timestretch = 0;
+
+ edit_cursor = 0;
+ playhead_cursor = 0;
+
+ location_marker_color = color_map[cLocationMarker];
+ location_range_color = color_map[cLocationRange];
+ location_cd_marker_color = color_map[cLocationCDMarker];
+ location_loop_color = color_map[cLocationLoop];
+ location_punch_color = color_map[cLocationPunch];
+
+ range_marker_drag_rect = 0;
+ marker_drag_line = 0;
+
+ mouse_mode = MouseZoom; /* force change in next call */
+ set_mouse_mode (MouseObject, true);
+
+ frames_per_unit = 2048; /* too early to use set_frames_per_unit */
+ zoom_focus = ZoomFocusLeft;
+ zoom_range_clock.ValueChanged.connect (slot (*this, &Editor::zoom_adjustment_changed));
+
+ initialize_rulers ();
+ initialize_canvas ();
+
+ track_canvas_scroller.add (*track_canvas);
+ track_canvas_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+ track_canvas_scroller.set_name ("TrackCanvasScroller");
+
+ track_canvas_scroller.get_vadjustment()->value_changed.connect (slot (*this, &Editor::tie_vertical_scrolling));
+ track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
+
+ track_canvas_scroller.get_hadjustment()->set_lower (0.0);
+ track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
+ track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
+ track_canvas_scroller.get_hadjustment()->value_changed.connect (slot (*this, &Editor::canvas_horizontally_scrolled));
+
+ edit_vscrollbar.set_adjustment(track_canvas_scroller.get_vadjustment());
+ edit_hscrollbar.set_adjustment(track_canvas_scroller.get_hadjustment());
+
+ edit_hscrollbar.button_press_event.connect (slot (*this, &Editor::hscroll_slider_button_press));
+ edit_hscrollbar.button_release_event.connect (slot (*this, &Editor::hscroll_slider_button_release));
+ edit_hscrollbar.size_allocate.connect (slot (*this, &Editor::hscroll_slider_allocate));
+
+ time_canvas_scroller.add (*time_canvas);
+ time_canvas_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+ time_canvas_scroller.set_hadjustment (track_canvas_scroller.get_hadjustment());
+ time_canvas_scroller.set_name ("TimeCanvasScroller");
+
+ edit_controls_vbox.set_spacing (track_spacing);
+ edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
+ edit_controls_scroller.add_with_viewport (edit_controls_hbox);
+ edit_controls_scroller.set_name ("EditControlsBase");
+ edit_controls_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_NEVER);
+
+ Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
+
+ viewport->set_shadow_type (GTK_SHADOW_NONE);
+ viewport->set_name ("EditControlsBase");
+ viewport->add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK);
+ viewport->button_release_event.connect (slot (*this, &Editor::edit_controls_button_release));
+
+ build_cursors ();
+ setup_toolbar ();
+
+ XMLNode* node = ARDOUR_UI::instance()->editor_settings();
+ set_state (*node);
+
+ edit_cursor_clock.ValueChanged.connect (slot (*this, &Editor::edit_cursor_clock_changed));
+
+ time_canvas_vbox.pack_start (*minsec_ruler, false, false);
+ time_canvas_vbox.pack_start (*smpte_ruler, false, false);
+ time_canvas_vbox.pack_start (*frames_ruler, false, false);
+ time_canvas_vbox.pack_start (*bbt_ruler, false, false);
+ time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
+ time_canvas_vbox.set_usize (-1, (int)(timebar_height * visible_timebars));
+
+ bbt_label.set_name ("EditorTimeButton");
+ bbt_label.set_usize (-1, (int)timebar_height);
+ bbt_label.set_alignment (1.0, 0.5);
+ bbt_label.set_padding (5,0);
+ minsec_label.set_name ("EditorTimeButton");
+ minsec_label.set_usize (-1, (int)timebar_height);
+ minsec_label.set_alignment (1.0, 0.5);
+ minsec_label.set_padding (5,0);
+ smpte_label.set_name ("EditorTimeButton");
+ smpte_label.set_usize (-1, (int)timebar_height);
+ smpte_label.set_alignment (1.0, 0.5);
+ smpte_label.set_padding (5,0);
+ frame_label.set_name ("EditorTimeButton");
+ frame_label.set_usize (-1, (int)timebar_height);
+ frame_label.set_alignment (1.0, 0.5);
+ frame_label.set_padding (5,0);
+ tempo_label.set_name ("EditorTimeButton");
+ tempo_label.set_usize (-1, (int)timebar_height);
+ tempo_label.set_alignment (1.0, 0.5);
+ tempo_label.set_padding (5,0);
+ meter_label.set_name ("EditorTimeButton");
+ meter_label.set_usize (-1, (int)timebar_height);
+ meter_label.set_alignment (1.0, 0.5);
+ meter_label.set_padding (5,0);
+ mark_label.set_name ("EditorTimeButton");
+ mark_label.set_usize (-1, (int)timebar_height);
+ mark_label.set_alignment (1.0, 0.5);
+ mark_label.set_padding (5,0);
+ range_mark_label.set_name ("EditorTimeButton");
+ range_mark_label.set_usize (-1, (int)timebar_height);
+ range_mark_label.set_alignment (1.0, 0.5);
+ range_mark_label.set_padding (5,0);
+ transport_mark_label.set_name ("EditorTimeButton");
+ transport_mark_label.set_usize (-1, (int)timebar_height);
+ transport_mark_label.set_alignment (1.0, 0.5);
+ transport_mark_label.set_padding (5,0);
+
+ time_button_vbox.pack_start (minsec_label, false, false);
+ time_button_vbox.pack_start (smpte_label, false, false);
+ time_button_vbox.pack_start (frame_label, false, false);
+ time_button_vbox.pack_start (bbt_label, false, false);
+ time_button_vbox.pack_start (meter_label, false, false);
+ time_button_vbox.pack_start (tempo_label, false, false);
+ time_button_vbox.pack_start (mark_label, false, false);
+
+ time_button_event_box.add (time_button_vbox);
+
+ time_button_event_box.set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
+ time_button_event_box.set_name ("TimebarLabelBase");
+ time_button_event_box.button_release_event.connect (slot (*this, &Editor::ruler_label_button_release));
+
+ /* these enable us to have a dedicated window (for cursor setting, etc.)
+ for the canvas areas.
+ */
+
+ track_canvas_event_box.add (track_canvas_scroller);
+
+ time_canvas_event_box.add (time_canvas_vbox);
+ time_canvas_event_box.set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK);
+
+
+ edit_packer.set_col_spacings (0);
+ edit_packer.set_row_spacings (0);
+ edit_packer.set_homogeneous (false);
+ edit_packer.set_name ("EditorWindow");
+
+// edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
+// edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+// edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, GTK_FILL, 0, 0, 0);
+ edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+
+ edit_packer.attach (time_button_event_box, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+ edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+
+ edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, GTK_FILL, GTK_FILL|GTK_EXPAND, 0, 0);
+ edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
+ edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, 0, GTK_FILL|GTK_EXPAND, 0, 0);
+
+ edit_frame.set_name ("BaseFrame");
+ edit_frame.set_shadow_type (GTK_SHADOW_IN);
+ edit_frame.add (edit_packer);
+
+ zoom_in_button.set_name ("EditorTimeButton");
+ zoom_out_button.set_name ("EditorTimeButton");
+ ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
+ ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
+
+// zoom_onetoone_button.set_name ("EditorTimeButton");
+ zoom_out_full_button.set_name ("EditorTimeButton");
+// ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
+ ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
+
+ zoom_in_button.add (*(manage (new Gtk::Pixmap (zoom_in_button_xpm))));
+ zoom_out_button.add (*(manage (new Gtk::Pixmap (zoom_out_button_xpm))));
+ zoom_out_full_button.add (*(manage (new Gtk::Pixmap (zoom_out_full_button_xpm))));
+// zoom_onetoone_button.add (*(manage (new Gtk::Pixmap (zoom_onetoone_button_xpm))));
+
+
+ zoom_in_button.clicked.connect (bind (slot (*this, &Editor::temporal_zoom_step), false));
+ zoom_out_button.clicked.connect (bind (slot (*this, &Editor::temporal_zoom_step), true));
+ zoom_out_full_button.clicked.connect (slot (*this, &Editor::temporal_zoom_session));
+// zoom_onetoone_button.clicked.connect (bind (slot (*this, &Editor::temporal_zoom), 1.0));
+
+ zoom_indicator_box.pack_start (zoom_out_button, false, false);
+ zoom_indicator_box.pack_start (zoom_in_button, false, false);
+ zoom_indicator_box.pack_start (zoom_range_clock, false, false);
+// zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
+ zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
+
+ zoom_indicator_label.set_text (_("Zoom Span"));
+ zoom_indicator_label.set_name ("ToolBarLabel");
+
+
+ zoom_indicator_vbox.set_spacing (3);
+ zoom_indicator_vbox.set_border_width (3);
+ zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
+ zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
+
+
+ bottom_hbox.set_border_width (3);
+ bottom_hbox.set_spacing (3);
+
+ route_list.set_name ("TrackListDisplay");
+ route_list.set_usize (75,-1);
+ route_list.column_titles_active();
+ route_list.set_compare_func (route_list_compare_func);
+ route_list.set_shadow_type (GTK_SHADOW_IN);
+ route_list.set_selection_mode (GTK_SELECTION_MULTIPLE);
+ route_list.set_reorderable (true);
+ edit_group_list.set_usize (75, -1);
+
+ route_list_scroller.add (route_list);
+ route_list_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ route_list.select_row.connect (slot (*this, &Editor::route_list_selected));
+ route_list.unselect_row.connect (slot (*this, &Editor::route_list_unselected));
+ route_list.row_move.connect (slot (*this, &Editor::queue_route_list_reordered));
+ route_list.click_column.connect (slot (*this, &Editor::route_list_column_click));
+
+ edit_group_list_button_label.set_text (_("Edit Groups"));
+ edit_group_list_button_label.set_name ("EditGroupTitleButton");
+ edit_group_list_button.add (edit_group_list_button_label);
+ edit_group_list_button.set_name ("EditGroupTitleButton");
+
+ edit_group_list.column_titles_hide();
+ edit_group_list.set_name ("MixerGroupList");
+ edit_group_list.set_shadow_type (GTK_SHADOW_IN);
+ edit_group_list.set_selection_mode (GTK_SELECTION_MULTIPLE);
+ edit_group_list.set_reorderable (false);
+ edit_group_list.set_usize (75, -1);
+ edit_group_list.set_column_auto_resize (0, true);
+ edit_group_list.columns_autosize ();
+
+ edit_group_list_scroller.add (edit_group_list);
+ edit_group_list_scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ edit_group_list_button.clicked.connect (slot (*this, &Editor::edit_group_list_button_clicked));
+ edit_group_list.button_press_event.connect (slot (*this, &Editor::edit_group_list_button_press_event));
+ edit_group_list.select_row.connect (slot (*this, &Editor::edit_group_selected));
+ edit_group_list.unselect_row.connect (slot (*this, &Editor::edit_group_unselected));
+
+ list<string> stupid_list;
+
+ stupid_list.push_back ("*");
+ stupid_list.push_back (_("-all-"));
+
+ edit_group_list.rows().push_back (stupid_list);
+ edit_group_list.rows().back().set_data (0);
+ edit_group_list.rows().back().select();
+
+ edit_group_vbox.pack_start (edit_group_list_button, false, false);
+ edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
+
+ route_list_frame.set_name ("BaseFrame");
+ route_list_frame.set_shadow_type (GTK_SHADOW_IN);
+ route_list_frame.add (route_list_scroller);
+
+ edit_group_list_frame.set_name ("BaseFrame");
+ edit_group_list_frame.set_shadow_type (GTK_SHADOW_IN);
+ edit_group_list_frame.add (edit_group_vbox);
+
+ route_group_vpane.add1 (route_list_frame);
+ route_group_vpane.add2 (edit_group_list_frame);
+
+ list_vpacker.pack_start (route_group_vpane, true, true);
+
+ region_list_hidden_node = region_list_display.rows().end();
+
+ region_list_display.add_events (GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK|GDK_POINTER_MOTION_MASK);
+
+ region_list_display.drag_dest_set (GTK_DEST_DEFAULT_ALL,
+ target_table, n_targets - 1,
+ GdkDragAction (GDK_ACTION_COPY|GDK_ACTION_MOVE));
+ region_list_display.drag_data_received.connect (slot (*this, &Editor::region_list_display_drag_data_received));
+
+ region_list_scroller.add (region_list_display);
+ region_list_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ region_list_display.set_name ("RegionListDisplay");
+ region_list_display.set_usize (100, -1);
+ region_list_display.column_titles_active ();
+ region_list_display.set_selection_mode (GTK_SELECTION_SINGLE);
+
+ region_list_display.set_data ("editor", this);
+ region_list_display.set_compare_func (_region_list_sorter);
+ region_list_sort_type = ByName;
+ reset_region_list_sort_type (region_list_sort_type);
+
+ region_list_display.set_flags (GTK_CAN_FOCUS);
+
+ region_list_display.key_press_event.connect (slot (*this, &Editor::region_list_display_key_press));
+ region_list_display.key_release_event.connect (slot (*this, &Editor::region_list_display_key_release));
+ region_list_display.button_press_event.connect (slot (*this, &Editor::region_list_display_button_press));
+ region_list_display.button_release_event.connect (slot (*this, &Editor::region_list_display_button_release));
+ region_list_display.motion_notify_event.connect (slot (*this, &Editor::region_list_display_motion));
+ region_list_display.enter_notify_event.connect (slot (*this, &Editor::region_list_display_enter_notify));
+ region_list_display.leave_notify_event.connect (slot (*this, &Editor::region_list_display_leave_notify));
+ region_list_display.select_row.connect (slot (*this, &Editor::region_list_display_selected));
+ region_list_display.unselect_row.connect (slot (*this, &Editor::region_list_display_unselected));
+ region_list_display.click_column.connect (slot (*this, &Editor::region_list_column_click));
+
+ named_selection_scroller.add (named_selection_display);
+ named_selection_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ named_selection_display.set_name ("RegionListDisplay");
+ named_selection_display.set_usize (100, -1);
+ named_selection_display.column_titles_active ();
+ named_selection_display.set_selection_mode (GTK_SELECTION_SINGLE);
+
+ named_selection_display.button_press_event.connect (slot (*this, &Editor::named_selection_display_button_press));
+ named_selection_display.select_row.connect (slot (*this, &Editor::named_selection_display_selected));
+ named_selection_display.unselect_row.connect (slot (*this, &Editor::named_selection_display_unselected));
+
+ region_selection_vpane.pack1 (region_list_scroller, true, true);
+ region_selection_vpane.pack2 (named_selection_scroller, true, true);
+
+ canvas_region_list_pane.pack1 (edit_frame, true, true);
+ canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
+
+ track_list_canvas_pane.size_allocate.connect_after (bind (slot (*this, &Editor::pane_allocation_handler),
+ static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
+ canvas_region_list_pane.size_allocate.connect_after (bind (slot (*this, &Editor::pane_allocation_handler),
+ static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
+ route_group_vpane.size_allocate.connect_after (bind (slot (*this, &Editor::pane_allocation_handler),
+ static_cast<Gtk::Paned*> (&route_group_vpane)));
+ region_selection_vpane.size_allocate.connect_after (bind (slot (*this, &Editor::pane_allocation_handler),
+ static_cast<Gtk::Paned*> (&region_selection_vpane)));
+
+ track_list_canvas_pane.pack1 (list_vpacker, true, true);
+ track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
+
+ /* provide special pane-handle event handling for easy "hide" action */
+
+ /* 0: collapse to show left/upper child
+ 1: collapse to show right/lower child
+ */
+
+ route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
+ region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
+ canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
+ track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
+
+ route_group_vpane.button_release_event.connect (bind (slot (pane_handler), static_cast<Paned*> (&route_group_vpane)));
+ region_selection_vpane.button_release_event.connect (bind (slot (pane_handler), static_cast<Paned*> (&region_selection_vpane)));
+ canvas_region_list_pane.button_release_event.connect (bind (slot (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
+ track_list_canvas_pane.button_release_event.connect (bind (slot (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
+
+ top_hbox.pack_start (toolbar_frame, true, true);
+
+ HBox *hbox = manage (new HBox);
+ hbox->pack_start (track_list_canvas_pane, true, true);
+
+ global_vpacker.pack_start (top_hbox, false, false);
+ global_vpacker.pack_start (*hbox, true, true);
+
+ global_hpacker.pack_start (global_vpacker, true, true);
+
+ set_name ("EditorWindow");
+
+ vpacker.pack_end (global_hpacker, true, true);
+
+ _playlist_selector = new PlaylistSelector();
+ _playlist_selector->delete_event.connect (bind (slot (just_hide_it), static_cast<Window *> (_playlist_selector)));
+
+ AudioRegionView::AudioRegionViewGoingAway.connect (slot (*this, &Editor::catch_vanishing_audio_regionview));
+
+ /* nudge stuff */
+
+ nudge_forward_button.add (*(manage (new Gtk::Pixmap (right_arrow_xpm))));
+ nudge_backward_button.add (*(manage (new Gtk::Pixmap (left_arrow_xpm))));
+
+ ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
+ ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
+
+ nudge_forward_button.set_name ("TransportButton");
+ nudge_backward_button.set_name ("TransportButton");
+
+ fade_context_menu.set_name ("ArdourContextMenu");
+
+ install_keybindings ();
+
+ set_title (_("ardour: editor"));
+ set_wmclass (_("ardour_editor"), "Ardour");
+
+ add (vpacker);
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ configure_event.connect (slot (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
+ delete_event.connect (slot (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
+
+ constructed = true;
+ instant_save ();
+}
+
+Editor::~Editor()
+{
+ /* <CMT Additions> */
+ if(image_socket_listener)
+ {
+ if(image_socket_listener->is_connected())
+ {
+ image_socket_listener->close_connection() ;
+ }
+
+ delete image_socket_listener ;
+ image_socket_listener = 0 ;
+ }
+ /* </CMT Additions> */
+}
+
+void
+Editor::add_toplevel_controls (Container& cont)
+{
+ vpacker.pack_start (cont, false, false);
+ cont.show_all ();
+}
+
+void
+Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
+{
+ /* note: the selection will take care of the vanishing
+ audioregionview by itself.
+ */
+
+ if (clicked_regionview == rv) {
+ clicked_regionview = 0;
+ }
+
+ if (entered_regionview == rv) {
+ set_entered_regionview (0);
+ }
+}
+
+void
+Editor::set_entered_regionview (AudioRegionView* rv)
+{
+ if (rv == entered_regionview) {
+ return;
+ }
+
+ if (entered_regionview) {
+ entered_regionview->exited ();
+ }
+
+ if ((entered_regionview = rv) != 0) {
+ entered_regionview->entered ();
+ }
+}
+
+void
+Editor::set_entered_track (TimeAxisView* tav)
+{
+ if (entered_track) {
+ entered_track->exited ();
+ }
+
+ if ((entered_track = tav) != 0) {
+ entered_track->entered ();
+ }
+}
+
+gint
+Editor::left_track_canvas (GdkEventCrossing *ev)
+{
+ set_entered_track (0);
+ set_entered_regionview (0);
+ return FALSE;
+}
+
+
+void
+Editor::initialize_canvas ()
+{
+ gtk_canvas_init ();
+
+ track_gtk_canvas = gtk_canvas_new_aa ();
+
+ /* adjust sensitivity for "picking" items */
+
+ // GTK_CANVAS(track_gtk_canvas)->close_enough = 2;
+
+ gtk_signal_connect (GTK_OBJECT(gtk_canvas_root (GTK_CANVAS(track_gtk_canvas))), "event",
+ (GtkSignalFunc) Editor::_track_canvas_event, this);
+ track_canvas = wrap (track_gtk_canvas);
+ track_canvas->set_name ("EditorMainCanvas");
+
+ track_canvas->add_events (GDK_POINTER_MOTION_HINT_MASK);
+
+ track_canvas->leave_notify_event.connect (slot (*this, &Editor::left_track_canvas));
+
+ /* set up drag-n-drop */
+
+ track_canvas->drag_dest_set (GTK_DEST_DEFAULT_ALL,
+ target_table, n_targets - 1,
+ GdkDragAction (GDK_ACTION_COPY|GDK_ACTION_MOVE));
+ track_canvas->drag_data_received.connect (slot (*this, &Editor::track_canvas_drag_data_received));
+
+ /* stuff for the verbose canvas cursor */
+
+ string fontname = get_font_for_style (N_("VerboseCanvasCursor"));
+
+ verbose_canvas_cursor = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)),
+ gtk_canvas_text_get_type(),
+ "font", fontname.c_str(),
+ "anchor", GTK_ANCHOR_NW,
+ "fill_color_rgba", color_map[cVerboseCanvasCursor],
+ NULL);
+ verbose_cursor_visible = false;
+
+ /* a group to hold time (measure) lines */
+
+ time_line_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", 0.0,
+ NULL);
+
+ cursor_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", 0.0,
+ NULL);
+
+ time_gtk_canvas = gtk_canvas_new_aa ();
+ time_canvas = wrap (time_gtk_canvas);
+ time_canvas->set_name ("EditorTimeCanvas");
+
+ time_canvas->add_events (GDK_POINTER_MOTION_HINT_MASK);
+
+ meter_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", 0.0,
+ NULL);
+ tempo_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", timebar_height,
+ NULL);
+ marker_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", timebar_height * 2.0,
+ NULL);
+ range_marker_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", timebar_height * 3.0,
+ NULL);
+ transport_marker_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", timebar_height * 4.0,
+ NULL);
+
+ tempo_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(tempo_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", max_canvas_coordinate,
+ "y2", timebar_height,
+ "fill_color_rgba", color_map[cTempoBar],
+ "outline_pixels", 0,
+ NULL);
+ meter_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(meter_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", max_canvas_coordinate,
+ "y2", timebar_height,
+ "fill_color_rgba", color_map[cMeterBar],
+ "outline_pixels", 0,
+ NULL);
+ marker_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(marker_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", max_canvas_coordinate,
+ "y2", timebar_height,
+ "fill_color_rgba", color_map[cMarkerBar],
+ "outline_pixels", 0,
+ NULL);
+ range_marker_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(range_marker_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", max_canvas_coordinate,
+ "y2", timebar_height,
+ "fill_color_rgba", color_map[cRangeMarkerBar],
+ "outline_pixels", 0,
+ NULL);
+ transport_marker_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(transport_marker_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", max_canvas_coordinate,
+ "y2", timebar_height,
+ "fill_color_rgba", color_map[cTransportMarkerBar],
+ "outline_pixels", 0,
+ NULL);
+
+ range_bar_drag_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(range_marker_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", timebar_height,
+ "fill_color_rgba", color_map[cRangeDragBarRectFill],
+ "outline_color_rgba", color_map[cRangeDragBarRect],
+ NULL);
+ gtk_canvas_item_hide (range_bar_drag_rect);
+
+ transport_bar_drag_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(transport_marker_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", timebar_height,
+ "fill_color_rgba", color_map[cTransportDragRectFill],
+ "outline_color_rgba", color_map[cTransportDragRect],
+ NULL);
+ gtk_canvas_item_hide (transport_bar_drag_rect);
+
+
+ marker_drag_line_points = gtk_canvas_points_new (2);
+ marker_drag_line_points->coords[0] = 0.0;
+ marker_drag_line_points->coords[1] = 0.0;
+ marker_drag_line_points->coords[2] = 0.0;
+ marker_drag_line_points->coords[3] = 0.0;
+
+
+ //cerr << "set mdl points, nc = " << marker_drag_line_points->num_points << endl;
+ marker_drag_line = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)),
+ gtk_canvas_line_get_type(),
+ "width_pixels", 1,
+ "fill_color_rgba", color_map[cMarkerDragLine],
+ "points", marker_drag_line_points,
+ NULL);
+ gtk_canvas_item_hide (marker_drag_line);
+
+ range_marker_drag_rect = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "fill_color_rgba", color_map[cRangeDragRectFill],
+ "outline_color_rgba", color_map[cRangeDragRect],
+ NULL);
+ gtk_canvas_item_hide (range_marker_drag_rect);
+
+
+ transport_loop_range_rect = gtk_canvas_item_new ((GTK_CANVAS_GROUP(time_line_group)),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "fill_color_rgba", color_map[cTransportLoopRectFill],
+ "outline_color_rgba", color_map[cTransportLoopRect],
+ "outline_pixels", 1,
+ NULL);
+ gtk_canvas_item_hide (transport_loop_range_rect);
+
+ transport_punch_range_rect = gtk_canvas_item_new ((GTK_CANVAS_GROUP(time_line_group)),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "fill_color_rgba", color_map[cTransportPunchRectFill],
+ "outline_color_rgba", color_map[cTransportPunchRect],
+ "outline_pixels", 0,
+ NULL);
+ gtk_canvas_item_lower_to_bottom (transport_punch_range_rect);
+ gtk_canvas_item_lower_to_bottom (transport_loop_range_rect); // loop on the bottom
+ gtk_canvas_item_hide (transport_punch_range_rect);
+
+ transport_punchin_line = gtk_canvas_item_new ((GTK_CANVAS_GROUP(time_line_group)),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "outline_color_rgba", color_map[cPunchInLine],
+ "outline_pixels", 1,
+ NULL);
+ gtk_canvas_item_hide (transport_punchin_line);
+
+ transport_punchout_line = gtk_canvas_item_new ((GTK_CANVAS_GROUP(time_line_group)),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "outline_color_rgba", color_map[cPunchOutLine],
+ "outline_pixels", 1,
+ NULL);
+ gtk_canvas_item_hide (transport_punchout_line);
+
+
+
+
+ // used to show zoom mode active zooming
+ zoom_rect = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "fill_color_rgba", color_map[cZoomRectFill],
+ "outline_color_rgba", color_map[cZoomRect],
+ "outline_pixels", 1,
+ NULL);
+ gtk_canvas_item_hide (zoom_rect);
+ gtk_signal_connect (GTK_OBJECT(zoom_rect), "event",
+ (GtkSignalFunc) PublicEditor::canvas_zoom_rect_event,
+ this);
+
+ // used as rubberband rect
+ rubberband_rect = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "outline_color_rgba", color_map[cRubberBandRect],
+ "fill_color_rgba", (guint32) color_map[cRubberBandRectFill],
+ "outline_pixels", 1,
+ NULL);
+ gtk_canvas_item_hide (rubberband_rect);
+
+
+
+ gtk_signal_connect (GTK_OBJECT(tempo_bar), "event",
+ (GtkSignalFunc) PublicEditor::canvas_tempo_bar_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(meter_bar), "event",
+ (GtkSignalFunc) PublicEditor::canvas_meter_bar_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(marker_bar), "event",
+ (GtkSignalFunc) PublicEditor::canvas_marker_bar_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(range_marker_bar), "event",
+ (GtkSignalFunc) PublicEditor::canvas_range_marker_bar_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(transport_marker_bar), "event",
+ (GtkSignalFunc) PublicEditor::canvas_transport_marker_bar_event,
+ this);
+
+ /* separator lines */
+
+ tempo_line_points = gtk_canvas_points_new (2);
+ tempo_line_points->coords[0] = 0;
+ tempo_line_points->coords[1] = timebar_height;
+ tempo_line_points->coords[2] = max_canvas_coordinate;
+ tempo_line_points->coords[3] = timebar_height;
+ //cerr << "set tl points, nc = " << tempo_line_points->num_points << endl;
+ tempo_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(tempo_group),
+ gtk_canvas_line_get_type(),
+ "width_pixels", 0,
+ "fill_color", "black",
+ "points", tempo_line_points,
+ NULL);
+
+ // cerr << "tempo line @ " << tempo_line << endl;
+
+ meter_line_points = gtk_canvas_points_new (2);
+ meter_line_points->coords[0] = 0;
+ meter_line_points->coords[1] = timebar_height;
+ meter_line_points->coords[2] = max_canvas_coordinate;
+ meter_line_points->coords[3] = timebar_height;
+ // cerr << "set ml points, nc = " << tempo_line_points->num_points << endl;
+ meter_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(meter_group),
+ gtk_canvas_line_get_type(),
+ "width_pixels", 0,
+ "fill_color", "black",
+ "points", meter_line_points,
+ NULL);
+
+ // cerr << "meter line @ " << tempo_line << endl;
+
+ marker_line_points = gtk_canvas_points_new (2);
+ marker_line_points->coords[0] = 0;
+ marker_line_points->coords[1] = timebar_height;
+ marker_line_points->coords[2] = max_canvas_coordinate;
+ marker_line_points->coords[3] = timebar_height;
+ // cerr << "set ml2 points, nc = " << marker_line_points->num_points << endl;
+ marker_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(marker_group),
+ gtk_canvas_line_get_type(),
+ "width_pixels", 0,
+ "fill_color", "black",
+ "points", marker_line_points,
+ NULL);
+ // cerr << "set rml points, nc = " << marker_line_points->num_points << endl;
+ range_marker_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(range_marker_group),
+ gtk_canvas_line_get_type(),
+ "width_pixels", 0,
+ "fill_color", "black",
+ "points", marker_line_points,
+ NULL);
+ // cerr << "set tml2 points, nc = " << marker_line_points->num_points << endl;
+ transport_marker_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(transport_marker_group),
+ gtk_canvas_line_get_type(),
+ "width_pixels", 0,
+ "fill_color", "black",
+ "points", marker_line_points,
+ NULL);
+
+ // cerr << "marker line @ " << marker_line << endl;
+
+ ZoomChanged.connect (bind (slot (*this, &Editor::update_loop_range_view), false));
+ ZoomChanged.connect (bind (slot (*this, &Editor::update_punch_range_view), false));
+
+ double time_height = timebar_height * 5;
+ double time_width = FLT_MAX/frames_per_unit;
+ gtk_canvas_set_scroll_region (GTK_CANVAS(time_gtk_canvas), 0.0, 0.0, time_width, time_height);
+
+ edit_cursor = new Cursor (*this, "blue", (GtkSignalFunc) _canvas_edit_cursor_event);
+ playhead_cursor = new Cursor (*this, "red", (GtkSignalFunc) _canvas_playhead_cursor_event);
+
+ track_canvas->size_allocate.connect (slot (*this, &Editor::track_canvas_allocate));
+}
+
+void
+Editor::show_window ()
+{
+ show_all ();
+
+ /* now reset all audio_time_axis heights, because widgets might need
+ to be re-hidden
+ */
+
+ TimeAxisView *tv;
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ tv = (static_cast<TimeAxisView*>(*i));
+ tv->reset_height ();
+ }
+}
+
+void
+Editor::tie_vertical_scrolling ()
+{
+ edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
+
+ float y1 = track_canvas_scroller.get_vadjustment()->get_value();
+ playhead_cursor->set_y_axis(y1);
+ edit_cursor->set_y_axis(y1);
+}
+
+void
+Editor::set_frames_per_unit (double fpu)
+{
+ jack_nframes_t frames;
+
+ if (fpu == frames_per_unit) {
+ return;
+ }
+
+ if (fpu < 1.0) {
+ fpu = 1.0;
+ }
+
+ // convert fpu to frame count
+
+ frames = (jack_nframes_t) (fpu * canvas_width);
+
+ /* don't allow zooms that fit more than the maximum number
+ of frames into an 800 pixel wide space.
+ */
+
+ if (max_frames / fpu < 800.0) {
+ return;
+ }
+
+ frames_per_unit = fpu;
+
+ if (frames != zoom_range_clock.current_duration()) {
+ zoom_range_clock.set (frames);
+ }
+
+ /* only update these if we not about to call reposition_x_origin,
+ which will do the same updates.
+ */
+
+ if (session) {
+ track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
+ }
+
+ if (!no_zoom_repos_update) {
+ track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
+ update_hscroller ();
+ update_fixed_rulers ();
+ tempo_map_changed (Change (0));
+ }
+
+ if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ (*i)->reshow_selection (selection->time);
+ }
+ }
+
+ ZoomChanged (); /* EMIT_SIGNAL */
+
+ if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
+ if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
+
+ instant_save ();
+
+}
+
+void
+Editor::instant_save ()
+{
+ if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
+ return;
+ }
+
+ if (session) {
+ session->add_instant_xml(get_state(), session->path());
+ } else {
+ Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
+ }
+}
+
+void
+Editor::reposition_x_origin (jack_nframes_t frame)
+{
+ if (frame != leftmost_frame) {
+ leftmost_frame = frame;
+ double pixel = frame_to_pixel (frame);
+ if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
+ track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
+ }
+ track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
+ XOriginChanged (); /* EMIT_SIGNAL */
+ }
+}
+
+void
+Editor::edit_cursor_clock_changed()
+{
+ if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
+ edit_cursor->set_position (edit_cursor_clock.current_time());
+ }
+}
+
+
+void
+Editor::zoom_adjustment_changed ()
+{
+ if (session == 0 || no_zoom_repos_update) {
+ return;
+ }
+
+ double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
+
+ if (fpu < 1.0) {
+ fpu = 1.0;
+ zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
+ }
+ else if (fpu > session->current_end_frame() / (double) canvas_width) {
+ fpu = session->current_end_frame() / (double) canvas_width;
+ zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
+ }
+
+ temporal_zoom (fpu);
+}
+
+void
+Editor::canvas_horizontally_scrolled ()
+{
+ /* XXX note the potential loss of accuracy here caused by
+ adjustments being 32bit floats with only a 24 bit mantissa,
+ whereas jack_nframes_t is at least a 32 bit uint32_teger.
+ */
+
+ leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
+
+ update_hscroller ();
+ update_fixed_rulers ();
+
+ if (!edit_hscroll_dragging) {
+ tempo_map_changed (Change (0));
+ } else {
+ update_tempo_based_rulers();
+ }
+}
+
+void
+Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
+{
+ if (!repos_zoom_queued) {
+ Main::idle.connect (bind (slot (*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
+ repos_zoom_queued = true;
+ }
+}
+
+gint
+Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
+{
+ /* if we need to force an update to the hscroller stuff,
+ don't set no_zoom_repos_update.
+ */
+
+ no_zoom_repos_update = (frame != leftmost_frame);
+
+ set_frames_per_unit (nfpu);
+ if (no_zoom_repos_update) {
+ reposition_x_origin (frame);
+ }
+ no_zoom_repos_update = false;
+ repos_zoom_queued = false;
+
+ return FALSE;
+}
+
+void
+Editor::realize_impl ()
+{
+ /* Even though we're not using acceleration, we want the
+ labels to show up.
+ */
+
+ track_context_menu.accelerate (*this->get_toplevel());
+ track_region_context_menu.accelerate (*this->get_toplevel());
+
+ Window::realize_impl ();
+
+ GdkPixmap* empty_pixmap = gdk_pixmap_new (get_window(), 1, 1, 1);
+ GdkPixmap* empty_bitmap = gdk_pixmap_new (get_window(), 1, 1, 1);
+ GdkColor white = { 0, 0, 0 };
+
+ null_cursor = gdk_cursor_new_from_pixmap (empty_pixmap, empty_bitmap, &white, &white, 0, 0);
+}
+
+void
+Editor::map__impl ()
+{
+ Window::map__impl ();
+
+ track_canvas_scroller.get_window().set_cursor (current_canvas_cursor);
+ time_canvas_scroller.get_window().set_cursor (timebar_cursor);
+}
+
+void
+Editor::track_canvas_allocate (GtkAllocation *alloc)
+{
+ canvas_width = alloc->width;
+ canvas_height = alloc->height;
+
+ if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
+
+ string fontname = get_font_for_style (N_("FirstActionMessage"));
+
+ const char *txt1 = _("Start a new session\n");
+ const char *txt2 = _("via Session menu");
+
+ /* this mess of code is here to find out how wide this text is and
+ position the message in the center of the editor window. there
+ are two lines, so we use the longer of the the lines to
+ compute width, and multiply the height by 2.
+ */
+
+ gint width;
+ gint lbearing;
+ gint rbearing;
+ gint ascent;
+ gint descent;
+
+ /* this is a dummy widget that exists so that we can get the
+ style from the RC file.
+ */
+
+ Label foo (_(txt2));
+ foo.set_name ("NoSessionMessage");
+ foo.ensure_style ();
+
+ gdk_string_extents (foo.get_style()->get_font(),
+ _(txt2),
+ &lbearing,
+ &rbearing,
+ &width,
+ &ascent,
+ &descent);
+
+ if (first_action_message == 0) {
+
+ char txt[strlen(txt1)+strlen(txt2)+1];
+
+ /* merge both lines */
+
+ strcpy (txt, _(txt1));
+ strcat (txt, _(txt2));
+
+ first_action_message = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)),
+ gtk_canvas_text_get_type(),
+ "font", fontname.c_str(),
+ "fill_color_rgba", color_map[cFirstActionMessage],
+ "x", (gdouble) (canvas_width - width) / 2.0,
+ "y", (gdouble) (canvas_height/2.0) - (2.0 * (ascent+descent)),
+ "anchor", GTK_ANCHOR_NORTH_WEST,
+ "text", txt,
+ NULL);
+
+ } else {
+
+ /* center it */
+
+ gtk_canvas_item_set (first_action_message,
+ "x", (gdouble) (canvas_width - width) / 2.0,
+ "y", (gdouble) (canvas_height/2.0) - (2.0 * (ascent+descent)),
+ NULL);
+ }
+ }
+
+ zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
+ edit_cursor->set_position (edit_cursor->current_frame);
+ playhead_cursor->set_position (playhead_cursor->current_frame);
+ reset_scrolling_region (alloc);
+
+ Resized (); /* EMIT_SIGNAL */
+}
+
+void
+Editor::reset_scrolling_region (GtkAllocation *alloc)
+{
+ guint32 last_canvas_unit;
+ double height;
+ guint32 canvas_alloc_height, canvas_alloc_width;
+ TrackViewList::iterator i;
+ static bool first_time = true;
+
+ /* We need to make sure that the canvas always has its
+ scrolling region set to larger of:
+
+ - the size allocated for it (within the container its packed in)
+ - the size required to see the entire session
+
+ If we don't ensure at least the first of these, the canvas
+ does some wierd and in my view unnecessary stuff to center
+ itself within the allocated area, which causes bad, bad
+ results.
+
+ XXX GnomeCanvas has fixed this, and has an option to
+ control the centering behaviour.
+ */
+
+ last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit);
+
+ height = 0;
+
+ if (session) {
+ for (i = track_views.begin(); i != track_views.end(); ++i) {
+ if ((*i)->control_parent) {
+ height += (*i)->effective_height;
+ height += track_spacing;
+ }
+ }
+
+ if (height) {
+ height -= track_spacing;
+ }
+ }
+
+ canvas_height = (guint32) height;
+
+ if (alloc) {
+ canvas_alloc_height = alloc->height;
+ canvas_alloc_width = alloc->width;
+ } else {
+ canvas_alloc_height = track_gtk_canvas->allocation.height;
+ canvas_alloc_width = track_gtk_canvas->allocation.width;
+ }
+
+ canvas_height = max (canvas_height, canvas_alloc_height);
+
+ gtk_canvas_set_scroll_region (GTK_CANVAS(track_gtk_canvas), 0.0, 0.0,
+ max (last_canvas_unit, canvas_alloc_width),
+ canvas_height);
+
+ if (edit_cursor) edit_cursor->set_length (canvas_alloc_height);
+ if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height);
+
+ if (marker_drag_line) {
+ marker_drag_line_points->coords[3] = canvas_height;
+ // cerr << "set mlA points, nc = " << marker_drag_line_points->num_points << endl;
+ gtk_canvas_item_set (marker_drag_line, "points", marker_drag_line_points, NULL);
+ }
+ if (range_marker_drag_rect) {
+ gtk_canvas_item_set (range_marker_drag_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
+ }
+ if (transport_loop_range_rect) {
+ gtk_canvas_item_set (transport_loop_range_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
+ }
+ if (transport_punch_range_rect) {
+ gtk_canvas_item_set (transport_punch_range_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
+ }
+ if (transport_punchin_line) {
+ gtk_canvas_item_set (transport_punchin_line, "y1", 0.0, "y2", (double) canvas_height, NULL);
+ }
+ if (transport_punchout_line) {
+ gtk_canvas_item_set (transport_punchout_line, "y1", 0.0, "y2", (double) canvas_height, NULL);
+ }
+
+
+ update_fixed_rulers ();
+
+ if (is_visible() && first_time) {
+ tempo_map_changed (Change (0));
+ first_time = false;
+ } else {
+ redisplay_tempo ();
+ }
+}
+
+void
+Editor::queue_session_control_changed (Session::ControlType t)
+{
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &Editor::session_control_changed), t));
+}
+
+void
+Editor::session_control_changed (Session::ControlType t)
+{
+ // right now we're only tracking the loop and punch state
+
+ switch (t) {
+ case Session::AutoLoop:
+ update_loop_range_view (true);
+ break;
+ case Session::PunchIn:
+ case Session::PunchOut:
+ update_punch_range_view (true);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+Editor::fake_add_edit_group (RouteGroup *group)
+{
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &Editor::add_edit_group), group));
+}
+
+void
+Editor::fake_handle_new_audio_region (AudioRegion *region)
+{
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &Editor::handle_new_audio_region), region));
+}
+
+void
+Editor::fake_handle_audio_region_removed (AudioRegion *region)
+{
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &Editor::handle_audio_region_removed), region));
+}
+
+void
+Editor::fake_handle_new_duration ()
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &Editor::handle_new_duration));
+}
+
+void
+Editor::start_scrolling ()
+{
+ scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
+ (slot (*this, &Editor::update_current_screen));
+
+ slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
+ (slot (*this, &Editor::update_slower));
+}
+
+void
+Editor::stop_scrolling ()
+{
+ scroll_connection.disconnect ();
+ slower_update_connection.disconnect ();
+}
+
+void
+Editor::map_position_change (jack_nframes_t frame)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &Editor::map_position_change), frame));
+
+ if (session == 0 || !_follow_playhead) {
+ return;
+ }
+
+ center_screen (frame);
+ playhead_cursor->set_position (frame);
+}
+
+void
+Editor::center_screen (jack_nframes_t frame)
+{
+ float page = canvas_width * frames_per_unit;
+
+ /* if we're off the page, then scroll.
+ */
+
+ if (frame < leftmost_frame || frame >= leftmost_frame + page) {
+ center_screen_internal (frame,page);
+ }
+}
+
+void
+Editor::center_screen_internal (jack_nframes_t frame, float page)
+{
+ page /= 2;
+
+ if (frame > page) {
+ frame -= (jack_nframes_t) page;
+ } else {
+ frame = 0;
+ }
+
+ reposition_x_origin (frame);
+}
+
+void
+Editor::handle_new_duration ()
+{
+ reset_scrolling_region ();
+
+ if (session) {
+ track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
+ track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
+ }
+
+ update_hscroller ();
+}
+
+void
+Editor::update_title_s (string snap_name)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::update_title_s), snap_name));
+
+ update_title ();
+}
+
+void
+Editor::update_title ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &Editor::update_title));
+
+ if (session) {
+ bool dirty = session->dirty();
+
+ string wintitle = _("ardour: editor: ");
+
+ if (dirty) {
+ wintitle += '[';
+ }
+
+ wintitle += session->name();
+
+ if (session->snap_name() != session->name()) {
+ wintitle += ':';
+ wintitle += session->snap_name();
+ }
+
+ if (dirty) {
+ wintitle += ']';
+ }
+
+ set_title (wintitle);
+ }
+}
+
+void
+Editor::connect_to_session (Session *t)
+{
+ session = t;
+
+ if (first_action_message) {
+ gtk_canvas_item_hide (first_action_message);
+ }
+
+ flush_track_canvas();
+
+ update_title ();
+
+ session->going_away.connect (slot (*this, &Editor::session_going_away));
+
+ /* These signals can all be emitted by a non-GUI thread. Therefore the
+ handlers for them must not attempt to directly interact with the GUI,
+ but use Gtkmmext::UI::instance()->call_slot();
+ */
+
+ session_connections.push_back (session->TransportStateChange.connect (slot (*this, &Editor::map_transport_state)));
+ session_connections.push_back (session->PositionChanged.connect (slot (*this, &Editor::map_position_change)));
+ session_connections.push_back (session->RouteAdded.connect (slot (*this, &Editor::handle_new_route_p)));
+ session_connections.push_back (session->AudioRegionAdded.connect (slot (*this, &Editor::fake_handle_new_audio_region)));
+ session_connections.push_back (session->AudioRegionRemoved.connect (slot (*this, &Editor::fake_handle_audio_region_removed)));
+ session_connections.push_back (session->DurationChanged.connect (slot (*this, &Editor::fake_handle_new_duration)));
+ session_connections.push_back (session->edit_group_added.connect (slot (*this, &Editor::fake_add_edit_group)));
+ session_connections.push_back (session->NamedSelectionAdded.connect (slot (*this, &Editor::handle_new_named_selection)));
+ session_connections.push_back (session->NamedSelectionRemoved.connect (slot (*this, &Editor::handle_new_named_selection)));
+ session_connections.push_back (session->DirtyChanged.connect (slot (*this, &Editor::update_title)));
+ session_connections.push_back (session->StateSaved.connect (slot (*this, &Editor::update_title_s)));
+ session_connections.push_back (session->AskAboutPlaylistDeletion.connect (slot (*this, &Editor::playlist_deletion_dialog)));
+ session_connections.push_back (session->RegionHiddenChange.connect (slot (*this, &Editor::region_hidden)));
+
+ session_connections.push_back (session->SMPTEOffsetChanged.connect (slot (*this, &Editor::update_just_smpte)));
+ session_connections.push_back (session->SMPTETypeChanged.connect (slot (*this, &Editor::update_just_smpte)));
+
+ session_connections.push_back (session->tempo_map().StateChanged.connect (slot (*this, &Editor::tempo_map_changed)));
+
+ session->foreach_edit_group(this, &Editor::add_edit_group);
+
+ editor_mixer_button.toggled.connect (slot (*this, &Editor::editor_mixer_button_toggled));
+ editor_mixer_button.set_name (X_("EditorMixerButton"));
+
+ edit_cursor_clock.set_session (session);
+ selection_start_clock.set_session (session);
+ selection_end_clock.set_session (session);
+ zoom_range_clock.set_session (session);
+ _playlist_selector->set_session (session);
+ nudge_clock.set_session (session);
+
+ switch (session->get_edit_mode()) {
+ case Splice:
+ edit_mode_selector.get_entry()->set_text (edit_mode_strings[splice_index]);
+ break;
+
+ case Slide:
+ edit_mode_selector.get_entry()->set_text (edit_mode_strings[slide_index]);
+ break;
+ }
+
+ Location* loc = session->locations()->auto_loop_location();
+ if (loc == 0) {
+ loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
+ if (loc->start() == loc->end()) {
+ loc->set_end (loc->start() + 1);
+ }
+ session->locations()->add (loc, false);
+ session->set_auto_loop_location (loc);
+ }
+ else {
+ // force name
+ loc->set_name (_("Loop"));
+ }
+
+ loc = session->locations()->auto_punch_location();
+ if (loc == 0) {
+ loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
+ if (loc->start() == loc->end()) {
+ loc->set_end (loc->start() + 1);
+ }
+ session->locations()->add (loc, false);
+ session->set_auto_punch_location (loc);
+ }
+ else {
+ // force name
+ loc->set_name (_("Punch"));
+ }
+
+ update_loop_range_view (true);
+ update_punch_range_view (true);
+
+ session->ControlChanged.connect (slot (*this, &Editor::queue_session_control_changed));
+
+
+ refresh_location_display ();
+ session->locations()->added.connect (slot (*this, &Editor::add_new_location));
+ session->locations()->removed.connect (slot (*this, &Editor::location_gone));
+ session->locations()->changed.connect (slot (*this, &Editor::refresh_location_display));
+ session->locations()->StateChanged.connect (slot (*this, &Editor::refresh_location_display_s));
+ session->locations()->end_location()->changed.connect (slot (*this, &Editor::end_location_changed));
+
+ reset_scrolling_region ();
+
+ redisplay_regions ();
+ redisplay_named_selections ();
+
+ route_list.freeze ();
+ route_list.clear ();
+ session->foreach_route (this, &Editor::handle_new_route);
+ // route_list.select_all ();
+ route_list.sort ();
+ route_list_reordered ();
+ route_list.thaw ();
+
+ if (embed_audio_item) {
+ embed_audio_item->set_sensitive (true);
+ }
+ if (import_audio_item) {
+ import_audio_item->set_sensitive (true);
+ }
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
+ }
+
+ /* ::reposition_x_origin() doesn't work right here, since the old
+ position may be zero already, and it does nothing in such
+ circumstances.
+ */
+
+ leftmost_frame = 0;
+
+ track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
+ track_canvas_scroller.get_hadjustment()->set_value (0);
+
+ update_hscroller ();
+ restore_ruler_visibility ();
+ tempo_map_changed (Change (0));
+
+ edit_cursor->set_position (0);
+ playhead_cursor->set_position (0);
+
+ start_scrolling ();
+
+ XMLNode* node = ARDOUR_UI::instance()->editor_settings();
+ set_state (*node);
+
+ /* don't show master bus in a new session */
+
+ if (ARDOUR_UI::instance()->session_is_new ()) {
+
+ Gtk::CList_Helpers::RowList::iterator i;
+ Gtk::CList_Helpers::RowList& rowlist = route_list.rows();
+
+ route_list.freeze ();
+
+ for (i = rowlist.begin(); i != rowlist.end(); ++i) {
+ TimeAxisView *tv = (TimeAxisView *) i->get_data ();
+ AudioTimeAxisView *atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
+ if (atv->route().master()) {
+ (*i)->unselect ();
+ }
+ }
+ }
+
+ route_list.thaw ();
+ }
+}
+
+void
+Editor::build_cursors ()
+{
+ GdkPixmap *source, *mask;
+ GdkColor fg = { 0, 65535, 0, 0 }; /* Red. */
+ GdkColor bg = { 0, 0, 0, 65535 }; /* Blue. */
+
+ source = gdk_bitmap_create_from_data (NULL, hand_bits,
+ hand_width, hand_height);
+ mask = gdk_bitmap_create_from_data (NULL, handmask_bits,
+ handmask_width, handmask_height);
+ grabber_cursor = gdk_cursor_new_from_pixmap (source, mask, &fg, &bg, hand_x_hot, hand_y_hot);
+ gdk_pixmap_unref (source);
+ gdk_pixmap_unref (mask);
+
+
+ GdkColor mbg = { 0, 0, 0, 0 }; /* Black */
+ GdkColor mfg = { 0, 0, 0, 65535 }; /* Blue. */
+
+ source = gdk_bitmap_create_from_data (NULL, mag_bits,
+ mag_width, mag_height);
+ mask = gdk_bitmap_create_from_data (NULL, magmask_bits,
+ mag_width, mag_height);
+ zoom_cursor = gdk_cursor_new_from_pixmap (source, mask, &mfg, &mbg, mag_x_hot, mag_y_hot);
+ gdk_pixmap_unref (source);
+ gdk_pixmap_unref (mask);
+
+ GdkColor fbg = { 0, 65535, 65535, 65535 };
+ GdkColor ffg = { 0, 0, 0, 0 };
+
+ source = gdk_bitmap_create_from_data (NULL, fader_cursor_bits,
+ fader_cursor_width, fader_cursor_height);
+ mask = gdk_bitmap_create_from_data (NULL, fader_cursor_mask_bits,
+ fader_cursor_width, fader_cursor_height);
+ fader_cursor = gdk_cursor_new_from_pixmap (source, mask, &ffg, &fbg, fader_cursor_x_hot, fader_cursor_y_hot);
+ gdk_pixmap_unref (source);
+ gdk_pixmap_unref (mask);
+
+ source = gdk_bitmap_create_from_data (NULL, speaker_cursor_bits,
+ speaker_cursor_width, speaker_cursor_height);
+ mask = gdk_bitmap_create_from_data (NULL, speaker_cursor_mask_bits,
+ speaker_cursor_width, speaker_cursor_height);
+ speaker_cursor = gdk_cursor_new_from_pixmap (source, mask, &ffg, &fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
+ gdk_pixmap_unref (source);
+ gdk_pixmap_unref (mask);
+
+ cross_hair_cursor = gdk_cursor_new (GDK_CROSSHAIR);
+ trimmer_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
+ selector_cursor = gdk_cursor_new (GDK_XTERM);
+ time_fx_cursor = gdk_cursor_new (GDK_SIZING);
+ wait_cursor = gdk_cursor_new (GDK_WATCH);
+ timebar_cursor = gdk_cursor_new (GDK_LEFT_PTR);
+}
+
+void
+Editor::popup_fade_context_menu (int button, int32_t time, GtkCanvasItem* item, ItemType item_type)
+{
+ using namespace Menu_Helpers;
+ AudioRegionView* arv = static_cast<AudioRegionView*> (gtk_object_get_data (GTK_OBJECT(item), "regionview"));
+
+ if (arv == 0) {
+ fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ MenuList& items (fade_context_menu.items());
+
+ items.clear ();
+
+ switch (item_type) {
+ case FadeInItem:
+ case FadeInHandleItem:
+ if (arv->region.fade_in_active()) {
+ items.push_back (MenuElem (_("Deactivate"), bind (slot (*arv, &AudioRegionView::set_fade_in_active), false)));
+ } else {
+ items.push_back (MenuElem (_("Activate"), bind (slot (*arv, &AudioRegionView::set_fade_in_active), true)));
+ }
+
+ items.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Linear"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
+ items.push_back (MenuElem (_("Slowest"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
+ items.push_back (MenuElem (_("Slow"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
+ items.push_back (MenuElem (_("Fast"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
+ items.push_back (MenuElem (_("Fastest"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
+ break;
+
+ case FadeOutItem:
+ case FadeOutHandleItem:
+ if (arv->region.fade_out_active()) {
+ items.push_back (MenuElem (_("Deactivate"), bind (slot (*arv, &AudioRegionView::set_fade_out_active), false)));
+ } else {
+ items.push_back (MenuElem (_("Activate"), bind (slot (*arv, &AudioRegionView::set_fade_out_active), true)));
+ }
+
+ items.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Linear"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
+ items.push_back (MenuElem (_("Slowest"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
+ items.push_back (MenuElem (_("Slow"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
+ items.push_back (MenuElem (_("Fast"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
+ items.push_back (MenuElem (_("Fastest"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
+
+ break;
+ default:
+ fatal << _("programming error: ")
+ << X_("non-fade canvas item passed to popup_fade_context_menu()")
+ << endmsg;
+ /*NOTREACHED*/
+ }
+
+ fade_context_menu.popup (button, time);
+}
+
+void
+Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
+{
+ using namespace Menu_Helpers;
+ Menu* (Editor::*build_menu_function)(jack_nframes_t);
+ Menu *menu;
+
+ switch (item_type) {
+ case RegionItem:
+ case AudioRegionViewName:
+ case AudioRegionViewNameHighlight:
+ if (with_selection) {
+ build_menu_function = &Editor::build_track_selection_context_menu;
+ } else {
+ build_menu_function = &Editor::build_track_region_context_menu;
+ }
+ break;
+
+ case SelectionItem:
+ if (with_selection) {
+ build_menu_function = &Editor::build_track_selection_context_menu;
+ } else {
+ build_menu_function = &Editor::build_track_context_menu;
+ }
+ break;
+
+ case CrossfadeViewItem:
+ build_menu_function = &Editor::build_track_crossfade_context_menu;
+ break;
+
+ case StreamItem:
+ if (clicked_audio_trackview->get_diskstream()) {
+ build_menu_function = &Editor::build_track_context_menu;
+ } else {
+ build_menu_function = &Editor::build_track_bus_context_menu;
+ }
+ break;
+
+ default:
+ /* probably shouldn't happen but if it does, we don't care */
+ return;
+ }
+
+ menu = (this->*build_menu_function)(frame);
+ menu->set_name ("ArdourContextMenu");
+
+ /* now handle specific situations */
+
+ switch (item_type) {
+ case RegionItem:
+ case AudioRegionViewName:
+ case AudioRegionViewNameHighlight:
+ if (!with_selection) {
+ if (region_edit_menu_split_item) {
+ if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
+ region_edit_menu_split_item->set_sensitive (true);
+ } else {
+ region_edit_menu_split_item->set_sensitive (false);
+ }
+ }
+ if (region_edit_menu_split_multichannel_item) {
+ if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
+ region_edit_menu_split_multichannel_item->set_sensitive (true);
+ } else {
+ region_edit_menu_split_multichannel_item->set_sensitive (false);
+ }
+ }
+ }
+ break;
+
+ case SelectionItem:
+ break;
+
+ case CrossfadeViewItem:
+ break;
+
+ case StreamItem:
+ break;
+
+ default:
+ /* probably shouldn't happen but if it does, we don't care */
+ return;
+ }
+
+ if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
+
+ /* Bounce to disk */
+
+ using namespace Menu_Helpers;
+ MenuList& edit_items = menu->items();
+
+ edit_items.push_back (SeparatorElem());
+
+ switch (clicked_audio_trackview->audio_track()->freeze_state()) {
+ case AudioTrack::NoFreeze:
+ edit_items.push_back (MenuElem (_("Freeze"), slot (*this, &Editor::freeze_route)));
+ break;
+
+ case AudioTrack::Frozen:
+ edit_items.push_back (MenuElem (_("Unfreeze"), slot (*this, &Editor::unfreeze_route)));
+ break;
+
+ case AudioTrack::UnFrozen:
+ edit_items.push_back (MenuElem (_("Freeze"), slot (*this, &Editor::freeze_route)));
+ break;
+ }
+
+ }
+
+ menu->popup (button, time);
+}
+
+Menu*
+Editor::build_track_context_menu (jack_nframes_t ignored)
+{
+ using namespace Menu_Helpers;
+
+ MenuList& edit_items = track_context_menu.items();
+ edit_items.clear();
+
+ add_dstream_context_items (edit_items);
+ return &track_context_menu;
+}
+
+Menu*
+Editor::build_track_bus_context_menu (jack_nframes_t ignored)
+{
+ using namespace Menu_Helpers;
+
+ MenuList& edit_items = track_context_menu.items();
+ edit_items.clear();
+
+ add_bus_context_items (edit_items);
+ return &track_context_menu;
+}
+
+Menu*
+Editor::build_track_region_context_menu (jack_nframes_t frame)
+{
+ using namespace Menu_Helpers;
+ MenuList& edit_items = track_region_context_menu.items();
+ edit_items.clear();
+
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
+
+ if (atv) {
+ DiskStream* ds;
+ Playlist* pl;
+
+ if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
+ Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
+ for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+ add_region_context_items (atv->view, (*i), edit_items);
+ }
+ delete regions;
+ }
+ }
+
+ add_dstream_context_items (edit_items);
+
+ return &track_region_context_menu;
+}
+
+Menu*
+Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
+{
+ using namespace Menu_Helpers;
+ MenuList& edit_items = track_crossfade_context_menu.items();
+ edit_items.clear ();
+
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
+
+ if (atv) {
+ DiskStream* ds;
+ Playlist* pl;
+ AudioPlaylist* apl;
+
+ if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
+
+ Playlist::RegionList* regions = pl->regions_at (frame);
+ AudioPlaylist::Crossfades xfades;
+
+ apl->crossfades_at (frame, xfades);
+
+ bool many = xfades.size() > 1;
+
+ for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
+ add_crossfade_context_items (atv->view, (*i), edit_items, many);
+ }
+
+ for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
+ add_region_context_items (atv->view, (*i), edit_items);
+ }
+
+ delete regions;
+ }
+ }
+
+ add_dstream_context_items (edit_items);
+
+ return &track_crossfade_context_menu;
+}
+
+Menu*
+Editor::build_track_selection_context_menu (jack_nframes_t ignored)
+{
+ using namespace Menu_Helpers;
+ MenuList& edit_items = track_selection_context_menu.items();
+ edit_items.clear ();
+
+ add_selection_context_items (edit_items);
+ add_dstream_context_items (edit_items);
+
+ return &track_selection_context_menu;
+}
+
+void
+Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
+{
+ using namespace Menu_Helpers;
+ Menu *xfade_menu = manage (new Menu);
+ MenuList& items = xfade_menu->items();
+ xfade_menu->set_name ("ArdourContextMenu");
+ string str;
+
+ if (xfade->active()) {
+ str = _("Mute");
+ } else {
+ str = _("Unmute");
+ }
+
+ items.push_back (MenuElem (str, bind (slot (*this, &Editor::toggle_xfade_active), xfade)));
+ items.push_back (MenuElem (_("Edit"), bind (slot (*this, &Editor::edit_xfade), xfade)));
+
+ if (xfade->can_follow_overlap()) {
+
+ if (xfade->following_overlap()) {
+ str = _("Convert to short");
+ } else {
+ str = _("Convert to full");
+ }
+
+ items.push_back (MenuElem (str, bind (slot (*this, &Editor::toggle_xfade_length), xfade)));
+ }
+
+ if (many) {
+ str = xfade->out().name();
+ str += "->";
+ str += xfade->in().name();
+ } else {
+ str = _("Crossfade");
+ }
+
+ edit_items.push_back (MenuElem (str, *xfade_menu));
+ edit_items.push_back (SeparatorElem());
+}
+
+void
+Editor::xfade_edit_left_region ()
+{
+ if (clicked_crossfadeview) {
+ clicked_crossfadeview->left_view.show_region_editor ();
+ }
+}
+
+void
+Editor::xfade_edit_right_region ()
+{
+ if (clicked_crossfadeview) {
+ clicked_crossfadeview->right_view.show_region_editor ();
+ }
+}
+
+void
+Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
+{
+ using namespace Menu_Helpers;
+ Menu *region_menu = manage (new Menu);
+ MenuList& items = region_menu->items();
+ region_menu->set_name ("ArdourContextMenu");
+
+ AudioRegion* ar = 0;
+
+ if (region) {
+ ar = dynamic_cast<AudioRegion*> (region);
+ }
+
+ /* when this particular menu pops up, make the relevant region
+ become selected.
+ */
+
+ region_menu->map_event.connect (bind (slot (*this, &Editor::set_selected_regionview_from_map_event), sv, region));
+
+ items.push_back (MenuElem (_("Popup region editor"), slot (*this, &Editor::edit_region)));
+ items.push_back (MenuElem (_("Raise to top layer"), slot (*this, &Editor::raise_region_to_top)));
+ items.push_back (MenuElem (_("Lower to bottom layer"), slot (*this, &Editor::lower_region_to_bottom)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Define sync point"), slot (*this, &Editor::set_region_sync_from_edit_cursor)));
+ items.push_back (MenuElem (_("Remove sync point"), slot (*this, &Editor::remove_region_sync)));
+ items.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Audition"), slot (*this, &Editor::audition_selected_region)));
+ items.push_back (MenuElem (_("Export"), slot (*this, &Editor::export_region)));
+ items.push_back (MenuElem (_("Bounce"), slot (*this, &Editor::bounce_region_selection)));
+ items.push_back (SeparatorElem());
+
+ /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
+ might be able to figure out which overloaded member function to use in
+ a bind() call ...
+ */
+
+ void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
+
+ items.push_back (MenuElem (_("Lock"), bind (slot (*this, type_A_pmf), &Region::set_locked, true)));
+ items.push_back (MenuElem (_("Unlock"), bind (slot (*this, type_A_pmf), &Region::set_locked, false)));
+ items.push_back (SeparatorElem());
+
+ if (region->muted()) {
+ items.push_back (MenuElem (_("Unmute"), bind (slot (*this, type_A_pmf), &Region::set_muted, false)));
+ } else {
+ items.push_back (MenuElem (_("Mute"), bind (slot (*this, type_A_pmf), &Region::set_muted, true)));
+ }
+ items.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Original position"), slot (*this, &Editor::naturalize)));
+ items.push_back (SeparatorElem());
+
+
+ if (ar) {
+
+ items.push_back (MenuElem (_("Toggle envelope visibility"), slot (*this, &Editor::toggle_gain_envelope_visibility)));
+ items.push_back (MenuElem (_("Toggle envelope active"), slot (*this, &Editor::toggle_gain_envelope_active)));
+ items.push_back (SeparatorElem());
+
+ if (ar->scale_amplitude() != 1.0f) {
+ items.push_back (MenuElem (_("DeNormalize"), slot (*this, &Editor::denormalize_region)));
+ } else {
+ items.push_back (MenuElem (_("Normalize"), slot (*this, &Editor::normalize_region)));
+ }
+ }
+ items.push_back (MenuElem (_("Reverse"), slot (*this, &Editor::reverse_region)));
+ items.push_back (SeparatorElem());
+
+ /* Nudge region */
+
+ Menu *nudge_menu = manage (new Menu());
+ MenuList& nudge_items = nudge_menu->items();
+ nudge_menu->set_name ("ArdourContextMenu");
+
+ nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (slot (*this, &Editor::nudge_forward), false))));
+ nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (slot (*this, &Editor::nudge_backward), false))));
+ nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (slot (*this, &Editor::nudge_forward_capture_offset))));
+ nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (slot (*this, &Editor::nudge_backward_capture_offset))));
+
+ items.push_back (MenuElem (_("Nudge"), *nudge_menu));
+ items.push_back (SeparatorElem());
+
+ Menu *trim_menu = manage (new Menu);
+ MenuList& trim_items = trim_menu->items();
+ trim_menu->set_name ("ArdourContextMenu");
+
+ trim_items.push_back (MenuElem (_("Start to edit cursor"), slot (*this, &Editor::trim_region_from_edit_cursor)));
+ trim_items.push_back (MenuElem (_("Edit cursor to end"), slot (*this, &Editor::trim_region_to_edit_cursor)));
+
+ items.push_back (MenuElem (_("Trim"), *trim_menu));
+ items.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Split"), (slot (*this, &Editor::split_region))));
+ region_edit_menu_split_item = items.back();
+
+ items.push_back (MenuElem (_("Make mono regions"), (slot (*this, &Editor::split_multichannel_region))));
+ region_edit_menu_split_multichannel_item = items.back();
+
+ items.push_back (MenuElem (_("Duplicate"), (bind (slot (*this, &Editor::duplicate_dialog), true))));
+ items.push_back (MenuElem (_("Fill Track"), (slot (*this, &Editor::region_fill_track))));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Remove"), slot (*this, &Editor::remove_clicked_region)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Destroy"), slot (*this, &Editor::destroy_clicked_region)));
+
+ /* OK, stick the region submenu at the top of the list, and then add
+ the standard items.
+ */
+
+ /* we have to hack up the region name because "_" has a special
+ meaning for menu titles.
+ */
+
+ string::size_type pos = 0;
+ string menu_item_name = region->name();
+
+ while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
+ menu_item_name.replace (pos, 1, "__");
+ pos += 2;
+ }
+
+ edit_items.push_back (MenuElem (menu_item_name, *region_menu));
+ edit_items.push_back (SeparatorElem());
+}
+
+void
+Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
+{
+ using namespace Menu_Helpers;
+ Menu *selection_menu = manage (new Menu);
+ MenuList& items = selection_menu->items();
+ selection_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Play range"), slot (*this, &Editor::play_selection)));
+ items.push_back (MenuElem (_("Loop range"), slot (*this, &Editor::set_route_loop_selection)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Create chunk from range"), slot (*this, &Editor::name_selection)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Create Region"), slot (*this, &Editor::new_region_from_selection)));
+ items.push_back (MenuElem (_("Separate Region"), slot (*this, &Editor::separate_region_from_selection)));
+ items.push_back (MenuElem (_("Crop Region to range"), slot (*this, &Editor::crop_region_to_selection)));
+ items.push_back (MenuElem (_("Bounce range"), slot (*this, &Editor::bounce_range_selection)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Duplicate"), bind (slot (*this, &Editor::duplicate_dialog), false)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Export"), slot (*this, &Editor::export_selection)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Fill range w/Region"), slot (*this, &Editor::region_fill_selection)));
+
+ edit_items.push_back (MenuElem (_("Range"), *selection_menu));
+ edit_items.push_back (SeparatorElem());
+}
+
+void
+Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
+{
+ using namespace Menu_Helpers;
+
+ /* Playback */
+
+ Menu *play_menu = manage (new Menu);
+ MenuList& play_items = play_menu->items();
+ play_menu->set_name ("ArdourContextMenu");
+
+ play_items.push_back (MenuElem (_("Play from edit cursor")));
+ play_items.push_back (MenuElem (_("Play from start"), slot (*this, &Editor::play_from_start)));
+ play_items.push_back (MenuElem (_("Play region"), slot (*this, &Editor::play_selected_region)));
+ play_items.push_back (SeparatorElem());
+ play_items.push_back (MenuElem (_("Loop Region"), slot (*this, &Editor::loop_selected_region)));
+
+ edit_items.push_back (MenuElem (_("Play"), *play_menu));
+
+ /* Selection */
+
+ Menu *select_menu = manage (new Menu);
+ MenuList& select_items = select_menu->items();
+ select_menu->set_name ("ArdourContextMenu");
+
+ select_items.push_back (MenuElem (_("Select All in track"), bind (slot (*this, &Editor::select_all_in_track), false)));
+ select_items.push_back (MenuElem (_("Select All"), bind (slot (*this, &Editor::select_all), false)));
+ select_items.push_back (MenuElem (_("Invert in track"), slot (*this, &Editor::invert_selection_in_track)));
+ select_items.push_back (MenuElem (_("Invert"), slot (*this, &Editor::invert_selection)));
+ select_items.push_back (SeparatorElem());
+ select_items.push_back (MenuElem (_("Select loop range"), slot (*this, &Editor::set_selection_from_loop)));
+ select_items.push_back (MenuElem (_("Select punch range"), slot (*this, &Editor::set_selection_from_punch)));
+ select_items.push_back (SeparatorElem());
+
+ edit_items.push_back (MenuElem (_("Select"), *select_menu));
+
+ /* Cut-n-Paste */
+
+ Menu *cutnpaste_menu = manage (new Menu);
+ MenuList& cutnpaste_items = cutnpaste_menu->items();
+ cutnpaste_menu->set_name ("ArdourContextMenu");
+
+ cutnpaste_items.push_back (MenuElem (_("Cut"), slot (*this, &Editor::cut)));
+ cutnpaste_items.push_back (MenuElem (_("Copy"), slot (*this, &Editor::copy)));
+ cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (slot (*this, &Editor::paste), 1.0f)));
+ cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), slot (*this, &Editor::mouse_paste)));
+
+ cutnpaste_items.push_back (SeparatorElem());
+
+ cutnpaste_items.push_back (MenuElem (_("Align"), bind (slot (*this, &Editor::align), ARDOUR::SyncPoint)));
+ cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (slot (*this, &Editor::align_relative), ARDOUR::SyncPoint)));
+
+ cutnpaste_items.push_back (SeparatorElem());
+
+ cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (slot (*this, &Editor::paste_named_selection), 1.0f)));
+
+ cutnpaste_items.push_back (SeparatorElem());
+
+ cutnpaste_items.push_back (MenuElem (_("New Region from range"), slot (*this, &Editor::new_region_from_selection)));
+ cutnpaste_items.push_back (MenuElem (_("Separate Range"), slot (*this, &Editor::separate_region_from_selection)));
+
+ edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
+
+ /* Adding new material */
+
+ Menu *import_menu = manage (new Menu());
+ MenuList& import_items = import_menu->items();
+ import_menu->set_name ("ArdourContextMenu");
+
+ import_items.push_back (MenuElem (_("Insert Region"), bind (slot (*this, &Editor::insert_region_list_selection), 1.0f)));
+ import_items.push_back (MenuElem (_("Insert external sndfile"), bind (slot (*this, &Editor::insert_sndfile), false)));
+
+ edit_items.push_back (MenuElem (_("Import"), *import_menu));
+
+ /* Nudge track */
+
+ Menu *nudge_menu = manage (new Menu());
+ MenuList& nudge_items = nudge_menu->items();
+ nudge_menu->set_name ("ArdourContextMenu");
+
+ edit_items.push_back (SeparatorElem());
+ nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (slot (*this, &Editor::nudge_track), false, true))));
+ nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (slot (*this, &Editor::nudge_track), true, true))));
+ nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (slot (*this, &Editor::nudge_track), false, false))));
+ nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (slot (*this, &Editor::nudge_track), true, false))));
+
+ edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
+}
+
+void
+Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
+{
+ using namespace Menu_Helpers;
+
+ /* Playback */
+
+ Menu *play_menu = manage (new Menu);
+ MenuList& play_items = play_menu->items();
+ play_menu->set_name ("ArdourContextMenu");
+
+ play_items.push_back (MenuElem (_("Play from edit cursor")));
+ play_items.push_back (MenuElem (_("Play from start"), slot (*this, &Editor::play_from_start)));
+ edit_items.push_back (MenuElem (_("Play"), *play_menu));
+
+ /* Selection */
+
+ Menu *select_menu = manage (new Menu);
+ MenuList& select_items = select_menu->items();
+ select_menu->set_name ("ArdourContextMenu");
+
+ select_items.push_back (MenuElem (_("Select All in track"), bind (slot (*this, &Editor::select_all_in_track), false)));
+ select_items.push_back (MenuElem (_("Select All"), bind (slot (*this, &Editor::select_all), false)));
+ select_items.push_back (MenuElem (_("Invert in track"), slot (*this, &Editor::invert_selection_in_track)));
+ select_items.push_back (MenuElem (_("Invert"), slot (*this, &Editor::invert_selection)));
+ select_items.push_back (SeparatorElem());
+ select_items.push_back (MenuElem (_("Select loop range"), slot (*this, &Editor::set_selection_from_loop)));
+ select_items.push_back (MenuElem (_("Select punch range"), slot (*this, &Editor::set_selection_from_punch)));
+ select_items.push_back (SeparatorElem());
+
+ edit_items.push_back (MenuElem (_("Select"), *select_menu));
+
+ /* Cut-n-Paste */
+
+ Menu *cutnpaste_menu = manage (new Menu);
+ MenuList& cutnpaste_items = cutnpaste_menu->items();
+ cutnpaste_menu->set_name ("ArdourContextMenu");
+
+ cutnpaste_items.push_back (MenuElem (_("Cut"), slot (*this, &Editor::cut)));
+ cutnpaste_items.push_back (MenuElem (_("Copy"), slot (*this, &Editor::copy)));
+ cutnpaste_items.push_back (MenuElem (_("Paste"), bind (slot (*this, &Editor::paste), 1.0f)));
+
+ Menu *nudge_menu = manage (new Menu());
+ MenuList& nudge_items = nudge_menu->items();
+ nudge_menu->set_name ("ArdourContextMenu");
+
+ edit_items.push_back (SeparatorElem());
+ nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (slot (*this, &Editor::nudge_track), false, true))));
+ nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (slot (*this, &Editor::nudge_track), true, true))));
+ nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (slot (*this, &Editor::nudge_track), false, false))));
+ nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (slot (*this, &Editor::nudge_track), true, false))));
+
+ edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
+}
+
+/* CURSOR SETTING AND MARKS AND STUFF */
+
+void
+Editor::set_snap_to (SnapType st)
+{
+ snap_type = st;
+ vector<string> txt = internationalize (snap_type_strings);
+ snap_type_selector.get_entry()->set_text (txt[(int)st]);
+
+ instant_save ();
+
+ switch (snap_type) {
+ case SnapToAThirtysecondBeat:
+ case SnapToASixteenthBeat:
+ case SnapToAEighthBeat:
+ case SnapToAQuarterBeat:
+ case SnapToAThirdBeat:
+ update_tempo_based_rulers ();
+ default:
+ /* relax */
+ break;
+ }
+}
+
+void
+Editor::set_snap_mode (SnapMode mode)
+{
+ snap_mode = mode;
+ vector<string> txt = internationalize (snap_mode_strings);
+ snap_mode_selector.get_entry()->set_text (txt[(int)mode]);
+
+ instant_save ();
+}
+
+void
+Editor::add_location_from_selection ()
+{
+ if (selection->time.empty()) {
+ return;
+ }
+
+ if (session == 0 || clicked_trackview == 0) {
+ return;
+ }
+
+ jack_nframes_t start = selection->time[clicked_selection].start;
+ jack_nframes_t end = selection->time[clicked_selection].end;
+
+ Location *location = new Location (start, end, "selection");
+
+ session->begin_reversible_command (_("add marker"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->add (location, true);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+}
+
+void
+Editor::add_location_from_playhead_cursor ()
+{
+ jack_nframes_t where = session->audible_frame();
+
+ Location *location = new Location (where, where, "mark", Location::IsMark);
+ session->begin_reversible_command (_("add marker"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->add (location, true);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+}
+
+
+int
+Editor::set_state (const XMLNode& node)
+{
+ const XMLProperty* prop;
+ XMLNode* geometry;
+ int x, y, width, height, xoff, yoff;
+
+ if ((geometry = find_named_node (node, "geometry")) == 0) {
+
+ width = default_width;
+ height = default_height;
+ x = 1;
+ y = 1;
+ xoff = 0;
+ yoff = 21;
+
+ } else {
+
+ width = atoi(geometry->property("x_size")->value());
+ height = atoi(geometry->property("y_size")->value());
+ x = atoi(geometry->property("x_pos")->value());
+ y = atoi(geometry->property("y_pos")->value());
+ xoff = atoi(geometry->property("x_off")->value());
+ yoff = atoi(geometry->property("y_off")->value());
+ }
+
+ set_default_size(width, height);
+ set_uposition(x, y-yoff);
+
+ if ((prop = node.property ("zoom-focus"))) {
+ set_zoom_focus ((ZoomFocus) atoi (prop->value()));
+ }
+
+ if ((prop = node.property ("zoom"))) {
+ set_frames_per_unit (atof (prop->value()));
+ }
+
+ if ((prop = node.property ("snap-to"))) {
+ set_snap_to ((SnapType) atoi (prop->value()));
+ }
+
+ if ((prop = node.property ("snap-mode"))) {
+ set_snap_mode ((SnapMode) atoi (prop->value()));
+ }
+
+ if ((prop = node.property ("show-waveforms"))) {
+ bool yn = (prop->value() == "yes");
+ _show_waveforms = !yn;
+ set_show_waveforms (yn);
+ }
+
+ if ((prop = node.property ("show-waveforms-recording"))) {
+ bool yn = (prop->value() == "yes");
+ _show_waveforms_recording = !yn;
+ set_show_waveforms_recording (yn);
+ }
+
+ if ((prop = node.property ("show-measures"))) {
+ bool yn = (prop->value() == "yes");
+ _show_measures = !yn;
+ set_show_measures (yn);
+ }
+
+ if ((prop = node.property ("follow-playhead"))) {
+ bool yn = (prop->value() == "yes");
+ _follow_playhead = !yn;
+ set_follow_playhead (yn);
+ }
+
+ if ((prop = node.property ("xfades-visible"))) {
+ bool yn = (prop->value() == "yes");
+ _xfade_visibility = !yn;
+ set_xfade_visibility (yn);
+ }
+
+ if ((prop = node.property ("region-list-sort-type"))) {
+ region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
+ reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
+ }
+
+ if ((prop = node.property ("mouse-mode"))) {
+ MouseMode m = str2mousemode(prop->value());
+ mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
+ set_mouse_mode (m, true);
+ } else {
+ mouse_mode = MouseGain; /* lie, to force the mode switch */
+ set_mouse_mode (MouseObject, true);
+ }
+
+ if ((prop = node.property ("editor-mixer-button"))) {
+ editor_mixer_button.set_active(prop->value() == "yes");
+ }
+
+ return 0;
+}
+
+XMLNode&
+Editor::get_state ()
+{
+ XMLNode* node = new XMLNode ("Editor");
+ char buf[32];
+
+ if (is_realized()) {
+ Gdk_Window win = get_window();
+
+ int x, y, xoff, yoff, width, height;
+ win.get_root_origin(x, y);
+ win.get_position(xoff, yoff);
+ win.get_size(width, height);
+
+ XMLNode* geometry = new XMLNode ("geometry");
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%d", width);
+ geometry->add_property("x_size", string(buf));
+ snprintf(buf, sizeof(buf), "%d", height);
+ geometry->add_property("y_size", string(buf));
+ snprintf(buf, sizeof(buf), "%d", x);
+ geometry->add_property("x_pos", string(buf));
+ snprintf(buf, sizeof(buf), "%d", y);
+ geometry->add_property("y_pos", string(buf));
+ snprintf(buf, sizeof(buf), "%d", xoff);
+ geometry->add_property("x_off", string(buf));
+ snprintf(buf, sizeof(buf), "%d", yoff);
+ geometry->add_property("y_off", string(buf));
+ snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gtkobj()));
+ geometry->add_property("canvas_region_list_pane_pos", string(buf));
+ snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gtkobj()));
+ geometry->add_property("track_list_canvas_pane_pos", string(buf));
+ snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&region_selection_vpane)->gtkobj()));
+ geometry->add_property("region_selection_pane_pos", string(buf));
+ snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gtkobj()));
+ geometry->add_property("route_group_pane_pos", string(buf));
+
+ node->add_child_nocopy (*geometry);
+ }
+
+ snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
+ node->add_property ("zoom-focus", buf);
+ snprintf (buf, sizeof(buf), "%f", frames_per_unit);
+ node->add_property ("zoom", buf);
+ snprintf (buf, sizeof(buf), "%d", (int) snap_type);
+ node->add_property ("snap-to", buf);
+ snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
+ node->add_property ("snap-mode", buf);
+
+ node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
+ node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
+ node->add_property ("show-measures", _show_measures ? "yes" : "no");
+ node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
+ node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
+ node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
+ node->add_property ("mouse-mode", enum2str(mouse_mode));
+ node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
+
+ return *node;
+}
+
+
+
+TimeAxisView *
+Editor::trackview_by_y_position (double y)
+{
+ TrackViewList::iterator iter;
+ TimeAxisView *tv;
+
+ for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
+
+ tv = *iter;
+
+ if (tv->hidden()) {
+ continue;
+ }
+
+ if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
+ return tv;
+ }
+ }
+
+ return 0;
+}
+
+void
+Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
+{
+ Location* before = 0;
+ Location* after = 0;
+
+ if (!session) {
+ return;
+ }
+
+ const jack_nframes_t one_second = session->frame_rate();
+ const jack_nframes_t one_minute = session->frame_rate() * 60;
+
+ jack_nframes_t presnap = start;
+
+ switch (snap_type) {
+ case SnapToFrame:
+ break;
+
+ case SnapToCDFrame:
+ if (direction) {
+ start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
+ } else {
+ start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
+ }
+ break;
+ case SnapToSMPTEFrame:
+ if (direction) {
+ start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
+ } else {
+ start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
+ }
+ break;
+
+ case SnapToSMPTESeconds:
+ if (session->smpte_offset_negative())
+ {
+ start += session->smpte_offset ();
+ } else {
+ start -= session->smpte_offset ();
+ }
+ if (direction > 0) {
+ start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
+ } else {
+ start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
+ }
+
+ if (session->smpte_offset_negative())
+ {
+ start -= session->smpte_offset ();
+ } else {
+ start += session->smpte_offset ();
+ }
+ break;
+
+ case SnapToSMPTEMinutes:
+ if (session->smpte_offset_negative())
+ {
+ start += session->smpte_offset ();
+ } else {
+ start -= session->smpte_offset ();
+ }
+ if (direction) {
+ start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
+ } else {
+ start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
+ }
+ if (session->smpte_offset_negative())
+ {
+ start -= session->smpte_offset ();
+ } else {
+ start += session->smpte_offset ();
+ }
+ break;
+
+ case SnapToSeconds:
+ if (direction) {
+ start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
+ } else {
+ start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
+ }
+ break;
+
+ case SnapToMinutes:
+ if (direction) {
+ start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
+ } else {
+ start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
+ }
+ break;
+
+ case SnapToBar:
+ start = session->tempo_map().round_to_bar (start, direction);
+ break;
+
+ case SnapToBeat:
+ start = session->tempo_map().round_to_beat (start, direction);
+ break;
+
+ case SnapToAThirtysecondBeat:
+ start = session->tempo_map().round_to_beat_subdivision (start, 32);
+ break;
+
+ case SnapToASixteenthBeat:
+ start = session->tempo_map().round_to_beat_subdivision (start, 16);
+ break;
+
+ case SnapToAEighthBeat:
+ start = session->tempo_map().round_to_beat_subdivision (start, 8);
+ break;
+
+ case SnapToAQuarterBeat:
+ start = session->tempo_map().round_to_beat_subdivision (start, 4);
+ break;
+
+ case SnapToAThirdBeat:
+ start = session->tempo_map().round_to_beat_subdivision (start, 3);
+ break;
+
+ case SnapToEditCursor:
+ start = edit_cursor->current_frame;
+ break;
+
+ case SnapToMark:
+ if (for_mark) {
+ return;
+ }
+
+ before = session->locations()->first_location_before (start);
+ after = session->locations()->first_location_after (start);
+
+ if (direction < 0) {
+ if (before) {
+ start = before->start();
+ } else {
+ start = 0;
+ }
+ } else if (direction > 0) {
+ if (after) {
+ start = after->start();
+ } else {
+ start = session->current_end_frame();
+ }
+ } else {
+ if (before) {
+ if (after) {
+ /* find nearest of the two */
+ if ((start - before->start()) < (after->start() - start)) {
+ start = before->start();
+ } else {
+ start = after->start();
+ }
+ } else {
+ start = before->start();
+ }
+ } else if (after) {
+ start = after->start();
+ } else {
+ /* relax */
+ }
+ }
+ break;
+
+ case SnapToRegionStart:
+ case SnapToRegionEnd:
+ case SnapToRegionSync:
+ case SnapToRegionBoundary:
+ if (!region_boundary_cache.empty()) {
+ vector<jack_nframes_t>::iterator i;
+
+ if (direction > 0) {
+ i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
+ } else {
+ i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
+ }
+
+ if (i != region_boundary_cache.end()) {
+ start = *i;
+ } else {
+ start = region_boundary_cache.back();
+ }
+ }
+ break;
+ }
+
+ switch (snap_mode) {
+ case SnapNormal:
+ return;
+
+ case SnapMagnetic:
+
+ if (presnap > start) {
+ if (presnap > (start + unit_to_frame(snap_threshold))) {
+ start = presnap;
+ }
+
+ } else if (presnap < start) {
+ if (presnap < (start - unit_to_frame(snap_threshold))) {
+ start = presnap;
+ }
+ }
+
+ default:
+ return;
+
+ }
+}
+
+void
+Editor::setup_toolbar ()
+{
+ nstring pixmap_path;
+ vector<ToggleButton *> mouse_mode_buttons;
+
+ mouse_mode_buttons.push_back (&mouse_move_button);
+ mouse_mode_buttons.push_back (&mouse_select_button);
+ mouse_mode_buttons.push_back (&mouse_gain_button);
+ mouse_mode_buttons.push_back (&mouse_zoom_button);
+ mouse_mode_buttons.push_back (&mouse_timefx_button);
+ mouse_mode_buttons.push_back (&mouse_audition_button);
+ mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
+
+ mouse_mode_button_table.set_homogeneous (true);
+ mouse_mode_button_table.set_col_spacings (2);
+ mouse_mode_button_table.set_row_spacings (2);
+ mouse_mode_button_table.set_border_width (5);
+
+ mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
+ mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
+ mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
+
+ mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
+ mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
+ mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
+
+ mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
+ mouse_mode_tearoff->set_name ("MouseModeBase");
+
+ mouse_mode_tearoff->Detach.connect (bind (slot (*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
+ static_cast<Gtk::Widget*>(&mouse_mode_button_table)));
+ mouse_mode_tearoff->Attach.connect (bind (slot (*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
+ static_cast<Gtk::Widget*> (&mouse_mode_button_table), 1));
+
+ mouse_move_button.set_name ("MouseModeButton");
+ mouse_select_button.set_name ("MouseModeButton");
+ mouse_gain_button.set_name ("MouseModeButton");
+ mouse_zoom_button.set_name ("MouseModeButton");
+ mouse_timefx_button.set_name ("MouseModeButton");
+ mouse_audition_button.set_name ("MouseModeButton");
+
+ ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
+ ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
+ ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
+ ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
+ ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
+ ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
+
+ mouse_move_button.unset_flags (GTK_CAN_FOCUS);
+ mouse_select_button.unset_flags (GTK_CAN_FOCUS);
+ mouse_gain_button.unset_flags (GTK_CAN_FOCUS);
+ mouse_zoom_button.unset_flags (GTK_CAN_FOCUS);
+ mouse_timefx_button.unset_flags (GTK_CAN_FOCUS);
+ mouse_audition_button.unset_flags (GTK_CAN_FOCUS);
+
+ mouse_select_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
+ mouse_select_button.button_release_event.connect (slot (*this, &Editor::mouse_select_button_release));
+
+ mouse_move_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
+ mouse_gain_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
+ mouse_zoom_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
+ mouse_timefx_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
+ mouse_audition_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
+
+ // mouse_move_button.set_active (true);
+
+ /* automation control */
+
+ global_automation_button.set_name ("MouseModeButton");
+ automation_mode_button.set_name ("MouseModeButton");
+
+ automation_box.set_spacing (2);
+ automation_box.set_border_width (2);
+ automation_box.pack_start (global_automation_button, false, false);
+ automation_box.pack_start (automation_mode_button, false, false);
+
+ /* Edit mode */
+
+ edit_mode_label.set_name ("ToolBarLabel");
+
+ edit_mode_selector.set_name ("EditModeSelector");
+ edit_mode_selector.get_entry()->set_name ("EditModeSelector");
+ edit_mode_selector.get_popwin()->set_name ("EditModeSelector");
+
+ edit_mode_box.set_spacing (3);
+ edit_mode_box.set_border_width (3);
+
+ /* XXX another disgusting hack because of the way combo boxes size themselves */
+
+ Gtkmmext::set_usize_to_display_given_text (*edit_mode_selector.get_entry(), "EdgtMode", 2, 10);
+ edit_mode_selector.set_popdown_strings (internationalize (edit_mode_strings));
+ edit_mode_selector.set_value_in_list (true, false);
+
+ edit_mode_box.pack_start (edit_mode_label, false, false);
+ edit_mode_box.pack_start (edit_mode_selector, false, false);
+
+ edit_mode_selector.get_popwin()->unmap_event.connect (slot (*this, &Editor::edit_mode_selection_done));
+
+ /* Snap Type */
+
+ snap_type_label.set_name ("ToolBarLabel");
+
+ snap_type_selector.set_name ("SnapTypeSelector");
+ snap_type_selector.get_entry()->set_name ("SnapTypeSelector");
+ snap_type_selector.get_popwin()->set_name ("SnapTypeSelector");
+
+ snap_type_box.set_spacing (3);
+ snap_type_box.set_border_width (3);
+
+ /* XXX another disgusting hack because of the way combo boxes size themselves */
+
+ const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
+ Gtkmmext::set_usize_to_display_given_text (*snap_type_selector.get_entry(), "Region bounds", 2+FUDGE, 10);
+ snap_type_selector.set_popdown_strings (internationalize (snap_type_strings));
+ snap_type_selector.set_value_in_list (true, false);
+
+ snap_type_box.pack_start (snap_type_label, false, false);
+ snap_type_box.pack_start (snap_type_selector, false, false);
+
+ snap_type_selector.get_popwin()->unmap_event.connect (slot (*this, &Editor::snap_type_selection_done));
+
+ /* Snap mode, not snap type */
+
+ snap_mode_label.set_name ("ToolBarLabel");
+
+ snap_mode_selector.set_name ("SnapModeSelector");
+ snap_mode_selector.get_entry()->set_name ("SnapModeSelector");
+ snap_mode_selector.get_popwin()->set_name ("SnapModeSelector");
+
+ snap_mode_box.set_spacing (3);
+ snap_mode_box.set_border_width (3);
+
+ Gtkmmext::set_usize_to_display_given_text (*snap_mode_selector.get_entry(), "SngpMode", 2, 10);
+ snap_mode_selector.set_popdown_strings (internationalize (snap_mode_strings));
+ snap_mode_selector.set_value_in_list (true, false);
+
+ snap_mode_box.pack_start (snap_mode_label, false, false);
+ snap_mode_box.pack_start (snap_mode_selector, false, false);
+
+ snap_mode_selector.get_popwin()->unmap_event.connect (slot (*this, &Editor::snap_mode_selection_done));
+
+ /* Zoom focus mode */
+
+ zoom_focus_label.set_name ("ToolBarLabel");
+
+ zoom_focus_selector.set_name ("ZoomFocusSelector");
+ zoom_focus_selector.get_entry()->set_name ("ZoomFocusSelector");
+ zoom_focus_selector.get_popwin()->set_name ("ZoomFocusSelector");
+
+ zoom_focus_box.set_spacing (3);
+ zoom_focus_box.set_border_width (3);
+
+ /* XXX another disgusting hack because of the way combo boxes size themselves */
+
+ Gtkmmext::set_usize_to_display_given_text (*zoom_focus_selector.get_entry(), "Edgt Cursor", 2, 10);
+ zoom_focus_selector.set_popdown_strings (internationalize (zoom_focus_strings));
+ zoom_focus_selector.set_value_in_list (true, false);
+
+ zoom_focus_box.pack_start (zoom_focus_label, false, false);
+ zoom_focus_box.pack_start (zoom_focus_selector, false, false);
+
+ zoom_focus_selector.get_popwin()->unmap_event.connect (slot (*this, &Editor::zoom_focus_selection_done));
+
+ /* selection/cursor clocks */
+
+ toolbar_selection_cursor_label.set_name ("ToolBarLabel");
+ selection_start_clock_label.set_name ("ToolBarLabel");
+ selection_end_clock_label.set_name ("ToolBarLabel");
+ edit_cursor_clock_label.set_name ("ToolBarLabel");
+
+ selection_start_clock_label.set_text (_("Start:"));
+ selection_end_clock_label.set_text (_("End:"));
+ edit_cursor_clock_label.set_text (_("Edit:"));
+
+ toolbar_selection_clock_table.set_border_width (5);
+ toolbar_selection_clock_table.set_col_spacings (2);
+ toolbar_selection_clock_table.set_homogeneous (false);
+
+// toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
+// toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
+ toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, 0, 0, 0, 0);
+
+// toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
+// toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
+ toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, 0, 0);
+
+
+// toolbar_clock_vbox.set_spacing (2);
+// toolbar_clock_vbox.set_border_width (10);
+ /* the editor/mixer button will be enabled at session connect */
+
+ editor_mixer_button.set_active(false);
+ editor_mixer_button.set_sensitive(false);
+
+ HBox* hbox = new HBox;
+
+ hbox->pack_start (editor_mixer_button, false, false);
+ hbox->pack_start (toolbar_selection_clock_table, false, false);
+ hbox->pack_start (zoom_indicator_vbox, false, false);
+ hbox->pack_start (zoom_focus_box, false, false);
+ hbox->pack_start (snap_type_box, false, false);
+ hbox->pack_start (snap_mode_box, false, false);
+ hbox->pack_start (edit_mode_box, false, false);
+
+ VBox *vbox = manage (new VBox);
+
+ vbox->set_spacing (3);
+ vbox->set_border_width (3);
+
+ HBox *nbox = manage (new HBox);
+
+ nudge_forward_button.clicked.connect (bind (slot (*this, &Editor::nudge_forward), false));
+ nudge_backward_button.clicked.connect (bind (slot (*this, &Editor::nudge_backward), false));
+
+ nbox->pack_start (nudge_backward_button, false, false);
+ nbox->pack_start (nudge_forward_button, false, false);
+ nbox->pack_start (nudge_clock, false, false, 5);
+
+ nudge_label.set_name ("ToolBarLabel");
+
+ vbox->pack_start (nudge_label, false, false);
+ vbox->pack_start (*nbox, false, false);
+
+ hbox->pack_start (*vbox, false, false);
+
+ hbox->show_all ();
+
+ tools_tearoff = new TearOff (*hbox);
+ tools_tearoff->set_name ("MouseModeBase");
+
+ tools_tearoff->Detach.connect (bind (slot (*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
+ static_cast<Gtk::Widget*>(hbox)));
+ tools_tearoff->Attach.connect (bind (slot (*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
+ static_cast<Gtk::Widget*> (hbox), 0));
+
+ toolbar_hbox.set_spacing (8);
+ toolbar_hbox.set_border_width (2);
+
+ toolbar_hbox.pack_start (*tools_tearoff, false, false);
+ toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
+
+ toolbar_base.set_name ("ToolBarBase");
+ toolbar_base.add (toolbar_hbox);
+
+ toolbar_frame.set_shadow_type (GTK_SHADOW_OUT);
+ toolbar_frame.set_name ("BaseFrame");
+ toolbar_frame.add (toolbar_base);
+}
+
+gint
+Editor::_autoscroll_canvas (void *arg)
+{
+ return ((Editor *) arg)->autoscroll_canvas ();
+}
+
+gint
+Editor::autoscroll_canvas ()
+{
+ jack_nframes_t new_frame;
+ bool keep_calling = true;
+
+ if (autoscroll_direction < 0) {
+ if (leftmost_frame < autoscroll_distance) {
+ new_frame = 0;
+ } else {
+ new_frame = leftmost_frame - autoscroll_distance;
+ }
+ } else {
+ if (leftmost_frame > max_frames - autoscroll_distance) {
+ new_frame = max_frames;
+ } else {
+ new_frame = leftmost_frame + autoscroll_distance;
+ }
+ }
+
+ if (new_frame != leftmost_frame) {
+ reposition_x_origin (new_frame);
+ }
+
+ if (new_frame == 0 || new_frame == max_frames) {
+ /* we are done */
+ return FALSE;
+ }
+
+ autoscroll_cnt++;
+
+ if (autoscroll_cnt == 1) {
+
+ /* connect the timeout so that we get called repeatedly */
+
+ autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
+ keep_calling = false;
+
+ } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
+
+ /* after about a while, speed up a bit by changing the timeout interval */
+
+ autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
+ keep_calling = false;
+
+ } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
+
+ /* after about another while, speed up some more */
+
+ autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
+ keep_calling = false;
+
+ } else if (autoscroll_cnt >= 30) {
+
+ /* we've been scrolling for a while ... crank it up */
+
+ autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
+ }
+
+ return keep_calling;
+}
+
+void
+Editor::start_canvas_autoscroll (int dir)
+{
+ if (!session) {
+ return;
+ }
+
+ stop_canvas_autoscroll ();
+
+ autoscroll_direction = dir;
+ autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
+ autoscroll_cnt = 0;
+
+ /* do it right now, which will start the repeated callbacks */
+
+ autoscroll_canvas ();
+}
+
+void
+Editor::stop_canvas_autoscroll ()
+{
+ if (autoscroll_timeout_tag >= 0) {
+ gtk_timeout_remove (autoscroll_timeout_tag);
+ autoscroll_timeout_tag = -1;
+ }
+}
+
+int
+Editor::convert_drop_to_paths (vector<string>& paths,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time)
+
+{
+ string spath;
+ char *path;
+ int state;
+ gchar *tname = gdk_atom_name (data->type);
+
+ if (session == 0 || strcmp (tname, "text/plain") != 0) {
+ return -1;
+ }
+
+ /* Parse the "uri-list" format that Nautilus provides,
+ where each pathname is delimited by \r\n
+ */
+
+ path = (char *) data->data;
+ state = 0;
+
+ for (int n = 0; n < data->length; ++n) {
+
+ switch (state) {
+ case 0:
+ if (path[n] == '\r') {
+ state = 1;
+ } else {
+ spath += path[n];
+ }
+ break;
+ case 1:
+ if (path[n] == '\n') {
+ paths.push_back (spath);
+ spath = "";
+ state = 0;
+ } else {
+ warning << _("incorrectly formatted URI list, ignored")
+ << endmsg;
+ return -1;
+ }
+ break;
+ }
+ }
+
+ /* nautilus and presumably some other file managers prefix even text/plain with file:// */
+
+ for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
+
+ // cerr << "dropped text was " << *p << endl;
+
+ url_decode (*p);
+
+ // cerr << "decoded was " << *p << endl;
+
+ if ((*p).substr (0,7) == "file://") {
+ (*p) = (*p).substr (7);
+ }
+ }
+
+ return 0;
+}
+
+void
+Editor::track_canvas_drag_data_received (GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time)
+{
+ TimeAxisView* tvp;
+ AudioTimeAxisView* tv;
+ double cy;
+ vector<string> paths;
+ string spath;
+ GdkEvent ev;
+ jack_nframes_t frame;
+
+ if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
+ goto out;
+ }
+
+ /* D-n-D coordinates are window-relative, so convert to "world" coordinates
+ */
+
+ double wx;
+ double wy;
+
+ gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), (double) x, (double) y, &wx, &wy);
+
+ ev.type = GDK_BUTTON_RELEASE;
+ ev.button.x = wx;
+ ev.button.y = wy;
+
+ frame = event_frame (&ev, 0, &cy);
+
+ snap_to (frame);
+
+ if ((tvp = trackview_by_y_position (cy)) == 0) {
+
+ /* drop onto canvas background: create a new track */
+
+ insert_paths_as_new_tracks (paths, false);
+
+
+ } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
+
+ /* check that its an audio track, not a bus */
+
+ if (tv->get_diskstream()) {
+
+ for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
+ insert_sndfile_into (*p, true, tv, frame);
+ }
+ }
+
+ }
+
+ out:
+ gtk_drag_finish (context, TRUE, FALSE, time);
+}
+
+void
+Editor::new_tempo_section ()
+
+{
+}
+
+void
+Editor::map_transport_state ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &Editor::map_transport_state));
+
+ if (session->transport_stopped()) {
+ have_pending_keyboard_selection = false;
+ }
+}
+
+/* UNDO/REDO */
+
+Editor::State::State ()
+{
+ selection = new Selection;
+}
+
+Editor::State::~State ()
+{
+ delete selection;
+}
+
+UndoAction
+Editor::get_memento () const
+{
+ State *state = new State;
+
+ store_state (*state);
+ return bind (slot (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
+}
+
+void
+Editor::store_state (State& state) const
+{
+ *state.selection = *selection;
+}
+
+void
+Editor::restore_state (State *state)
+{
+ if (*selection == *state->selection) {
+ return;
+ }
+
+ *selection = *state->selection;
+ time_selection_changed ();
+ region_selection_changed ();
+
+ /* XXX other selection change handlers? */
+}
+
+void
+Editor::begin_reversible_command (string name)
+{
+ if (session) {
+ UndoAction ua = get_memento();
+ session->begin_reversible_command (name, &ua);
+ }
+}
+
+void
+Editor::commit_reversible_command ()
+{
+ if (session) {
+ UndoAction ua = get_memento();
+ session->commit_reversible_command (&ua);
+ }
+}
+
+void
+Editor::flush_track_canvas ()
+{
+ /* I don't think this is necessary, and only causes more problems.
+ I'm commenting it out
+ and if the imageframe folks don't have any issues, we can take
+ out this method entirely
+ */
+
+ //gtk_canvas_update_now (GTK_CANVAS(track_gtk_canvas));
+ //gtk_main_iteration ();
+}
+
+void
+Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
+{
+ if (!clicked_trackview) {
+ return;
+ }
+
+ if (with_undo) {
+ begin_reversible_command (_("set selected trackview"));
+ }
+
+ if (add) {
+
+ if (selection->selected (clicked_trackview)) {
+ if (!no_remove) {
+ selection->remove (clicked_trackview);
+ }
+ } else {
+ selection->add (clicked_trackview);
+ }
+
+ } else {
+
+ if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
+ /* no commit necessary */
+ return;
+ }
+
+ selection->set (clicked_trackview);
+ }
+
+ if (with_undo) {
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
+{
+ if (!clicked_control_point) {
+ return;
+ }
+
+ if (with_undo) {
+ begin_reversible_command (_("set selected control point"));
+ }
+
+ if (add) {
+
+ } else {
+
+ }
+
+ if (with_undo) {
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
+{
+ if (!clicked_regionview) {
+ return;
+ }
+
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
+
+ if (!atv) {
+ return;
+ }
+
+ RouteGroup* group = atv->route().edit_group();
+ vector<AudioRegionView*> all_equivalent_regions;
+
+ if (group && group->is_active()) {
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+
+ AudioTimeAxisView* tatv;
+
+ if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
+
+ if (tatv->route().edit_group() != group) {
+ continue;
+ }
+
+ AudioPlaylist* pl;
+ vector<AudioRegion*> results;
+ AudioRegionView* marv;
+ DiskStream* ds;
+
+ if ((ds = tatv->get_diskstream()) == 0) {
+ /* bus */
+ continue;
+ }
+
+ if ((pl = ds->playlist()) != 0) {
+ pl->get_equivalent_regions (clicked_regionview->region,
+ results);
+ }
+
+ for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
+ if ((marv = tatv->view->find_view (**ir)) != 0) {
+ all_equivalent_regions.push_back (marv);
+ }
+ }
+
+ }
+ }
+
+ } else {
+
+ all_equivalent_regions.push_back (clicked_regionview);
+
+ }
+
+ begin_reversible_command (_("set selected regionview"));
+
+ if (add) {
+
+ if (clicked_regionview->get_selected()) {
+ if (group && group->is_active() && selection->audio_regions.size() > 1) {
+ /* reduce selection down to just the one clicked */
+ selection->set (clicked_regionview);
+ } else {
+ selection->remove (clicked_regionview);
+ }
+ } else {
+ selection->add (all_equivalent_regions);
+ }
+
+ set_selected_track_from_click (add, false, no_track_remove);
+
+ } else {
+
+ // karsten wiese suggested these two lines to make
+ // a selected region rise to the top. but this
+ // leads to a mismatch between actual layering
+ // and visual layering. resolution required ....
+ //
+ // gtk_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
+ // gtk_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
+
+ if (clicked_regionview->get_selected()) {
+ /* no commit necessary: we are the one selected. */
+ return;
+
+ } else {
+
+ selection->set (all_equivalent_regions);
+ set_selected_track_from_click (add, false, false);
+ }
+ }
+
+ commit_reversible_command () ;
+}
+
+void
+Editor::set_selected_regionview_from_region_list (Region& r, bool add)
+{
+ vector<AudioRegionView*> all_equivalent_regions;
+ AudioRegion* region;
+
+ if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
+ return;
+ }
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+
+ AudioTimeAxisView* tatv;
+
+ if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
+
+ AudioPlaylist* pl;
+ vector<AudioRegion*> results;
+ AudioRegionView* marv;
+ 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<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
+ if ((marv = tatv->view->find_view (**ir)) != 0) {
+ all_equivalent_regions.push_back (marv);
+ }
+ }
+
+ }
+ }
+
+ begin_reversible_command (_("set selected regions"));
+
+ if (add) {
+
+ selection->add (all_equivalent_regions);
+
+ } else {
+
+ selection->set (all_equivalent_regions);
+ }
+
+ commit_reversible_command () ;
+}
+
+gint
+Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
+{
+ AudioRegionView* rv;
+ AudioRegion* ar;
+
+ if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
+ return TRUE;
+ }
+
+ if ((rv = sv->find_view (*ar)) == 0) {
+ return TRUE;
+ }
+
+ /* don't reset the selection if its something other than
+ a single other region.
+ */
+
+ if (selection->audio_regions.size() > 1) {
+ return TRUE;
+ }
+
+ begin_reversible_command (_("set selected regions"));
+
+ selection->set (rv);
+
+ commit_reversible_command () ;
+
+ return TRUE;
+}
+
+void
+Editor::set_edit_group_solo (Route& route, bool yn)
+{
+ RouteGroup *edit_group;
+
+ if ((edit_group = route.edit_group()) != 0) {
+ edit_group->apply (&Route::set_solo, yn, this);
+ } else {
+ route.set_solo (yn, this);
+ }
+}
+
+void
+Editor::set_edit_group_mute (Route& route, bool yn)
+{
+ RouteGroup *edit_group = 0;
+
+ if ((edit_group == route.edit_group()) != 0) {
+ edit_group->apply (&Route::set_mute, yn, this);
+ } else {
+ route.set_mute (yn, this);
+ }
+}
+
+void
+Editor::set_edit_menu (Menu& menu)
+{
+ edit_menu = &menu;
+ edit_menu->map_.connect (slot (*this, &Editor::edit_menu_map_handler));
+}
+
+void
+Editor::edit_menu_map_handler ()
+{
+ using namespace Menu_Helpers;
+ MenuList& edit_items = edit_menu->items();
+ string label;
+
+ /* Nuke all the old items */
+
+ edit_items.clear ();
+
+ if (session == 0) {
+ return;
+ }
+
+ if (session->undo_depth() == 0) {
+ label = _("Undo");
+ } else {
+ label = compose(_("Undo (%1)"), session->next_undo());
+ }
+
+ edit_items.push_back (MenuElem (label, bind (slot (*this, &Editor::undo), 1U)));
+
+ if (session->undo_depth() == 0) {
+ edit_items.back()->set_sensitive (false);
+ }
+
+ if (session->redo_depth() == 0) {
+ label = _("Redo");
+ } else {
+ label = compose(_("Redo (%1)"), session->next_redo());
+ }
+
+ edit_items.push_back (MenuElem (label, bind (slot (*this, &Editor::redo), 1U)));
+ if (session->redo_depth() == 0) {
+ edit_items.back()->set_sensitive (false);
+ }
+
+ vector<MenuItem*> mitems;
+
+ edit_items.push_back (SeparatorElem());
+ edit_items.push_back (MenuElem (_("Cut"), slot (*this, &Editor::cut)));
+ mitems.push_back (edit_items.back());
+ edit_items.push_back (MenuElem (_("Copy"), slot (*this, &Editor::copy)));
+ mitems.push_back (edit_items.back());
+ edit_items.push_back (MenuElem (_("Paste"), bind (slot (*this, &Editor::paste), 1.0f)));
+ mitems.push_back (edit_items.back());
+ edit_items.push_back (SeparatorElem());
+ edit_items.push_back (MenuElem (_("Align"), bind (slot (*this, &Editor::align), ARDOUR::SyncPoint)));
+ mitems.push_back (edit_items.back());
+ edit_items.push_back (MenuElem (_("Align Relative"), bind (slot (*this, &Editor::align_relative), ARDOUR::SyncPoint)));
+ mitems.push_back (edit_items.back());
+ edit_items.push_back (SeparatorElem());
+
+ if (selection->empty()) {
+ for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
+ (*i)->set_sensitive (false);
+ }
+ }
+
+ Menu* import_menu = manage (new Menu());
+ import_menu->set_name ("ArdourContextMenu");
+ MenuList& import_items = import_menu->items();
+
+ import_items.push_back (MenuElem (_("... as new track"), bind (slot (*this, &Editor::import_audio), true)));
+ import_items.push_back (MenuElem (_("... as new region"), bind (slot (*this, &Editor::import_audio), false)));
+
+ Menu* embed_menu = manage (new Menu());
+ embed_menu->set_name ("ArdourContextMenu");
+ MenuList& embed_items = embed_menu->items();
+
+ embed_items.push_back (MenuElem (_("... as new track"), bind (slot (*this, &Editor::insert_sndfile), true)));
+ embed_items.push_back (MenuElem (_("... as new region"), slot (*this, &Editor::embed_audio)));
+
+ edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
+ edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
+ edit_items.push_back (SeparatorElem());
+
+ edit_items.push_back (MenuElem (_("Remove last capture"), slot (*this, &Editor::remove_last_capture)));
+ if (!session->have_captured()) {
+ edit_items.back()->set_sensitive (false);
+ }
+}
+
+void
+Editor::duplicate_dialog (bool dup_region)
+{
+ if (dup_region) {
+ if (clicked_regionview == 0) {
+ return;
+ }
+ } else {
+ if (selection->time.length() == 0) {
+ return;
+ }
+ }
+
+ ArdourDialog win ("duplicate dialog");
+ Entry entry;
+ Label label (_("Duplicate how many times?"));
+ HBox hbox;
+ HBox button_box;
+ Button ok_button (_("OK"));
+ Button cancel_button (_("Cancel"));
+ VBox vbox;
+
+ button_box.set_spacing (7);
+ set_usize_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose
+ set_usize_to_display_given_text (cancel_button, _("Cancel"), 20, 15);
+ button_box.pack_end (ok_button, false, false);
+ button_box.pack_end (cancel_button, false, false);
+
+ hbox.set_spacing (5);
+ hbox.pack_start (label);
+ hbox.pack_start (entry, true, true);
+
+ vbox.set_spacing (5);
+ vbox.set_border_width (5);
+ vbox.pack_start (hbox);
+ vbox.pack_start (button_box);
+
+ win.add (vbox);
+ win.set_position (GTK_WIN_POS_MOUSE);
+ win.show_all ();
+
+ ok_button.clicked.connect (bind (slot (win, &ArdourDialog::stop), 0));
+ entry.activate.connect (bind (slot (win, &ArdourDialog::stop), 0));
+ cancel_button.clicked.connect (bind (slot (win, &ArdourDialog::stop), 1));
+
+ entry.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event));
+ entry.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event));
+
+ entry.set_text ("1");
+ set_usize_to_display_given_text (entry, X_("12345678"), 20, 15);
+ entry.select_region (0, entry.get_text_length());
+
+ win.set_position (GTK_WIN_POS_MOUSE);
+ win.realize ();
+ win.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ entry.grab_focus ();
+
+ win.run ();
+
+ if (win.run_status() != 0) {
+ return;
+ }
+
+ string text = entry.get_text();
+ float times;
+
+ if (sscanf (text.c_str(), "%f", &times) == 1) {
+ if (dup_region) {
+ AudioRegionSelection regions;
+ regions.add (clicked_regionview);
+ duplicate_some_regions (regions, times);
+ } else {
+ duplicate_selection (times);
+ }
+ }
+}
+
+void
+Editor::show_verbose_canvas_cursor ()
+{
+ gtk_canvas_item_raise_to_top (verbose_canvas_cursor);
+ gtk_canvas_item_show (verbose_canvas_cursor);
+ verbose_cursor_visible = true;
+}
+
+void
+Editor::hide_verbose_canvas_cursor ()
+{
+ gtk_canvas_item_hide (verbose_canvas_cursor);
+ verbose_cursor_visible = false;
+}
+
+void
+Editor::set_verbose_canvas_cursor (string txt, double x, double y)
+{
+ /* XXX get origin of canvas relative to root window,
+ add x and y and check compared to gdk_screen_{width,height}
+ */
+ gtk_canvas_item_set (verbose_canvas_cursor, "text", txt.c_str(), "x", x, "y", y, NULL);
+}
+
+void
+Editor::set_verbose_canvas_cursor_text (string txt)
+{
+ gtk_canvas_item_set (verbose_canvas_cursor, "text", txt.c_str(), NULL);
+}
+
+gint
+Editor::edit_mode_selection_done (GdkEventAny *ev)
+{
+ if (session == 0) {
+ return FALSE;
+ }
+
+ string choice = edit_mode_selector.get_entry()->get_text();
+ EditMode mode = Slide;
+
+ if (choice == _("Splice")) {
+ mode = Splice;
+ } else if (choice == _("Slide")) {
+ mode = Slide;
+ }
+
+ session->set_edit_mode (mode);
+
+ return FALSE;
+}
+
+gint
+Editor::snap_type_selection_done (GdkEventAny *ev)
+{
+ if (session == 0) {
+ return FALSE;
+ }
+
+ string choice = snap_type_selector.get_entry()->get_text();
+ SnapType snaptype = SnapToFrame;
+
+ if (choice == _("Beats/3")) {
+ snaptype = SnapToAThirdBeat;
+ } else if (choice == _("Beats/4")) {
+ snaptype = SnapToAQuarterBeat;
+ } else if (choice == _("Beats/8")) {
+ snaptype = SnapToAEighthBeat;
+ } else if (choice == _("Beats/16")) {
+ snaptype = SnapToASixteenthBeat;
+ } else if (choice == _("Beats/32")) {
+ snaptype = SnapToAThirtysecondBeat;
+ } else if (choice == _("Beats")) {
+ snaptype = SnapToBeat;
+ } else if (choice == _("Bars")) {
+ snaptype = SnapToBar;
+ } else if (choice == _("Marks")) {
+ snaptype = SnapToMark;
+ } else if (choice == _("Edit Cursor")) {
+ snaptype = SnapToEditCursor;
+ } else if (choice == _("Region starts")) {
+ snaptype = SnapToRegionStart;
+ } else if (choice == _("Region ends")) {
+ snaptype = SnapToRegionEnd;
+ } else if (choice == _("Region bounds")) {
+ snaptype = SnapToRegionBoundary;
+ } else if (choice == _("Region syncs")) {
+ snaptype = SnapToRegionSync;
+ } else if (choice == _("CD Frames")) {
+ snaptype = SnapToCDFrame;
+ } else if (choice == _("SMPTE Frames")) {
+ snaptype = SnapToSMPTEFrame;
+ } else if (choice == _("SMPTE Seconds")) {
+ snaptype = SnapToSMPTESeconds;
+ } else if (choice == _("SMPTE Minutes")) {
+ snaptype = SnapToSMPTEMinutes;
+ } else if (choice == _("Seconds")) {
+ snaptype = SnapToSeconds;
+ } else if (choice == _("Minutes")) {
+ snaptype = SnapToMinutes;
+ } else if (choice == _("None")) {
+ snaptype = SnapToFrame;
+ }
+
+ set_snap_to (snaptype);
+
+ return FALSE;
+}
+
+gint
+Editor::snap_mode_selection_done (GdkEventAny *ev)
+{
+ if(session == 0) return FALSE;
+
+ string choice = snap_mode_selector.get_entry()->get_text();
+ SnapMode mode = SnapNormal;
+
+ if (choice == _("Normal")) {
+ mode = SnapNormal;
+ } else if (choice == _("Magnetic")) {
+ mode = SnapMagnetic;
+ }
+
+ set_snap_mode (mode);
+
+ return FALSE;
+}
+
+gint
+Editor::zoom_focus_selection_done (GdkEventAny *ev)
+{
+ if (session == 0) {
+ return FALSE;
+ }
+
+ string choice = zoom_focus_selector.get_entry()->get_text();
+ ZoomFocus focus_type = ZoomFocusLeft;
+
+ if (choice == _("Left")) {
+ focus_type = ZoomFocusLeft;
+ } else if (choice == _("Right")) {
+ focus_type = ZoomFocusRight;
+ } else if (choice == _("Center")) {
+ focus_type = ZoomFocusCenter;
+ } else if (choice == _("Playhead")) {
+ focus_type = ZoomFocusPlayhead;
+ } else if (choice == _("Edit Cursor")) {
+ focus_type = ZoomFocusEdit;
+ }
+
+ set_zoom_focus (focus_type);
+
+ return FALSE;
+}
+
+gint
+Editor::edit_controls_button_release (GdkEventButton* ev)
+{
+ if (Keyboard::is_context_menu_event (ev)) {
+ ARDOUR_UI::instance()->add_route ();
+ }
+ return TRUE;
+}
+
+void
+Editor::track_selection_changed ()
+{
+ switch (selection->tracks.size()){
+ case 0:
+ break;
+ default:
+ set_selected_mixer_strip (*(selection->tracks.front()));
+ break;
+ }
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->set_selected (false);
+ if (mouse_mode == MouseRange) {
+ (*i)->hide_selection ();
+ }
+ }
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ (*i)->set_selected (true);
+ if (mouse_mode == MouseRange) {
+ (*i)->show_selection (selection->time);
+ }
+ }
+}
+
+void
+Editor::time_selection_changed ()
+{
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->hide_selection ();
+ }
+
+ if (selection->tracks.empty()) {
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->show_selection (selection->time);
+ }
+ } else {
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ (*i)->show_selection (selection->time);
+ }
+ }
+}
+
+void
+Editor::region_selection_changed ()
+{
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->set_selected_regionviews (selection->audio_regions);
+ }
+}
+
+void
+Editor::point_selection_changed ()
+{
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->set_selected_points (selection->points);
+ }
+}
+
+void
+Editor::run_sub_event_loop ()
+{
+ Keyboard::the_keyboard().allow_focus (true);
+ sub_event_loop_status = 0;
+ Main::run ();
+}
+
+void
+Editor::finish_sub_event_loop (int status)
+{
+ Main::quit ();
+ Keyboard::the_keyboard().allow_focus (false);
+ sub_event_loop_status = status;
+}
+
+gint
+Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
+{
+ finish_sub_event_loop (status);
+ return TRUE;
+}
+
+gint
+Editor::mouse_select_button_release (GdkEventButton* ev)
+{
+ /* this handles just right-clicks */
+
+ if (ev->button != 3) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+Editor::TrackViewList *
+Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
+{
+ TrackViewList *v;
+ TrackViewList::iterator i;
+
+ v = new TrackViewList;
+
+ if (track == 0 && group == 0) {
+
+ /* all views */
+
+ for (i = track_views.begin(); i != track_views.end (); ++i) {
+ v->push_back (*i);
+ }
+
+ } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
+
+ /* just the view for this track
+ */
+
+ v->push_back (track);
+
+ } else {
+
+ /* views for all tracks in the edit group */
+
+ for (i = track_views.begin(); i != track_views.end (); ++i) {
+
+ if (group == 0 || (*i)->edit_group() == group) {
+ v->push_back (*i);
+ }
+ }
+ }
+
+ return v;
+}
+
+void
+Editor::set_zoom_focus (ZoomFocus f)
+{
+ if (zoom_focus != f) {
+ zoom_focus = f;
+ vector<string> txt = internationalize (zoom_focus_strings);
+ zoom_focus_selector.get_entry()->set_text (txt[(int)f]);
+ ZoomFocusChanged (); /* EMIT_SIGNAL */
+
+ instant_save ();
+ }
+}
+
+void
+Editor::ensure_float (Window& win)
+{
+ win.set_transient_for (*this);
+}
+
+void
+Editor::pane_allocation_handler (GtkAllocation *alloc, Gtk::Paned* which)
+{
+ /* recover or initialize pane positions. do this here rather than earlier because
+ we don't want the positions to change the child allocations, which they seem to do.
+ */
+
+ int pos;
+ XMLProperty* prop;
+ char buf[32];
+ XMLNode* node = ARDOUR_UI::instance()->editor_settings();
+ int width, height;
+ static int32_t done[4] = { 0, 0, 0, 0 };
+ XMLNode* geometry;
+
+ if ((geometry = find_named_node (*node, "geometry")) == 0) {
+ width = default_width;
+ height = default_height;
+ } else {
+ width = atoi(geometry->property("x_size")->value());
+ height = atoi(geometry->property("y_size")->value());
+ }
+
+ if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
+
+ if (done[0]) {
+ return;
+ }
+
+ if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
+ pos = 75;
+ snprintf (buf, sizeof(buf), "%d", pos);
+ } else {
+ pos = atoi (prop->value());
+ }
+
+ if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gtkobj())->allocation.width > pos)) {
+ track_list_canvas_pane.set_position (pos);
+ }
+
+ } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
+
+ if (done[1]) {
+ return;
+ }
+
+ if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
+ pos = width - (95 * 2);
+ snprintf (buf, sizeof(buf), "%d", pos);
+ } else {
+ pos = atoi (prop->value());
+ }
+
+ if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gtkobj())->allocation.width > pos)) {
+ canvas_region_list_pane.set_position (pos);
+ }
+
+ } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
+
+ if (done[2]) {
+ return;
+ }
+
+ if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
+ pos = width - (95 * 2);
+ snprintf (buf, sizeof(buf), "%d", pos);
+ } else {
+ pos = atoi (prop->value());
+ }
+
+ if ((done[2] = GTK_WIDGET(route_group_vpane.gtkobj())->allocation.height > pos)) {
+ route_group_vpane.set_position (pos);
+ }
+
+ } else if (which == static_cast<Gtk::Paned*> (&region_selection_vpane)) {
+
+ if (done[3]) {
+ return;
+ }
+
+ if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
+ pos = width - (95 * 2);
+ snprintf (buf, sizeof(buf), "%d", pos);
+ } else {
+ pos = atoi (prop->value());
+ }
+
+ if ((done[3] = GTK_WIDGET(region_selection_vpane.gtkobj())->allocation.height > pos)) {
+ region_selection_vpane.set_position (pos);
+ }
+ }
+}
+
+void
+Editor::detach_tearoff (Gtk::Box* b, Gtk::Widget* w)
+{
+ if (tools_tearoff->torn_off() &&
+ mouse_mode_tearoff->torn_off()) {
+ top_hbox.remove (toolbar_frame);
+ }
+
+ ensure_float (*w->get_toplevel());
+}
+
+void
+Editor::reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n)
+{
+ if (toolbar_frame.get_parent() == 0) {
+ top_hbox.pack_end (toolbar_frame);
+ }
+}
+
+void
+Editor::set_show_measures (bool yn)
+{
+ if (_show_measures != yn) {
+ hide_measures ();
+
+ if ((_show_measures = yn) == true) {
+ draw_measures ();
+ }
+ DisplayControlChanged (ShowMeasures);
+ instant_save ();
+ }
+}
+
+void
+Editor::set_follow_playhead (bool yn)
+{
+ if (_follow_playhead != yn) {
+ if ((_follow_playhead = yn) == true) {
+ /* catch up */
+ update_current_screen ();
+ }
+ DisplayControlChanged (FollowPlayhead);
+ instant_save ();
+ }
+}
+
+void
+Editor::toggle_xfade_active (Crossfade* xfade)
+{
+ xfade->set_active (!xfade->active());
+}
+
+void
+Editor::toggle_xfade_length (Crossfade* xfade)
+{
+ xfade->set_follow_overlap (!xfade->following_overlap());
+}
+
+void
+Editor::edit_xfade (Crossfade* xfade)
+{
+ CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
+
+ ensure_float (cew);
+
+ cew.ok_button.clicked.connect (bind (slot (cew, &ArdourDialog::stop), 1));
+ cew.cancel_button.clicked.connect (bind (slot (cew, &ArdourDialog::stop), 0));
+ cew.delete_event.connect (slot (cew, &ArdourDialog::wm_doi_event_stop));
+
+ cew.run ();
+
+ if (cew.run_status() == 1) {
+ cew.apply ();
+ xfade->StateChanged (Change (~0));
+ }
+}
+
+PlaylistSelector&
+Editor::playlist_selector () const
+{
+ return *_playlist_selector;
+}
+
+jack_nframes_t
+Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
+{
+ jack_nframes_t ret;
+
+ ret = nudge_clock.current_duration (pos);
+ next = ret + 1; /* XXXX fix me */
+
+ return ret;
+}
+
+void
+Editor::end_location_changed (Location* location)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &Editor::end_location_changed), location));
+ track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
+}
+
+int
+Editor::playlist_deletion_dialog (Playlist* pl)
+{
+ ArdourDialog dialog ("playlist deletion dialog");
+ Label label (compose (_("Playlist %1 is currently unused.\n"
+ "If left alone, no audio files used by it will be cleaned.\n"
+ "If deleted, audio files used by it alone by will cleaned."),
+ pl->name()));
+ HBox button_box;
+ Button del_button (_("Delete playlist"));
+ Button keep_button (_("Keep playlist"));
+ Button abort_button (_("Cancel cleanup"));
+ VBox vbox;
+
+ button_box.set_spacing (7);
+ button_box.set_homogeneous (true);
+ button_box.pack_end (del_button, false, false);
+ button_box.pack_end (keep_button, false, false);
+ button_box.pack_end (abort_button, false, false);
+
+ vbox.set_spacing (5);
+ vbox.set_border_width (5);
+ vbox.pack_start (label);
+ vbox.pack_start (button_box);
+
+ dialog.add (vbox);
+ dialog.set_position (GTK_WIN_POS_CENTER);
+ dialog.show_all ();
+
+ del_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 0));
+ keep_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 1));
+ abort_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 2));
+
+ dialog.realize ();
+ dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ dialog.run ();
+
+ switch (dialog.run_status()) {
+ case 1:
+ /* keep the playlist */
+ return 1;
+ break;
+ case 0:
+ /* delete the playlist */
+ return 0;
+ break;
+ case 2:
+ /* abort cleanup */
+ return -1;
+ break;
+ default:
+ /* keep the playlist */
+ return 1;
+ }
+}
+
+bool
+Editor::audio_region_selection_covers (jack_nframes_t where)
+{
+ for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
+ if ((*a)->region.covers (where)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+Editor::prepare_for_cleanup ()
+{
+ cut_buffer->clear_audio_regions ();
+ cut_buffer->clear_playlists ();
+
+ selection->clear_audio_regions ();
+ selection->clear_playlists ();
+}
+
+void
+Editor::init_colormap ()
+{
+ for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
+ pair<ColorID,int> newpair;
+
+ newpair.first = (ColorID) x;
+ newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
+ color_map.insert (newpair);
+ }
+}
+
+Location*
+Editor::transport_loop_location()
+{
+ if (session) {
+ return session->locations()->auto_loop_location();
+ } else {
+ return 0;
+ }
+}
+
+Location*
+Editor::transport_punch_location()
+{
+ if (session) {
+ return session->locations()->auto_punch_location();
+ } else {
+ return 0;
+ }
+}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
new file mode 100644
index 0000000000..9f90c9f4a2
--- /dev/null
+++ b/gtk2_ardour/editor.h
@@ -0,0 +1,1823 @@
+/*
+ Copyright (C) 2000-2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_editor_h__
+#define __ardour_editor_h__
+
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+#include <sys/time.h>
+
+#include <cmath>
+
+#include <sndfile.h>
+
+#include <gtk--.h>
+#include <gtk--/layout.h>
+#include <gtk-canvas.h>
+#include <gtk-canvas/gtk-canvas-util.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/click_box.h>
+
+#include <ardour/stateful.h>
+#include <ardour/session.h>
+#include <ardour/tempo.h>
+#include <ardour/location.h>
+#include <ardour/region.h>
+
+#include "keyboard_target.h"
+#include "audio_clock.h"
+#include "gtk-custom-ruler.h"
+#include "ardour_dialog.h"
+#include "public_editor.h"
+#include "editing.h"
+#include "enums.h"
+#include "region_selection.h"
+
+namespace Gtkmmext {
+ class TearOff;
+}
+
+namespace LinuxAudioSystems {
+ class AudioEngine;
+}
+
+namespace ARDOUR {
+ class DiskStream;
+ class RouteGroup;
+ class Source;
+ class Playlist;
+ class Region;
+ class Location;
+ class TempoSection;
+ class NamedSelection;
+ class Session;
+ class AudioFilter;
+ class Crossfade;
+}
+
+namespace LADSPA {
+ class Plugin;
+}
+
+class TimeAxisView;
+class AudioTimeAxisView;
+class AutomationTimeAxisView;
+class AudioRegionView;
+class CrossfadeView;
+class PluginSelector;
+class PlaylistSelector;
+class Marker;
+class GroupedButtons;
+class AutomationLine;
+class UIExportSpecification;
+class ExportDialog;
+class Selection;
+class TimeSelection;
+class TrackSelection;
+class AutomationSelection;
+class MixerStrip;
+class SoundFileSelector;
+class StreamView;
+class ControlPoint;
+
+/* <CMT Additions> */
+class ImageFrameView;
+class ImageFrameTimeAxisView;
+class ImageFrameTimeAxis;
+class MarkerTimeAxis ;
+class MarkerView ;
+class ImageFrameSocketHandler ;
+class TimeAxisViewItem ;
+/* </CMT Additions> */
+
+
+class Editor : public PublicEditor
+{
+ public:
+ Editor (ARDOUR::AudioEngine&);
+ ~Editor ();
+
+ void connect_to_session (ARDOUR::Session *);
+ ARDOUR::Session* current_session() const { return session; }
+
+ jack_nframes_t leftmost_position() const { return leftmost_frame; }
+ jack_nframes_t current_page_frames() const {
+ return (jack_nframes_t) floor (canvas_width * frames_per_unit);
+ }
+
+ void set_snap_to (Editing::SnapType);
+ void set_snap_mode (Editing::SnapMode);
+ void set_snap_threshold (double pixel_distance) {snap_threshold = pixel_distance;}
+
+ void undo (uint32_t n = 1);
+ void redo (uint32_t n = 1);
+
+ XMLNode& get_state ();
+ int set_state (const XMLNode& );
+
+ void set_mouse_mode (Editing::MouseMode, bool force=true);
+ void step_mouse_mode (bool next);
+ Editing::MouseMode current_mouse_mode () { return mouse_mode; }
+
+ void add_imageframe_time_axis(std::string track_name, void*) ;
+ void add_imageframe_marker_time_axis(std::string track_name, TimeAxisView* marked_track, void*) ;
+ void connect_to_image_compositor() ;
+ void scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) ;
+ TimeAxisView* get_named_time_axis(std::string name) ;
+ /* </CMT Additions> */
+
+ /* public access to auditioning */
+
+ bool consider_auditioning (ARDOUR::AudioRegion*);
+
+ /* option editor-access */
+
+ void set_show_waveforms (bool yn);
+ bool show_waveforms() const { return _show_waveforms; }
+
+ void set_show_waveforms_recording (bool yn);
+ bool show_waveforms_recording() const { return _show_waveforms_recording; }
+
+ /* things that need to be public to be used in the main menubar */
+
+ void new_region_from_selection ();
+ void separate_region_from_selection ();
+ void toggle_playback (bool with_abort);
+
+ /* undo related */
+
+ void set_edit_menu (Gtk::Menu&);
+
+ jack_nframes_t unit_to_frame (double unit) {
+ return (jack_nframes_t) rint (unit * frames_per_unit);
+ }
+
+ double frame_to_unit (jack_nframes_t frame) {
+ return rint ((double) frame / (double) frames_per_unit);
+ }
+
+ double frame_to_unit (double frame) {
+ return rint (frame / frames_per_unit);
+ }
+
+ /* NOTE: these functions assume that the "pixel" coordinate is
+ the result of using the world->canvas affine transform on a
+ world coordinate. These coordinates already take into
+ account any scrolling carried out by adjusting the
+ xscroll_adjustment.
+ */
+
+ jack_nframes_t pixel_to_frame (double pixel) {
+
+ /* pixel can be less than zero when motion events
+ are processed. since we've already run the world->canvas
+ affine, that means that the location *really* is "off
+ to the right" and thus really is "before the start".
+ */
+
+ if (pixel >= 0) {
+ return (jack_nframes_t) rint (pixel * frames_per_unit * GTK_CANVAS(track_gtk_canvas)->pixels_per_unit);
+ } else {
+ return 0;
+ }
+ }
+
+ gulong frame_to_pixel (jack_nframes_t frame) {
+ return (gulong) rint ((frame / (frames_per_unit * GTK_CANVAS(track_gtk_canvas)->pixels_per_unit)));
+ }
+
+ /* selection */
+
+ Selection& get_selection() const { return *selection; }
+ Selection& get_cut_buffer() const { return *cut_buffer; }
+
+ void play_selection ();
+ void select_all_in_track (bool add);
+ void select_all (bool add);
+ void invert_selection_in_track ();
+ void invert_selection ();
+
+ /* tempo */
+
+ void set_show_measures (bool yn);
+ bool show_measures () const { return _show_measures; }
+
+ /* export */
+
+ /* these initiate export ... */
+
+ void export_session();
+ void export_selection();
+
+ /* this is what actually does it */
+
+ void export_audiofile (ARDOUR::AudioExportSpecification&);
+
+ /* */
+
+ void add_toplevel_controls (Gtk::Container&);
+
+ void set_zoom_focus (Editing::ZoomFocus);
+ Editing::ZoomFocus get_zoom_focus () const { return zoom_focus; }
+ gdouble get_current_zoom () { return frames_per_unit; }
+
+ void temporal_zoom_step (bool coarser);
+
+ /* stuff that AudioTimeAxisView and related classes use */
+
+ PlaylistSelector& playlist_selector() const;
+ void route_name_changed (TimeAxisView *);
+ gdouble frames_per_unit;
+ jack_nframes_t leftmost_frame;
+ void clear_playlist (ARDOUR::Playlist&);
+
+ TrackViewList* get_valid_views (TimeAxisView*, ARDOUR::RouteGroup* grp = 0);
+
+ Width editor_mixer_strip_width;
+ void show_editor_mixer (bool yn);
+ void set_selected_mixer_strip (TimeAxisView&);
+ void unselect_strip_in_display (TimeAxisView& tv);
+ void select_strip_in_display (TimeAxisView& tv);
+
+ /* nudge is initiated by transport controls owned by ARDOUR_UI */
+
+ void nudge_forward (bool next);
+ void nudge_backward (bool next);
+
+ /* nudge initiated from context menu */
+
+ void nudge_forward_capture_offset ();
+ void nudge_backward_capture_offset ();
+
+ /* playhead/screen stuff */
+
+ void set_follow_playhead (bool yn);
+ void toggle_follow_playhead ();
+ bool follow_playhead() const { return _follow_playhead; }
+
+ /* xfades */
+
+ void toggle_xfades_active();
+ void toggle_xfade_visibility ();
+ void set_xfade_visibility (bool yn);
+ bool xfade_visibility() const { return _xfade_visibility; }
+
+ /* redirect shared ops menu. caller must free returned menu */
+
+ Gtk::Menu* redirect_menu ();
+
+ /* floating windows/transient */
+
+ void ensure_float (Gtk::Window&);
+
+ void show_window ();
+
+ void scroll_tracks_down_line ();
+ void scroll_tracks_up_line ();
+
+ bool new_regionviews_display_gain () { return _new_regionviews_show_envelope; }
+ void prepare_for_cleanup ();
+
+ void reposition_x_origin (jack_nframes_t sample);
+
+ protected:
+ void map_transport_state ();
+ void map_position_change (jack_nframes_t);
+
+ void realize_impl();
+ void map__impl();
+
+ private:
+
+ ARDOUR::Session *session;
+ ARDOUR::AudioEngine& engine;
+ bool constructed;
+
+ PlaylistSelector* _playlist_selector;
+
+ enum ItemType {
+ RegionItem,
+ StreamItem,
+ PlayheadCursorItem,
+ EditCursorItem,
+ MarkerItem,
+ MarkerBarItem,
+ RangeMarkerBarItem,
+ TransportMarkerBarItem,
+ SelectionItem,
+ GainControlPointItem,
+ GainLineItem,
+ GainAutomationControlPointItem,
+ GainAutomationLineItem,
+ PanAutomationControlPointItem,
+ PanAutomationLineItem,
+ RedirectAutomationControlPointItem,
+ RedirectAutomationLineItem,
+ MeterMarkerItem,
+ TempoMarkerItem,
+ MeterBarItem,
+ TempoBarItem,
+ AudioRegionViewNameHighlight,
+ AudioRegionViewName,
+ StartSelectionTrimItem,
+ EndSelectionTrimItem,
+ AutomationTrackItem,
+ FadeInItem,
+ FadeInHandleItem,
+ FadeOutItem,
+ FadeOutHandleItem,
+
+ /* <CMT Additions> */
+ MarkerViewItem,
+ MarkerTimeAxisItem,
+ MarkerViewHandleStartItem,
+ MarkerViewHandleEndItem,
+ ImageFrameItem,
+ ImageFrameTimeAxisItem,
+ ImageFrameHandleStartItem,
+ ImageFrameHandleEndItem,
+ /* </CMT Additions> */
+
+ CrossfadeViewItem,
+
+ /* don't remove this */
+
+ NoItem
+ };
+
+ void set_frames_per_unit (double);
+ void frames_per_unit_modified ();
+
+ Editing::MouseMode mouse_mode;
+ void mouse_insert (GdkEventButton *);
+
+ void pane_allocation_handler (GtkAllocation*, Gtk::Paned*);
+
+ Gtk::HPaned canvas_region_list_pane;
+ Gtk::HPaned track_list_canvas_pane;
+
+ Gtk::EventBox meter_base;
+ Gtk::HBox meter_box;
+ Gtk::EventBox marker_base;
+ Gtk::HBox marker_box;
+ Gtk::VBox scrollers_rulers_markers_box;
+
+ void location_changed (ARDOUR::Location *);
+ void location_flags_changed (ARDOUR::Location *, void *);
+ void refresh_location_display ();
+ void refresh_location_display_s (ARDOUR::Change);
+ void refresh_location_display_internal (ARDOUR::Locations::LocationList&);
+ void add_new_location (ARDOUR::Location *);
+ void location_gone (ARDOUR::Location *);
+ void remove_marker (GtkCanvasItem*, GdkEvent*);
+ gint really_remove_marker (ARDOUR::Location* loc);
+
+ uint32_t location_marker_color;
+ uint32_t location_range_color;
+ uint32_t location_loop_color;
+ uint32_t location_punch_color;
+ uint32_t location_cd_marker_color;
+
+ struct LocationMarkers {
+ Marker* start;
+ Marker* end;
+
+ ~LocationMarkers ();
+
+ void hide();
+ void show ();
+ void set_name (const string&);
+ void set_position (jack_nframes_t start, jack_nframes_t end = 0);
+ void set_color_rgba (uint32_t);
+ };
+
+ LocationMarkers *find_location_markers (ARDOUR::Location *);
+ ARDOUR::Location* find_location_from_marker (Marker *, bool& is_start);
+
+ typedef map<ARDOUR::Location*,LocationMarkers *> LocationMarkerMap;
+ LocationMarkerMap location_markers;
+
+ void hide_marker (GtkCanvasItem*, GdkEvent*);
+ void clear_marker_display ();
+ void mouse_add_new_marker (jack_nframes_t where);
+
+ TimeAxisView* clicked_trackview;
+ AudioTimeAxisView* clicked_audio_trackview;
+ AudioRegionView* clicked_regionview;
+ AudioRegionView* latest_regionview;
+ uint32_t clicked_selection;
+ CrossfadeView* clicked_crossfadeview;
+ ControlPoint* clicked_control_point;
+
+ void catch_vanishing_audio_regionview (AudioRegionView *);
+ void set_selected_control_point_from_click (bool add = false, bool with_undo = true, bool no_remove=false);
+ void set_selected_track_from_click (bool add = false, bool with_undo = true, bool no_remove=false);
+ void set_selected_regionview_from_click (bool add = false, bool no_track_remove=false);
+ void set_selected_regionview_from_region_list (ARDOUR::Region& region, bool add = false);
+ gint set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*);
+ void collect_new_region_view (AudioRegionView *);
+
+ Gtk::Menu track_context_menu;
+ Gtk::Menu track_region_context_menu;
+ Gtk::Menu track_selection_context_menu;
+ Gtk::Menu track_crossfade_context_menu;
+
+ Gtk::MenuItem* region_edit_menu_split_item;
+ Gtk::MenuItem* region_edit_menu_split_multichannel_item;
+ Gtk::Menu * track_region_edit_playlist_menu;
+ Gtk::Menu * track_edit_playlist_submenu;
+ Gtk::Menu * track_selection_edit_playlist_submenu;
+
+ void popup_track_context_menu (int, int, ItemType, bool, jack_nframes_t);
+ Gtk::Menu* build_track_context_menu (jack_nframes_t);
+ Gtk::Menu* build_track_bus_context_menu (jack_nframes_t);
+ Gtk::Menu* build_track_region_context_menu (jack_nframes_t frame);
+ Gtk::Menu* build_track_crossfade_context_menu (jack_nframes_t);
+ Gtk::Menu* build_track_selection_context_menu (jack_nframes_t);
+ void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&);
+ void add_bus_context_items (Gtk::Menu_Helpers::MenuList&);
+ void add_region_context_items (StreamView*, ARDOUR::Region*, Gtk::Menu_Helpers::MenuList&);
+ void add_crossfade_context_items (StreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many);
+ void add_selection_context_items (Gtk::Menu_Helpers::MenuList&);
+
+ void handle_new_route (ARDOUR::Route&);
+ void handle_new_route_p (ARDOUR::Route*);
+ void remove_route (TimeAxisView *);
+ bool route_removal;
+
+ Gtk::HBox global_hpacker;
+ Gtk::VBox global_vpacker;
+ Gtk::VBox vpacker;
+
+ GdkCursor *current_canvas_cursor;
+
+ GtkWidget *track_gtk_canvas;
+ GtkWidget *time_gtk_canvas;
+ Gtk::Widget *track_canvas;
+ Gtk::Widget *time_canvas;
+
+ GtkCanvasItem* first_action_message;
+ GtkCanvasItem *verbose_canvas_cursor;
+ bool verbose_cursor_visible;
+
+ void session_control_changed (ARDOUR::Session::ControlType);
+ void queue_session_control_changed (ARDOUR::Session::ControlType);
+
+
+ gint track_canvas_motion (GtkCanvasItem*, GdkEvent*);
+ void set_verbose_canvas_cursor (string, double x, double y);
+ void set_verbose_canvas_cursor_text (string);
+ void show_verbose_canvas_cursor();
+ void hide_verbose_canvas_cursor();
+
+ bool verbose_cursor_on; // so far unused
+
+ void flush_track_canvas ();
+ void flush_time_canvas ();
+
+ Gtk::EventBox time_canvas_event_box;
+ Gtk::EventBox track_canvas_event_box;
+ Gtk::EventBox time_button_event_box;
+
+ GtkCanvasItem *minsec_group;
+ GtkCanvasItem *bbt_group;
+ GtkCanvasItem *smpte_group;
+ GtkCanvasItem *frame_group;
+ GtkCanvasItem *tempo_group;
+ GtkCanvasItem *meter_group;
+ GtkCanvasItem *marker_group;
+ GtkCanvasItem *range_marker_group;
+ GtkCanvasItem *transport_marker_group;
+
+ enum {
+ ruler_metric_smpte = 0,
+ ruler_metric_bbt = 1,
+ ruler_metric_frames = 2,
+ ruler_metric_minsec = 3,
+
+ ruler_time_tempo = 4,
+ ruler_time_meter = 5,
+ ruler_time_marker = 6,
+ ruler_time_range_marker = 7,
+ ruler_time_transport_marker = 8,
+ };
+
+ static GtkCustomMetric ruler_metrics[4];
+ bool ruler_shown[9];
+ bool no_ruler_shown_update;
+
+ gint ruler_button_press (GdkEventButton*);
+ gint ruler_button_release (GdkEventButton*);
+ gint ruler_mouse_motion (GdkEventMotion*);
+
+ gint ruler_pressed_button;
+ Gtk::Widget * ruler_grabbed_widget;
+
+ void initialize_rulers ();
+ void update_just_smpte ();
+ void update_fixed_rulers ();
+ void update_tempo_based_rulers ();
+ void popup_ruler_menu (jack_nframes_t where = 0, ItemType type = RegionItem);
+ void update_ruler_visibility ();
+ void ruler_toggled (int);
+ gint ruler_label_button_release (GdkEventButton*);
+ void store_ruler_visibility ();
+ void restore_ruler_visibility ();
+
+ static gint _metric_get_smpte (GtkCustomRulerMark **, gulong, gulong, gint);
+ static gint _metric_get_bbt (GtkCustomRulerMark **, gulong, gulong, gint);
+ static gint _metric_get_frames (GtkCustomRulerMark **, gulong, gulong, gint);
+ static gint _metric_get_minsec (GtkCustomRulerMark **, gulong, gulong, gint);
+
+ gint metric_get_smpte (GtkCustomRulerMark **, gulong, gulong, gint);
+ gint metric_get_bbt (GtkCustomRulerMark **, gulong, gulong, gint);
+ gint metric_get_frames (GtkCustomRulerMark **, gulong, gulong, gint);
+ gint metric_get_minsec (GtkCustomRulerMark **, gulong, gulong, gint);
+
+ GtkWidget *_smpte_ruler;
+ GtkWidget *_bbt_ruler;
+ GtkWidget *_frames_ruler;
+ GtkWidget *_minsec_ruler;
+ Gtk::Widget *smpte_ruler;
+ Gtk::Widget *bbt_ruler;
+ Gtk::Widget *frames_ruler;
+ Gtk::Widget *minsec_ruler;
+ static Editor *ruler_editor;
+
+ static const double timebar_height;
+ guint32 visible_timebars;
+ Gtk::Menu *editor_ruler_menu;
+
+
+ GtkCanvasItem *tempo_bar;
+ GtkCanvasItem *meter_bar;
+ GtkCanvasItem *marker_bar;
+ GtkCanvasItem *range_marker_bar;
+
+ GtkCanvasItem *transport_marker_bar;
+
+
+ GtkCanvasItem *tempo_line;
+ GtkCanvasItem *meter_line;
+ GtkCanvasItem *marker_line;
+ GtkCanvasItem *range_marker_line;
+ GtkCanvasItem *transport_marker_line;
+
+ GtkCanvasPoints *tempo_line_points;
+ GtkCanvasPoints *meter_line_points;
+ GtkCanvasPoints *marker_line_points;
+ GtkCanvasPoints *range_marker_line_points;
+ GtkCanvasPoints *transport_marker_line_points;
+
+ Gtk::Label minsec_label;
+ Gtk::Label bbt_label;
+ Gtk::Label smpte_label;
+ Gtk::Label frame_label;
+ Gtk::Label tempo_label;
+ Gtk::Label meter_label;
+ Gtk::Label mark_label;
+ Gtk::Label range_mark_label;
+ Gtk::Label transport_mark_label;
+
+
+ Gtk::VBox time_button_vbox;
+ Gtk::HBox time_button_hbox;
+
+ struct Cursor {
+ Editor& editor;
+ GtkCanvasPoints *points;
+ GtkCanvasItem *canvas_item;
+ jack_nframes_t current_frame;
+ GtkSignalFunc callback;
+ double length;
+
+ Cursor (Editor&, const string& color, GtkSignalFunc callback);
+ ~Cursor ();
+
+ void set_position (jack_nframes_t);
+ void set_length (double units);
+ void set_y_axis (double position);
+ };
+
+ friend struct Cursor; /* it needs access to several private
+ fields. XXX fix me.
+ */
+
+ Cursor* playhead_cursor;
+ Cursor* edit_cursor;
+ GtkCanvasItem* cursor_group;
+
+ 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 *);
+
+ ARDOUR::Region* find_next_region (jack_nframes_t, ARDOUR::RegionPoint, int32_t dir, TrackViewList&, TimeAxisView ** = 0);
+
+ vector<jack_nframes_t> region_boundary_cache;
+ void build_region_boundary_cache ();
+
+ Gtk::VBox trackview_vpacker;
+
+ Gtk::HBox top_hbox;
+ Gtk::HBox bottom_hbox;
+
+ Gtk::Table edit_packer;
+ Gtk::Frame edit_frame;
+ Gtk::VScrollbar edit_vscrollbar;
+
+ /* the horizontal scroller works in a rather different way
+ than a regular scrollbar, since its used for
+ zoom control/indication as well. But more importantly,
+ its different components (slider, left arrow, right arrow)
+ have to be packed separately into the edit_packer.
+ */
+
+ Gtk::HScrollbar edit_hscrollbar;
+ Gtk::DrawingArea edit_hscroll_slider;
+ Gtk::Arrow edit_hscroll_left_arrow;
+ Gtk::Arrow edit_hscroll_right_arrow;
+ Gtk::EventBox edit_hscroll_left_arrow_event;
+ Gtk::EventBox edit_hscroll_right_arrow_event;
+ gint edit_hscroll_slider_width;
+ gint edit_hscroll_slider_height;
+ static const gint edit_hscroll_edge_width = 3;
+ bool edit_hscroll_dragging;
+ double edit_hscroll_drag_last;
+
+ void hscroll_slider_allocate (GtkAllocation *);
+ gint hscroll_slider_expose (GdkEventExpose*);
+ gint hscroll_slider_button_press (GdkEventButton*);
+ gint hscroll_slider_button_release (GdkEventButton*);
+ gint hscroll_slider_motion (GdkEventMotion*);
+
+ gint hscroll_trough_expose (GdkEventExpose*);
+ gint hscroll_trough_button_press (GdkEventButton*);
+ gint hscroll_trough_button_release (GdkEventButton*);
+
+ void update_hscroller ();
+
+ gint hscroll_left_arrow_button_press (GdkEventButton *);
+ gint hscroll_left_arrow_button_release (GdkEventButton *);
+ gint hscroll_right_arrow_button_press (GdkEventButton *);
+ gint hscroll_right_arrow_button_release (GdkEventButton *);
+
+ guint32 canvas_width;
+ guint32 canvas_height;
+
+ Gtk::ScrolledWindow track_canvas_scroller;
+ Gtk::ScrolledWindow time_canvas_scroller;
+ Gtk::ScrolledWindow edit_controls_scroller;
+
+ gint edit_controls_button_release (GdkEventButton*);
+ Gtk::Menu *edit_controls_left_menu;
+ Gtk::Menu *edit_controls_right_menu;
+
+ void track_canvas_scroller_realized ();
+ void time_canvas_scroller_realized ();
+
+ Gtk::VBox track_canvas_vbox;
+ Gtk::VBox time_canvas_vbox;
+ Gtk::VBox edit_controls_vbox;
+ Gtk::HBox edit_controls_hbox;
+
+ void tie_vertical_scrolling ();
+ void canvas_horizontally_scrolled ();
+ void reposition_and_zoom (jack_nframes_t sample, double fpu);
+ gint deferred_reposition_and_zoom (jack_nframes_t sample, double fpu);
+ void end_location_changed (ARDOUR::Location*);
+ bool repos_zoom_queued;
+ bool no_zoom_repos_update;
+ bool no_tempo_map_update;
+
+ Gtk::CTree region_list_display;
+ Gtk::CTree_Helpers::RowList::iterator region_list_hidden_node;
+ Gtk::Menu *region_list_menu;
+ vector<Gtk::MenuItem*> rl_context_menu_region_items;
+ Gtk::ScrolledWindow region_list_scroller;
+ Gtk::Frame region_list_frame;
+
+ gint region_list_display_key_press (GdkEventKey *);
+ gint region_list_display_key_release (GdkEventKey *);
+ gint region_list_display_button_press (GdkEventButton *);
+ gint region_list_display_button_release (GdkEventButton *);
+ gint region_list_display_enter_notify (GdkEventCrossing *);
+ gint region_list_display_leave_notify (GdkEventCrossing *);
+ void region_list_display_selected (gint row, gint col, GdkEvent* ev);
+ void region_list_display_unselected (gint row, gint col, GdkEvent* ev);
+ void region_list_column_click (gint);
+ void region_list_clear ();
+ void build_region_list_menu ();
+
+ Gtk::CheckMenuItem* toggle_auto_regions_item;
+ Gtk::CheckMenuItem* toggle_full_region_list_item;
+
+ Gtk::MenuItem* import_audio_item;
+ Gtk::MenuItem* embed_audio_item;
+
+ bool show_automatic_regions_in_region_list;
+ Editing::RegionListSortType region_list_sort_type;
+
+ void reset_region_list_sort_direction (bool);
+ void reset_region_list_sort_type (Editing::RegionListSortType);
+
+ void toggle_full_region_list ();
+ void toggle_show_auto_regions ();
+
+ static gint _region_list_sorter (GtkCList*, gconstpointer, gconstpointer);
+ gint region_list_sorter (gconstpointer, gconstpointer);
+
+ /* named selections */
+
+ Gtk::VPaned region_selection_vpane;
+ Gtk::CList named_selection_display;
+ Gtk::ScrolledWindow named_selection_scroller;
+
+ void name_selection();
+ void named_selection_name_chosen ();
+ void create_named_selection (string);
+ void paste_named_selection (float times);
+
+ void handle_new_named_selection ();
+ void add_named_selection_to_named_selection_display (ARDOUR::NamedSelection&);
+ void redisplay_named_selections ();
+
+ gint named_selection_display_button_press (GdkEventButton *ev);
+ void named_selection_display_selected (gint row, gint col, GdkEvent *ev);
+ void named_selection_display_unselected (gint row, gint col, GdkEvent *ev);
+
+ /* track views */
+ int track_spacing;
+ TrackViewList track_views;
+ TimeAxisView *trackview_by_y_position (double ypos);
+
+ static GdkCursor* cross_hair_cursor;
+ static GdkCursor* trimmer_cursor;
+ static GdkCursor* selector_cursor;
+ static GdkCursor* grabber_cursor;
+ static GdkCursor* zoom_cursor;
+ static GdkCursor* time_fx_cursor;
+ static GdkCursor* fader_cursor;
+ static GdkCursor* speaker_cursor;
+ static GdkCursor* null_cursor;
+ static GdkCursor* wait_cursor;
+ static GdkCursor* timebar_cursor;
+
+ static void build_cursors ();
+
+ SigC::Connection scroll_connection;
+ jack_nframes_t last_update_frame;
+ void center_screen (jack_nframes_t);
+ void center_screen_internal (jack_nframes_t, float);
+
+ void update_current_screen ();
+ SigC::Connection slower_update_connection;
+ void update_slower ();
+
+ gint show_track_context_menu (GdkEventButton *);
+ void hide_track_context_menu ();
+
+ void session_going_away ();
+
+ jack_nframes_t cut_buffer_start;
+ jack_nframes_t cut_buffer_length;
+
+ gint typed_event (GtkCanvasItem*, GdkEvent*, ItemType);
+ gint button_press_handler (GtkCanvasItem*, GdkEvent*, ItemType);
+ gint button_release_handler (GtkCanvasItem*, GdkEvent*, ItemType);
+ gint motion_handler (GtkCanvasItem*, GdkEvent*, ItemType);
+ gint enter_handler (GtkCanvasItem*, GdkEvent*, ItemType);
+ gint leave_handler (GtkCanvasItem*, GdkEvent*, ItemType);
+
+ /* KEYMAP HANDLING */
+
+ void install_keybindings ();
+
+ int ensure_cursor (jack_nframes_t* pos);
+
+ void fake_handle_new_audio_region (ARDOUR::AudioRegion *);
+ void handle_new_audio_region (ARDOUR::AudioRegion *);
+ void fake_handle_audio_region_removed (ARDOUR::AudioRegion *);
+ void handle_audio_region_removed (ARDOUR::AudioRegion *);
+ void add_audio_region_to_region_display (ARDOUR::AudioRegion *);
+ void region_hidden (ARDOUR::Region*);
+ void redisplay_regions ();
+ void insert_into_tmp_audio_regionlist(ARDOUR::AudioRegion *);
+
+ list<ARDOUR::AudioRegion *> tmp_audio_region_list;
+
+ void cut_copy (Editing::CutCopyOp);
+ void cut_copy_points (Editing::CutCopyOp);
+ void cut_copy_regions (Editing::CutCopyOp);
+ void cut_copy_ranges (Editing::CutCopyOp);
+
+ void mouse_paste ();
+ void paste_internal (jack_nframes_t position, float times);
+
+ /* EDITING OPERATIONS */
+
+ void toggle_region_mute ();
+ void toggle_region_opaque ();
+ void raise_region ();
+ void raise_region_to_top ();
+ void lower_region ();
+ void lower_region_to_bottom ();
+ void split_region ();
+ void split_region_at (jack_nframes_t);
+ void split_regions_at (jack_nframes_t, AudioRegionSelection&);
+ void crop_region_to_selection ();
+ void set_region_sync_from_edit_cursor ();
+ void remove_region_sync();
+ void align_selection (ARDOUR::RegionPoint, jack_nframes_t position);
+ void align_selection_relative (ARDOUR::RegionPoint point, jack_nframes_t position);
+ void align_region (ARDOUR::Region&, ARDOUR::RegionPoint point, jack_nframes_t position);
+ void align_region_internal (ARDOUR::Region&, ARDOUR::RegionPoint point, jack_nframes_t position);
+ void remove_some_regions ();
+ void remove_clicked_region ();
+ void destroy_clicked_region ();
+ void edit_region ();
+ void duplicate_some_regions (AudioRegionSelection&, float times);
+ void duplicate_selection (float times);
+ void region_fill_selection ();
+
+ void region_fill_track ();
+ void audition_playlist_region_standalone (ARDOUR::AudioRegion&);
+ void audition_playlist_region_via_route (ARDOUR::AudioRegion&, ARDOUR::Route&);
+ void split_multichannel_region();
+ void reverse_region ();
+ void normalize_region ();
+ void denormalize_region ();
+
+ ARDOUR::Region* region_list_button_region;
+ void audition_region_from_region_list ();
+ void remove_region_from_region_list ();
+ void hide_region_from_region_list ();
+ void remove_selected_regions_from_region_list ();
+
+ void align (ARDOUR::RegionPoint);
+ void align_relative (ARDOUR::RegionPoint);
+ void naturalize ();
+
+ void cut ();
+ void copy ();
+ void paste (float times);
+
+ int get_prefix (float&, bool&);
+
+ void keyboard_paste ();
+ void keyboard_duplicate_region ();
+ void keyboard_duplicate_selection ();
+ void keyboard_nudge ();
+ void keyboard_insert_region_list_selection ();
+
+ void region_from_selection ();
+ void create_region_from_selection (std::vector<ARDOUR::AudioRegion*>&);
+
+ bool region_renamed;
+ void rename_region ();
+ void rename_region_finished (bool);
+
+ void play_from_start ();
+ void play_from_edit_cursor ();
+ void play_selected_region ();
+ void audition_selected_region ();
+ void toggle_loop_playback ();
+ 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_session ();
+ void temporal_zoom (gdouble scale);
+ void temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, string op);
+ void temporal_zoom_to_frame (bool coarser, jack_nframes_t frame);
+
+ void amplitude_zoom (gdouble scale);
+ void amplitude_zoom_step (bool in);
+
+ ARDOUR::AudioRegion* region_list_display_drag_region;
+ char need_wave_cursor;
+ gint region_list_display_motion (GdkEventMotion*);
+
+ void insert_region_list_drag (ARDOUR::AudioRegion&);
+ void insert_region_list_selection (float times);
+
+ void insert_sndfile (bool as_tracks);
+ void embed_audio (); // inserts into region list
+ int reject_because_rate_differs (string path, SF_INFO& finfo, string action, bool multiple_pending);
+
+ void do_embed_sndfiles (vector<string> paths, bool split);
+ void embed_sndfile (string path, bool split, bool multiple_files, bool& check_sr);
+
+ void do_insert_sndfile (vector<string> path, bool multi, jack_nframes_t frame);
+ void insert_paths_as_new_tracks (std::vector<std::string> paths, bool multi); // inserts files as new tracks
+ void insert_sndfile_into (string path, bool multi, AudioTimeAxisView* tv, jack_nframes_t& frame, bool prompt=true);
+ static void* _insert_sndfile_thread (void*);
+ void* insert_sndfile_thread (void*);
+
+ /* generic interthread progress window */
+
+ ArdourDialog* interthread_progress_window;
+ Gtk::Label interthread_progress_label;
+ Gtk::VBox interthread_progress_vbox;
+ Gtk::ProgressBar interthread_progress_bar;
+ Gtk::Button interthread_cancel_button;
+ Gtk::Label interthread_cancel_label;
+ SigC::Connection interthread_progress_connection;
+ void interthread_cancel_clicked ();
+ void build_interthread_progress_window ();
+ ARDOUR::InterThreadInfo* current_interthread_info;
+
+ /* import specific info */
+
+ ARDOUR::Session::import_status import_status;
+ gint import_progress_timeout (void *);
+ static void *_import_thread (void *);
+ void* import_thread ();
+ void catch_new_audio_region (ARDOUR::AudioRegion*);
+ ARDOUR::AudioRegion* last_audio_region;
+
+ /* to support this ... */
+
+ void import_audio (bool as_tracks);
+ void do_import (vector<string> paths, bool split, bool as_tracks);
+
+ void move_to_start ();
+ void move_to_end ();
+ void goto_frame ();
+ void center_playhead ();
+ void center_edit_cursor ();
+ void edit_cursor_backward ();
+ void edit_cursor_forward ();
+ void playhead_backward ();
+ void playhead_forward ();
+ void scroll_backward (float pages=0.8f);
+ void scroll_forward (float pages=0.8f);
+ void scroll_tracks_down ();
+ void scroll_tracks_up ();
+ void delete_sample_forward ();
+ void delete_sample_backward ();
+ void delete_screen ();
+ void search_backwards ();
+ void search_forwards ();
+ void set_mark ();
+ void clear_markers ();
+ void clear_ranges ();
+ void clear_locations ();
+ void jump_forward_to_mark ();
+ void jump_backward_to_mark ();
+ void cursor_align (bool playhead_to_edit);
+
+ void remove_last_capture ();
+
+ void set_selection_from_range (ARDOUR::Location&);
+ void set_selection_from_punch ();
+ void set_selection_from_loop ();
+
+ void add_location_from_selection ();
+ void set_route_loop_selection ();
+
+ void add_location_from_playhead_cursor ();
+
+ void reverse_selection ();
+ void edit_envelope ();
+
+ void start_scrolling ();
+ void stop_scrolling ();
+
+ void keyboard_selection_begin ();
+ void keyboard_selection_finish (bool add);
+ bool have_pending_keyboard_selection;
+ jack_nframes_t pending_keyboard_selection_start;
+
+ ARDOUR::AudioRegion* select_region_for_operation (int dir, TimeAxisView **tv);
+ void extend_selection_to_end_of_region (bool next);
+ void extend_selection_to_start_of_region (bool previous);
+
+ Editing::SnapType snap_type;
+ Editing::SnapMode snap_mode;
+ double snap_threshold;
+
+ void soundfile_chosen_for_insert (string selection, bool split_channels);
+ void soundfile_chosen_for_embed (string selection, bool split_channels);
+ void soundfile_chosen_for_import (string selection, bool split_channels);
+
+ void handle_gui_changes (string, void *);
+
+ void hide_all_tracks (bool with_select);
+
+ void route_list_selected (gint row, gint col, GdkEvent* ev);
+ void route_list_unselected (gint row, gint col, GdkEvent* ev);
+ void redisplay_route_list();
+ gint route_list_reordered ();
+ bool ignore_route_list_reorder;
+ void queue_route_list_reordered (gint row, gint col);
+
+ struct DragInfo {
+ GtkCanvasItem* item;
+ void* data;
+ jack_nframes_t last_frame_position;
+ int32_t pointer_frame_offset;
+ jack_nframes_t grab_frame;
+ jack_nframes_t last_pointer_frame;
+ jack_nframes_t current_pointer_frame;
+ double grab_x, grab_y;
+ double cumulative_x_drag;
+ double cumulative_y_drag;
+ double current_pointer_x;
+ double current_pointer_y;
+ void (Editor::*motion_callback)(GtkCanvasItem*, GdkEvent*);
+ void (Editor::*finished_callback)(GtkCanvasItem*, GdkEvent*);
+ TimeAxisView* last_trackview;
+ bool x_constrained;
+ bool copy;
+ bool was_rolling;
+ bool first_move;
+ bool move_threshold_passsed;
+ bool want_move_threshold;
+ bool brushing;
+ ARDOUR::Location* copied_location;
+ } drag_info;
+
+ struct LineDragInfo {
+ uint32_t before;
+ uint32_t after;
+ };
+
+ LineDragInfo current_line_drag_info;
+
+ void start_grab (GdkEvent*, GdkCursor* cursor = 0);
+ bool end_grab (GtkCanvasItem*, GdkEvent*);
+
+ Gtk::Menu fade_context_menu;
+ void popup_fade_context_menu (int, int, GtkCanvasItem*, ItemType);
+
+ void start_fade_in_grab (GtkCanvasItem*, GdkEvent*);
+ void start_fade_out_grab (GtkCanvasItem*, GdkEvent*);
+ void fade_in_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void fade_out_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void fade_in_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+ void fade_out_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+
+ std::set<ARDOUR::Playlist*> motion_frozen_playlists;
+ void region_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void region_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+ void region_copy_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+
+ void cursor_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void cursor_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+ void marker_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void marker_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+ void control_point_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void control_point_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+ void line_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void line_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+
+ void tempo_marker_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void tempo_marker_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+ void meter_marker_drag_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void meter_marker_drag_finished_callback (GtkCanvasItem*, GdkEvent*);
+
+ gint mouse_rename_region (GtkCanvasItem*, GdkEvent*);
+
+ void start_region_grab (GtkCanvasItem*, GdkEvent*);
+ void start_region_copy_grab (GtkCanvasItem*, GdkEvent*);
+ void start_region_brush_grab (GtkCanvasItem*, GdkEvent*);
+ void start_selection_grab (GtkCanvasItem*, GdkEvent*);
+ void start_cursor_grab (GtkCanvasItem*, GdkEvent*);
+ void start_marker_grab (GtkCanvasItem*, GdkEvent*);
+ void start_control_point_grab (GtkCanvasItem*, GdkEvent*);
+ void start_line_grab_from_regionview (GtkCanvasItem*, GdkEvent*);
+ void start_line_grab_from_line (GtkCanvasItem*, GdkEvent*);
+ void start_line_grab (AutomationLine *, GdkEvent*);
+ void start_tempo_marker_grab (GtkCanvasItem*, GdkEvent*);
+ void start_meter_marker_grab (GtkCanvasItem*, GdkEvent*);
+
+ void region_view_item_click (AudioRegionView&, GdkEventButton*);
+
+ void remove_gain_control_point (GtkCanvasItem*, GdkEvent*);
+ void remove_control_point (GtkCanvasItem*, GdkEvent*);
+
+ void mouse_brush_insert_region (AudioRegionView*, jack_nframes_t pos);
+ void brush (jack_nframes_t);
+
+ void show_verbose_time_cursor (jack_nframes_t frame, double offset = 0, double xpos=-1, double ypos=-1);
+ void show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, double offset = 0, double xpos=-1, double ypos=-1);
+
+ /* static versions of these are public in PublicEditor */
+
+ gint _canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_automation_track_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_line_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint _canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) ;
+ gint _canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) ;
+ gint _canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ gint _canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ gint _canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ gint _canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ gint _canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ gint _canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+
+ /* now the real things */
+
+ gint canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, CrossfadeView*);
+ gint canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*);
+ gint canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*);
+ gint canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*);
+ gint canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*);
+ gint canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*);
+ gint canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, AudioTimeAxisView*);
+ gint canvas_automation_track_event (GtkCanvasItem* item, GdkEvent* event, AutomationTimeAxisView*);
+ gint canvas_marker_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_line_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event);
+ gint canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event);
+
+ /* these are not publically accessible, but we still need the static versions
+ till we use Gnome::Canvas.
+ */
+
+ static gint _canvas_copy_region_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint canvas_copy_region_event (GtkCanvasItem* item, GdkEvent* event);
+
+ static gint _canvas_playhead_cursor_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint canvas_playhead_cursor_event (GtkCanvasItem* item, GdkEvent* event);
+
+ static gint _canvas_edit_cursor_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint canvas_edit_cursor_event (GtkCanvasItem* item, GdkEvent* event);
+
+ static gint _track_canvas_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ gint track_canvas_event (GtkCanvasItem* item, GdkEvent* event);
+
+ gint track_canvas_button_press_event (GdkEventButton *);
+ gint track_canvas_button_release_event (GdkEventButton *);
+
+ void track_canvas_allocate (GtkAllocation* alloc);
+ void time_canvas_allocate (GtkAllocation* alloc);
+
+ void set_edit_cursor (GdkEvent* event);
+ void set_playhead_cursor (GdkEvent* event);
+
+ void kbd_driver (SigC::Slot1<void,GdkEvent*>, bool use_track_canvas = true, bool use_time_canvas = true, bool can_select = true);
+ void kbd_set_playhead_cursor ();
+ void kbd_set_edit_cursor ();
+ void kbd_split ();
+ void kbd_align (ARDOUR::RegionPoint);
+ void kbd_align_relative (ARDOUR::RegionPoint);
+ void kbd_brush ();
+ void kbd_audition ();
+
+ void kbd_do_split (GdkEvent*);
+ void kbd_do_align (GdkEvent*, ARDOUR::RegionPoint);
+ void kbd_do_align_relative (GdkEvent*, ARDOUR::RegionPoint);
+ void kbd_do_brush (GdkEvent*);
+ void kbd_do_audition (GdkEvent*);
+
+ void fake_handle_new_duration ();
+ void handle_new_duration ();
+ void initialize_canvas ();
+ void reset_scrolling_region (GtkAllocation* alloc = 0);
+ void scroll_canvas ();
+
+ /* sub-event loop handling */
+
+ int32_t sub_event_loop_status;
+ void run_sub_event_loop ();
+ void finish_sub_event_loop (int status);
+ gint finish_sub_event_loop_on_delete (GdkEventAny*, int32_t status);
+
+ /* display control */
+
+ bool _show_measures;
+ bool _show_waveforms;
+ bool _follow_playhead;
+ bool _show_waveforms_recording;
+
+ void add_bbt_marks (ARDOUR::TempoMap::BBTPointList&);
+
+ ARDOUR::TempoMap::BBTPointList *current_bbt_points;
+
+ typedef vector<GtkCanvasItem*> TimeLineList;
+ TimeLineList free_measure_lines;
+ TimeLineList used_measure_lines;
+
+ GtkCanvasItem* time_line_group;
+ GtkCanvasItem* get_time_line ();
+ void hide_measures ();
+ void draw_measures ();
+ void draw_time_bars ();
+
+ void new_tempo_section ();
+
+ void mouse_add_new_tempo_event (jack_nframes_t where);
+ void mouse_add_new_meter_event (jack_nframes_t where);
+
+ void remove_tempo_marker (GtkCanvasItem*);
+ void remove_meter_marker (GtkCanvasItem*);
+ gint real_remove_tempo_marker (ARDOUR::TempoSection*);
+ gint real_remove_meter_marker (ARDOUR::MeterSection*);
+
+ void edit_tempo_section (ARDOUR::TempoSection*);
+ void edit_meter_section (ARDOUR::MeterSection*);
+ void edit_tempo_marker (GtkCanvasItem*);
+ void edit_meter_marker (GtkCanvasItem*);
+
+ void marker_menu_edit ();
+ void marker_menu_remove ();
+ void marker_menu_rename ();
+ void marker_menu_hide ();
+ void marker_menu_loop_range ();
+ void marker_menu_play_from ();
+ void marker_menu_set_playhead ();
+ void marker_menu_set_from_playhead ();
+ void marker_menu_set_from_selection ();
+ void new_transport_marker_menu_set_loop ();
+ void new_transport_marker_menu_set_punch ();
+ void update_loop_range_view (bool visibility=false);
+ void update_punch_range_view (bool visibility=false);
+ gint new_transport_marker_menu_popdown (GdkEventAny*);
+ void marker_context_menu (GdkEventButton*, GtkCanvasItem*);
+ void tm_marker_context_menu (GdkEventButton*, GtkCanvasItem*);
+ void transport_marker_context_menu (GdkEventButton*, GtkCanvasItem*);
+ void new_transport_marker_context_menu (GdkEventButton*, GtkCanvasItem*);
+ void build_marker_menu ();
+ void build_tm_marker_menu ();
+ void build_transport_marker_menu ();
+ void build_new_transport_marker_menu ();
+
+ Gtk::Menu* tm_marker_menu;
+ Gtk::Menu* marker_menu;
+ Gtk::Menu* transport_marker_menu;
+ Gtk::Menu* new_transport_marker_menu;
+ GtkCanvasItem* marker_menu_item;
+
+ typedef list<Marker*> Marks;
+ Marks metric_marks;
+
+ void remove_metric_marks ();
+ void draw_metric_marks (const ARDOUR::Metrics& metrics);
+
+ void tempo_map_changed (ARDOUR::Change);
+ void redisplay_tempo ();
+
+ void snap_to (jack_nframes_t& first, int32_t direction = 0, bool for_mark = false);
+ uint32_t bbt_beat_subdivision;
+
+ /* toolbar */
+
+ Gtk::ToggleButton editor_mixer_button;
+
+ void editor_mixer_button_toggled ();
+
+ AudioClock selection_start_clock;
+ Gtk::Label selection_start_clock_label;
+ AudioClock selection_end_clock;
+ Gtk::Label selection_end_clock_label;
+ AudioClock edit_cursor_clock;
+ Gtk::Label edit_cursor_clock_label;
+ AudioClock zoom_range_clock;
+ Gtk::Button zoom_in_button;
+ Gtk::Button zoom_out_button;
+ Gtk::Button zoom_out_full_button;
+ Gtk::Button zoom_onetoone_button;
+
+ Gtk::VBox toolbar_clock_vbox;
+ Gtk::VBox toolbar_selection_clock_vbox;
+ Gtk::Table toolbar_selection_clock_table;
+ Gtk::Label toolbar_selection_cursor_label;
+
+ Gtk::Table mouse_mode_button_table;
+ Gtkmmext::TearOff* mouse_mode_tearoff;
+ Gtk::ToggleButton mouse_select_button;
+ Gtk::ToggleButton mouse_move_button;
+ Gtk::ToggleButton mouse_gain_button;
+ Gtk::ToggleButton mouse_zoom_button;
+ Gtk::ToggleButton mouse_timefx_button;
+ Gtk::ToggleButton mouse_audition_button;
+ GroupedButtons *mouse_mode_button_set;
+ void mouse_mode_toggled (Editing::MouseMode m);
+ bool ignore_mouse_mode_toggle;
+
+ gint mouse_select_button_release (GdkEventButton*);
+
+ Gtk::VBox automation_box;
+ Gtk::Button automation_mode_button;
+ Gtk::ToggleButton global_automation_button;
+
+ Gtk::Combo edit_mode_selector;
+ Gtk::Label edit_mode_label;
+ Gtk::VBox edit_mode_box;
+
+ gint edit_mode_selection_done (GdkEventAny*);
+
+ Gtk::Combo snap_type_selector;
+ Gtk::Label snap_type_label;
+ Gtk::VBox snap_type_box;
+
+ gint snap_type_selection_done (GdkEventAny*);
+
+ Gtk::Combo snap_mode_selector;
+ Gtk::Label snap_mode_label;
+ Gtk::VBox snap_mode_box;
+
+ gint snap_mode_selection_done (GdkEventAny*);
+
+ Gtk::Combo zoom_focus_selector;
+ Gtk::Label zoom_focus_label;
+ Gtk::VBox zoom_focus_box;
+
+ gint zoom_focus_selection_done (GdkEventAny*);
+
+ Gtk::Label zoom_indicator_label;
+ Gtk::HBox zoom_indicator_box;
+ Gtk::VBox zoom_indicator_vbox;
+
+ void update_zoom_indicator ();
+ void zoom_adjustment_changed();
+
+ void edit_cursor_clock_changed();
+
+ void setup_toolbar ();
+
+ Gtkmmext::TearOff* tools_tearoff;
+ Gtk::HBox toolbar_hbox;
+ Gtk::EventBox toolbar_base;
+ Gtk::Frame toolbar_frame;
+
+ /* selection process */
+
+ Selection* selection;
+ Selection* cut_buffer;
+
+ void time_selection_changed ();
+ void track_selection_changed ();
+ void region_selection_changed ();
+ void point_selection_changed ();
+ void audio_track_selection_changed ();
+ void line_selection_changed ();
+
+ enum SelectionOp {
+ CreateSelection,
+ SelectionStartTrim,
+ SelectionEndTrim,
+ SelectionMove
+ } selection_op;
+
+ void start_selection_op (GtkCanvasItem* item, GdkEvent* event, SelectionOp);
+ void drag_selection (GtkCanvasItem* item, GdkEvent* event);
+ void end_selection_op (GtkCanvasItem* item, GdkEvent* event);
+ void cancel_selection ();
+
+ void region_selection_op (void (ARDOUR::Region::*pmf)(void));
+ void region_selection_op (void (ARDOUR::Region::*pmf)(void*), void*);
+ void region_selection_op (void (ARDOUR::Region::*pmf)(bool), bool);
+
+ bool audio_region_selection_covers (jack_nframes_t where);
+
+ Gtk::VPaned route_group_vpane;
+ Gtk::Frame route_list_frame;
+ Gtk::Frame edit_group_list_frame;
+
+ /* transport range select process */
+ enum RangeMarkerOp {
+ CreateRangeMarker,
+ CreateTransportMarker
+ } range_marker_op;
+
+ void start_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event, RangeMarkerOp);
+ void drag_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event);
+ void end_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event);
+
+
+ GtkCanvasItem *range_bar_drag_rect;
+ GtkCanvasItem *transport_bar_drag_rect;
+ GtkCanvasItem *marker_drag_line;
+ GtkCanvasPoints *marker_drag_line_points;
+ GtkCanvasItem *range_marker_drag_rect;
+
+ void update_marker_drag_item (ARDOUR::Location *);
+
+ GtkCanvasItem *transport_bar_range_rect;
+ GtkCanvasItem *transport_bar_preroll_rect;
+ GtkCanvasItem *transport_bar_postroll_rect;
+ GtkCanvasItem *transport_loop_range_rect;
+ GtkCanvasItem *transport_punch_range_rect;
+ GtkCanvasItem *transport_punchin_line;
+ GtkCanvasItem *transport_punchout_line;
+ GtkCanvasItem *transport_preroll_rect;
+ GtkCanvasItem *transport_postroll_rect;
+
+ ARDOUR::Location* transport_loop_location();
+ ARDOUR::Location* transport_punch_location();
+
+ ARDOUR::Location *temp_location;
+
+ /* object rubberband select process */
+
+ void start_rubberband_select (GtkCanvasItem* item, GdkEvent* event);
+ void drag_rubberband_select (GtkCanvasItem* item, GdkEvent* event);
+ void end_rubberband_select (GtkCanvasItem* item, GdkEvent* event);
+
+ bool select_all_within (jack_nframes_t start, jack_nframes_t end, gdouble topy, gdouble boty, bool add);
+
+ GtkCanvasItem *rubberband_rect;
+
+ /* mouse zoom process */
+
+ void start_mouse_zoom (GtkCanvasItem* item, GdkEvent* event);
+ void drag_mouse_zoom (GtkCanvasItem* item, GdkEvent* event);
+ void end_mouse_zoom (GtkCanvasItem* item, GdkEvent* event);
+
+ GtkCanvasItem *zoom_rect;
+ void reposition_zoom_rect (jack_nframes_t start, jack_nframes_t end);
+
+ /* diskstream/route display management */
+
+ Gtk::CList route_list;
+ Gtk::ScrolledWindow route_list_scroller;
+ Gtk::Menu *route_list_menu;
+
+ void route_list_column_click (gint);
+ void build_route_list_menu ();
+ void select_all_routes ();
+ void unselect_all_routes ();
+ void select_all_audiotracks ();
+ void unselect_all_audiotracks ();
+ void select_all_audiobus ();
+ void unselect_all_audiobus ();
+
+ /* edit group management */
+
+ Gtk::Button edit_group_list_button;
+ Gtk::Label edit_group_list_button_label;
+ Gtk::CList edit_group_list;
+ Gtk::ScrolledWindow edit_group_list_scroller;
+ Gtk::Menu *edit_group_list_menu;
+ Gtk::VBox edit_group_vbox;
+
+
+ void edit_group_list_column_click (gint);
+ void build_edit_group_list_menu ();
+ void select_all_edit_groups ();
+ void unselect_all_edit_groups ();
+ void new_edit_group ();
+ void edit_group_list_button_clicked ();
+ gint edit_group_list_button_press_event (GdkEventButton* ev);
+ void edit_group_selected (gint row, gint col, GdkEvent* ev);
+ void edit_group_unselected (gint row, gint col, GdkEvent* ev);
+ void fake_add_edit_group (ARDOUR::RouteGroup* group);
+ void add_edit_group (ARDOUR::RouteGroup* group);
+ void group_flags_changed (void*, ARDOUR::RouteGroup*);
+
+ Gtk::VBox list_vpacker;
+
+ static GdkPixmap* check_pixmap;
+ static GdkBitmap* check_mask;
+ static GdkPixmap* empty_pixmap;
+ static GdkBitmap* empty_mask;
+
+ /* autoscrolling */
+
+ int autoscroll_timeout_tag;
+ int autoscroll_direction;
+ uint32_t autoscroll_cnt;
+ jack_nframes_t autoscroll_distance;
+
+ static gint _autoscroll_canvas (void *);
+ gint autoscroll_canvas ();
+ void start_canvas_autoscroll (int direction);
+ void stop_canvas_autoscroll ();
+ void maybe_autoscroll (GdkEvent*);
+
+ /* trimming */
+ enum TrimOp {
+ StartTrim,
+ EndTrim,
+ ContentsTrim,
+ } trim_op;
+
+ void start_trim (GtkCanvasItem*, GdkEvent*);
+ void point_trim (GdkEvent*);
+ void trim_motion_callback (GtkCanvasItem*, GdkEvent*);
+ void single_contents_trim (AudioRegionView&, jack_nframes_t, bool, bool, bool);
+ void single_start_trim (AudioRegionView&, jack_nframes_t, bool, bool);
+ void single_end_trim (AudioRegionView&, jack_nframes_t, bool, bool);
+
+ void trim_finished_callback (GtkCanvasItem*, GdkEvent*);
+ void thaw_region_after_trim (AudioRegionView& rv);
+
+ void trim_region_to_edit_cursor ();
+ void trim_region_from_edit_cursor ();
+
+ bool show_gain_after_trim;
+
+ /* Drag-n-Drop */
+
+ int convert_drop_to_paths (std::vector<std::string>& paths,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time);
+
+ void track_canvas_drag_data_received (GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time);
+
+ void region_list_display_drag_data_received (GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time);
+
+ /* audio export */
+
+ ExportDialog *export_dialog;
+ void export_range (jack_nframes_t start, jack_nframes_t end);
+
+ int write_region_selection(AudioRegionSelection&);
+ bool write_region (string path, ARDOUR::AudioRegion&);
+ void export_region ();
+ void write_a_region ();
+ void bounce_region_selection ();
+ void bounce_range_selection ();
+ void external_edit_region ();
+
+ int write_audio_selection (TimeSelection&);
+ bool write_audio_range (ARDOUR::Playlist&, uint32_t channels, list<ARDOUR::AudioRange>&);
+
+ void write_selection ();
+
+ /* history */
+
+ UndoAction get_memento() const;
+
+ void begin_reversible_command (string cmd_name);
+ void commit_reversible_command ();
+
+ /* visual history */
+
+ UndoHistory visual_history;
+ UndoCommand current_visual_command;
+
+ void begin_reversible_visual_command (string cmd_name);
+ void commit_reversible_visual_command ();
+
+ void update_title ();
+ void update_title_s (string snapshot_name);
+
+ struct State {
+ Selection* selection;
+ double frames_per_unit;
+
+ State();
+ ~State();
+ };
+
+ void store_state (State&) const;
+ void restore_state (State *);
+
+ void instant_save ();
+
+ ARDOUR::AudioRegion* last_audition_region;
+
+ /* freeze operations */
+
+ ARDOUR::InterThreadInfo freeze_status;
+ gint freeze_progress_timeout (void *);
+ static void* _freeze_thread (void*);
+ void* freeze_thread ();
+
+ void freeze_route ();
+ void unfreeze_route ();
+
+ /* edit-group solo + mute */
+
+ void set_edit_group_solo (ARDOUR::Route&, bool);
+ void set_edit_group_mute (ARDOUR::Route&, bool);
+
+ /* duplication */
+
+ void duplicate_dialog (bool for_region);
+
+ /* edit menu */
+
+ Gtk::Menu* edit_menu;
+ void edit_menu_map_handler ();
+
+ jack_nframes_t event_frame (GdkEvent*, double* px = 0, double* py = 0);
+
+ void time_fx_motion (GtkCanvasItem*, GdkEvent*);
+ void start_time_fx (GtkCanvasItem*, GdkEvent*);
+ void end_time_fx (GtkCanvasItem*, GdkEvent*);
+
+ struct TimeStretchDialog : public ArdourDialog {
+ ARDOUR::Session::TimeStretchRequest request;
+ Editor& editor;
+ AudioRegionSelection regions;
+ Gtk::ProgressBar progress_bar;
+ Gtk::ToggleButton quick_button;
+ Gtk::ToggleButton antialias_button;
+ Gtk::Button cancel_button;
+ Gtk::Button action_button;
+ Gtk::HBox lower_button_box;
+ Gtk::HBox upper_button_box;
+ Gtk::VBox packer;
+ int status;
+
+ TimeStretchDialog (Editor& e);
+
+ gint update_progress ();
+ SigC::Connection first_cancel;
+ SigC::Connection first_delete;
+ void cancel_timestretch_in_progress ();
+ gint delete_timestretch_in_progress (GdkEventAny*);
+ };
+
+ /* "whats mine is yours" */
+
+ friend class TimeStretchDialog;
+
+ TimeStretchDialog* current_timestretch;
+
+ static void* timestretch_thread (void *arg);
+ int run_timestretch (AudioRegionSelection&, float fraction);
+ void do_timestretch (TimeStretchDialog&);
+
+ /* editor-mixer strip */
+
+ MixerStrip *current_mixer_strip;
+ Gtk::VBox current_mixer_strip_vbox;
+ void cms_deleted ();
+ void current_mixer_strip_hidden ();
+ void current_mixer_strip_removed ();
+
+ void detach_tearoff (Gtk::Box* b, Gtk::Widget* w);
+ void reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n);
+
+ /* nudging tracks */
+
+ void nudge_track (bool use_edit_cursor, bool forwards);
+
+ /* xfades */
+
+ bool _xfade_visibility;
+
+ /* <CMT Additions> */
+ void handle_new_imageframe_time_axis_view(std::string track_name, void* src) ;
+ void handle_new_imageframe_marker_time_axis_view(std::string track_name, TimeAxisView* marked_track) ;
+
+ void start_imageframe_grab(GtkCanvasItem*, GdkEvent*) ;
+ void start_markerview_grab(GtkCanvasItem*, GdkEvent*) ;
+
+ void imageframe_drag_motion_callback(GtkCanvasItem*, GdkEvent*) ;
+ void markerview_drag_motion_callback(GtkCanvasItem*, GdkEvent*) ;
+ void timeaxis_item_drag_finished_callback(GtkCanvasItem*, GdkEvent*) ;
+
+ gint canvas_imageframe_item_view_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameView* ifv);
+ gint canvas_imageframe_view_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameTimeAxis* ifta);
+ gint canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameView* ifv);
+ gint canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameView* ifv);
+
+ gint canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, MarkerTimeAxis* mta);
+ gint canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mv);
+ gint canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mv);
+ gint canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mv);
+
+ void imageframe_start_handle_op(GtkCanvasItem* item, GdkEvent* event) ;
+ void imageframe_end_handle_op(GtkCanvasItem* item, GdkEvent* event) ;
+ void imageframe_start_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) ;
+ void imageframe_start_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) ;
+ void imageframe_end_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) ;
+ void imageframe_end_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) ;
+
+ void markerview_item_start_handle_op(GtkCanvasItem* item, GdkEvent* event) ;
+ void markerview_item_end_handle_op(GtkCanvasItem* item, GdkEvent* event) ;
+ void markerview_start_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) ;
+ void markerview_start_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) ;
+ void markerview_end_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) ;
+ void markerview_end_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) ;
+
+ void popup_imageframe_edit_menu(int button, int32_t time, GtkCanvasItem* ifv, bool with_frame) ;
+ void popup_marker_time_axis_edit_menu(int button, int32_t time, GtkCanvasItem* ifv, bool with_frame) ;
+
+ ImageFrameSocketHandler* image_socket_listener ;
+ /* </CMT Additions> */
+
+ void toggle_xfade_active (ARDOUR::Crossfade*);
+ void toggle_xfade_length (ARDOUR::Crossfade*);
+ void edit_xfade (ARDOUR::Crossfade*);
+ void remove_xfade ();
+ void xfade_edit_left_region ();
+ void xfade_edit_right_region ();
+
+ static const int32_t default_width = 995;
+ static const int32_t default_height = 765;
+
+ /* nudge */
+
+ Gtk::Button nudge_forward_button;
+ Gtk::Button nudge_backward_button;
+ Gtk::HBox nudge_hbox;
+ Gtk::VBox nudge_vbox;
+ Gtk::Label nudge_label;
+ AudioClock nudge_clock;
+
+ jack_nframes_t get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next);
+
+ /* audio filters */
+
+ void apply_filter (ARDOUR::AudioFilter&, string cmd);
+
+ /* handling cleanup */
+
+ int playlist_deletion_dialog (ARDOUR::Playlist*);
+
+ vector<SigC::Connection> session_connections;
+
+ /* tracking step changes of track height */
+
+ TimeAxisView* current_stepping_trackview;
+ struct timeval last_track_height_step_timestamp;
+ gint track_height_step_timeout();
+ SigC::Connection step_timeout;
+
+ TimeAxisView* entered_track;
+ AudioRegionView* entered_regionview;
+ bool clear_entered_track;
+ gint left_track_canvas (GdkEventCrossing*);
+ void set_entered_track (TimeAxisView*);
+ void set_entered_regionview (AudioRegionView*);
+ gint left_automation_track ();
+
+ bool _new_regionviews_show_envelope;
+
+ void toggle_gain_envelope_visibility ();
+ void toggle_gain_envelope_active ();
+
+ typedef map<Editing::ColorID,std::string> ColorStyleMap;
+ void init_colormap ();
+};
+
+#endif /* __ardour_editor_h__ */
diff --git a/gtk2_ardour/editor_audiotrack.cc b/gtk2_ardour/editor_audiotrack.cc
new file mode 100644
index 0000000000..b9ae734bde
--- /dev/null
+++ b/gtk2_ardour/editor_audiotrack.cc
@@ -0,0 +1,65 @@
+#include <ardour/location.h>
+#include <ardour/diskstream.h>
+
+#include "editor.h"
+#include "editing.h"
+#include "audio_time_axis.h"
+#include "regionview.h"
+#include "selection.h"
+
+using namespace ARDOUR;
+
+void
+Editor::set_route_loop_selection ()
+{
+ if (session == 0 || selection->time.empty()) {
+ return;
+ }
+
+ jack_nframes_t start = selection->time[clicked_selection].start;
+ jack_nframes_t end = selection->time[clicked_selection].end;
+
+ Location* loc = transport_loop_location();
+
+ if (loc) {
+
+ loc->set (start, end);
+
+ // enable looping, reposition and start rolling
+ session->request_auto_loop (true);
+ session->request_locate (loc->start(), true);
+ }
+
+}
+
+void
+Editor::set_show_waveforms (bool yn)
+{
+ AudioTimeAxisView* atv;
+
+ if (_show_waveforms != yn) {
+ _show_waveforms = yn;
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(*i)) != 0) {
+ atv->set_show_waveforms (yn);
+ }
+ }
+ DisplayControlChanged (Editing::ShowWaveforms);
+ }
+}
+
+void
+Editor::set_show_waveforms_recording (bool yn)
+{
+ AudioTimeAxisView* atv;
+
+ if (_show_waveforms_recording != yn) {
+ _show_waveforms_recording = yn;
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(*i)) != 0) {
+ atv->set_show_waveforms_recording (yn);
+ }
+ }
+ DisplayControlChanged (Editing::ShowWaveformsRecording);
+ }
+}
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
new file mode 100644
index 0000000000..060b7d4842
--- /dev/null
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -0,0 +1,999 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+
+#include <gtk-canvas.h>
+
+#include <ardour/diskstream.h>
+#include <ardour/audioplaylist.h>
+
+#include "editor.h"
+#include "public_editor.h"
+#include "regionview.h"
+#include "streamview.h"
+#include "crossfade_view.h"
+#include "audio_time_axis.h"
+#include "region_gain_line.h"
+#include "automation_gain_line.h"
+#include "automation_pan_line.h"
+#include "automation_time_axis.h"
+#include "redirect_automation_line.h"
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+
+gint
+Editor::_canvas_copy_region_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ Editor* editor = (Editor*)data;
+ return editor->canvas_copy_region_event (item, event);
+}
+
+gint
+Editor::_canvas_crossfade_view_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ CrossfadeView* xfv = static_cast<CrossfadeView*> (data);
+ Editor* editor = dynamic_cast<Editor*>(&xfv->get_time_axis_view().editor);
+ return editor->canvas_crossfade_view_event (item, event, xfv);
+}
+
+gint
+Editor::_canvas_fade_in_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AudioRegionView* rv = static_cast<AudioRegionView*> (data);
+ Editor* editor = dynamic_cast<Editor*>(&rv->get_time_axis_view().editor);
+ return editor->canvas_fade_in_event (item, event, rv);
+}
+
+gint
+Editor::_canvas_fade_in_handle_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AudioRegionView* rv = static_cast<AudioRegionView*> (data);
+ Editor* editor = dynamic_cast<Editor*>(&rv->get_time_axis_view().editor);
+ return editor->canvas_fade_in_handle_event (item, event, rv);
+}
+
+gint
+Editor::_canvas_fade_out_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AudioRegionView* rv = static_cast<AudioRegionView*> (data);
+ Editor* editor = dynamic_cast<Editor*>(&rv->get_time_axis_view().editor);
+ return editor->canvas_fade_out_event (item, event, rv);
+}
+
+gint
+Editor::_canvas_fade_out_handle_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AudioRegionView* rv = static_cast<AudioRegionView*> (data);
+ Editor* editor = dynamic_cast<Editor*>(&rv->get_time_axis_view().editor);
+ return editor->canvas_fade_out_handle_event (item, event, rv);
+}
+
+gint
+Editor::_canvas_region_view_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AudioRegionView *rv = reinterpret_cast<AudioRegionView *>(data);
+ Editor* editor = dynamic_cast<Editor*>(&rv->get_time_axis_view().editor);
+
+ return editor->canvas_region_view_event (item, event, rv);
+}
+
+gint
+Editor::_canvas_region_view_name_highlight_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AudioRegionView *rv = reinterpret_cast<AudioRegionView *> (data);
+ Editor* editor = dynamic_cast<Editor*>(&rv->get_time_axis_view().editor);
+
+ return editor->canvas_region_view_name_highlight_event (item, event);
+}
+
+gint
+Editor::_canvas_region_view_name_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AudioRegionView *rv = reinterpret_cast<AudioRegionView *> (data);
+ Editor* editor = dynamic_cast<Editor*>(&rv->get_time_axis_view().editor);
+
+ return editor->canvas_region_view_name_event (item, event);
+}
+
+gint
+Editor::_canvas_stream_view_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* note that stream views are by definition audio track views */
+
+ AudioTimeAxisView *tv = (AudioTimeAxisView *) data;
+ Editor* editor = dynamic_cast<Editor*>(&tv->editor);
+
+ return editor->canvas_stream_view_event (item, event, tv);
+}
+
+gint
+Editor::_canvas_automation_track_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AutomationTimeAxisView* atv = (AutomationTimeAxisView*) data;
+ Editor* editor = dynamic_cast<Editor*>(&atv->editor);
+
+ return editor->canvas_automation_track_event (item, event, atv);
+}
+
+gint
+Editor::_canvas_control_point_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ ControlPoint *cp = reinterpret_cast<ControlPoint *>(data);
+ Editor* editor = dynamic_cast<Editor*>(&cp->line.trackview.editor);
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_control_point = cp;
+ clicked_trackview = &cp->line.trackview;
+ clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
+ clicked_regionview = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return editor->canvas_control_point_event (item, event);
+}
+
+gint
+Editor::_canvas_line_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ AutomationLine *line = reinterpret_cast<AutomationLine*> (data);
+ Editor* editor = dynamic_cast<Editor*>(&line->trackview.editor);
+
+ return editor->canvas_line_event (item, event);
+}
+
+gint
+Editor::_canvas_tempo_marker_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ Editor* editor = dynamic_cast<Editor*>((PublicEditor*) data);
+ return editor->canvas_tempo_marker_event (item, event);
+}
+
+gint
+Editor::_canvas_meter_marker_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ Editor* editor = dynamic_cast<Editor*>((PublicEditor *) data);
+ return editor->canvas_meter_marker_event (item, event);
+}
+
+gint
+Editor::_canvas_tempo_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* XXX NO CAST */
+ Editor* editor = (Editor*) data;
+ return editor->canvas_tempo_bar_event (item, event);
+}
+
+gint
+Editor::_canvas_meter_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* XXX NO CAST */
+ Editor* editor = (Editor*) data;
+ return editor->canvas_meter_bar_event (item, event);
+}
+
+gint
+Editor::_canvas_marker_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ Editor* editor = dynamic_cast<Editor*>((PublicEditor*) data);
+ return editor->canvas_marker_event (item, event);
+}
+
+gint
+Editor::_canvas_marker_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* NO CAST */
+ Editor* editor = (Editor*) data;
+ return editor->canvas_marker_bar_event (item, event);
+}
+
+gint
+Editor::_canvas_range_marker_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* NO CAST */
+ Editor* editor = (Editor*) data;
+ return editor->canvas_range_marker_bar_event (item, event);
+}
+
+gint
+Editor::_canvas_transport_marker_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* NO CAST */
+ Editor* editor = (Editor*) data;
+ return editor->canvas_transport_marker_bar_event (item, event);
+}
+
+gint
+Editor::_canvas_playhead_cursor_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* NO CAST */
+ Editor* editor = (Editor*) data;
+ return editor->canvas_playhead_cursor_event (item, event);
+}
+
+gint
+Editor::_canvas_edit_cursor_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* NO CAST */
+ Editor* editor = (Editor*) data;
+ return editor->canvas_edit_cursor_event (item, event);
+}
+
+gint
+Editor::_canvas_zoom_rect_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ Editor* editor = dynamic_cast<Editor*>((PublicEditor*) data);
+ return editor->canvas_zoom_rect_event (item, event);
+}
+
+gint
+Editor::_canvas_selection_rect_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ Editor* editor = dynamic_cast<Editor*>((PublicEditor*) data);
+ return editor->canvas_selection_rect_event (item, event);
+}
+
+gint
+Editor::_canvas_selection_start_trim_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ Editor* editor = dynamic_cast<Editor*>((PublicEditor*) data);
+ return editor->canvas_selection_start_trim_event (item, event);
+}
+
+gint
+Editor::_canvas_selection_end_trim_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ Editor* editor = dynamic_cast<Editor*>((PublicEditor*) data);
+ return editor->canvas_selection_end_trim_event (item, event);
+}
+
+gint
+Editor::_track_canvas_event (GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ /* NO CAST */
+
+ Editor* editor = (Editor*) data;
+ return editor->track_canvas_event (item, event);
+}
+
+/********** END OF.TATIC EVENT HANDLERS */
+
+gint
+Editor::track_canvas_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ gint x, y;
+
+ switch (event->type) {
+ case GDK_MOTION_NOTIFY:
+ /* keep those motion events coming */
+ track_canvas->get_pointer (x, y);
+ return track_canvas_motion (item, event);
+
+ case GDK_BUTTON_RELEASE:
+ switch (event->button.button) {
+ case 4:
+ case 5:
+ button_release_handler (item, event, NoItem);
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+Editor::track_canvas_motion (GtkCanvasItem *item, GdkEvent *ev)
+{
+ if (verbose_cursor_visible) {
+ gtk_canvas_item_set (verbose_canvas_cursor,
+ "x", ev->motion.x + 20,
+ "y", ev->motion.y + 20,
+ NULL);
+ }
+ return FALSE;
+}
+
+gint
+Editor::typed_event (GtkCanvasItem *item, GdkEvent *event, ItemType type)
+{
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ ret = button_press_handler (item, event, type);
+ break;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, type);
+ break;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, type);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, type);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, type);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+gint
+Editor::canvas_region_view_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv)
+{
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_regionview = rv;
+ clicked_control_point = 0;
+ clicked_trackview = &rv->get_time_axis_view();
+ clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
+ ret = button_press_handler (item, event, RegionItem);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, RegionItem);
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, RegionItem);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ set_entered_regionview (rv);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ set_entered_regionview (0);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+gint
+Editor::canvas_stream_view_event (GtkCanvasItem *item, GdkEvent *event, AudioTimeAxisView *tv)
+{
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_regionview = 0;
+ clicked_control_point = 0;
+ clicked_trackview = tv;
+ clicked_audio_trackview = tv;
+ ret = button_press_handler (item, event, StreamItem);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, StreamItem);
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, StreamItem);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+
+gint
+Editor::canvas_automation_track_event (GtkCanvasItem *item, GdkEvent *event, AutomationTimeAxisView *atv)
+{
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_regionview = 0;
+ clicked_control_point = 0;
+ clicked_trackview = atv;
+ clicked_audio_trackview = 0;
+ ret = button_press_handler (item, event, AutomationTrackItem);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, AutomationTrackItem);
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, AutomationTrackItem);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, AutomationTrackItem);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, AutomationTrackItem);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+gint
+Editor::canvas_fade_in_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv)
+{
+ /* we handle only button 3 press/release events */
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ clicked_regionview = rv;
+ clicked_control_point = 0;
+ clicked_trackview = &rv->get_time_axis_view();
+ clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
+ if (event->button.button == 3) {
+ return button_press_handler (item, event, FadeInItem);
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ if (event->button.button == 3) {
+ return button_release_handler (item, event, FadeInItem);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ /* proxy for the regionview */
+
+ return canvas_region_view_event (rv->get_canvas_group(), event, rv);
+}
+
+gint
+Editor::canvas_fade_in_handle_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv)
+{
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_regionview = rv;
+ clicked_control_point = 0;
+ clicked_trackview = &rv->get_time_axis_view();
+ clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
+ ret = button_press_handler (item, event, FadeInHandleItem);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, FadeInHandleItem);
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, FadeInHandleItem);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, FadeInHandleItem);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, FadeInHandleItem);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+gint
+Editor::canvas_fade_out_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv)
+{
+ /* we handle only button 3 press/release events */
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ clicked_regionview = rv;
+ clicked_control_point = 0;
+ clicked_trackview = &rv->get_time_axis_view();
+ clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
+ if (event->button.button == 3) {
+ return button_press_handler (item, event, FadeOutItem);
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ if (event->button.button == 3) {
+ return button_release_handler (item, event, FadeOutItem);
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ /* proxy for the regionview */
+
+ return canvas_region_view_event (rv->get_canvas_group(), event, rv);
+}
+
+gint
+Editor::canvas_fade_out_handle_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv)
+{
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_regionview = rv;
+ clicked_control_point = 0;
+ clicked_trackview = &rv->get_time_axis_view();
+ clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
+ ret = button_press_handler (item, event, FadeOutHandleItem);
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, FadeOutHandleItem);
+ break;
+
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, FadeOutHandleItem);
+ break;
+
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, FadeOutHandleItem);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, FadeOutHandleItem);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+struct DescendingRegionLayerSorter {
+ bool operator()(Region* a, Region* b) {
+ return a->layer() > b->layer();
+ }
+};
+
+gint
+Editor::canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, CrossfadeView* xfv)
+{
+ /* we handle only button 3 press/release events */
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ clicked_crossfadeview = xfv;
+ clicked_trackview = &clicked_crossfadeview->get_time_axis_view();
+ if (event->button.button == 3) {
+ return button_press_handler (item, event, CrossfadeViewItem);
+ }
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ if (event->button.button == 3) {
+ gint ret = button_release_handler (item, event, CrossfadeViewItem);
+ return ret;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+
+ /* proxy for the upper most regionview */
+
+ /* XXX really need to check if we are in the name highlight,
+ and proxy to that when required.
+ */
+
+ TimeAxisView& tv (xfv->get_time_axis_view());
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(&tv)) != 0) {
+
+ if (atv->is_audio_track()) {
+
+ AudioPlaylist* pl = atv->get_diskstream()->playlist();
+ Playlist::RegionList* rl = pl->regions_at (event_frame (event));
+
+ if (!rl->empty()) {
+ DescendingRegionLayerSorter cmp;
+ rl->sort (cmp);
+
+ AudioRegionView* arv = atv->view->find_view (*(dynamic_cast<AudioRegion*> (rl->front())));
+
+ /* proxy */
+
+ delete rl;
+
+ return canvas_region_view_event (arv->get_canvas_group(), event, arv);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+gint
+Editor::canvas_control_point_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ ItemType type;
+ ControlPoint *cp;
+
+ if ((cp = static_cast<ControlPoint *> (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) {
+ fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if (dynamic_cast<AudioRegionGainLine*> (&cp->line) != 0) {
+ type = GainControlPointItem;
+ } else if (dynamic_cast<AutomationGainLine*> (&cp->line) != 0) {
+ type = GainAutomationControlPointItem;
+ } else if (dynamic_cast<AutomationPanLine*> (&cp->line) != 0) {
+ type = PanAutomationControlPointItem;
+ } else if (dynamic_cast<RedirectAutomationLine*> (&cp->line) != 0) {
+ type = RedirectAutomationControlPointItem;
+ } else {
+ return FALSE;
+ }
+
+ return typed_event (item, event, type);
+}
+
+gint
+Editor::canvas_line_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ ItemType type;
+ AutomationLine *al;
+
+ if ((al = static_cast<AutomationLine *> (gtk_object_get_data (GTK_OBJECT(item), "line"))) == 0) {
+ fatal << _("programming error: line canvas item has no line object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if (dynamic_cast<AudioRegionGainLine*> (al) != 0) {
+ type = GainLineItem;
+ } else if (dynamic_cast<AutomationGainLine*> (al) != 0) {
+ type = GainAutomationLineItem;
+ } else if (dynamic_cast<AutomationPanLine*> (al) != 0) {
+ type = PanAutomationLineItem;
+ } else if (dynamic_cast<RedirectAutomationLine*> (al) != 0) {
+ type = RedirectAutomationLineItem;
+ } else {
+ return FALSE;
+ }
+
+ return typed_event (item, event, type);
+}
+
+
+gint
+Editor::canvas_selection_rect_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ gint ret = FALSE;
+ SelectionRect *rect = 0;
+
+ if ((rect = reinterpret_cast<SelectionRect*> (gtk_object_get_data (GTK_OBJECT(item), "rect"))) == 0) {
+ fatal << _("programming error: no \"rect\" pointer associated with selection item") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_selection = rect->id;
+ ret = button_press_handler (item, event, SelectionItem);
+ break;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, SelectionItem);
+ break;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, SelectionItem);
+ break;
+ /* Don't need these at the moment. */
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, SelectionItem);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, SelectionItem);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+gint
+Editor::canvas_selection_start_trim_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ gint ret = FALSE;
+ SelectionRect *rect = 0;
+
+ if ((rect = reinterpret_cast<SelectionRect*> (gtk_object_get_data (GTK_OBJECT(item), "rect"))) == 0) {
+ fatal << _("programming error: no \"rect\" pointer associated with selection item") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_selection = rect->id;
+ ret = button_press_handler (item, event, StartSelectionTrimItem);
+ break;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, StartSelectionTrimItem);
+ break;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, StartSelectionTrimItem);
+ break;
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, StartSelectionTrimItem);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, StartSelectionTrimItem);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+gint
+Editor::canvas_selection_end_trim_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ gint ret = FALSE;
+ SelectionRect *rect = 0;
+
+ if ((rect = reinterpret_cast<SelectionRect*> (gtk_object_get_data (GTK_OBJECT(item), "rect"))) == 0) {
+ fatal << _("programming error: no \"rect\" pointer associated with selection item") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_selection = rect->id;
+ ret = button_press_handler (item, event, EndSelectionTrimItem);
+ break;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, EndSelectionTrimItem);
+ break;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, EndSelectionTrimItem);
+ break;
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, EndSelectionTrimItem);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, EndSelectionTrimItem);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
+gint
+Editor::canvas_region_view_name_highlight_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_regionview = reinterpret_cast<AudioRegionView *> (gtk_object_get_data(GTK_OBJECT(item), "regionview"));
+ clicked_control_point = 0;
+ clicked_trackview = &clicked_regionview->get_time_axis_view();
+ clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
+ ret = button_press_handler (item, event, AudioRegionViewNameHighlight);
+ break;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, AudioRegionViewNameHighlight);
+ break;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, AudioRegionViewNameHighlight);
+ break;
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, AudioRegionViewNameHighlight);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, AudioRegionViewNameHighlight);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+gint
+Editor::canvas_region_view_name_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ gint ret = FALSE;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_regionview = reinterpret_cast<AudioRegionView *> (gtk_object_get_data(GTK_OBJECT(item), "regionview"));
+ clicked_control_point = 0;
+ clicked_trackview = &clicked_regionview->get_time_axis_view();
+ clicked_audio_trackview = dynamic_cast<AudioTimeAxisView*>(clicked_trackview);
+ ret = button_press_handler (item, event, AudioRegionViewName);
+ break;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, AudioRegionViewName);
+ break;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, AudioRegionViewName);
+ break;
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, AudioRegionViewName);
+ break;
+
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, AudioRegionViewName);
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+gint
+Editor::canvas_marker_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, MarkerItem);
+}
+
+gint
+Editor::canvas_marker_bar_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, MarkerBarItem);
+}
+
+gint
+Editor::canvas_range_marker_bar_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, RangeMarkerBarItem);
+}
+
+gint
+Editor::canvas_transport_marker_bar_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, TransportMarkerBarItem);
+}
+
+gint
+Editor::canvas_tempo_marker_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, TempoMarkerItem);
+}
+
+gint
+Editor::canvas_meter_marker_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, MeterMarkerItem);
+}
+
+gint
+Editor::canvas_tempo_bar_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, TempoBarItem);
+}
+
+gint
+Editor::canvas_meter_bar_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, MeterBarItem);
+}
+
+gint
+Editor::canvas_playhead_cursor_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, PlayheadCursorItem);
+}
+
+gint
+Editor::canvas_edit_cursor_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, EditCursorItem);
+}
+
+gint
+Editor::canvas_zoom_rect_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, NoItem);
+}
+
+gint
+Editor::canvas_copy_region_event (GtkCanvasItem *item, GdkEvent *event)
+{
+ return typed_event (item, event, RegionItem);
+}
+
diff --git a/gtk2_ardour/editor_cursors.cc b/gtk2_ardour/editor_cursors.cc
new file mode 100644
index 0000000000..0afbee4fdd
--- /dev/null
+++ b/gtk2_ardour/editor_cursors.cc
@@ -0,0 +1,121 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+
+#include <gtk-canvas.h>
+
+#include "utils.h"
+#include "editor.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+
+Editor::Cursor::Cursor (Editor& ed, const string& color, GtkSignalFunc callbck)
+ : editor (ed), callback (callbck), length(1.0)
+{
+ GtkCanvasGroup *group;
+ points = gtk_canvas_points_new (2);
+
+ /* "randomly" initialize coords */
+
+ points->coords[0] = -9383839.0;
+ points->coords[1] = 0.0;
+ points->coords[2] = 1.0;
+ points->coords[3] = 0.0;
+
+ group = GTK_CANVAS_GROUP (editor.cursor_group);
+
+ // cerr << "set cursor points, nc = " << points->num_points << endl;
+ canvas_item = gtk_canvas_item_new (group,
+ gtk_canvas_line_get_type(),
+ "points", points,
+ "fill_color", color.c_str(),
+ "width_pixels", 1,
+ "first_arrowhead", (gboolean) TRUE,
+ "last_arrowhead", (gboolean) TRUE,
+ "arrow_shape_a", 11.0,
+ "arrow_shape_b", 0.0,
+ "arrow_shape_c", 9.0,
+ NULL);
+
+ // cerr << "cursor line @ " << canvas_item << endl;
+
+ gtk_object_set_data (GTK_OBJECT(canvas_item), "cursor", this);
+ gtk_signal_connect (GTK_OBJECT(canvas_item), "event", callback, &editor);
+
+ current_frame = 1; /* force redraw at 0 */
+}
+
+Editor::Cursor::~Cursor ()
+
+{
+ gtk_object_destroy (GTK_OBJECT(canvas_item));
+ gtk_canvas_points_unref (points);
+}
+
+void
+Editor::Cursor::set_position (jack_nframes_t frame)
+{
+ double new_pos = editor.frame_to_unit (frame);
+
+ if (editor.session == 0) {
+ gtk_canvas_item_hide (canvas_item);
+ } else {
+ gtk_canvas_item_show (canvas_item);
+ }
+
+ current_frame = frame;
+
+ if (new_pos == points->coords[0]) {
+
+ /* change in position is not visible, so just raise it */
+
+ gtk_canvas_item_raise_to_top (canvas_item);
+ return;
+ }
+
+ points->coords[0] = new_pos;
+ points->coords[2] = new_pos;
+
+ // cerr << "set cursor2 al points, nc = " << points->num_points << endl;
+ gtk_canvas_item_set (canvas_item, "points", points, NULL);
+ gtk_canvas_item_raise_to_top (canvas_item);
+}
+
+void
+Editor::Cursor::set_length (double units)
+{
+ length = units;
+ points->coords[3] = points->coords[1] + length;
+ // cerr << "set cursor3 al points, nc = " << points->num_points << endl;
+ gtk_canvas_item_set (canvas_item, "points", points, NULL);
+}
+
+void
+Editor::Cursor::set_y_axis (double position)
+{
+ points->coords[1] = position;
+ points->coords[3] = position + length;
+ // cerr << "set cursor4 al points, nc = " << points->num_points << endl;
+ gtk_canvas_item_set (canvas_item, "points", points, NULL);
+}
diff --git a/gtk2_ardour/editor_edit_groups.cc b/gtk2_ardour/editor_edit_groups.cc
new file mode 100644
index 0000000000..8af7d31f5d
--- /dev/null
+++ b/gtk2_ardour/editor_edit_groups.cc
@@ -0,0 +1,210 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+
+#include <gtkmmext/stop_signal.h>
+#include <ardour/route_group.h>
+
+#include "editor.h"
+#include "keyboard.h"
+#include "marker.h"
+#include "time_axis_view.h"
+#include "prompter.h"
+
+#include <ardour/route.h>
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+
+void
+Editor::edit_group_list_column_click (gint col)
+
+{
+ if (edit_group_list_menu == 0) {
+ build_edit_group_list_menu ();
+ }
+
+ edit_group_list_menu->popup (0, 0);
+}
+
+void
+Editor::build_edit_group_list_menu ()
+
+{
+ using namespace Gtk::Menu_Helpers;
+
+ edit_group_list_menu = new Menu;
+ edit_group_list_menu->set_name ("ArdourContextMenu");
+ MenuList& items = edit_group_list_menu->items();
+
+ items.push_back (MenuElem (_("Show All"), slot (*this, &Editor::select_all_edit_groups)));
+ items.push_back (MenuElem (_("Hide All"), slot (*this, &Editor::unselect_all_edit_groups)));
+}
+
+void
+Editor::unselect_all_edit_groups ()
+
+{
+}
+
+void
+Editor::select_all_edit_groups ()
+
+{
+ CList_Helpers::RowList::iterator i;
+
+ /* XXX potential race with remove_track(), but the select operation
+ cannot be done with the track_lock held.
+ */
+
+ for (i = route_list.rows().begin(); i != route_list.rows().end(); ++i) {
+ i->select ();
+ }
+}
+
+void
+Editor::new_edit_group ()
+
+{
+ if (session == 0) {
+ return;
+ }
+
+ ArdourPrompter prompter;
+ string result;
+
+ prompter.set_prompt (_("Name for new edit group"));
+ prompter.done.connect (Gtk::Main::quit.slot());
+
+ prompter.show_all ();
+
+ Gtk::Main::run ();
+
+ if (prompter.status != Gtkmmext::Prompter::entered) {
+ return;
+ }
+
+ prompter.get_result (result);
+
+ if (result.length()) {
+ session->add_edit_group (result);
+ }
+}
+
+void
+Editor::edit_group_list_button_clicked ()
+{
+ new_edit_group ();
+}
+
+gint
+Editor::edit_group_list_button_press_event (GdkEventButton* ev)
+{
+ gint row, col;
+
+ if (edit_group_list.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) {
+ return FALSE;
+ }
+
+ if (col == 1) {
+
+ if (Keyboard::is_edit_event (ev)) {
+ // RouteGroup* group = (RouteGroup *) edit_group_list.row(row).get_data ();
+ // edit_route_group (group);
+
+ return stop_signal (edit_group_list, "button_press_event");
+
+ } else {
+ /* allow regular select to occur */
+ return FALSE;
+ }
+
+ } else if (col == 0) {
+
+ RouteGroup* group = reinterpret_cast<RouteGroup *>(edit_group_list.row(row).get_data ());
+
+ if (group) {
+ group->set_active (!group->is_active(), this);
+ }
+ }
+
+ return stop_signal (edit_group_list, "button_press_event");
+}
+
+void
+Editor::edit_group_selected (gint row, gint col, GdkEvent* ev)
+{
+ RouteGroup* group = (RouteGroup *) edit_group_list.row(row).get_data ();
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ if ((*i)->edit_group() == group) {
+ select_strip_in_display (*(*i));
+ }
+ }
+}
+
+void
+Editor::edit_group_unselected (gint row, gint col, GdkEvent* ev)
+{
+ RouteGroup* group = (RouteGroup *) edit_group_list.row(row).get_data ();
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ if ((*i)->edit_group() == group) {
+ unselect_strip_in_display (*(*i));
+ }
+ }
+}
+
+void
+Editor::add_edit_group (RouteGroup* group)
+{
+ list<string> names;
+
+ names.push_back ("*");
+ names.push_back (group->name());
+
+ edit_group_list.rows().push_back (names);
+ edit_group_list.rows().back().set_data (group);
+ edit_group_list.rows().back().select();
+
+ group->FlagsChanged.connect (bind (slot (*this, &Editor::group_flags_changed), group));
+}
+
+void
+Editor::group_flags_changed (void* src, RouteGroup* group)
+{
+ if (src != this) {
+ // select row
+ }
+
+ CList_Helpers::RowIterator ri = edit_group_list.rows().find_data (group);
+
+ if (group->is_active()) {
+ edit_group_list.cell (ri->get_row_num(),0).set_pixmap (check_pixmap, check_mask);
+ } else {
+ edit_group_list.cell (ri->get_row_num(),0).set_pixmap (empty_pixmap, empty_mask);
+ }
+}
+
diff --git a/gtk2_ardour/editor_enums.h b/gtk2_ardour/editor_enums.h
new file mode 100644
index 0000000000..419f0e2809
--- /dev/null
+++ b/gtk2_ardour/editor_enums.h
@@ -0,0 +1,10 @@
+#ifndef __ardour_gtk_editor_enums_h__
+#define __ardour_gtk_editor_enums_h__
+
+enum EditorDisplayControl {
+ ShowMeasures,
+ ShowWaveforms,
+ FollowPlayhead
+};
+
+#endif /* __ardour_gtk_editor_enums_h__ */
diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc
new file mode 100644
index 0000000000..b4ee6eecdf
--- /dev/null
+++ b/gtk2_ardour/editor_export_audio.cc
@@ -0,0 +1,437 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <unistd.h>
+#include <climits>
+#include "export_dialog.h"
+#include "editor.h"
+#include "public_editor.h"
+#include "selection.h"
+#include "time_axis_view.h"
+#include "audio_time_axis.h"
+#include "regionview.h"
+#include "ardour_message.h"
+
+#include <pbd/pthread_utils.h>
+#include <ardour/types.h>
+#include <ardour/export.h>
+#include <ardour/audio_track.h>
+#include <ardour/filesource.h>
+#include <ardour/diskstream.h>
+#include <ardour/audioregion.h>
+#include <ardour/audioplaylist.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace Gtk;
+
+void
+Editor::export_session()
+{
+ if (session) {
+ export_range (0, session->current_end_frame());
+ }
+}
+
+void
+Editor::export_selection ()
+{
+ if (session) {
+ if (selection->time.empty()) {
+ ArdourMessage message (this, X_("norange"), _("There is no range to export.\n\nSelect a range using the range mouse mode"));
+ return;
+ }
+
+ export_range (selection->time.front().start,
+ selection->time.front().end);
+ }
+}
+
+void
+Editor::export_range (jack_nframes_t start, jack_nframes_t end)
+{
+ if (session) {
+ if (export_dialog == 0) {
+ export_dialog = new ExportDialog (*this);
+ }
+
+ export_dialog->connect_to_session (session);
+ export_dialog->set_range (start, end);
+ export_dialog->start_export();
+ }
+}
+
+void
+Editor::export_region ()
+{
+ if (clicked_regionview == 0) {
+ return;
+ }
+
+ ExportDialog* dialog = new ExportDialog (*this, &clicked_regionview->region);
+
+ dialog->connect_to_session (session);
+ dialog->set_range (0, clicked_regionview->region.length());
+ dialog->start_export();
+}
+
+void
+Editor::write_a_region ()
+{
+ if (clicked_regionview == 0) {
+ return;
+ }
+
+ FileSelection file_selector;
+
+ file_selector.get_selection_entry()->activate.connect (bind (slot (*this, &Editor::finish_sub_event_loop), 1));
+ file_selector.get_cancel_button()->clicked.connect (bind (slot (*this, &Editor::finish_sub_event_loop), -1));
+ file_selector.get_ok_button()->clicked.connect (bind (slot (*this, &Editor::finish_sub_event_loop), 1));
+ file_selector.delete_event.connect (bind (slot (*this, &Editor::finish_sub_event_loop_on_delete), -1));
+
+ file_selector.show_all();
+
+ run_sub_event_loop ();
+
+ if (sub_event_loop_status == 1) {
+ string path = file_selector.get_filename();
+ printf ("got region: %s\n", path.c_str());
+ if (path.length()) {
+ write_region (path, clicked_regionview->region);
+ }
+ }
+}
+
+int
+Editor::write_region_selection (AudioRegionSelection& regions)
+{
+ for (AudioRegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
+ if (write_region ("", (*i)->region) == false) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void
+Editor::bounce_region_selection ()
+{
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+
+ AudioRegion& region ((*i)->region);
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&(*i)->get_time_axis_view());
+ AudioTrack* track = dynamic_cast<AudioTrack*>(&(atv->route()));
+
+ InterThreadInfo itt;
+
+ itt.done = false;
+ itt.cancel = false;
+ itt.progress = 0.0f;
+
+ track->bounce_range (region.position(), region.position() + region.length(), itt);
+ }
+}
+
+bool
+Editor::write_region (string path, AudioRegion& region)
+{
+ FileSource* fs;
+ const jack_nframes_t chunk_size = 4096;
+ jack_nframes_t to_read;
+ Sample buf[chunk_size];
+ gain_t gain_buffer[chunk_size];
+ jack_nframes_t pos;
+ char s[PATH_MAX+1];
+ uint32_t cnt;
+ vector<FileSource *> sources;
+ uint32_t nchans;
+
+ nchans = region.n_channels();
+
+ /* don't do duplicate of the entire source if that's what is going on here */
+
+ if (region.start() == 0 && region.length() == region.source().length()) {
+ /* XXX should link(2) to create a new inode with "path" */
+ return true;
+ }
+
+ if (path.length() == 0) {
+
+ for (uint32_t n=0; n < nchans; ++n) {
+
+ for (cnt = 0; cnt < 999999; ++cnt) {
+ if (nchans == 1) {
+ snprintf (s, sizeof(s), "%s/%s_%" PRIu32 ".wav", session->sound_dir().c_str(),
+ legalize_for_path(region.name()).c_str(), cnt);
+ }
+ else {
+ snprintf (s, sizeof(s), "%s/%s_%" PRIu32 "-%" PRId32 ".wav", session->sound_dir().c_str(),
+ legalize_for_path(region.name()).c_str(), cnt, n);
+ }
+
+ path = s;
+
+ if (::access (path.c_str(), F_OK) != 0) {
+ break;
+ }
+ }
+
+ if (cnt == 999999) {
+ error << "" << endmsg;
+ goto error_out;
+ }
+
+
+
+ try {
+ fs = new FileSource (path, session->frame_rate());
+ }
+
+ catch (failed_constructor& err) {
+ goto error_out;
+ }
+
+ sources.push_back (fs);
+ }
+ }
+ else {
+ /* TODO: make filesources based on passed path */
+
+ }
+
+ to_read = region.length();
+ pos = region.position();
+
+ while (to_read) {
+ jack_nframes_t this_time;
+
+ this_time = min (to_read, chunk_size);
+
+ for (vector<FileSource *>::iterator src=sources.begin(); src != sources.end(); ++src) {
+
+ fs = (*src);
+
+ if (region.read_at (buf, buf, gain_buffer, pos, this_time) != this_time) {
+ break;
+ }
+
+ if (fs->write (buf, this_time) != this_time) {
+ error << "" << endmsg;
+ goto error_out;
+ }
+ }
+
+ to_read -= this_time;
+ pos += this_time;
+ }
+
+ time_t tnow;
+ struct tm* now;
+ time (&tnow);
+ now = localtime (&tnow);
+
+ for (vector<FileSource *>::iterator src = sources.begin(); src != sources.end(); ++src) {
+ (*src)->update_header (0, *now, tnow);
+ }
+
+ return true;
+
+error_out:
+
+ for (vector<FileSource*>::iterator i = sources.begin(); i != sources.end(); ++i) {
+ (*i)->mark_for_remove ();
+ delete (*i);
+ }
+
+ return 0;
+}
+
+int
+Editor::write_audio_selection (TimeSelection& ts)
+{
+ int ret = 0;
+
+ if (selection->tracks.empty()) {
+ return 0;
+ }
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(*i)) == 0) {
+ continue;
+ }
+
+ if (atv->is_audio_track()) {
+
+ Playlist* playlist = atv->get_diskstream()->playlist();
+
+ if (playlist && write_audio_range (*playlist, atv->get_diskstream()->n_channels(), ts) == 0) {
+ ret = -1;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
+bool
+Editor::write_audio_range (Playlist& playlist, uint32_t channels, list<AudioRange>& range)
+{
+ FileSource* fs;
+ const jack_nframes_t chunk_size = 4096;
+ jack_nframes_t nframes;
+ Sample buf[chunk_size];
+ gain_t gain_buffer[chunk_size];
+ jack_nframes_t pos;
+ char s[PATH_MAX+1];
+ uint32_t cnt;
+ string path;
+ vector<FileSource *> sources;
+
+ for (uint32_t n=0; n < channels; ++n) {
+
+ for (cnt = 0; cnt < 999999; ++cnt) {
+ if (channels == 1) {
+ snprintf (s, sizeof(s), "%s/%s_%" PRIu32 ".wav", session->sound_dir().c_str(),
+ legalize_for_path(playlist.name()).c_str(), cnt);
+ }
+ else {
+ snprintf (s, sizeof(s), "%s/%s_%" PRIu32 "-%" PRId32 ".wav", session->sound_dir().c_str(),
+ legalize_for_path(playlist.name()).c_str(), cnt, n);
+ }
+
+ if (::access (s, F_OK) != 0) {
+ break;
+ }
+ }
+
+ if (cnt == 999999) {
+ error << "" << endmsg;
+ goto error_out;
+ }
+
+ path = s;
+
+ try {
+ fs = new FileSource (path, session->frame_rate());
+ }
+
+ catch (failed_constructor& err) {
+ goto error_out;
+ }
+
+ sources.push_back (fs);
+
+ }
+
+
+ for (list<AudioRange>::iterator i = range.begin(); i != range.end();) {
+
+ nframes = (*i).length();
+ pos = (*i).start;
+
+ while (nframes) {
+ jack_nframes_t this_time;
+
+ this_time = min (nframes, chunk_size);
+
+ for (uint32_t n=0; n < channels; ++n) {
+
+ fs = sources[n];
+
+ if (playlist.read (buf, buf, gain_buffer, pos, this_time, n) != this_time) {
+ break;
+ }
+
+ if (fs->write (buf, this_time) != this_time) {
+ goto error_out;
+ }
+ }
+
+ nframes -= this_time;
+ pos += this_time;
+ }
+
+ list<AudioRange>::iterator tmp = i;
+ ++tmp;
+
+ if (tmp != range.end()) {
+
+ /* fill gaps with silence */
+
+ nframes = (*tmp).start - (*i).end;
+
+ while (nframes) {
+
+ jack_nframes_t this_time = min (nframes, chunk_size);
+ memset (buf, 0, sizeof (Sample) * this_time);
+
+ for (uint32_t n=0; n < channels; ++n) {
+
+ fs = sources[n];
+ if (fs->write (buf, this_time) != this_time) {
+ goto error_out;
+ }
+ }
+
+ nframes -= this_time;
+ }
+ }
+
+ i = tmp;
+ }
+
+ time_t tnow;
+ struct tm* now;
+ time (&tnow);
+ now = localtime (&tnow);
+
+ for (uint32_t n=0; n < channels; ++n) {
+ sources[n]->update_header (0, *now, tnow);
+ // do we need to ref it again?
+ }
+
+ return true;
+
+error_out:
+ /* unref created files */
+
+ for (vector<FileSource*>::iterator i = sources.begin(); i != sources.end(); ++i) {
+ (*i)->mark_for_remove ();
+ delete *i;
+ }
+
+ return false;
+}
+
+void
+Editor::write_selection ()
+{
+ if (!selection->time.empty()) {
+ write_audio_selection (selection->time);
+ } else if (!selection->audio_regions.empty()) {
+ write_region_selection (selection->audio_regions);
+ }
+}
diff --git a/gtk2_ardour/editor_hscroller.cc b/gtk2_ardour/editor_hscroller.cc
new file mode 100644
index 0000000000..d22c1e69ed
--- /dev/null
+++ b/gtk2_ardour/editor_hscroller.cc
@@ -0,0 +1,270 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include "editor.h"
+
+#include <ardour/session.h>
+
+using namespace std;
+using namespace ARDOUR;
+
+void
+Editor::hscroll_slider_allocate (GtkAllocation *alloc)
+{
+ //edit_hscroll_slider_width = alloc->width;
+ //edit_hscroll_slider_height = alloc->height ;
+
+ if (session) {
+ track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
+ }
+
+}
+
+gint
+Editor::hscroll_slider_expose (GdkEventExpose *ev)
+{
+ GdkRectangle draw_rect;
+ GdkRectangle bar_rect;
+ gint bar_max = edit_hscroll_slider_width - 2;
+
+ bar_rect.y = 1;
+ bar_rect.height = edit_hscroll_slider_height - 2;
+
+ if (session) {
+ bar_rect.width = (gint) floor (bar_max * ((canvas_width * frames_per_unit) / session->current_end_frame()));
+
+ if (bar_rect.width > bar_max) {
+ bar_rect.x = 1;
+ bar_rect.width = bar_max;
+ } else {
+ bar_rect.x = 1 + (gint) floor (bar_max * ((double) leftmost_frame / session->current_end_frame()));
+ }
+
+ } else {
+ bar_rect.x = 1;
+ bar_rect.width = bar_max;
+ }
+
+ /* make sure we can see the bar at all times, and have enough to do zoom-trim on */
+
+ bar_rect.width = max ((guint16) (edit_hscroll_edge_width+5), bar_rect.width);
+
+ gdk_rectangle_intersect (&ev->area, &bar_rect, &draw_rect);
+
+ gtk_paint_box (edit_hscroll_slider.get_style()->gtkobj(),
+ edit_hscroll_slider.get_window(),
+ GTK_STATE_ACTIVE,
+ GTK_SHADOW_IN,
+ &ev->area,
+ GTK_WIDGET(edit_hscroll_slider.gtkobj()),
+ "trough",
+ 0, 0, -1, -1);
+
+ gtk_paint_box (edit_hscroll_slider.get_style()->gtkobj(),
+ edit_hscroll_slider.get_window(),
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT,
+ &draw_rect,
+ GTK_WIDGET(edit_hscroll_slider.gtkobj()),
+ "hscale",
+ bar_rect.x, bar_rect.y, bar_rect.width, bar_rect.height);
+
+
+ return TRUE;
+}
+
+gint
+Editor::hscroll_slider_button_press (GdkEventButton *ev)
+{
+ if (!session) {
+ return TRUE;
+ }
+
+ edit_hscroll_dragging = true;
+ //cerr << "PRESS" << endl;
+
+ return TRUE;
+
+ gint start;
+ gint width;
+ gint end;
+ gint x;
+
+ start = (gint) floor (edit_hscroll_slider_width * ((double) leftmost_frame / session->current_end_frame()));
+ width = (gint) floor (edit_hscroll_slider_width * ((canvas_width * frames_per_unit) / session->current_end_frame()));
+
+ end = start + width - 1;
+ x = (gint) max (0.0, ev->x);
+
+ if (x >= start && x <= end) {
+
+ edit_hscroll_drag_last = x;
+ edit_hscroll_dragging = true;
+ Gtk::Main::grab_add (edit_hscroll_slider);
+ }
+
+ return TRUE;
+}
+
+gint
+Editor::hscroll_slider_button_release (GdkEventButton *ev)
+{
+ if (!session) {
+ return TRUE;
+ }
+
+ gint start;
+ gint width;
+ gint end;
+ gint x;
+ gint bar_max = edit_hscroll_slider_width - 2;
+ jack_nframes_t new_leftmost = 0;
+
+ //cerr << "RELESAE" << endl;
+
+ if (edit_hscroll_dragging) {
+ // lets do a tempo redisplay now only, because it is dog slow
+ tempo_map_changed (Change (0));
+ edit_hscroll_dragging = false;
+ }
+
+ return TRUE;
+
+
+ start = (gint) floor (bar_max * ((double) leftmost_frame / session->current_end_frame()));
+ width = (gint) floor (bar_max * ((canvas_width * frames_per_unit) / session->current_end_frame()));
+
+ end = start + width - 1;
+ x = (gint) max (0.0, ev->x);
+
+ if (!edit_hscroll_dragging) {
+
+ new_leftmost = (jack_nframes_t) floor (((double) x/bar_max) * session->current_end_frame());
+ reposition_x_origin (new_leftmost);
+ }
+
+ if (edit_hscroll_dragging) {
+ // lets do a tempo redisplay now only, because it is dog slow
+ tempo_map_changed (Change (0));
+ edit_hscroll_dragging = false;
+ Gtk::Main::grab_remove (edit_hscroll_slider);
+ }
+
+ return TRUE;
+}
+
+gint
+Editor::hscroll_slider_motion (GdkEventMotion *ev)
+{
+ gint x, y;
+ GdkModifierType state;
+ gint bar_max = edit_hscroll_slider_width - 2;
+
+ if (!session || !edit_hscroll_dragging) {
+ return TRUE;
+ }
+
+ edit_hscroll_slider.get_window().get_pointer (x, y, state);
+
+ jack_nframes_t new_frame;
+ jack_nframes_t frames;
+ double distance;
+ double fract;
+
+ distance = x - edit_hscroll_drag_last;
+ fract = fabs (distance) / bar_max;
+ frames = (jack_nframes_t) floor (session->current_end_frame() * fract);
+
+ if (distance < 0) {
+ if (leftmost_frame < frames) {
+ new_frame = 0;
+ } else {
+ new_frame = leftmost_frame - frames;
+ }
+ } else {
+ if (leftmost_frame > max_frames - frames) {
+ new_frame = max_frames;
+ } else {
+ new_frame = leftmost_frame + frames;
+ }
+ }
+
+ if (new_frame != leftmost_frame) {
+ reposition_x_origin (new_frame);
+ }
+
+ edit_hscroll_drag_last = x;
+
+ return TRUE;
+}
+
+void
+Editor::update_hscroller ()
+{
+ //edit_hscroll_slider.queue_draw ();
+// if (session) {
+// track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
+// track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
+// }
+}
+
+gint
+Editor::hscroll_left_arrow_button_press (GdkEventButton *ev)
+{
+ if (!session) {
+ return FALSE;
+ }
+
+ start_canvas_autoscroll (-1);
+ return TRUE;
+}
+
+gint
+Editor::hscroll_right_arrow_button_press (GdkEventButton *ev)
+{
+ if (!session) {
+ return FALSE;
+ }
+
+ start_canvas_autoscroll (1);
+ return TRUE;
+}
+
+gint
+Editor::hscroll_left_arrow_button_release (GdkEventButton *ev)
+{
+ if (!session) {
+ return FALSE;
+ }
+
+ stop_canvas_autoscroll ();
+ return TRUE;
+}
+
+gint
+Editor::hscroll_right_arrow_button_release (GdkEventButton *ev)
+{
+ if (!session) {
+ return FALSE;
+ }
+
+ stop_canvas_autoscroll ();
+ return TRUE;
+}
diff --git a/gtk2_ardour/editor_imageframe.cc b/gtk2_ardour/editor_imageframe.cc
new file mode 100644
index 0000000000..57dbd0613e
--- /dev/null
+++ b/gtk2_ardour/editor_imageframe.cc
@@ -0,0 +1,1179 @@
+#include "imageframe_view.h"
+#include "imageframe_time_axis.h"
+#include "imageframe_time_axis_view.h"
+#include "imageframe_time_axis_group.h"
+#include "marker_time_axis_view.h"
+#include "marker_time_axis.h"
+#include "marker_view.h"
+#include "editor.h"
+#include "i18n.h"
+#include <gtkmmext/gtk_ui.h>
+#include <pbd/error.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+
+#include "imageframe_socket_handler.h"
+#include "ardour_image_compositor_socket.h"
+#include "public_editor.h"
+
+/* <CMT Additions file="editor.cc"> */
+
+void
+Editor::add_imageframe_time_axis(std::string track_name, void* src)
+{
+ // check for duplicate name
+ if(get_named_time_axis(track_name))
+ {
+ warning << "Repeated time axis name" << std::endl ;
+ }
+ else
+ {
+ Gtkmmext::UI::instance()->call_slot(bind(slot(*this, &Editor::handle_new_imageframe_time_axis_view),track_name, src)) ;
+ }
+}
+
+void
+Editor::connect_to_image_compositor()
+{
+ if(image_socket_listener == 0)
+ {
+ image_socket_listener = ImageFrameSocketHandler::create_instance(*this) ;
+ }
+
+ if(image_socket_listener->is_connected() == true)
+ {
+ return ;
+ }
+
+ // XXX should really put this somewhere safe
+ std::string host_ip = "127.0.0.1" ;
+
+ bool retcode = image_socket_listener->connect(host_ip,ardourvis::DEFAULT_PORT) ;
+
+ if(retcode == false)
+ {
+ // XXX need to get some return status here
+ warning << "Image Compositor Connection attempt failed" << std::endl ;
+ return ;
+ }
+
+ // add the socket to the gui loop, and keep the retuned tag value of the input
+ gint tag = gdk_input_add(image_socket_listener->get_socket_descriptor(), GDK_INPUT_READ,ImageFrameSocketHandler::image_socket_callback,image_socket_listener) ;
+ image_socket_listener->set_gdk_input_tag(tag) ;
+}
+
+void
+Editor::scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item)
+{
+ jack_nframes_t offset = static_cast<jack_nframes_t>(frames_per_unit * (edit_hscroll_slider_width/2)) ;
+
+ jack_nframes_t x_pos = 0 ;
+ if(item->get_position() < offset)
+ {
+ x_pos = 0 ;
+ }
+ else
+ {
+ x_pos = item->get_position() - offset + (item->get_duration() / 2) ;
+ }
+
+ reposition_x_origin(x_pos) ;
+}
+
+void
+Editor::add_imageframe_marker_time_axis(std::string track_name, TimeAxisView* marked_track, void* src)
+{
+ // Can we only bind 2 data Items?
+ // @todo we really want to bind the src attribute too, for the moment tracks can only be added remotely,
+ // so this is not too much of an issue, however will need to be looked at again
+ Gtkmmext::UI::instance()->call_slot(SigC::bind(slot(*this, &Editor::handle_new_imageframe_marker_time_axis_view),track_name, marked_track)) ;
+}
+
+void
+Editor::popup_imageframe_edit_menu(int button, int32_t time, GtkCanvasItem* ifv, bool with_item)
+{
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview) ;
+
+ if(ifta)
+ {
+ ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_selected_imageframe_group() ;
+
+ if(iftag)
+ {
+ ImageFrameView* selected_ifv = ifta->get_view()->get_selected_imageframe_view() ;
+ ifta->popup_imageframe_edit_menu(button, time, selected_ifv, with_item) ;
+ }
+ }
+}
+
+void
+Editor::popup_marker_time_axis_edit_menu(int button, int32_t time, GtkCanvasItem* ifv, bool with_item)
+{
+ MarkerTimeAxis* mta = dynamic_cast<MarkerTimeAxis*>(clicked_trackview) ;
+
+ if(mta)
+ {
+ MarkerView* selected_mv = mta->get_view()->get_selected_time_axis_item() ;
+ if(selected_mv)
+ {
+ mta->popup_marker_time_axis_edit_menu(button,time, selected_mv, with_item) ;
+ }
+ }
+}
+
+TimeAxisView*
+Editor::get_named_time_axis(std::string name)
+{
+ TimeAxisView* tav = 0 ;
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i)
+ {
+ if (((TimeAxisView*)*i)->name() == name)
+ {
+ tav = ((TimeAxisView*)*i) ;
+ break ;
+ }
+ }
+ return(tav) ;
+}
+
+/* </CMT Additions file="editor.cc"> */
+
+
+
+
+
+
+/* <CMT Additions file="editor_canvas_events.cc"> */
+
+/**
+ * ---------------------------------------------------------------------------------------------------
+ * Static event handlers
+ * These handlers deal with events from the GtkCanvas, a c-based component
+ */
+
+
+gint
+Editor::_canvas_imageframe_start_handle_event(GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ ImageFrameView* ifv = (ImageFrameView*) data ;
+ Editor* editor = dynamic_cast<Editor*> (&ifv->get_time_axis_view().editor);
+ return editor->canvas_imageframe_start_handle_event(item,event,ifv);
+}
+
+gint
+Editor::_canvas_imageframe_end_handle_event(GtkCanvasItem *item, GdkEvent *event, gpointer data)
+{
+ ImageFrameView* ifv = (ImageFrameView*) data ;
+ Editor* editor = dynamic_cast<Editor*> (&ifv->get_time_axis_view().editor);
+ return editor->canvas_imageframe_end_handle_event(item,event,ifv);
+}
+
+
+gint
+Editor::_canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data)
+{
+ ImageFrameView *ifv = (ImageFrameView *) data ;
+ Editor* editor = dynamic_cast<Editor*> (&ifv->get_time_axis_view().editor);
+ return editor->canvas_imageframe_item_view_event (item, event, ifv) ;
+}
+
+gint
+Editor::_canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data)
+{
+ ImageFrameTimeAxis *ifta = (ImageFrameTimeAxis*) data ;
+ Editor* editor = dynamic_cast<Editor*> (&ifta->editor);
+ return editor->canvas_imageframe_view_event (item, event, ifta);
+}
+
+gint
+Editor::_canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data)
+{
+ MarkerTimeAxis* mta = (MarkerTimeAxis*)data ;
+ Editor* editor = dynamic_cast<Editor*> (&mta->editor);
+ return editor->canvas_marker_time_axis_view_event(item,event,mta);
+}
+
+gint
+Editor::_canvas_markerview_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data)
+{
+ MarkerView* mv = (MarkerView*) data ;
+ Editor* editor = dynamic_cast<Editor*> (&mv->get_time_axis_view().editor);
+ return editor->canvas_markerview_item_view_event(item,event,mv);
+}
+
+gint
+Editor::_canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data)
+{
+ MarkerView* mv = (MarkerView*)data ;
+ Editor* editor = dynamic_cast<Editor*> (&mv->get_time_axis_view().editor);
+ return editor->canvas_markerview_start_handle_event(item,event,mv);
+}
+
+gint
+Editor::_canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data)
+{
+ MarkerView* mv = (MarkerView*)data ;
+ Editor* editor = dynamic_cast<Editor*> (&mv->get_time_axis_view().editor);
+ return editor->canvas_markerview_end_handle_event(item,event,mv);
+}
+
+/**
+ * ---------------------------------------------------------------------------------------------------
+ * End of Static event handlers
+ */
+
+gint
+Editor::canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent *event, ImageFrameView *ifv)
+{
+ gint ret = FALSE ;
+ ImageFrameTimeAxisGroup* iftag = 0 ;
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_trackview = &ifv->get_time_axis_view();
+ iftag = ifv->get_time_axis_group() ;
+ dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv);
+ ret = button_press_handler (item, event, ImageFrameItem) ;
+ break ;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, ImageFrameItem) ;
+ break ;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, ImageFrameItem) ;
+ break ;
+ default:
+ break ;
+ }
+ return(ret) ;
+}
+
+gint
+Editor::canvas_imageframe_start_handle_event(GtkCanvasItem *item, GdkEvent *event, ImageFrameView *ifv)
+{
+ gint ret = FALSE ;
+ ImageFrameTimeAxisGroup* iftag = 0 ;
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_trackview = &ifv->get_time_axis_view() ;
+ iftag = ifv->get_time_axis_group() ;
+ dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv);
+
+ ret = button_press_handler (item, event, ImageFrameHandleStartItem) ;
+ break ;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, ImageFrameHandleStartItem) ;
+ break;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, ImageFrameHandleStartItem) ;
+ break ;
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, ImageFrameHandleStartItem) ;
+ break ;
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, ImageFrameHandleStartItem) ;
+ break ;
+ default:
+ break ;
+ }
+ return(ret) ;
+}
+
+gint
+Editor::canvas_imageframe_end_handle_event(GtkCanvasItem *item, GdkEvent *event, ImageFrameView *ifv)
+{
+ gint ret = FALSE ;
+ ImageFrameTimeAxisGroup* iftag = 0 ;
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_trackview = &ifv->get_time_axis_view() ;
+ iftag = ifv->get_time_axis_group() ;
+ dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv);
+
+ ret = button_press_handler (item, event, ImageFrameHandleEndItem) ;
+ break ;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, ImageFrameHandleEndItem) ;
+ break ;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler (item, event, ImageFrameHandleEndItem) ;
+ break ;
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler (item, event, ImageFrameHandleEndItem) ;
+ break ;
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler (item, event, ImageFrameHandleEndItem);
+ break ;
+ default:
+ break ;
+ }
+ return(ret) ;
+}
+
+gint
+Editor::canvas_imageframe_view_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameTimeAxis* ifta)
+{
+ gint ret = FALSE ;
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_trackview = ifta ;
+ ret = button_press_handler (item, event, ImageFrameTimeAxisItem) ;
+ break ;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler (item, event, ImageFrameTimeAxisItem) ;
+ break ;
+ case GDK_MOTION_NOTIFY:
+ break ;
+ default:
+ break ;
+ }
+ return(ret) ;
+}
+
+gint
+Editor::canvas_marker_time_axis_view_event(GtkCanvasItem *item, GdkEvent* event, MarkerTimeAxis* mta)
+{
+ gint ret = FALSE ;
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_trackview = mta ;
+ ret = button_press_handler(item, event, MarkerTimeAxisItem) ;
+ break ;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler(item, event, MarkerTimeAxisItem) ;
+ break ;
+ case GDK_MOTION_NOTIFY:
+ default:
+ break ;
+ }
+ return(ret) ;
+}
+
+
+gint
+Editor::canvas_markerview_item_view_event(GtkCanvasItem *item, GdkEvent* event, MarkerView* mta)
+{
+ gint ret = FALSE ;
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_trackview = &mta->get_time_axis_view() ;
+ dynamic_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->set_selected_time_axis_item(mta);
+ ret = button_press_handler(item, event, MarkerViewItem) ;
+ break ;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler(item, event, MarkerViewItem) ;
+ break ;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler(item, event, MarkerViewItem) ;
+ break ;
+ default:
+ break ;
+ }
+ return(ret) ;
+}
+
+gint
+Editor::canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mta)
+{
+ gint ret = FALSE ;
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_trackview = &mta->get_time_axis_view() ;
+ dynamic_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->set_selected_time_axis_item(mta) ;
+ ret = button_press_handler(item, event, MarkerViewHandleStartItem) ;
+ break ;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler(item, event, MarkerViewHandleStartItem) ;
+ break ;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler(item, event, MarkerViewHandleStartItem) ;
+ break ;
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler(item, event, MarkerViewHandleStartItem) ;
+ break ;
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler(item, event, MarkerViewHandleStartItem) ;
+ break ;
+ default:
+ break ;
+ }
+ return(ret) ;
+}
+
+gint
+Editor::canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mta)
+{
+ gint ret = FALSE ;
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ clicked_trackview = &mta->get_time_axis_view() ;
+ dynamic_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->set_selected_time_axis_item(mta) ;
+ ret = button_press_handler(item, event, MarkerViewHandleEndItem) ;
+ break ;
+ case GDK_BUTTON_RELEASE:
+ ret = button_release_handler(item, event, MarkerViewHandleEndItem) ;
+ break ;
+ case GDK_MOTION_NOTIFY:
+ ret = motion_handler(item, event, MarkerViewHandleEndItem) ;
+ break ;
+ case GDK_ENTER_NOTIFY:
+ ret = enter_handler(item, event, MarkerViewHandleEndItem) ;
+ break ;
+ case GDK_LEAVE_NOTIFY:
+ ret = leave_handler(item, event, MarkerViewHandleEndItem) ;
+ break ;
+ default:
+ break ;
+ }
+ return(ret) ;
+}
+
+
+/* </CMT Additions file="editor_canvas_events.cc"> */
+
+
+/*
+ ---------------------------------------------------------------------------------------------------
+ ---------------------------------------------------------------------------------------------------
+ ---------------------------------------------------------------------------------------------------
+*/
+
+
+
+/* <CMT Additions file="editor_mouse.cc"> */
+
+void
+Editor::start_imageframe_grab(GtkCanvasItem* item, GdkEvent* event)
+{
+ ImageFrameView* ifv = ((ImageFrameTimeAxis*)clicked_trackview)->get_view()->get_selected_imageframe_view() ;
+ drag_info.copy = false ;
+ drag_info.item = item ;
+ drag_info.data = ifv ;
+ drag_info.motion_callback = &Editor::imageframe_drag_motion_callback;
+ drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback;
+ drag_info.last_frame_position = ifv->get_position() ;
+
+ drag_info.last_trackview = &ifv->get_time_axis_view() ;
+
+ /* this is subtle. raising the regionview itself won't help,
+ because raise_to_top() just puts the item on the top of
+ its parent's stack. so, we need to put the trackview canvas_display group
+ on the top, since its parent is the whole canvas.
+
+ however, this hides the measure bars within that particular trackview,
+ so move them to the top afterwards.
+ */
+
+ gtk_canvas_item_raise_to_top(drag_info.item) ;
+ gtk_canvas_item_raise_to_top(drag_info.last_trackview->canvas_display) ;
+ //gtk_canvas_item_raise_to_top(time_line_group) ;
+ gtk_canvas_item_raise_to_top (cursor_group);
+
+ start_grab(event) ;
+
+ drag_info.pointer_frame_offset = pixel_to_frame(drag_info.grab_x) - drag_info.last_frame_position;
+}
+
+
+void
+Editor::start_markerview_grab(GtkCanvasItem* item, GdkEvent* event)
+{
+ MarkerView* mv = ((MarkerTimeAxis*)clicked_trackview)->get_view()->get_selected_time_axis_item() ;
+ drag_info.copy = false ;
+ drag_info.item = item ;
+ drag_info.data = mv ;
+ drag_info.motion_callback = &Editor::markerview_drag_motion_callback;
+ drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback;
+ drag_info.last_frame_position = mv->get_position() ;
+
+ drag_info.last_trackview = &mv->get_time_axis_view() ;
+
+ /* this is subtle. raising the regionview itself won't help,
+ because raise_to_top() just puts the item on the top of
+ its parent's stack. so, we need to put the trackview canvas_display group
+ on the top, since its parent is the whole canvas.
+
+ however, this hides the measure bars within that particular trackview,
+ so move them to the top afterwards.
+ */
+
+ gtk_canvas_item_raise_to_top(drag_info.item) ;
+ gtk_canvas_item_raise_to_top(drag_info.last_trackview->canvas_display) ;
+ //gtk_canvas_item_raise_to_top(time_line_group) ;
+ gtk_canvas_item_raise_to_top (cursor_group);
+
+ start_grab(event) ;
+
+ drag_info.pointer_frame_offset = pixel_to_frame(drag_info.grab_x) - drag_info.last_frame_position ;
+}
+
+
+void
+Editor::markerview_drag_motion_callback(GtkCanvasItem*, GdkEvent* event)
+{
+ double cx, cy ;
+
+ MarkerView* mv = reinterpret_cast<MarkerView*>(drag_info.data) ;
+ jack_nframes_t pending_region_position ;
+ jack_nframes_t pointer_frame ;
+
+ pointer_frame = event_frame(event, &cx, &cy) ;
+
+ snap_to(pointer_frame) ;
+
+ if (pointer_frame > (jack_nframes_t) drag_info.pointer_frame_offset)
+ {
+ pending_region_position = pointer_frame - drag_info.pointer_frame_offset ;
+ snap_to(pending_region_position) ;
+
+ // we dont allow marker items to extend beyond, or in front of the marked items so
+ // cap the value to the marked items position and duration
+ if((pending_region_position + mv->get_duration()) >= ((mv->get_marked_item()->get_position()) + (mv->get_marked_item()->get_duration())))
+ {
+ pending_region_position = (mv->get_marked_item()->get_position() + mv->get_marked_item()->get_duration()) - (mv->get_duration()) ;
+ }
+ else if(pending_region_position <= mv->get_marked_item()->get_position())
+ {
+ pending_region_position = mv->get_marked_item()->get_position() ;
+ }
+ }
+ else
+ {
+ pending_region_position = mv->get_marked_item()->get_position() ;
+ }
+
+ drag_info.last_frame_position = pending_region_position ;
+
+ // we treat this as a special case, usually we want to send the identitiy of the caller
+ // but in this case, that would trigger our socket handler to handle the event, sending
+ // notification to the image compositor. This would be fine, except that we have not
+ // finished the drag, we therefore do not want to sent notification until we have
+ // completed the drag, only then do we want the image compositor notofied.
+ // We therefore set the caller identity to the special case of 0
+ mv->set_position(pending_region_position, 0) ;
+
+ show_verbose_time_cursor(pending_region_position) ;
+}
+
+void
+Editor::imageframe_drag_motion_callback(GtkCanvasItem*, GdkEvent* event)
+{
+ double cx, cy ;
+
+ ImageFrameView* ifv = reinterpret_cast<ImageFrameView*>(drag_info.data) ;
+
+ jack_nframes_t pending_region_position;
+ jack_nframes_t pointer_frame;
+
+ pointer_frame = event_frame(event, &cx, &cy) ;
+
+ snap_to(pointer_frame) ;
+
+ if (pointer_frame > (jack_nframes_t) drag_info.pointer_frame_offset)
+ {
+ pending_region_position = pointer_frame - drag_info.pointer_frame_offset ;
+ snap_to(pending_region_position) ;
+ }
+ else
+ {
+ pending_region_position = 0 ;
+ }
+
+ drag_info.grab_x = cx;
+ //drag_info.last_frame_position = pending_region_position ;
+ drag_info.current_pointer_frame = pending_region_position ;
+
+ // we treat this as a special case, usually we want to send the identitiy of the caller
+ // but in this case, that would trigger our socket handler to handle the event, sending
+ // notification to the image compositor. This would be fine, except that we have not
+ // finished the drag, we therefore do not want to sent notification until we have
+ // completed the drag, only then do we want the image compositor notofied.
+ // We therefore set the caller identity to the special case of 0
+ ifv->set_position(pending_region_position, 0) ;
+
+ show_verbose_time_cursor(pending_region_position) ;
+}
+
+void
+Editor::timeaxis_item_drag_finished_callback(GtkCanvasItem*, GdkEvent* event)
+{
+ jack_nframes_t where ;
+ TimeAxisViewItem* tavi = reinterpret_cast<TimeAxisViewItem*>(drag_info.data) ;
+
+ bool item_x_movement = (drag_info.last_frame_position != tavi->get_position()) ;
+
+ hide_verbose_canvas_cursor() ;
+
+ /* no x or y movement either means the regionview hasn't been moved, or has been moved
+ but is back in it's original position/trackview.*/
+
+ if(!item_x_movement && event && event->type == GDK_BUTTON_RELEASE)
+ {
+ /* No motion: either set the current region, or align the clicked region
+ with the current one.
+ */
+ return;
+ }
+
+ if(item_x_movement)
+ {
+ /* base the new region position on the current position of the regionview.*/
+ where = drag_info.current_pointer_frame ;
+
+ // final call to set position after the motion to tell interested parties of the new position
+ tavi->set_position(where, this) ;
+ }
+ else
+ {
+ //where = tavi->get_position() ;
+ }
+
+
+}
+
+
+void
+Editor::imageframe_start_handle_op(GtkCanvasItem* item, GdkEvent* event)
+{
+ // get the selected item from the parent time axis
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview) ;
+ if(ifta)
+ {
+ ImageFrameView* ifv = ifta->get_view()->get_selected_imageframe_view() ;
+
+ if (ifv == 0) {
+ fatal << _("programming error: no ImageFrameView selected") << endmsg;
+ /*NOTREACHED*/
+ return ;
+ }
+
+ drag_info.item = ifv->get_canvas_frame() ;
+ drag_info.data = ifv;
+ drag_info.grab_x = event->motion.x;
+ drag_info.cumulative_x_drag = 0;
+ drag_info.motion_callback = &Editor::imageframe_start_handle_trim_motion ;
+ drag_info.finished_callback = &Editor::imageframe_start_handle_end_trim ;
+
+ flush_track_canvas() ;
+
+ start_grab(event) ;
+
+ show_verbose_time_cursor(ifv->get_position(), 10) ;
+ }
+}
+
+void
+Editor::imageframe_end_handle_op(GtkCanvasItem* item, GdkEvent* event)
+{
+ // get the selected item from the parent time axis
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview) ;
+
+ if(ifta)
+ {
+ ImageFrameView* ifv = ifta->get_view()->get_selected_imageframe_view() ;
+
+ if (ifv == 0)
+ {
+ fatal << _("programming error: no ImageFrameView selected") << endmsg ;
+ /*NOTREACHED*/
+ return ;
+ }
+
+ drag_info.item = ifv->get_canvas_frame() ;
+ drag_info.data = ifv ;
+ drag_info.grab_x = event->motion.x ;
+ drag_info.cumulative_x_drag = 0 ;
+ drag_info.motion_callback = &Editor::imageframe_end_handle_trim_motion ;
+ drag_info.finished_callback = &Editor::imageframe_end_handle_end_trim ;
+
+ flush_track_canvas() ;
+
+ start_grab(event, trimmer_cursor) ;
+
+ show_verbose_time_cursor(ifv->get_position() + ifv->get_duration(), 10) ;
+ }
+}
+
+void
+Editor::imageframe_start_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event)
+{
+ ImageFrameView* ifv = reinterpret_cast<ImageFrameView*> (drag_info.data) ;
+
+ jack_nframes_t start = 0 ;
+ jack_nframes_t end = 0 ;
+ jack_nframes_t pointer_frame = event_frame(event) ;
+
+ // chekc th eposition of the item is not locked
+ if(!ifv->get_position_locked()) {
+ snap_to(pointer_frame) ;
+
+ if(pointer_frame != drag_info.last_pointer_frame) {
+ start = ifv->get_position() ;
+ end = ifv->get_position() + ifv->get_duration() ;
+
+ if (pointer_frame > end) {
+ start = end ;
+ } else {
+ start = pointer_frame ;
+ }
+
+ // are we getting bigger or smaller?
+ jack_nframes_t new_dur_val = end - start ;
+
+ // start handle, so a smaller pointer frame increases our component size
+ if(pointer_frame <= drag_info.grab_frame)
+ {
+ if(ifv->get_max_duration_active() && (new_dur_val > ifv->get_max_duration()))
+ {
+ new_dur_val = ifv->get_max_duration() ;
+ start = end - new_dur_val ;
+ }
+ else
+ {
+ // current values are ok
+ }
+ }
+ else
+ {
+ if(ifv->get_min_duration_active() && (new_dur_val < ifv->get_min_duration()))
+ {
+ new_dur_val = ifv->get_min_duration() ;
+ start = end - new_dur_val ;
+ }
+ else
+ {
+ // current values are ok
+ }
+ }
+
+ drag_info.last_pointer_frame = pointer_frame ;
+
+ /* re-calculatethe duration and position of the imageframeview */
+ drag_info.cumulative_x_drag = new_dur_val ;
+
+ // we treat this as a special case, usually we want to send the identitiy of the caller
+ // but in this case, that would trigger our socket handler to handle the event, sending
+ // notification to the image compositor. This would be fine, except that we have not
+ // finished the drag, we therefore do not want to sent notification until we have
+ // completed the drag, only then do we want the image compositor notofied.
+ // We therefore set the caller identity to the special case of 0
+ ifv->set_duration(new_dur_val, 0) ;
+ ifv->set_position(start, 0) ;
+ }
+ }
+
+ show_verbose_time_cursor(start, 10) ;
+}
+
+void
+Editor::imageframe_start_handle_end_trim(GtkCanvasItem* item, GdkEvent* event)
+{
+ ImageFrameView* ifv = reinterpret_cast<ImageFrameView *> (drag_info.data) ;
+
+ if (drag_info.cumulative_x_drag == 0)
+ {
+ /* just a click */
+ }
+ else
+ {
+ jack_nframes_t temp = ifv->get_position() + ifv->get_duration() ;
+
+ ifv->set_position((jack_nframes_t) (temp - drag_info.cumulative_x_drag), this) ;
+ ifv->set_duration((jack_nframes_t) drag_info.cumulative_x_drag, this) ;
+ }
+
+ flush_track_canvas() ;
+}
+
+void
+Editor::imageframe_end_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event)
+{
+ ImageFrameView* ifv = reinterpret_cast<ImageFrameView *> (drag_info.data) ;
+
+ jack_nframes_t start = 0 ;
+ jack_nframes_t end = 0 ;
+ jack_nframes_t pointer_frame = event_frame(event) ;
+ jack_nframes_t new_dur_val = 0 ;
+
+ snap_to(pointer_frame) ;
+
+ if (pointer_frame != drag_info.last_pointer_frame)
+ {
+ start = ifv->get_position() ;
+ end = ifv->get_position() + ifv->get_duration() ;
+ if (pointer_frame < start)
+ {
+ end = start ;
+ }
+ else
+ {
+ end = pointer_frame ;
+ }
+
+ new_dur_val = end - start ;
+
+ // are we getting bigger or smaller?
+ if(pointer_frame >= drag_info.last_pointer_frame)
+ {
+ if(ifv->get_max_duration_active() && (new_dur_val > ifv->get_max_duration()))
+ {
+ new_dur_val = ifv->get_max_duration() ;
+ }
+ }
+ else
+ {
+ if(ifv->get_min_duration_active() && (new_dur_val < ifv->get_min_duration()))
+ {
+ new_dur_val = ifv->get_min_duration() ;
+ }
+ }
+
+ drag_info.last_pointer_frame = pointer_frame ;
+ drag_info.cumulative_x_drag = new_dur_val ;
+
+ // we treat this as a special case, usually we want to send the identitiy of the caller
+ // but in this case, that would trigger our socket handler to handle the event, sending
+ // notification to the image compositor. This would be fine, except that we have not
+ // finished the drag, we therefore do not want to sent notification until we have
+ // completed the drag, only then do we want the image compositor notofied.
+ // We therefore set the caller identity to the special case of 0
+ ifv->set_duration(new_dur_val, 0) ;
+ }
+
+ show_verbose_time_cursor(new_dur_val, 10) ;
+}
+
+
+void
+Editor::imageframe_end_handle_end_trim (GtkCanvasItem* item, GdkEvent* event)
+{
+ ImageFrameView* ifv = reinterpret_cast<ImageFrameView *> (drag_info.data) ;
+
+ if (drag_info.cumulative_x_drag == 0)
+ {
+ /* just a click */
+ }
+ else
+ {
+ jack_nframes_t new_duration = (jack_nframes_t)drag_info.cumulative_x_drag ;
+ if((new_duration <= ifv->get_max_duration()) && (new_duration >= ifv->get_min_duration()))
+ {
+ ifv->set_duration(new_duration, this) ;
+ }
+ }
+
+ flush_track_canvas ();
+}
+
+
+void
+Editor::markerview_item_start_handle_op(GtkCanvasItem* item, GdkEvent* event)
+{
+ MarkerView* mv = reinterpret_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->get_selected_time_axis_item() ;
+
+ if (mv == 0)
+ {
+ fatal << _("programming error: no MarkerView selected") << endmsg ;
+ /*NOTREACHED*/
+ return ;
+ }
+
+ drag_info.item = mv->get_canvas_frame() ;
+ drag_info.data = mv;
+ drag_info.grab_x = event->motion.x;
+
+ drag_info.cumulative_x_drag = 0 ;
+ drag_info.motion_callback = &Editor::markerview_start_handle_trim_motion ;
+ drag_info.finished_callback = &Editor::markerview_start_handle_end_trim ;
+
+ flush_track_canvas() ;
+
+ start_grab(event, trimmer_cursor) ;
+}
+
+void
+Editor::markerview_item_end_handle_op(GtkCanvasItem* item, GdkEvent* event)
+{
+ MarkerView* mv = reinterpret_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->get_selected_time_axis_item() ;
+ if (mv == 0)
+ {
+ fatal << _("programming error: no MarkerView selected") << endmsg ;
+ /*NOTREACHED*/
+ return ;
+ }
+
+ drag_info.item = mv->get_canvas_frame() ;
+ drag_info.data = mv ;
+ drag_info.grab_x = event->motion.x ;
+ drag_info.cumulative_x_drag = 0 ;
+
+ drag_info.motion_callback = &Editor::markerview_end_handle_trim_motion ;
+ drag_info.finished_callback = &Editor::markerview_end_handle_end_trim ;
+
+ flush_track_canvas () ;
+
+ start_grab(event, trimmer_cursor) ;
+}
+
+
+void
+Editor::markerview_start_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event)
+{
+ MarkerView* mv = reinterpret_cast<MarkerView*> (drag_info.data) ;
+
+ jack_nframes_t start = 0 ;
+ jack_nframes_t end = 0 ;
+ jack_nframes_t pointer_frame = event_frame(event) ;
+
+ // chekc th eposition of the item is not locked
+ if(!mv->get_position_locked())
+ {
+ snap_to(pointer_frame) ;
+ if(pointer_frame != drag_info.last_pointer_frame)
+ {
+ start = mv->get_position() ;
+ end = mv->get_position() + mv->get_duration() ;
+
+ if (pointer_frame > end)
+ {
+ start = end ;
+ }
+ else
+ {
+ start = pointer_frame ;
+ }
+
+ // are we getting bigger or smaller?
+ jack_nframes_t new_dur_val = end - start ;
+
+ if(pointer_frame <= drag_info.grab_frame)
+ {
+ if(mv->get_max_duration_active() && (new_dur_val > mv->get_max_duration()))
+ {
+ new_dur_val = mv->get_max_duration() ;
+ start = end - new_dur_val ;
+ }
+ else
+ {
+ // current values are ok
+ }
+ }
+ else
+ {
+ if(mv->get_min_duration_active() && (new_dur_val < mv->get_min_duration()))
+ {
+ new_dur_val = mv->get_min_duration() ;
+ start = end - new_dur_val ;
+ }
+ else
+ {
+ // current values are ok
+ }
+ }
+
+ drag_info.last_pointer_frame = pointer_frame ;
+
+ /* re-calculatethe duration and position of the imageframeview */
+ drag_info.cumulative_x_drag = new_dur_val ;
+
+ // we treat this as a special case, usually we want to send the identitiy of the caller
+ // but in this case, that would trigger our socket handler to handle the event, sending
+ // notification to the image compositor. This would be fine, except that we have not
+ // finished the drag, we therefore do not want to sent notification until we have
+ // completed the drag, only then do we want the image compositor notofied.
+ // We therefore set the caller identity to the special case of 0
+ mv->set_duration(new_dur_val, 0) ;
+ mv->set_position(start, 0) ;
+ }
+ }
+
+ show_verbose_time_cursor(start, 10) ;
+}
+
+void
+Editor::markerview_start_handle_end_trim(GtkCanvasItem* item, GdkEvent* event)
+{
+ MarkerView* mv = reinterpret_cast<MarkerView*> (drag_info.data) ;
+
+ if (drag_info.cumulative_x_drag == 0)
+ {
+ /* just a click */
+ }
+ else
+ {
+ jack_nframes_t temp = mv->get_position() + mv->get_duration() ;
+
+ mv->set_position((jack_nframes_t) (temp - drag_info.cumulative_x_drag), this) ;
+ mv->set_duration((jack_nframes_t) drag_info.cumulative_x_drag, this) ;
+ }
+
+ flush_track_canvas() ;
+}
+
+void
+Editor::markerview_end_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event)
+{
+ MarkerView* mv = reinterpret_cast<MarkerView*> (drag_info.data) ;
+
+ jack_nframes_t start = 0 ;
+ jack_nframes_t end = 0 ;
+ jack_nframes_t pointer_frame = event_frame(event) ;
+ jack_nframes_t new_dur_val = 0 ;
+
+ snap_to(pointer_frame) ;
+
+ if (pointer_frame != drag_info.last_pointer_frame)
+ {
+ start = mv->get_position() ;
+ end = mv->get_position() + mv->get_duration() ;
+
+ if(pointer_frame < start)
+ {
+ end = start ;
+ }
+ else
+ {
+ end = pointer_frame ;
+ }
+
+ new_dur_val = end - start ;
+
+ // are we getting bigger or smaller?
+ if(pointer_frame >= drag_info.last_pointer_frame)
+ {
+ // we cant extend beyond the item we are marking
+ ImageFrameView* marked_item = mv->get_marked_item() ;
+ jack_nframes_t marked_end = marked_item->get_position() + marked_item->get_duration() ;
+
+ if(mv->get_max_duration_active() && (new_dur_val > mv->get_max_duration()))
+ {
+ if((start + mv->get_max_duration()) > marked_end)
+ {
+ new_dur_val = marked_end - start ;
+ }
+ else
+ {
+ new_dur_val = mv->get_max_duration() ;
+ }
+ }
+ else if(end > marked_end)
+ {
+ new_dur_val = marked_end - start ;
+ }
+ }
+ else
+ {
+ if(mv->get_min_duration_active() && (new_dur_val < mv->get_min_duration()))
+ {
+ new_dur_val = mv->get_min_duration() ;
+ }
+ }
+
+
+ drag_info.last_pointer_frame = pointer_frame ;
+ drag_info.cumulative_x_drag = new_dur_val ;
+
+ // we treat this as a special case, usually we want to send the identitiy of the caller
+ // but in this case, that would trigger our socket handler to handle the event, sending
+ // notification to the image compositor. This would be fine, except that we have not
+ // finished the drag, we therefore do not want to sent notification until we have
+ // completed the drag, only then do we want the image compositor notofied.
+ // We therefore set the caller identity to the special case of 0
+ mv->set_duration(new_dur_val, 0) ;
+ }
+
+ show_verbose_time_cursor(new_dur_val, 10) ;
+}
+
+
+void
+Editor::markerview_end_handle_end_trim (GtkCanvasItem* item, GdkEvent* event)
+{
+ MarkerView* mv = reinterpret_cast<MarkerView*> (drag_info.data) ;
+
+ if (drag_info.cumulative_x_drag == 0)
+ {
+ /* just a click */
+ }
+ else
+ {
+ jack_nframes_t new_duration = (jack_nframes_t)drag_info.cumulative_x_drag ;
+ mv->set_duration(new_duration, this) ;
+ }
+
+ flush_track_canvas() ;
+}
+
+
+/* </CMT Additions file="editor_mouse.cc"> */
+
+
+
+
+
+
+
+/* <CMT Additions file="editor_route_list.cc"> */
+
+void
+Editor::handle_new_imageframe_time_axis_view(std::string track_name, void* src)
+{
+ ImageFrameTimeAxis* iftav ;
+ iftav = new ImageFrameTimeAxis(track_name, *this, *session, track_canvas) ;
+ iftav->set_time_axis_name(track_name, this) ;
+ track_views.push_back(iftav) ;
+ const gchar *rowdata[1] ;
+ rowdata[0] = iftav->name().c_str() ;
+ route_list.rows().push_back(rowdata) ;
+ route_list.rows().back().set_data(iftav) ;
+ route_list.rows().back().select() ;
+ iftav->GoingAway.connect(bind(slot(*this, &Editor::remove_route), (TimeAxisView*)iftav)) ;
+ iftav->gui_changed.connect(slot(*this, &Editor::handle_gui_changes)) ;
+}
+
+void
+Editor::handle_new_imageframe_marker_time_axis_view(std::string track_name, TimeAxisView* marked_track)
+{
+ MarkerTimeAxis* mta = new MarkerTimeAxis (*this, *this->current_session(), track_canvas, track_name, marked_track) ;
+ ((ImageFrameTimeAxis*)marked_track)->add_marker_time_axis(mta, this) ;
+ track_views.push_back(mta) ;
+ const gchar *rowdata[1] ;
+ rowdata[0] = mta->name().c_str() ;
+ route_list.rows().push_back(rowdata) ;
+ route_list.rows().back().set_data (mta) ;
+ route_list.rows().back().select() ;
+ mta->GoingAway.connect(bind(slot (*this, &Editor::remove_route), (TimeAxisView*)mta)) ;
+ }
+
+
+/* </CMT Additions file="editor_route_list.cc"> */
diff --git a/gtk2_ardour/editor_keyboard.cc b/gtk2_ardour/editor_keyboard.cc
new file mode 100644
index 0000000000..8fb0e64235
--- /dev/null
+++ b/gtk2_ardour/editor_keyboard.cc
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/audioregion.h>
+
+#include "editor.h"
+#include "regionview.h"
+#include "selection.h"
+
+void
+Editor::kbd_driver (SigC::Slot1<void,GdkEvent*> theslot, bool use_track_canvas, bool use_time_canvas, bool can_select)
+{
+ gint x, y;
+ double dx, dy;
+ GdkEvent ev;
+ GdkModifierType mask;
+ Gdk_Window evw (track_canvas->get_window().get_pointer (x, y, mask));
+ bool doit = false;
+
+ if (use_track_canvas && gdk_window_get_pointer (track_canvas_event_box.get_window(),
+ &x, &y, &mask)) {
+ doit = true;
+
+ } else if (use_time_canvas && gdk_window_get_pointer (time_canvas_event_box.get_window(),
+ &x, &y, &mask)) {
+ doit = true;
+ }
+
+ if (doit) {
+
+ if (entered_regionview && can_select) {
+ selection->set (entered_regionview);
+ }
+
+ gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), x, y, &dx, &dy);
+
+ ev.type = GDK_BUTTON_PRESS;
+ ev.button.x = dx;
+ ev.button.y = dy;
+ ev.button.state = 0; /* XXX correct? */
+
+ theslot (&ev);
+ }
+}
+
+void
+Editor::kbd_set_playhead_cursor ()
+{
+ kbd_driver (slot (*this, &Editor::set_playhead_cursor), true, true, false);
+}
+
+void
+Editor::kbd_set_edit_cursor ()
+{
+ kbd_driver (slot (*this, &Editor::set_edit_cursor), true, true, false);
+}
+
+
+void
+Editor::kbd_do_split (GdkEvent* ev)
+{
+ jack_nframes_t where = event_frame (ev);
+
+ if (entered_regionview) {
+ if (selection->audio_regions.find (entered_regionview) != selection->audio_regions.end()) {
+ split_regions_at (where, selection->audio_regions);
+ } else {
+ AudioRegionSelection s;
+ s.add (entered_regionview);
+ split_regions_at (where, s);
+ }
+ }
+}
+
+void
+Editor::kbd_split ()
+{
+ kbd_driver (slot (*this, &Editor::kbd_do_split), true, true, false);
+}
+
+void
+Editor::kbd_do_align (GdkEvent* ev, ARDOUR::RegionPoint what)
+{
+ align (what);
+}
+
+void
+Editor::kbd_align (ARDOUR::RegionPoint what)
+{
+ kbd_driver (bind (slot (*this, &Editor::kbd_do_align), what));
+}
+
+void
+Editor::kbd_do_align_relative (GdkEvent* ev, ARDOUR::RegionPoint what)
+{
+ align (what);
+}
+
+void
+Editor::kbd_align_relative (ARDOUR::RegionPoint what)
+{
+ kbd_driver (bind (slot (*this, &Editor::kbd_do_align), what), true, true, false);
+}
+
+void
+Editor::kbd_do_brush (GdkEvent *ev)
+{
+ brush (event_frame (ev, 0, 0));
+}
+
+void
+Editor::kbd_brush ()
+{
+ kbd_driver (slot (*this, &Editor::kbd_do_brush), true, true, false);
+}
+
+void
+Editor::kbd_do_audition (GdkEvent *ignored)
+{
+ audition_selected_region ();
+}
+
+void
+Editor::kbd_audition ()
+{
+ kbd_driver (slot (*this, &Editor::kbd_do_audition), true, false, true);
+}
diff --git a/gtk2_ardour/editor_keys.cc b/gtk2_ardour/editor_keys.cc
new file mode 100644
index 0000000000..dbcb2a1e52
--- /dev/null
+++ b/gtk2_ardour/editor_keys.cc
@@ -0,0 +1,268 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+
+#include <string>
+
+#include <pbd/error.h>
+
+#include <gtkmmext/popup_selector.h>
+
+#include <ardour/session.h>
+#include <ardour/region.h>
+
+#include "ardour_ui.h"
+#include "editor.h"
+#include "time_axis_view.h"
+#include "regionview.h"
+#include "selection.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+
+void
+Editor::install_keybindings ()
+{
+ /* add named actions for the editor */
+
+ add_action ("toggle-xfades-active", slot (*this, &Editor::toggle_xfades_active));
+
+ add_action ("playhead-to-next-region-start", bind (slot (*this, &Editor::cursor_to_next_region_point), playhead_cursor, RegionPoint (Start)));
+ add_action ("playhead-to-next-region-end", bind (slot (*this, &Editor::cursor_to_next_region_point), playhead_cursor, RegionPoint (End)));
+ add_action ("playhead-to-next-region-sync", bind (slot (*this, &Editor::cursor_to_next_region_point), playhead_cursor, RegionPoint (SyncPoint)));
+
+ add_action ("playhead-to-previous-region-start", bind (slot (*this, &Editor::cursor_to_previous_region_point), playhead_cursor, RegionPoint (Start)));
+ add_action ("playhead-to-previous-region-end", bind (slot (*this, &Editor::cursor_to_previous_region_point), playhead_cursor, RegionPoint (End)));
+ add_action ("playhead-to-previous-region-sync", bind (slot (*this, &Editor::cursor_to_previous_region_point), playhead_cursor, RegionPoint (SyncPoint)));
+
+ add_action ("edit-cursor-to-next-region-start", bind (slot (*this, &Editor::cursor_to_next_region_point), edit_cursor, RegionPoint (Start)));
+ add_action ("edit-cursor-to-next-region-end", bind (slot (*this, &Editor::cursor_to_next_region_point), edit_cursor, RegionPoint (End)));
+ add_action ("edit-cursor-to-next-region-sync", bind (slot (*this, &Editor::cursor_to_next_region_point), edit_cursor, RegionPoint (SyncPoint)));
+
+ add_action ("edit-cursor-to-previous-region-start", bind (slot (*this, &Editor::cursor_to_previous_region_point), edit_cursor, RegionPoint (Start)));
+ add_action ("edit-cursor-to-previous-region-end", bind (slot (*this, &Editor::cursor_to_previous_region_point), edit_cursor, RegionPoint (End)));
+ add_action ("edit-cursor-to-previous-region-sync", bind (slot (*this, &Editor::cursor_to_previous_region_point), edit_cursor, RegionPoint (SyncPoint)));
+
+ add_action ("playhead-to-range-start", bind (slot (*this, &Editor::cursor_to_selection_start), playhead_cursor));
+ add_action ("playhead-to-range-end", bind (slot (*this, &Editor::cursor_to_selection_end), playhead_cursor));
+
+ add_action ("edit-cursor-to-range-start", bind (slot (*this, &Editor::cursor_to_selection_start), edit_cursor));
+ add_action ("edit-cursor-to-range-end", bind (slot (*this, &Editor::cursor_to_selection_end), edit_cursor));
+
+ add_action ("jump-forward-to-mark", slot (*this, &Editor::jump_forward_to_mark));
+ add_action ("jump-backward-to-mark", slot (*this, &Editor::jump_backward_to_mark));
+ add_action ("add-location-from-playhead", slot (*this, &Editor::add_location_from_playhead_cursor));
+
+ add_action ("nudge-forward", bind (slot (*this, &Editor::nudge_forward), false));
+ add_action ("nudge-next-forward", bind (slot (*this, &Editor::nudge_forward), true));
+ add_action ("nudge-backward", bind (slot (*this, &Editor::nudge_backward), false));
+ add_action ("nudge-next-backward", bind (slot (*this, &Editor::nudge_backward), true));
+
+ add_action ("toggle-playback", bind (slot (*this, &Editor::toggle_playback), false));
+ add_action ("toggle-playback-forget-capture", bind (slot (*this, &Editor::toggle_playback), true));
+
+ add_action ("toggle-loop-playback", slot (*this, &Editor::toggle_loop_playback));
+
+ add_action ("temporal-zoom-out", bind (slot (*this, &Editor::temporal_zoom_step), true));
+ add_action ("temporal-zoom-in", bind (slot (*this, &Editor::temporal_zoom_step), false));
+ add_action ("zoom-to-session", slot (*this, &Editor::temporal_zoom_session));
+
+ add_action ("scroll-tracks-up", slot (*this, &Editor::scroll_tracks_up));
+ add_action ("scroll-tracks-down", slot (*this, &Editor::scroll_tracks_down));
+ add_action ("step-tracks-up", slot (*this, &Editor::scroll_tracks_up_line));
+ add_action ("step-tracks-down", slot (*this, &Editor::scroll_tracks_down_line));
+
+ add_action ("scroll-backward", bind (slot (*this, &Editor::scroll_backward), 0.8f));
+ add_action ("scroll-forward", bind (slot (*this, &Editor::scroll_forward), 0.8f));
+ add_action ("goto", slot (*this, &Editor::goto_frame));
+ add_action ("center-playhead", slot (*this, &Editor::center_playhead));
+ add_action ("center-edit_cursor", slot (*this, &Editor::center_edit_cursor));
+ add_action ("playhead-forward", slot (*this, &Editor::playhead_forward));
+ add_action ("playhead-backward", slot (*this, &Editor::playhead_backward));
+ add_action ("playhead-to-edit", bind (slot (*this, &Editor::cursor_align), true));
+ add_action ("edit-to-playhead", bind (slot (*this, &Editor::cursor_align), false));
+
+ add_action ("align-regions-start", bind (slot (*this, &Editor::align), ARDOUR::Start));
+ add_action ("align-regions-start-relative", bind (slot (*this, &Editor::align_relative), ARDOUR::Start));
+ add_action ("align-regions-end", bind (slot (*this, &Editor::align), ARDOUR::End));
+ add_action ("align-regions-end-relative", bind (slot (*this, &Editor::align_relative), ARDOUR::End));
+ add_action ("align-regions-sync", bind (slot (*this, &Editor::align), ARDOUR::SyncPoint));
+ add_action ("align-regions-sync-relative", bind (slot (*this, &Editor::align_relative), ARDOUR::SyncPoint));
+
+ add_action ("set-playhead", slot (*this, &Editor::kbd_set_playhead_cursor));
+ add_action ("set-edit-cursor", slot (*this, &Editor::kbd_set_edit_cursor));
+
+ add_action ("set-mouse-mode-object", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseObject, false));
+ add_action ("set-mouse-mode-range", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseRange, false));
+ add_action ("set-mouse-mode-gain", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseGain, false));
+ add_action ("set-mouse-mode-zoom", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseZoom, false));
+ add_action ("set-mouse-mode-timefx", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseTimeFX, false));
+
+ add_action ("set-undo", bind (slot (*this, &Editor::undo), 1U));
+ add_action ("set-redo", bind (slot (*this, &Editor::redo), 1U));
+
+ add_action ("export-session", slot (*this, &Editor::export_session));
+ add_action ("export-range", slot (*this, &Editor::export_selection));
+
+ add_action ("editor-cut", slot (*this, &Editor::cut));
+ add_action ("editor-copy", slot (*this, &Editor::copy));
+ add_action ("editor-paste", slot (*this, &Editor::keyboard_paste));
+ add_action ("duplicate-region", slot (*this, &Editor::keyboard_duplicate_region));
+ add_action ("duplicate-range", slot (*this, &Editor::keyboard_duplicate_selection));
+ add_action ("insert-region", slot (*this, &Editor::keyboard_insert_region_list_selection));
+ add_action ("reverse-region", slot (*this, &Editor::reverse_region));
+ add_action ("normalize-region", slot (*this, &Editor::normalize_region));
+ add_action ("editor-crop", slot (*this, &Editor::crop_region_to_selection));
+ add_action ("insert-chunk", bind (slot (*this, &Editor::paste_named_selection), 1.0f));
+
+ add_action ("split-at-edit-cursor", slot (*this, &Editor::split_region));
+ add_action ("split-at-mouse", slot (*this, &Editor::kbd_split));
+
+ add_action ("brush-at-mouse", slot (*this, &Editor::kbd_brush));
+ add_action ("audition-at-mouse", slot (*this, &Editor::kbd_audition));
+
+ add_action ("start-range", slot (*this, &Editor::keyboard_selection_begin));
+ add_action ("finish-range", bind (slot (*this, &Editor::keyboard_selection_finish), false));
+ add_action ("finish-add-range", bind (slot (*this, &Editor::keyboard_selection_finish), true));
+
+ add_action ("extend-range-to-end-of-region", bind (slot (*this, &Editor::extend_selection_to_end_of_region), false));
+ add_action ("extend-range-to-start-of-region", bind (slot (*this, &Editor::extend_selection_to_start_of_region), false));
+
+ add_action ("zoom-focus-left", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusLeft));
+ add_action ("zoom-focus-right", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusRight));
+ add_action ("zoom-focus-center", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusCenter));
+ add_action ("zoom-focus-playhead", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusPlayhead));
+ add_action ("zoom-focus-edit", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusEdit));
+
+ add_action ("toggle-follow-playhead", (slot (*this, &Editor::toggle_follow_playhead)));
+ add_action ("remove-last-capture", (slot (*this, &Editor::remove_last_capture)));
+
+ add_action ("snap-to-frame", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToFrame)));
+ add_action ("snap-to-cd-frame", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToCDFrame)));
+ add_action ("snap-to-smpte-frame", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToSMPTEFrame)));
+ add_action ("snap-to-smpte-seconds", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToSMPTESeconds)));
+ add_action ("snap-to-smpte-minutes", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToSMPTEMinutes)));
+ add_action ("snap-to-seconds", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToSeconds)));
+ add_action ("snap-to-minutes", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToMinutes)));
+ add_action ("snap-to-thirtyseconds", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToAThirtysecondBeat)));
+ add_action ("snap-to-asixteenthbeat", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToASixteenthBeat)));
+ add_action ("snap-to-eighths", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToAEighthBeat)));
+ add_action ("snap-to-quarters", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToAQuarterBeat)));
+ add_action ("snap-to-thirds", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToAThirdBeat)));
+ add_action ("snap-to-beat", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToBeat)));
+ add_action ("snap-to-bar", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToBar)));
+ add_action ("snap-to-mark", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToMark)));
+ add_action ("snap-to-edit-cursor", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToEditCursor)));
+ add_action ("snap-to-region-start", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToRegionStart)));
+ add_action ("snap-to-region-end", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToRegionEnd)));
+ add_action ("snap-to-region-sync", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToRegionSync)));
+ add_action ("snap-to-region-boundary", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToRegionBoundary)));
+}
+
+void
+Editor::keyboard_selection_finish (bool add)
+{
+ if (session && have_pending_keyboard_selection) {
+ begin_reversible_command (_("keyboard selection"));
+ if (!add) {
+ selection->set (0, pending_keyboard_selection_start, session->audible_frame());
+ } else {
+ selection->add (pending_keyboard_selection_start, session->audible_frame());
+ }
+ commit_reversible_command ();
+ have_pending_keyboard_selection = false;
+ }
+}
+
+void
+Editor::keyboard_selection_begin ()
+{
+ if (session) {
+ pending_keyboard_selection_start = session->audible_frame();
+ have_pending_keyboard_selection = true;
+ }
+}
+
+void
+Editor::keyboard_duplicate_region ()
+{
+ if (selection->audio_regions.empty()) {
+ return;
+ }
+
+ float prefix;
+ bool was_floating;
+
+ if (get_prefix (prefix, was_floating) == 0) {
+ duplicate_some_regions (selection->audio_regions, prefix);
+ } else {
+ duplicate_some_regions (selection->audio_regions, 1);
+ }
+}
+
+void
+Editor::keyboard_duplicate_selection ()
+{
+ float prefix;
+ bool was_floating;
+
+ if (get_prefix (prefix, was_floating) == 0) {
+ duplicate_selection (prefix);
+ } else {
+ duplicate_selection (1);
+ }
+}
+
+void
+Editor::keyboard_paste ()
+{
+ float prefix;
+ bool was_floating;
+
+ if (get_prefix (prefix, was_floating) == 0) {
+ paste (prefix);
+ } else {
+ paste (1);
+ }
+}
+
+void
+Editor::keyboard_insert_region_list_selection ()
+{
+ float prefix;
+ bool was_floating;
+
+ if (get_prefix (prefix, was_floating) == 0) {
+ insert_region_list_selection (prefix);
+ } else {
+ insert_region_list_selection (1);
+ }
+}
+
+int
+Editor::get_prefix (float& val, bool& was_floating)
+{
+ return Keyboard::the_keyboard().get_prefix (val, was_floating);
+}
+
diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc
new file mode 100644
index 0000000000..54612000d1
--- /dev/null
+++ b/gtk2_ardour/editor_markers.cc
@@ -0,0 +1,911 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <sigc++/rettype.h>
+#include <cstdlib>
+#include <cmath>
+
+#include <gtk-canvas.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include <ardour/location.h>
+
+#include "editor.h"
+#include "marker.h"
+#include "selection.h"
+#include "editing.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+
+void
+Editor::clear_marker_display ()
+{
+ for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
+ delete i->second;
+ }
+
+ location_markers.clear ();
+}
+
+void
+Editor::add_new_location (Location *location)
+{
+ LocationMarkers *lam = new LocationMarkers;
+ uint32_t color;
+
+ if (location->is_cd_marker()) {
+ color = location_cd_marker_color;
+ } else if (location->is_mark()) {
+ color = location_marker_color;
+ } else if (location->is_auto_loop()) {
+ color = location_loop_color;
+ } else if (location->is_auto_punch()) {
+ color = location_punch_color;
+ } else {
+ color = location_range_color;
+ }
+
+ if (location->is_mark()) {
+ lam->start = new Marker (*this, GTK_CANVAS_GROUP(marker_group), color,
+ location->name(), Marker::Mark, PublicEditor::canvas_marker_event, location->start());
+ lam->end = 0;
+
+ } else if (location->is_auto_loop()) {
+ // transport marker
+ lam->start = new Marker (*this, GTK_CANVAS_GROUP(transport_marker_group), color,
+ location->name(), Marker::LoopStart, PublicEditor::canvas_marker_event, location->start());
+ lam->end = new Marker (*this, GTK_CANVAS_GROUP(transport_marker_group), color,
+ location->name(), Marker::LoopEnd, PublicEditor::canvas_marker_event, location->end());
+
+ } else if (location->is_auto_punch()) {
+ // transport marker
+ lam->start = new Marker (*this, GTK_CANVAS_GROUP(transport_marker_group), color,
+ location->name(), Marker::PunchIn, PublicEditor::canvas_marker_event, location->start());
+ lam->end = new Marker (*this, GTK_CANVAS_GROUP(transport_marker_group), color,
+ location->name(), Marker::PunchOut, PublicEditor::canvas_marker_event, location->end());
+
+ } else {
+
+ // range marker
+ lam->start = new Marker (*this, GTK_CANVAS_GROUP(range_marker_group), color,
+ location->name(), Marker::Start, PublicEditor::canvas_marker_event, location->start());
+ lam->end = new Marker (*this, GTK_CANVAS_GROUP(range_marker_group), color,
+ location->name(), Marker::End, PublicEditor::canvas_marker_event, location->end());
+ }
+
+ if (location->is_hidden ()) {
+ lam->hide();
+ } else {
+ lam->show ();
+ }
+
+ location->start_changed.connect (slot (*this, &Editor::location_changed));
+ location->end_changed.connect (slot (*this, &Editor::location_changed));
+ location->changed.connect (slot (*this, &Editor::location_changed));
+ location->name_changed.connect (slot (*this, &Editor::location_changed));
+ location->FlagsChanged.connect (slot (*this, &Editor::location_flags_changed));
+
+ pair<Location*,LocationMarkers*> newpair;
+
+ newpair.first = location;
+ newpair.second = lam;
+
+ location_markers.insert (newpair);
+}
+
+void
+Editor::location_changed (Location *location)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &Editor::location_changed), location));
+
+ LocationMarkers *lam = find_location_markers (location);
+
+ if (lam == 0) {
+ /* a location that isn't "marked" with markers */
+ return;
+ }
+
+ lam->set_name (location->name());
+ lam->set_position (location->start(), location->end());
+
+ if (location->is_auto_loop()) {
+ update_loop_range_view ();
+ } else if (location->is_auto_punch()) {
+ update_punch_range_view ();
+ }
+}
+
+void
+Editor::location_flags_changed (Location *location, void *src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::location_flags_changed), location, src));
+
+ LocationMarkers *lam = find_location_markers (location);
+
+ if (lam == 0) {
+ /* a location that isn't "marked" with markers */
+ return;
+ }
+
+ if (location->is_cd_marker()) {
+ lam->set_color_rgba (location_cd_marker_color);
+ } else if (location->is_mark()) {
+ lam->set_color_rgba (location_marker_color);
+ } else if (location->is_auto_punch()) {
+ lam->set_color_rgba (location_punch_color);
+ } else if (location->is_auto_loop()) {
+ lam->set_color_rgba (location_loop_color);
+ } else {
+ lam->set_color_rgba (location_range_color);
+ }
+
+ if (location->is_hidden()) {
+ lam->hide();
+ } else {
+ lam->show ();
+ }
+}
+
+Editor::LocationMarkers::~LocationMarkers ()
+{
+ if (start) {
+ delete start;
+ }
+
+ if (end) {
+ delete end;
+ }
+}
+
+Editor::LocationMarkers *
+Editor::find_location_markers (Location *location)
+{
+ LocationMarkerMap::iterator i;
+
+ for (i = location_markers.begin(); i != location_markers.end(); ++i) {
+ if ((*i).first == location) {
+ return (*i).second;
+ }
+ }
+
+ return 0;
+}
+
+Location *
+Editor::find_location_from_marker (Marker *marker, bool& is_start)
+{
+ LocationMarkerMap::iterator i;
+
+ for (i = location_markers.begin(); i != location_markers.end(); ++i) {
+ LocationMarkers *lm = (*i).second;
+ if (lm->start == marker) {
+ is_start = true;
+ return (*i).first;
+ } else if (lm->end == marker) {
+ is_start = false;
+ return (*i).first;
+ }
+ }
+
+ return 0;
+}
+
+void
+Editor::refresh_location_display_internal (Locations::LocationList& locations)
+{
+ clear_marker_display ();
+
+ for (Locations::LocationList::iterator i = locations.begin(); i != locations.end(); ++i) {
+ add_new_location (*i);
+ }
+}
+
+void
+Editor::refresh_location_display ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &Editor::refresh_location_display));
+
+ if (session) {
+ session->locations()->apply (*this, &Editor::refresh_location_display_internal);
+ }
+}
+
+void
+Editor::refresh_location_display_s (Change ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::refresh_location_display_s), ignored));
+
+ if (session) {
+ session->locations()->apply (*this, &Editor::refresh_location_display_internal);
+ }
+}
+
+void
+Editor::LocationMarkers::hide()
+{
+ start->hide ();
+ if (end) { end->hide(); }
+}
+
+void
+Editor::LocationMarkers::show()
+{
+ start->show ();
+ if (end) { end->show(); }
+}
+
+void
+Editor::LocationMarkers::set_name (const string& str)
+{
+ start->set_name (str);
+ if (end) { end->set_name (str); }
+}
+
+void
+Editor::LocationMarkers::set_position (jack_nframes_t startf,
+ jack_nframes_t endf)
+{
+ start->set_position (startf);
+ if (end) { end->set_position (endf); }
+}
+
+void
+Editor::LocationMarkers::set_color_rgba (uint32_t rgba)
+{
+ start->set_color_rgba (rgba);
+ if (end) { end->set_color_rgba (rgba); }
+}
+
+void
+Editor::mouse_add_new_marker (jack_nframes_t where)
+{
+ if (session) {
+ Location *location = new Location (where, where, "mark", Location::IsMark);
+ session->begin_reversible_command (_("add marker"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->add (location, true);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+ }
+}
+
+void
+Editor::remove_marker (GtkCanvasItem* item, GdkEvent* event)
+{
+ Marker* marker;
+ bool is_start;
+
+ if ((marker = static_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* loc = find_location_from_marker (marker, is_start);
+
+ if (session && loc) {
+ if (loc->is_end()) {
+ /* you can't hide or delete this marker */
+ return;
+ }
+ if (loc->is_auto_loop() || loc->is_auto_punch()) {
+ // just hide them
+ loc->set_hidden (true, this);
+ }
+ else {
+ Gtk::Main::idle.connect (bind (slot (*this, &Editor::really_remove_marker), loc));
+ }
+ }
+}
+
+gint
+Editor::really_remove_marker (Location* loc)
+{
+ session->begin_reversible_command (_("remove marker"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->remove (loc);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+ return FALSE;
+}
+
+void
+Editor::location_gone (Location *location)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::location_gone), location));
+
+ LocationMarkerMap::iterator i;
+
+ if (location == transport_loop_location()) {
+ update_loop_range_view (true);
+ }
+
+ if (location == transport_punch_location()) {
+ update_punch_range_view (true);
+ }
+
+ for (i = location_markers.begin(); i != location_markers.end(); ++i) {
+ if ((*i).first == location) {
+ delete (*i).second;
+ location_markers.erase (i);
+ break;
+ }
+ }
+}
+
+void
+Editor::tm_marker_context_menu (GdkEventButton* ev, GtkCanvasItem* item)
+{
+ if (tm_marker_menu == 0) {
+ build_tm_marker_menu ();
+ }
+
+ marker_menu_item = item;
+ tm_marker_menu->popup (1, ev->time);
+
+}
+
+
+void
+Editor::marker_context_menu (GdkEventButton* ev, GtkCanvasItem* item)
+{
+ Marker * marker;
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ bool is_start;
+ Location * loc = find_location_from_marker (marker, is_start);
+ if (loc == transport_loop_location() || loc == transport_punch_location()) {
+ if (transport_marker_menu == 0) {
+ build_transport_marker_menu ();
+ }
+ marker_menu_item = item;
+ transport_marker_menu->popup (1, ev->time);
+ }
+ else {
+ if (marker_menu == 0) {
+ build_marker_menu ();
+ }
+
+ Menu_Helpers::MenuList & children = marker_menu->items();
+ // XXX: should really find this some other way
+ if (children.size() >= 3) {
+ MenuItem * loopitem = children[2];
+ if (loopitem) {
+ if (loc->is_mark()) {
+ loopitem->set_sensitive(false);
+ }
+ else {
+ loopitem->set_sensitive(true);
+ }
+ }
+ }
+
+ marker_menu_item = item;
+ marker_menu->popup (1, ev->time);
+ }
+}
+
+
+void
+Editor::new_transport_marker_context_menu (GdkEventButton* ev, GtkCanvasItem* item)
+{
+ if (new_transport_marker_menu == 0) {
+ build_new_transport_marker_menu ();
+ }
+
+ new_transport_marker_menu->popup (1, ev->time);
+
+}
+
+void
+Editor::transport_marker_context_menu (GdkEventButton* ev, GtkCanvasItem* item)
+{
+ if (transport_marker_menu == 0) {
+ build_transport_marker_menu ();
+ }
+
+ transport_marker_menu->popup (1, ev->time);
+}
+
+void
+Editor::build_marker_menu ()
+{
+ using namespace Menu_Helpers;
+
+ marker_menu = new Menu;
+ MenuList& items = marker_menu->items();
+ marker_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Locate to"), slot (*this, &Editor::marker_menu_set_playhead)));
+ items.push_back (MenuElem (_("Play from"), slot (*this, &Editor::marker_menu_play_from)));
+ items.push_back (MenuElem (_("Loop range"), slot (*this, &Editor::marker_menu_loop_range)));
+ items.push_back (MenuElem (_("Set from playhead"), slot (*this, &Editor::marker_menu_set_from_playhead)));
+ items.push_back (MenuElem (_("Set from range"), slot (*this, &Editor::marker_menu_set_from_selection)));
+
+ items.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Rename"), slot (*this, &Editor::marker_menu_rename)));
+ items.push_back (MenuElem (_("Hide"), slot (*this, &Editor::marker_menu_hide)));
+ items.push_back (MenuElem (_("Remove"), slot (*this, &Editor::marker_menu_remove)));
+}
+
+void
+Editor::build_tm_marker_menu ()
+{
+ using namespace Menu_Helpers;
+
+ tm_marker_menu = new Menu;
+ MenuList& items = tm_marker_menu->items();
+ tm_marker_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Edit"), slot (*this, &Editor::marker_menu_edit)));
+ items.push_back (MenuElem (_("Remove"), slot (*this, &Editor::marker_menu_remove)));
+}
+
+void
+Editor::build_new_transport_marker_menu ()
+{
+ using namespace Menu_Helpers;
+
+ new_transport_marker_menu = new Menu;
+ MenuList& items = new_transport_marker_menu->items();
+ new_transport_marker_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Set Loop Range"), slot (*this, &Editor::new_transport_marker_menu_set_loop)));
+ items.push_back (MenuElem (_("Set Punch Range"), slot (*this, &Editor::new_transport_marker_menu_set_punch)));
+
+ new_transport_marker_menu->unmap_event.connect ( slot (*this, &Editor::new_transport_marker_menu_popdown));
+}
+
+void
+Editor::build_transport_marker_menu ()
+{
+ using namespace Menu_Helpers;
+
+ transport_marker_menu = new Menu;
+ MenuList& items = transport_marker_menu->items();
+ transport_marker_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Locate to"), slot (*this, &Editor::marker_menu_set_playhead)));
+ items.push_back (MenuElem (_("Play from"), slot (*this, &Editor::marker_menu_play_from)));
+ items.push_back (MenuElem (_("Set from playhead"), slot (*this, &Editor::marker_menu_set_from_playhead)));
+ items.push_back (MenuElem (_("Set from range"), slot (*this, &Editor::marker_menu_set_from_selection)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Hide"), slot (*this, &Editor::marker_menu_hide)));
+}
+
+void
+Editor::marker_menu_hide ()
+{
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* l;
+ bool is_start;
+
+ if ((l = find_location_from_marker (marker, is_start)) != 0) {
+ l->set_hidden (true, this);
+ }
+}
+
+void
+Editor::marker_menu_play_from ()
+{
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* l;
+ bool is_start;
+
+ if ((l = find_location_from_marker (marker, is_start)) != 0) {
+
+ if (l->is_mark()) {
+ session->request_locate (l->start(), true);
+ }
+ else {
+ //session->request_bounded_roll (l->start(), l->end());
+
+ if (is_start) {
+ session->request_locate (l->start(), true);
+ } else {
+ session->request_locate (l->end(), true);
+ }
+ }
+ }
+}
+
+void
+Editor::marker_menu_set_playhead ()
+{
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* l;
+ bool is_start;
+
+ if ((l = find_location_from_marker (marker, is_start)) != 0) {
+
+ if (l->is_mark()) {
+ session->request_locate (l->start(), false);
+ }
+ else {
+ if (is_start) {
+ session->request_locate (l->start(), false);
+ } else {
+ session->request_locate (l->end(), false);
+ }
+ }
+ }
+}
+
+void
+Editor::marker_menu_set_from_playhead ()
+{
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* l;
+ bool is_start;
+
+ if ((l = find_location_from_marker (marker, is_start)) != 0) {
+
+ if (l->is_mark()) {
+ l->set_start (session->transport_frame ());
+ }
+ else {
+ if (is_start) {
+ l->set_start (session->transport_frame ());
+ } else {
+ l->set_end (session->transport_frame ());
+ }
+ }
+ }
+}
+
+void
+Editor::marker_menu_set_from_selection ()
+{
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* l;
+ bool is_start;
+
+ if ((l = find_location_from_marker (marker, is_start)) != 0) {
+
+ if (l->is_mark()) {
+ // nothing for now
+ }
+ else {
+
+ /* if range selection use first to last */
+
+ if (mouse_mode == Editing::MouseRange) {
+ if (!selection->time.empty()) {
+ l->set_start (selection->time.start());
+ l->set_end (selection->time.end_frame());
+ }
+ }
+ else {
+ if (!selection->audio_regions.empty()) {
+ l->set_start (selection->audio_regions.start());
+ l->set_end (selection->audio_regions.end_frame());
+ }
+ }
+ }
+ }
+}
+
+void
+Editor::marker_menu_loop_range ()
+{
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* l;
+ bool is_start;
+
+ if ((l = find_location_from_marker (marker, is_start)) != 0) {
+ Location* l2;
+ if ((l2 = transport_loop_location()) != 0) {
+ l2->set (l->start(), l->end());
+
+ // enable looping, reposition and start rolling
+ session->request_auto_loop(true);
+ session->request_locate (l2->start(), true);
+ }
+ }
+}
+
+void
+Editor::marker_menu_edit ()
+{
+ MeterMarker* mm;
+ TempoMarker* tm;
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((mm = dynamic_cast<MeterMarker*> (marker)) != 0) {
+ edit_meter_section (&mm->meter());
+ } else if ((tm = dynamic_cast<TempoMarker*> (marker)) != 0) {
+ edit_tempo_section (&tm->tempo());
+ } else {
+ fatal << X_("programming erorr: unhandled marker type in Editor::marker_menu_edit")
+ << endmsg;
+ /*NOTREACHED*/
+ }
+}
+
+void
+Editor::marker_menu_remove ()
+{
+ MeterMarker* mm;
+ TempoMarker* tm;
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((mm = dynamic_cast<MeterMarker*> (marker)) != 0) {
+ remove_meter_marker (marker_menu_item);
+ } else if ((tm = dynamic_cast<TempoMarker*> (marker)) != 0) {
+ remove_tempo_marker (marker_menu_item);
+ } else {
+ remove_marker (marker_menu_item, (GdkEvent*) 0);
+ }
+}
+
+void
+Editor::marker_menu_rename ()
+{
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* loc;
+ bool is_start;
+
+ loc = find_location_from_marker (marker, is_start);
+
+ if (!loc) return;
+
+ Dialog dialog;
+ Entry entry;
+ Button ok_button (_("OK"));
+ Button cancel_button (_("Cancel"));
+
+ if (loc->is_mark()) {
+ dialog.set_title (_("ardour: rename mark"));
+ } else {
+ dialog.set_title (_("ardour: rename range"));
+ }
+
+ dialog.set_name ("MarkRenameWindow");
+ dialog.set_usize (300, -1);
+ dialog.set_position (GTK_WIN_POS_MOUSE);
+ dialog.set_modal (true);
+
+ 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);
+
+ entry.set_text (loc->name());
+ entry.set_name ("MarkerNameDisplay");
+ ok_button.set_name ("EditorGTKButton");
+ cancel_button.set_name ("EditorGTKButton");
+
+ entry.activate.connect (bind (slot (*this, &Editor::finish_sub_event_loop), 1));
+ cancel_button.clicked.connect (bind (slot (*this, &Editor::finish_sub_event_loop), -1));
+ ok_button.clicked.connect (bind (slot (*this, &Editor::finish_sub_event_loop), 1));
+ dialog.delete_event.connect (bind (slot (*this, &Editor::finish_sub_event_loop_on_delete), -1));
+
+ dialog.show_all ();
+ entry.grab_focus ();
+
+ run_sub_event_loop ();
+
+ if (sub_event_loop_status == 1) {
+
+ Location* l;
+ bool is_start;
+
+ if ((l = find_location_from_marker (marker, is_start)) != 0) {
+ l->set_name (entry.get_text());
+ }
+ }
+}
+
+gint
+Editor::new_transport_marker_menu_popdown (GdkEventAny *ev)
+{
+ // hide rects
+ gtk_canvas_item_hide (transport_bar_drag_rect);
+ gtk_canvas_item_hide (range_marker_drag_rect);
+
+ return FALSE;
+}
+
+void
+Editor::new_transport_marker_menu_set_loop ()
+{
+ if (!session) return;
+
+ begin_reversible_command (_("set loop range"));
+
+ Location* tll;
+
+ if ((tll = transport_loop_location()) == 0) {
+ Location* loc = new Location (temp_location->start(), temp_location->end(), _("Loop"), Location::IsAutoLoop);
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->add (loc, true);
+ session->set_auto_loop_location (loc);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ }
+ else {
+ session->add_undo (rettype<void>(bind (slot (*tll, &Location::set), tll->start(), tll->end())));
+ session->add_redo (rettype<void>(bind (slot (*tll, &Location::set), temp_location->start(), temp_location->end())));
+ tll->set_hidden (false, this);
+ tll->set (temp_location->start(), temp_location->end());
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::new_transport_marker_menu_set_punch ()
+{
+ if (!session) return;
+
+ begin_reversible_command (_("set punch range"));
+
+ Location* tpl;
+
+ if ((tpl = transport_punch_location()) == 0) {
+ tpl = new Location (temp_location->start(), temp_location->end(), _("Punch"), Location::IsAutoPunch);
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->add (tpl, true);
+ session->set_auto_punch_location (tpl);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ } else {
+ session->add_undo (rettype<void>(bind (slot (*tpl, &Location::set), tpl->start(), tpl->end())));
+ session->add_redo (rettype<void>(bind (slot (*tpl, &Location::set), temp_location->start(), temp_location->end())));
+ tpl->set_hidden(false, this);
+ tpl->set(temp_location->start(), temp_location->end());
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::update_loop_range_view (bool visibility)
+{
+ if (session == 0) {
+ return;
+ }
+
+ Location* tll;
+
+ if (session->get_auto_loop() && ((tll = transport_loop_location()) != 0)) {
+
+ double x1 = frame_to_pixel (tll->start());
+ double x2 = frame_to_pixel (tll->end());
+
+ gtk_canvas_item_set (transport_loop_range_rect, "x1", x1, "x2", x2, NULL);
+
+ if (visibility) {
+ gtk_canvas_item_show (transport_loop_range_rect);
+ }
+ }
+ else if (visibility) {
+ gtk_canvas_item_hide (transport_loop_range_rect);
+ }
+}
+
+void
+Editor::update_punch_range_view (bool visibility)
+{
+ if (session == 0) {
+ return;
+ }
+
+ Location* tpl;
+
+ if ((session->get_punch_in() || session->get_punch_out()) && ((tpl = transport_punch_location()) != 0)) {
+
+ double x1 = frame_to_pixel (tpl->start());
+ double x2 = frame_to_pixel (tpl->end());
+
+ gtk_canvas_item_set (transport_punch_range_rect, "x1", x1, "x2", x2, NULL);
+
+ if (visibility) {
+ gtk_canvas_item_show (transport_punch_range_rect);
+ }
+ }
+ else if (visibility) {
+ gtk_canvas_item_hide (transport_punch_range_rect);
+ }
+
+// if (session->get_punch_in()) {
+// double x = frame_to_pixel (transport_punch_location->start());
+// gtk_canvas_item_set (transport_punchin_line, "x1", x, "x2", x, NULL);
+
+// if (visibility) {
+// gtk_canvas_item_show (transport_punchin_line);
+// }
+// }
+// else if (visibility) {
+// gtk_canvas_item_hide (transport_punchin_line);
+// }
+
+// if (session->get_punch_out()) {
+// double x = frame_to_pixel (transport_punch_location->end());
+
+// gtk_canvas_item_set (transport_punchout_line, "x1", x, "x2", x, NULL);
+
+// if (visibility) {
+// gtk_canvas_item_show (transport_punchout_line);
+// }
+// }
+// else if (visibility) {
+// gtk_canvas_item_hide (transport_punchout_line);
+// }
+}
diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc
new file mode 100644
index 0000000000..b5f2ea6cc1
--- /dev/null
+++ b/gtk2_ardour/editor_mixer.cc
@@ -0,0 +1,311 @@
+/*
+ Copyright (C) 2003-2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gtkmmext/utils.h>
+#include <ardour/audioengine.h>
+
+#include "editor.h"
+#include "mixer_strip.h"
+#include "ardour_ui.h"
+#include "selection.h"
+#include "audio_time_axis.h"
+
+#include "i18n.h"
+
+void
+Editor::editor_mixer_button_toggled ()
+{
+ show_editor_mixer (editor_mixer_button.get_active());
+}
+
+void
+Editor::cms_deleted ()
+{
+ current_mixer_strip = 0;
+}
+
+void
+Editor::show_editor_mixer (bool yn)
+{
+ if (yn) {
+
+ if (current_mixer_strip == 0) {
+
+ if (selection->tracks.empty()) {
+
+ if (track_views.empty()) {
+ return;
+ }
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
+
+ current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(),
+ *session,
+ atv->route(), false);
+
+ current_mixer_strip->GoingAway.connect (slot (*this, &Editor::cms_deleted));
+ break;
+ }
+ }
+
+ } else {
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
+
+ current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(),
+ *session,
+ atv->route(), false);
+ current_mixer_strip->GoingAway.connect (slot (*this, &Editor::cms_deleted));
+ break;
+ }
+ }
+
+ }
+
+ if (current_mixer_strip == 0) {
+ return;
+ }
+ }
+
+ if (current_mixer_strip->get_parent() == 0) {
+
+ current_mixer_strip->set_embedded (true);
+ current_mixer_strip->Hiding.connect (slot (*this, &Editor::current_mixer_strip_hidden));
+ current_mixer_strip->GoingAway.connect (slot (*this, &Editor::current_mixer_strip_removed));
+ current_mixer_strip->set_width (editor_mixer_strip_width);
+ current_mixer_strip->show_all ();
+
+ global_hpacker.pack_start (*current_mixer_strip, false, false);
+ global_hpacker.reorder_child (*current_mixer_strip, 0);
+ }
+
+ } else {
+
+ if (current_mixer_strip) {
+ editor_mixer_strip_width = current_mixer_strip->get_width ();
+ if (current_mixer_strip->get_parent() != 0) {
+ global_hpacker.remove (*current_mixer_strip);
+ }
+ }
+ }
+}
+
+void
+Editor::set_selected_mixer_strip (TimeAxisView& view)
+{
+ AudioTimeAxisView* at;
+ bool show = false;
+
+ if (!session || (at = dynamic_cast<AudioTimeAxisView*>(&view)) == 0) {
+ return;
+ }
+
+ if (current_mixer_strip) {
+
+ /* might be nothing to do */
+
+ if (&current_mixer_strip->route() == &at->route()) {
+ return;
+ }
+
+ if (current_mixer_strip->get_parent()) {
+ show = true;
+ }
+
+ delete current_mixer_strip;
+ current_mixer_strip = 0;
+ }
+
+ current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(),
+ *session,
+ at->route());
+ current_mixer_strip->GoingAway.connect (slot (*this, &Editor::cms_deleted));
+
+ if (show) {
+ show_editor_mixer (true);
+ }
+}
+
+void
+Editor::update_current_screen ()
+{
+ if (session && engine.running()) {
+
+ jack_nframes_t frame;
+
+ frame = session->audible_frame();
+
+ /* only update if the playhead is on screen or we are following it */
+
+ if (_follow_playhead) {
+
+ gtk_canvas_item_show (playhead_cursor->canvas_item);
+
+ if (frame != last_update_frame) {
+
+ if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) {
+
+ if (session->transport_speed() < 0) {
+ if (frame > (current_page_frames()/2)) {
+ center_screen (frame-(current_page_frames()/2));
+ } else {
+ center_screen (current_page_frames()/2);
+ }
+ } else {
+ center_screen (frame+(current_page_frames()/2));
+ }
+ }
+
+ playhead_cursor->set_position (frame);
+ }
+
+ } else {
+
+ if (frame != last_update_frame) {
+ if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) {
+ gtk_canvas_item_hide (playhead_cursor->canvas_item);
+ } else {
+ playhead_cursor->set_position (frame);
+ }
+ }
+ }
+
+ last_update_frame = frame;
+
+ if (current_mixer_strip) {
+ current_mixer_strip->fast_update ();
+ }
+
+ }
+}
+
+void
+Editor::update_slower ()
+{
+ if (current_mixer_strip) {
+ current_mixer_strip->update ();
+ }
+}
+
+void
+Editor::current_mixer_strip_removed ()
+{
+ if (current_mixer_strip) {
+ /* it is being deleted */
+ current_mixer_strip = 0;
+ }
+}
+
+void
+Editor::current_mixer_strip_hidden ()
+{
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+
+ AudioTimeAxisView* tmp;
+
+ if ((tmp = dynamic_cast<AudioTimeAxisView*>(*i)) != 0) {
+ if (&(tmp->route()) == &(current_mixer_strip->route())) {
+ (*i)->set_selected (false);
+ break;
+ }
+ }
+ }
+ global_hpacker.remove (*current_mixer_strip);
+}
+
+void
+Editor::session_going_away ()
+{
+ for (vector<SigC::Connection>::iterator i = session_connections.begin(); i != session_connections.end(); ++i) {
+ (*i).disconnect ();
+ }
+
+ stop_scrolling ();
+ selection->clear ();
+ cut_buffer->clear ();
+
+ clicked_regionview = 0;
+ clicked_trackview = 0;
+ clicked_audio_trackview = 0;
+ clicked_crossfadeview = 0;
+ entered_regionview = 0;
+ entered_track = 0;
+ latest_regionview = 0;
+ region_list_display_drag_region = 0;
+ last_update_frame = 0;
+ drag_info.item = 0;
+ last_audition_region = 0;
+ region_list_button_region = 0;
+
+ /* hide all tracks */
+
+ hide_all_tracks (false);
+
+ /* rip everything out of the list displays */
+
+ region_list_clear (); // no clear() method in gtkmm 1.2
+ route_list.clear ();
+ named_selection_display.clear ();
+ edit_group_list.clear ();
+
+ edit_cursor_clock.set_session (0);
+ selection_start_clock.set_session (0);
+ selection_end_clock.set_session (0);
+ zoom_range_clock.set_session (0);
+ nudge_clock.set_session (0);
+
+ /* put editor/mixer toggle button in off position and disable until a new session is loaded */
+
+ editor_mixer_button.set_active(false);
+ editor_mixer_button.set_sensitive(false);
+ /* clear tempo/meter rulers */
+
+ remove_metric_marks ();
+ hide_measures ();
+ clear_marker_display ();
+
+ if (current_bbt_points) {
+ delete current_bbt_points;
+ current_bbt_points = 0;
+ }
+
+ if (embed_audio_item) {
+ embed_audio_item->set_sensitive (false);
+ }
+
+ if (import_audio_item) {
+ import_audio_item->set_sensitive (false);
+ }
+
+ /* mixer strip will be deleted all by itself
+ when its route is deleted.
+ */
+
+ current_mixer_strip = 0;
+
+ set_title (_("ardour: editor"));
+
+ session = 0;
+}
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
new file mode 100644
index 0000000000..2c0d90f703
--- /dev/null
+++ b/gtk2_ardour/editor_mouse.cc
@@ -0,0 +1,4584 @@
+/*
+ Copyright (C) 2000-2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <stdint.h>
+#include <cmath>
+#include <set>
+#include <string>
+#include <algorithm>
+
+#include <pbd/error.h>
+#include <gtkmmext/utils.h>
+
+#include "ardour_ui.h"
+#include "editor.h"
+#include "time_axis_view.h"
+#include "audio_time_axis.h"
+#include "regionview.h"
+#include "marker.h"
+#include "streamview.h"
+#include "region_gain_line.h"
+#include "automation_time_axis.h"
+#include "prompter.h"
+#include "utils.h"
+#include "selection.h"
+#include "keyboard.h"
+#include "editing.h"
+#include "rgb_macros.h"
+#include "extra_bind.h"
+
+#include <ardour/types.h>
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/diskstream.h>
+#include <ardour/playlist.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/audioregion.h>
+#include <ardour/dB.h>
+#include <ardour/utils.h>
+#include <ardour/region_factory.h>
+
+#include <bitset>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace SigC;
+using namespace Gtk;
+using namespace Editing;
+
+jack_nframes_t
+Editor::event_frame (GdkEvent* event, double* pcx, double* pcy)
+{
+ double cx, cy;
+
+ if (pcx == 0) {
+ pcx = &cx;
+ }
+ if (pcy == 0) {
+ pcy = &cy;
+ }
+
+ *pcx = 0;
+ *pcy = 0;
+
+ switch (event->type) {
+ case GDK_BUTTON_RELEASE:
+ case GDK_BUTTON_PRESS:
+ case GDK_2BUTTON_PRESS:
+ case GDK_3BUTTON_PRESS:
+ gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), event->button.x, event->button.y, pcx, pcy);
+ break;
+ case GDK_MOTION_NOTIFY:
+ gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), event->motion.x, event->motion.y, pcx, pcy);
+ break;
+ case GDK_ENTER_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), event->crossing.x, event->crossing.y, pcx, pcy);
+ break;
+ default:
+ warning << compose (_("Editor::event_frame() used on unhandled event type %1"), event->type) << endmsg;
+ break;
+ }
+
+ /* note that pixel_to_frame() never returns less than zero, so even if the pixel
+ position is negative (as can be the case with motion events in particular),
+ the frame location is always positive.
+ */
+
+ return pixel_to_frame (*pcx);
+}
+
+void
+Editor::mouse_mode_toggled (MouseMode m)
+{
+ if (ignore_mouse_mode_toggle) {
+ return;
+ }
+
+ switch (m) {
+ case MouseRange:
+ if (mouse_select_button.get_active()) {
+ set_mouse_mode (m);
+ }
+ break;
+
+ case MouseObject:
+ if (mouse_move_button.get_active()) {
+ set_mouse_mode (m);
+ }
+ break;
+
+ case MouseGain:
+ if (mouse_gain_button.get_active()) {
+ set_mouse_mode (m);
+ }
+ break;
+
+ case MouseZoom:
+ if (mouse_zoom_button.get_active()) {
+ set_mouse_mode (m);
+ }
+ break;
+
+ case MouseTimeFX:
+ if (mouse_timefx_button.get_active()) {
+ set_mouse_mode (m);
+ }
+ break;
+
+ case MouseAudition:
+ if (mouse_audition_button.get_active()) {
+ set_mouse_mode (m);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+Editor::set_mouse_mode (MouseMode m, bool force)
+{
+ if (drag_info.item) {
+ return;
+ }
+
+ if (m == mouse_mode && !force) {
+ return;
+ }
+
+ mouse_mode = m;
+
+ instant_save ();
+
+ if (mouse_mode != MouseRange) {
+
+ /* in all modes except range, hide the range selection,
+ show the object (region) selection.
+ */
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ (*i)->set_should_show_selection (true);
+ }
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->hide_selection ();
+ }
+
+ } else {
+
+ /* in range mode, hide object (region) selection, and show the
+ range selection.
+ */
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ (*i)->set_should_show_selection (false);
+ }
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ if ((*i)->selected()) {
+ (*i)->show_selection (selection->time);
+ }
+ }
+ }
+
+ /* XXX the hack of unsetting all other buttongs should go
+ away once GTK2 allows us to use regular radio buttons drawn like
+ normal buttons, rather than my silly GroupedButton hack.
+ */
+
+ ignore_mouse_mode_toggle = true;
+
+ switch (mouse_mode) {
+ case MouseRange:
+ mouse_select_button.set_active (true);
+ current_canvas_cursor = selector_cursor;
+ break;
+
+ case MouseObject:
+ mouse_move_button.set_active (true);
+ current_canvas_cursor = grabber_cursor;
+ break;
+
+ case MouseGain:
+ mouse_gain_button.set_active (true);
+ current_canvas_cursor = cross_hair_cursor;
+ break;
+
+ case MouseZoom:
+ mouse_zoom_button.set_active (true);
+ current_canvas_cursor = zoom_cursor;
+ break;
+
+ case MouseTimeFX:
+ mouse_timefx_button.set_active (true);
+ current_canvas_cursor = time_fx_cursor; // just use playhead
+ break;
+
+ case MouseAudition:
+ mouse_audition_button.set_active (true);
+ current_canvas_cursor = speaker_cursor;
+ break;
+ }
+
+ ignore_mouse_mode_toggle = false;
+
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor);
+ }
+}
+
+void
+Editor::step_mouse_mode (bool next)
+{
+ switch (current_mouse_mode()) {
+ case MouseObject:
+ if (next) set_mouse_mode (MouseRange);
+ else set_mouse_mode (MouseTimeFX);
+ break;
+
+ case MouseRange:
+ if (next) set_mouse_mode (MouseZoom);
+ else set_mouse_mode (MouseObject);
+ break;
+
+ case MouseZoom:
+ if (next) set_mouse_mode (MouseGain);
+ else set_mouse_mode (MouseRange);
+ break;
+
+ case MouseGain:
+ if (next) set_mouse_mode (MouseTimeFX);
+ else set_mouse_mode (MouseZoom);
+ break;
+
+ case MouseTimeFX:
+ if (next) set_mouse_mode (MouseAudition);
+ else set_mouse_mode (MouseGain);
+ break;
+
+ case MouseAudition:
+ if (next) set_mouse_mode (MouseObject);
+ else set_mouse_mode (MouseTimeFX);
+ break;
+ }
+}
+
+gint
+Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type)
+{
+ jack_nframes_t where = event_frame (event, 0, 0);
+
+ if (session && session->actively_recording()) {
+ return TRUE;
+ }
+
+ /* 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
+ mouse operation is a region alignment.
+ */
+
+ if (((mouse_mode == MouseObject) ||
+ (mouse_mode == MouseAudition && item_type == RegionItem) ||
+ (mouse_mode == MouseTimeFX && item_type == RegionItem)) &&
+ event->type == GDK_BUTTON_PRESS &&
+ event->button.button <= 3) {
+
+ AudioRegionView* rv;
+ ControlPoint* cp;
+
+ /* not dbl-click or triple-click */
+
+ switch (item_type) {
+ case RegionItem:
+ set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
+ break;
+
+ case AudioRegionViewNameHighlight:
+ case AudioRegionViewName:
+ if ((rv = reinterpret_cast<AudioRegionView *> (gtk_object_get_data(GTK_OBJECT(item), "regionview"))) != 0) {
+ set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
+ }
+ break;
+
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ if ((cp = reinterpret_cast<ControlPoint *> (gtk_object_get_data(GTK_OBJECT(item), "control_point"))) != 0) {
+ set_selected_control_point_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true);
+ }
+ break;
+
+ case StreamItem:
+ break;
+
+ case AutomationTrackItem:
+ break;
+
+ default:
+ break;
+ }
+ }
+
+#define SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE
+#ifdef SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE
+ /* in range mode, button 1/2/3 press potentially selects a track */
+
+ if (mouse_mode == MouseRange &&
+ event->type == GDK_BUTTON_PRESS &&
+ event->button.button <= 3) {
+
+ AudioRegionView* rv;
+
+ switch (item_type) {
+ case StreamItem:
+ case RegionItem:
+ case AutomationTrackItem:
+ set_selected_track_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true, true);
+ break;
+
+ case AudioRegionViewNameHighlight:
+ case AudioRegionViewName:
+ rv = reinterpret_cast<AudioRegionView *> (gtk_object_get_data(GTK_OBJECT(item), "regionview"));
+ default:
+ break;
+ }
+ }
+#endif
+
+ if (drag_info.item == 0 &&
+ (Keyboard::is_delete_event (&event->button) ||
+ Keyboard::is_context_menu_event (&event->button) ||
+ Keyboard::is_edit_event (&event->button))) {
+
+ /* handled by button release */
+ return TRUE;
+ }
+
+ switch (event->button.button) {
+ case 1:
+
+ if (event->type == GDK_BUTTON_PRESS) {
+
+ if (drag_info.item) {
+ gtk_canvas_item_ungrab (drag_info.item, event->button.time);
+ }
+
+ /* single mouse clicks on any of these item types operate
+ independent of mouse mode, mostly because they are
+ not on the main track canvas or because we want
+ them to be modeless.
+ */
+
+ switch (item_type) {
+ case EditCursorItem:
+ case PlayheadCursorItem:
+ start_cursor_grab (item, event);
+ return TRUE;
+
+ case MarkerItem:
+ if (Keyboard::modifier_state_equals (event->button.state,
+ Keyboard::ModifierMask(Keyboard::Control|Keyboard::Shift))) {
+ hide_marker (item, event);
+ } else {
+ start_marker_grab (item, event);
+ }
+ return TRUE;
+
+ case TempoMarkerItem:
+ start_tempo_marker_grab (item, event);
+ return TRUE;
+
+ case MeterMarkerItem:
+ start_meter_marker_grab (item, event);
+ return TRUE;
+
+ case TempoBarItem:
+ return TRUE;
+
+ case MeterBarItem:
+ return TRUE;
+
+ case RangeMarkerBarItem:
+ start_range_markerbar_op (item, event, CreateRangeMarker);
+ return TRUE;
+ break;
+ case TransportMarkerBarItem:
+ start_range_markerbar_op (item, event, CreateTransportMarker);
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ switch (mouse_mode) {
+ case MouseRange:
+ switch (item_type) {
+ case StartSelectionTrimItem:
+ start_selection_op (item, event, SelectionStartTrim);
+ break;
+
+ case EndSelectionTrimItem:
+ start_selection_op (item, event, SelectionEndTrim);
+ break;
+
+ case SelectionItem:
+ if (Keyboard::modifier_state_contains
+ (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) {
+ // 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)) {
+ /* grab selection for moving */
+ start_selection_op (item, event, SelectionMove);
+ }
+ else {
+ /* this was debated, but decided the more common action was to
+ make a new selection */
+ start_selection_op (item, event, CreateSelection);
+ }
+ break;
+
+ default:
+ start_selection_op (item, event, CreateSelection);
+ }
+ return TRUE;
+ break;
+
+ case MouseObject:
+ if (Keyboard::modifier_state_contains (event->button.state,
+ Keyboard::ModifierMask(Keyboard::Control|Keyboard::Alt))
+ && event->type == GDK_BUTTON_PRESS) {
+
+ start_rubberband_select (item, event);
+
+ } else if (event->type == GDK_BUTTON_PRESS) {
+
+ switch (item_type) {
+ case FadeInHandleItem:
+ start_fade_in_grab (item, event);
+ return TRUE;
+
+ case FadeOutHandleItem:
+ start_fade_out_grab (item, event);
+ return TRUE;
+
+ case RegionItem:
+ if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+ start_region_copy_grab (item, event);
+ } else if (Keyboard::the_keyboard().key_is_down (GDK_b)) {
+ start_region_brush_grab (item, event);
+ } else {
+ start_region_grab (item, event);
+ }
+ break;
+
+ case AudioRegionViewNameHighlight:
+ start_trim (item, event);
+ return TRUE;
+ break;
+
+ case AudioRegionViewName:
+ /* rename happens on edit clicks */
+ start_trim (clicked_regionview->get_name_highlight(), event);
+ return TRUE;
+ break;
+
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ start_control_point_grab (item, event);
+ return TRUE;
+ break;
+
+ case GainAutomationLineItem:
+ case PanAutomationLineItem:
+ case RedirectAutomationLineItem:
+ start_line_grab_from_line (item, event);
+ return TRUE;
+ break;
+
+ case StreamItem:
+ case AutomationTrackItem:
+ start_rubberband_select (item, event);
+ break;
+
+ /* <CMT Additions> */
+ case ImageFrameHandleStartItem:
+ imageframe_start_handle_op(item, event) ;
+ return(TRUE) ;
+ break ;
+ case ImageFrameHandleEndItem:
+ imageframe_end_handle_op(item, event) ;
+ return(TRUE) ;
+ break ;
+ case MarkerViewHandleStartItem:
+ markerview_item_start_handle_op(item, event) ;
+ return(TRUE) ;
+ break ;
+ case MarkerViewHandleEndItem:
+ markerview_item_end_handle_op(item, event) ;
+ return(TRUE) ;
+ break ;
+ /* </CMT Additions> */
+
+ /* <CMT Additions> */
+ case MarkerViewItem:
+ start_markerview_grab(item, event) ;
+ break ;
+ case ImageFrameItem:
+ start_imageframe_grab(item, event) ;
+ break ;
+ /* </CMT Additions> */
+
+ default:
+ break;
+ }
+ }
+ return TRUE;
+ break;
+
+ case MouseGain:
+ switch (item_type) {
+ case RegionItem:
+ // start_line_grab_from_regionview (item, event);
+ break;
+
+ case GainControlPointItem:
+ start_control_point_grab (item, event);
+ return TRUE;
+
+ case GainLineItem:
+ start_line_grab_from_line (item, event);
+ return TRUE;
+
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ start_control_point_grab (item, event);
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+ return TRUE;
+ break;
+
+ switch (item_type) {
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ start_control_point_grab (item, event);
+ break;
+
+ case GainAutomationLineItem:
+ case PanAutomationLineItem:
+ case RedirectAutomationLineItem:
+ start_line_grab_from_line (item, event);
+ break;
+
+ case RegionItem:
+ // XXX need automation mode to identify which
+ // line to use
+ // start_line_grab_from_regionview (item, event);
+ break;
+
+ default:
+ break;
+ }
+ return TRUE;
+ break;
+
+ case MouseZoom:
+ if (event->type == GDK_BUTTON_PRESS) {
+ start_mouse_zoom (item, event);
+ }
+
+ return TRUE;
+ break;
+
+ case MouseTimeFX:
+ if (item_type == RegionItem) {
+ start_time_fx (item, event);
+ }
+ break;
+
+ case MouseAudition:
+ /* handled in release */
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case 2:
+ switch (mouse_mode) {
+ case MouseObject:
+ if (event->type == GDK_BUTTON_PRESS) {
+ switch (item_type) {
+ case RegionItem:
+ if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+ start_region_copy_grab (item, event);
+ } else {
+ start_region_grab (item, event);
+ }
+
+ break;
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ start_control_point_grab (item, event);
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+
+ switch (item_type) {
+ case AudioRegionViewNameHighlight:
+ start_trim (item, event);
+ return TRUE;
+ break;
+
+ case AudioRegionViewName:
+ start_trim (clicked_regionview->get_name_highlight(), event);
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case MouseRange:
+ if (event->type == GDK_BUTTON_PRESS) {
+ /* relax till release */
+ }
+ return TRUE;
+ break;
+
+
+ case MouseZoom:
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+ temporal_zoom_session();
+ } else {
+ temporal_zoom_to_frame (true, event_frame(event));
+ }
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case 3:
+ break;
+
+ case 4:
+ switch (mouse_mode) {
+ case MouseZoom:
+ //temporal_zoom_to_frame (true, where);
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+ temporal_zoom_to_frame (true, where);
+ }
+ else {
+ temporal_zoom_step (true);
+ }
+ break;
+ default:
+
+ if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) {
+ scroll_backward (0.6f);
+ }
+ else if (Keyboard::no_modifier_keys_pressed (&event->button)) {
+ scroll_tracks_up_line ();
+ } else {
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
+ if (clicked_trackview) {
+ if (!current_stepping_trackview) {
+ TimeoutSig t;
+ step_timeout = t.connect (slot (*this, &Editor::track_height_step_timeout), 500);
+ current_stepping_trackview = clicked_trackview;
+ }
+ gettimeofday (&last_track_height_step_timestamp, 0);
+ current_stepping_trackview->step_height (true);
+ }
+ }
+ else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+ temporal_zoom_to_frame (true, where);
+ }
+ }
+ }
+ break;
+
+ case 5:
+ switch (mouse_mode) {
+ case MouseZoom:
+ // temporal_zoom_to_frame (false, where);
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+ temporal_zoom_to_frame (false, where);
+ }
+ else {
+ temporal_zoom_step (false);
+ }
+ break;
+ default:
+
+ if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) {
+ scroll_forward (0.6f);
+ }
+ else if (Keyboard::no_modifier_keys_pressed (&event->button)) {
+ scroll_tracks_down_line ();
+ } else {
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
+ if (clicked_trackview) {
+ if (!current_stepping_trackview) {
+ TimeoutSig t;
+ step_timeout = t.connect (slot (*this, &Editor::track_height_step_timeout), 500);
+ current_stepping_trackview = clicked_trackview;
+ }
+ gettimeofday (&last_track_height_step_timestamp, 0);
+ current_stepping_trackview->step_height (false);
+ }
+ } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+ temporal_zoom_to_frame (false, where);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ return FALSE;
+}
+
+gint
+Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type)
+{
+ jack_nframes_t where = event_frame (event, 0, 0);
+
+ /* no action if we're recording */
+
+ if (session && session->actively_recording()) {
+ return TRUE;
+ }
+
+ /* first, see if we're finishing a drag ... */
+
+ if (drag_info.item) {
+ if (end_grab (item, event)) {
+ /* grab dragged, so do nothing else */
+ return TRUE;
+ }
+ }
+
+ /* edit events get handled here */
+
+ if (drag_info.item == 0 && Keyboard::is_edit_event (&event->button)) {
+ switch (item_type) {
+ case RegionItem:
+ edit_region ();
+ break;
+
+ case TempoMarkerItem:
+ edit_tempo_marker (item);
+ break;
+
+ case MeterMarkerItem:
+ edit_meter_marker (item);
+ break;
+
+ case AudioRegionViewName:
+ if (clicked_regionview->name_active()) {
+ return mouse_rename_region (item, event);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return TRUE;
+ }
+
+ /* context menu events get handled here */
+
+ if (Keyboard::is_context_menu_event (&event->button)) {
+
+ if (drag_info.item == 0) {
+
+ /* no matter which button pops up the context menu, tell the menu
+ widget to use button 1 to drive menu selection.
+ */
+
+ switch (item_type) {
+ case FadeInItem:
+ case FadeInHandleItem:
+ case FadeOutItem:
+ case FadeOutHandleItem:
+ popup_fade_context_menu (1, event->button.time, item, item_type);
+ break;
+
+ case StreamItem:
+ popup_track_context_menu (1, event->button.time, item_type, false, where);
+ break;
+
+ case RegionItem:
+ case AudioRegionViewNameHighlight:
+ case AudioRegionViewName:
+ popup_track_context_menu (1, event->button.time, item_type, false, where);
+ break;
+
+ case SelectionItem:
+ popup_track_context_menu (1, event->button.time, item_type, true, where);
+ break;
+
+ case AutomationTrackItem:
+ popup_track_context_menu (1, event->button.time, item_type, false, where);
+ break;
+
+ case MarkerBarItem:
+ case RangeMarkerBarItem:
+ case TransportMarkerBarItem:
+ case TempoBarItem:
+ case MeterBarItem:
+ popup_ruler_menu (pixel_to_frame(event->button.x), item_type);
+ break;
+
+ case MarkerItem:
+ marker_context_menu (&event->button, item);
+ break;
+
+ case TempoMarkerItem:
+ tm_marker_context_menu (&event->button, item);
+ break;
+
+ case MeterMarkerItem:
+ tm_marker_context_menu (&event->button, item);
+ break;
+
+ case CrossfadeViewItem:
+ popup_track_context_menu (1, event->button.time, item_type, false, where);
+ break;
+
+ /* <CMT Additions> */
+ case ImageFrameItem:
+ popup_imageframe_edit_menu(1, event->button.time, item, true) ;
+ break ;
+ case ImageFrameTimeAxisItem:
+ popup_imageframe_edit_menu(1, event->button.time, item, false) ;
+ break ;
+ case MarkerViewItem:
+ popup_marker_time_axis_edit_menu(1, event->button.time, item, true) ;
+ break ;
+ case MarkerTimeAxisItem:
+ popup_marker_time_axis_edit_menu(1, event->button.time, item, false) ;
+ break ;
+ /* <CMT Additions> */
+
+
+ default:
+ break;
+ }
+
+ return TRUE;
+ }
+ }
+
+ /* delete events get handled here */
+
+ if (drag_info.item == 0 && Keyboard::is_delete_event (&event->button)) {
+
+ switch (item_type) {
+ case TempoMarkerItem:
+ remove_tempo_marker (item);
+ break;
+
+ case MeterMarkerItem:
+ remove_meter_marker (item);
+ break;
+
+ case MarkerItem:
+ remove_marker (item, event);
+ break;
+
+ case RegionItem:
+ if (mouse_mode == MouseObject) {
+ remove_clicked_region ();
+ }
+ break;
+
+ case GainControlPointItem:
+ if (mouse_mode == MouseGain) {
+ remove_gain_control_point (item, event);
+ }
+ break;
+
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ remove_control_point (item, event);
+ break;
+
+ default:
+ break;
+ }
+ return TRUE;
+ }
+
+ switch (event->button.button) {
+ case 1:
+
+ switch (item_type) {
+ /* see comments in button_press_handler */
+ case EditCursorItem:
+ case PlayheadCursorItem:
+ case MarkerItem:
+ case GainLineItem:
+ case GainAutomationLineItem:
+ case PanAutomationLineItem:
+ case RedirectAutomationLineItem:
+ case StartSelectionTrimItem:
+ case EndSelectionTrimItem:
+ return TRUE;
+
+ case MarkerBarItem:
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (where, 0, true);
+ }
+ mouse_add_new_marker (where);
+ return TRUE;
+
+ case TempoBarItem:
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (where);
+ }
+ mouse_add_new_tempo_event (where);
+ return TRUE;
+
+ case MeterBarItem:
+ mouse_add_new_meter_event (pixel_to_frame (event->button.x));
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ switch (mouse_mode) {
+ case MouseObject:
+ switch (item_type) {
+ case AutomationTrackItem:
+ dynamic_cast<AutomationTimeAxisView*>(clicked_trackview)->add_automation_event
+ (item,
+ event,
+ where,
+ event->button.y);
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case MouseGain:
+ switch (item_type) {
+ case RegionItem:
+ clicked_regionview->add_gain_point_event (item, event);
+ return TRUE;
+ break;
+
+ case AutomationTrackItem:
+ dynamic_cast<AutomationTimeAxisView*>(clicked_trackview)->
+ add_automation_event (item, event, where, event->button.y);
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case MouseAudition:
+ switch (item_type) {
+ case RegionItem:
+ audition_selected_region ();
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ return TRUE;
+ break;
+
+
+ case 2:
+ switch (mouse_mode) {
+
+ case MouseObject:
+ switch (item_type) {
+ case RegionItem:
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
+ raise_region ();
+ } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::Shift|Keyboard::Alt))) {
+ lower_region ();
+ } else {
+ // Button2 click is unused
+ }
+ return TRUE;
+
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case MouseRange:
+
+ // x_style_paste (where, 1.0);
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case 3:
+ break;
+
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+void
+Editor::maybe_autoscroll (GdkEvent* event)
+{
+ jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
+ jack_nframes_t rightmost_frame = leftmost_frame + one_page;
+
+ jack_nframes_t frame = drag_info.current_pointer_frame;
+
+ if (autoscroll_timeout_tag < 0) {
+ if (frame > rightmost_frame) {
+ if (rightmost_frame < max_frames) {
+ start_canvas_autoscroll (1);
+ }
+ } else if (frame < leftmost_frame) {
+ if (leftmost_frame > 0) {
+ start_canvas_autoscroll (-1);
+ }
+ }
+ } else {
+ if (frame >= leftmost_frame && frame < rightmost_frame) {
+ stop_canvas_autoscroll ();
+ }
+ }
+}
+
+gint
+Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type)
+{
+ ControlPoint* cp;
+ Marker * marker;
+ double fraction;
+
+ switch (item_type) {
+ case GainControlPointItem:
+ if (mouse_mode == MouseGain) {
+ cp = reinterpret_cast<ControlPoint*>(gtk_object_get_data (GTK_OBJECT(item), "control_point"));
+ cp->set_visible (true);
+
+ double at_x, at_y;
+ at_x = cp->get_x();
+ at_y = cp->get_y ();
+ gtk_canvas_item_i2w (cp->item, &at_x, &at_y);
+ at_x += 20.0;
+ at_y += 20.0;
+
+ fraction = 1.0 - (cp->get_y() / cp->line.height());
+
+ set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y);
+ show_verbose_canvas_cursor ();
+
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor);
+ }
+ }
+ break;
+
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ cp = reinterpret_cast<ControlPoint*>(gtk_object_get_data (GTK_OBJECT(item), "control_point"));
+ cp->set_visible (true);
+
+ double at_x, at_y;
+ at_x = cp->get_x();
+ at_y = cp->get_y ();
+ gtk_canvas_item_i2w (cp->item, &at_x, &at_y);
+ at_x += 20.0;
+ at_y += 20.0;
+
+ fraction = 1.0 - (cp->get_y() / cp->line.height());
+
+ set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y);
+ show_verbose_canvas_cursor ();
+
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor);
+ }
+ break;
+
+ case GainLineItem:
+ if (mouse_mode == MouseGain) {
+ gtk_canvas_item_set (item, "fill_color_rgba", color_map[cEnteredGainLine], NULL);
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor);
+ }
+ }
+ break;
+
+ case GainAutomationLineItem:
+ case RedirectAutomationLineItem:
+ case PanAutomationLineItem:
+ gtk_canvas_item_set (item, "fill_color_rgba", color_map[cEnteredAutomationLine], NULL);
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor);
+ }
+ break;
+
+ case AudioRegionViewNameHighlight:
+ if (is_drawable() && mouse_mode == MouseObject) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor);
+ }
+ break;
+
+ case StartSelectionTrimItem:
+ case EndSelectionTrimItem:
+ /* <CMT Additions> */
+ case ImageFrameHandleStartItem:
+ case ImageFrameHandleEndItem:
+ case MarkerViewHandleStartItem:
+ case MarkerViewHandleEndItem:
+ /* </CMT Additions> */
+
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor);
+ }
+ break;
+
+ case EditCursorItem:
+ case PlayheadCursorItem:
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), grabber_cursor);
+ }
+ break;
+
+ case AudioRegionViewName:
+
+ /* when the name is not an active item, the entire name highlight is for trimming */
+
+ if (!reinterpret_cast<AudioRegionView *> (gtk_object_get_data(GTK_OBJECT(item), "regionview"))->name_active()) {
+ if (mouse_mode == MouseObject && is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor);
+ }
+ }
+ break;
+
+
+ case AutomationTrackItem:
+ if (is_drawable()) {
+ GdkCursor *cursor;
+ switch (mouse_mode) {
+ case MouseRange:
+ cursor = selector_cursor;
+ break;
+ case MouseZoom:
+ cursor = zoom_cursor;
+ break;
+ default:
+ cursor = cross_hair_cursor;
+ break;
+ }
+
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), cursor);
+
+ AutomationTimeAxisView* atv;
+ if ((atv = static_cast<AutomationTimeAxisView*>(gtk_object_get_data(GTK_OBJECT(item), "trackview"))) != 0) {
+ clear_entered_track = false;
+ set_entered_track (atv);
+ }
+ }
+ break;
+
+ case MarkerBarItem:
+ case RangeMarkerBarItem:
+ case TransportMarkerBarItem:
+ case MeterBarItem:
+ case TempoBarItem:
+ if (is_drawable()) {
+ gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor);
+ }
+ break;
+
+ case MarkerItem:
+ if ((marker = static_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ break;
+ }
+ marker->set_color_rgba (color_map[cEnteredMarker]);
+ // fall through
+ case MeterMarkerItem:
+ case TempoMarkerItem:
+ if (is_drawable()) {
+ gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor);
+ }
+ break;
+ case FadeInHandleItem:
+ case FadeOutHandleItem:
+ if (mouse_mode == MouseObject) {
+ gtk_canvas_item_set (item, "fill_color_rgba", 0, "outline_pixels", 1, NULL);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* second pass to handle entered track status in a comprehensible way.
+ */
+
+ switch (item_type) {
+ case GainLineItem:
+ case GainAutomationLineItem:
+ case RedirectAutomationLineItem:
+ case PanAutomationLineItem:
+ case GainControlPointItem:
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ /* these do not affect the current entered track state */
+ clear_entered_track = false;
+ break;
+
+ case AutomationTrackItem:
+ /* handled above already */
+ break;
+
+ default:
+ set_entered_track (0);
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type)
+{
+ AutomationLine* al;
+ ControlPoint* cp;
+ Marker *marker;
+ Location *loc;
+ AudioRegionView* rv;
+ bool is_start;
+
+ switch (item_type) {
+ case GainControlPointItem:
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case RedirectAutomationControlPointItem:
+ cp = reinterpret_cast<ControlPoint*>(gtk_object_get_data (GTK_OBJECT(item), "control_point"));
+ if (cp->line.npoints() > 1) {
+ if (!cp->selected) {
+ cp->set_visible (false);
+ }
+ }
+
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor);
+ }
+
+ hide_verbose_canvas_cursor ();
+ break;
+
+ case AudioRegionViewNameHighlight:
+ case StartSelectionTrimItem:
+ case EndSelectionTrimItem:
+ case EditCursorItem:
+ case PlayheadCursorItem:
+ /* <CMT Additions> */
+ case ImageFrameHandleStartItem:
+ case ImageFrameHandleEndItem:
+ case MarkerViewHandleStartItem:
+ case MarkerViewHandleEndItem:
+ /* </CMT Additions> */
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor);
+ }
+ break;
+
+ case GainLineItem:
+ case GainAutomationLineItem:
+ case RedirectAutomationLineItem:
+ case PanAutomationLineItem:
+ al = reinterpret_cast<AutomationLine*> (gtk_object_get_data (GTK_OBJECT(item),"line"));
+ gtk_canvas_item_set (item, "fill_color_rgba", al->get_line_color(), NULL);
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor);
+ }
+ break;
+
+ case AudioRegionViewName:
+ /* see enter_handler() for notes */
+ if (!reinterpret_cast<AudioRegionView *> (gtk_object_get_data(GTK_OBJECT(item), "regionview"))->name_active()) {
+ if (is_drawable() && mouse_mode == MouseObject) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor);
+ }
+ }
+ break;
+
+ case RangeMarkerBarItem:
+ case TransportMarkerBarItem:
+ case MeterBarItem:
+ case TempoBarItem:
+ case MarkerBarItem:
+ if (is_drawable()) {
+ gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor);
+ }
+ break;
+
+ case MarkerItem:
+ if ((marker = static_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ break;
+ }
+ loc = find_location_from_marker (marker, is_start);
+ if (loc) location_flags_changed (loc, this);
+ // fall through
+ case MeterMarkerItem:
+ case TempoMarkerItem:
+
+ if (is_drawable()) {
+ gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor);
+ }
+
+ break;
+
+ case FadeInHandleItem:
+ case FadeOutHandleItem:
+ rv = static_cast<AudioRegionView*>(gtk_object_get_data (GTK_OBJECT(item), "regionview"));
+ gtk_canvas_item_set (item, "fill_color_rgba", rv->get_fill_color(), "outline_pixels", 0, NULL);
+ break;
+
+ case AutomationTrackItem:
+ if (is_drawable()) {
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor);
+
+ clear_entered_track = true;
+ Main::idle.connect (slot (*this, &Editor::left_automation_track));
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+Editor::left_automation_track ()
+{
+ if (clear_entered_track) {
+ set_entered_track (0);
+ clear_entered_track = false;
+ }
+ return FALSE;
+}
+
+gint
+Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type)
+{
+ 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);
+
+ if (current_stepping_trackview) {
+ /* don't keep the persistent stepped trackview if the mouse moves */
+ current_stepping_trackview = 0;
+ step_timeout.disconnect ();
+ }
+
+ if (session && session->actively_recording()) {
+ /* Sorry. no dragging stuff around while we record */
+ return TRUE;
+ }
+
+ drag_info.current_pointer_frame = event_frame (event, &drag_info.current_pointer_x,
+ &drag_info.current_pointer_y);
+ if (drag_info.item) {
+ /* item != 0 is the best test i can think of for
+ dragging.
+ */
+ if (!drag_info.move_threshold_passsed)
+ {
+ drag_info.move_threshold_passsed = (abs ((int) (drag_info.current_pointer_x - drag_info.grab_x)) > 4);
+
+ // and change the initial grab loc/frame if this drag info wants us to
+ if (drag_info.want_move_threshold && drag_info.move_threshold_passsed) {
+ drag_info.grab_frame = drag_info.current_pointer_frame;
+ drag_info.grab_x = drag_info.current_pointer_x;
+ drag_info.grab_y = drag_info.current_pointer_y;
+ drag_info.last_pointer_frame = drag_info.grab_frame;
+ drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
+ }
+ }
+ }
+
+ switch (item_type) {
+ case PlayheadCursorItem:
+ case EditCursorItem:
+ case MarkerItem:
+ case GainControlPointItem:
+ case RedirectAutomationControlPointItem:
+ case GainAutomationControlPointItem:
+ case PanAutomationControlPointItem:
+ case TempoMarkerItem:
+ case MeterMarkerItem:
+ case AudioRegionViewNameHighlight:
+ case StartSelectionTrimItem:
+ case EndSelectionTrimItem:
+ case SelectionItem:
+ case GainLineItem:
+ case RedirectAutomationLineItem:
+ case GainAutomationLineItem:
+ case PanAutomationLineItem:
+ case FadeInHandleItem:
+ case FadeOutHandleItem:
+ /* <CMT Additions> */
+ case ImageFrameHandleStartItem:
+ case ImageFrameHandleEndItem:
+ case MarkerViewHandleStartItem:
+ case MarkerViewHandleEndItem:
+ /* </CMT Additions> */
+ if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK ||
+ (event->motion.state & GDK_BUTTON2_MASK))) {
+ maybe_autoscroll (event);
+ (this->*(drag_info.motion_callback)) (item, event);
+ goto handled;
+ }
+ goto not_handled;
+
+ default:
+ break;
+ }
+
+ switch (mouse_mode) {
+ case MouseObject:
+ case MouseRange:
+ case MouseZoom:
+ case MouseTimeFX:
+ if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK ||
+ (event->motion.state & GDK_BUTTON2_MASK))) {
+ maybe_autoscroll (event);
+ (this->*(drag_info.motion_callback)) (item, event);
+ goto handled;
+ }
+ goto not_handled;
+ break;
+
+ default:
+ break;
+ }
+
+ handled:
+ track_canvas_motion (item, event);
+ return TRUE;
+
+ not_handled:
+ return FALSE;
+}
+
+void
+Editor::start_grab (GdkEvent* event, GdkCursor *cursor)
+{
+ if (drag_info.item == 0) {
+ fatal << _("programming error: start_grab called without drag item") << endmsg;
+ /*NOTREACHED*/
+ return;
+ }
+
+ if (cursor == 0) {
+ cursor = grabber_cursor;
+ }
+
+ // if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained
+
+ if (event->button.button == 2) {
+ drag_info.x_constrained = true;
+ } else {
+ drag_info.x_constrained = false;
+ }
+
+ drag_info.grab_frame = event_frame(event, &drag_info.grab_x, &drag_info.grab_y);
+ drag_info.last_pointer_frame = drag_info.grab_frame;
+ drag_info.current_pointer_frame = drag_info.grab_frame;
+ drag_info.current_pointer_x = drag_info.grab_x;
+ drag_info.current_pointer_y = drag_info.grab_y;
+ drag_info.cumulative_x_drag = 0;
+ drag_info.cumulative_y_drag = 0;
+ drag_info.first_move = true;
+ drag_info.move_threshold_passsed = false;
+ drag_info.want_move_threshold = false;
+ drag_info.pointer_frame_offset = 0;
+ drag_info.brushing = false;
+ drag_info.copied_location = 0;
+
+ gtk_canvas_item_grab (drag_info.item,
+ GDK_POINTER_MOTION_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK,
+ cursor,
+ event->button.time);
+
+ if (session && session->transport_rolling()) {
+ drag_info.was_rolling = true;
+ } else {
+ drag_info.was_rolling = false;
+ }
+
+ switch (snap_type) {
+ case SnapToRegionStart:
+ case SnapToRegionEnd:
+ case SnapToRegionSync:
+ case SnapToRegionBoundary:
+ build_region_boundary_cache ();
+ break;
+ default:
+ break;
+ }
+}
+
+bool
+Editor::end_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ bool did_drag = false;
+
+ stop_canvas_autoscroll ();
+
+ if (drag_info.item == 0) {
+ return false;
+ }
+
+ gtk_canvas_item_ungrab (drag_info.item, event->button.time);
+
+ if (drag_info.finished_callback) {
+ (this->*(drag_info.finished_callback)) (item, event);
+ }
+
+ did_drag = !drag_info.first_move;
+
+ hide_verbose_canvas_cursor();
+
+ drag_info.item = 0;
+ drag_info.copy = false;
+ drag_info.motion_callback = 0;
+ drag_info.finished_callback = 0;
+ drag_info.last_trackview = 0;
+ drag_info.last_frame_position = 0;
+ drag_info.grab_frame = 0;
+ drag_info.last_pointer_frame = 0;
+ drag_info.current_pointer_frame = 0;
+ drag_info.brushing = false;
+
+ if (drag_info.copied_location) {
+ delete drag_info.copied_location;
+ drag_info.copied_location = 0;
+ }
+
+ return did_drag;
+}
+
+void
+Editor::set_edit_cursor (GdkEvent* event)
+{
+ jack_nframes_t pointer_frame = event_frame (event);
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ if (snap_type != SnapToEditCursor) {
+ snap_to (pointer_frame);
+ }
+ }
+
+ edit_cursor->set_position (pointer_frame);
+ edit_cursor_clock.set (pointer_frame);
+}
+
+void
+Editor::set_playhead_cursor (GdkEvent* event)
+{
+ jack_nframes_t pointer_frame = event_frame (event);
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (pointer_frame);
+ }
+
+ if (session) {
+ session->request_locate (pointer_frame, session->transport_rolling());
+ }
+}
+
+void
+Editor::start_fade_in_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::fade_in_drag_motion_callback;
+ drag_info.finished_callback = &Editor::fade_in_drag_finished_callback;
+
+ start_grab (event);
+
+ if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "regionview"))) == 0) {
+ fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
+
+ drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->region.fade_in().back()->when + arv->region.position());
+}
+
+void
+Editor::fade_in_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
+ jack_nframes_t pos;
+ jack_nframes_t fade_length;
+
+ if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+ pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ pos = 0;
+ }
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (pos);
+ }
+
+ if (pos < (arv->region.position() + 64)) {
+ fade_length = 64; // this should be a minimum defined somewhere
+ } else if (pos > arv->region.last_frame()) {
+ fade_length = arv->region.length();
+ } else {
+ fade_length = pos - arv->region.position();
+ }
+
+ arv->reset_fade_in_shape_width (fade_length);
+
+ show_verbose_duration_cursor (arv->region.position(), arv->region.position() + fade_length, 10);
+
+ drag_info.first_move = false;
+}
+
+void
+Editor::fade_in_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (drag_info.first_move) return;
+
+ AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
+ jack_nframes_t pos;
+ jack_nframes_t fade_length;
+
+ if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+ pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ pos = 0;
+ }
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (pos);
+ }
+
+ if (pos < (arv->region.position() + 64)) {
+ fade_length = 64; // this should be a minimum defined somewhere
+ }
+ else if (pos > arv->region.last_frame()) {
+ fade_length = arv->region.length();
+ }
+ else {
+ fade_length = pos - arv->region.position();
+ }
+
+ begin_reversible_command (_("change fade in length"));
+ session->add_undo (arv->region.get_memento());
+ arv->region.set_fade_in_length (fade_length);
+ session->add_redo_no_execute (arv->region.get_memento());
+ commit_reversible_command ();
+ fade_in_drag_motion_callback (item, event);
+}
+
+void
+Editor::start_fade_out_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::fade_out_drag_motion_callback;
+ drag_info.finished_callback = &Editor::fade_out_drag_finished_callback;
+
+ start_grab (event);
+
+ if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "regionview"))) == 0) {
+ fatal << _("programming error: fade out canvas item has no regionview data pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
+
+ drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region.length() - (jack_nframes_t) arv->region.fade_out().back()->when + arv->region.position());
+}
+
+void
+Editor::fade_out_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
+ jack_nframes_t pos;
+ jack_nframes_t fade_length;
+
+ if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+ pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ pos = 0;
+ }
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (pos);
+ }
+
+ if (pos > (arv->region.last_frame() - 64)) {
+ fade_length = 64; // this should really be a minimum fade defined somewhere
+ }
+ else if (pos < arv->region.position()) {
+ fade_length = arv->region.length();
+ }
+ else {
+ fade_length = arv->region.last_frame() - pos;
+ }
+
+ arv->reset_fade_out_shape_width (fade_length);
+
+ show_verbose_duration_cursor (arv->region.last_frame() - fade_length, arv->region.last_frame(), 10);
+
+ drag_info.first_move = false;
+}
+
+void
+Editor::fade_out_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (drag_info.first_move) return;
+
+ AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
+ jack_nframes_t pos;
+ jack_nframes_t fade_length;
+
+ if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+ pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ pos = 0;
+ }
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (pos);
+ }
+
+ if (pos > (arv->region.last_frame() - 64)) {
+ fade_length = 64; // this should really be a minimum fade defined somewhere
+ }
+ else if (pos < arv->region.position()) {
+ fade_length = arv->region.length();
+ }
+ else {
+ fade_length = arv->region.last_frame() - pos;
+ }
+
+ begin_reversible_command (_("change fade out length"));
+ session->add_undo (arv->region.get_memento());
+ arv->region.set_fade_out_length (fade_length);
+ session->add_redo_no_execute (arv->region.get_memento());
+ commit_reversible_command ();
+
+ fade_out_drag_motion_callback (item, event);
+}
+
+void
+Editor::start_cursor_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::cursor_drag_motion_callback;
+ drag_info.finished_callback = &Editor::cursor_drag_finished_callback;
+
+ start_grab (event);
+
+ if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "cursor"))) == 0) {
+ fatal << _("programming error: cursor canvas item has no cursor data pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Cursor* cursor = (Cursor *) drag_info.data;
+
+ if (session && cursor == playhead_cursor) {
+ if (drag_info.was_rolling) {
+ session->request_stop ();
+ }
+ }
+
+ drag_info.pointer_frame_offset = drag_info.grab_frame - cursor->current_frame;
+
+ show_verbose_time_cursor (cursor->current_frame, 10);
+}
+
+void
+Editor::cursor_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ Cursor* cursor = (Cursor *) drag_info.data;
+ jack_nframes_t adjusted_frame;
+
+ if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+ adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ adjusted_frame = 0;
+ }
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ if (cursor != edit_cursor || snap_type != SnapToEditCursor) {
+ snap_to (adjusted_frame);
+ }
+ }
+
+ if (adjusted_frame == drag_info.last_pointer_frame) return;
+
+ cursor->set_position (adjusted_frame);
+
+ if (cursor == edit_cursor) {
+ edit_cursor_clock.set (cursor->current_frame);
+ }
+
+ show_verbose_time_cursor (cursor->current_frame, 10);
+
+ drag_info.last_pointer_frame = adjusted_frame;
+ drag_info.first_move = false;
+}
+
+void
+Editor::cursor_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (drag_info.first_move) return;
+
+ cursor_drag_motion_callback (item, event);
+
+ if (item == playhead_cursor->canvas_item) {
+ if (session) {
+ session->request_locate (playhead_cursor->current_frame, drag_info.was_rolling);
+ }
+ } else if (item == edit_cursor->canvas_item) {
+ edit_cursor->set_position (edit_cursor->current_frame);
+ edit_cursor_clock.set (edit_cursor->current_frame);
+ }
+}
+
+void
+Editor::update_marker_drag_item (Location *location)
+{
+ double x1 = frame_to_pixel (location->start());
+ double x2 = frame_to_pixel (location->end());
+
+ if (location->is_mark()) {
+ marker_drag_line_points->coords[0] = x1;
+ marker_drag_line_points->coords[2] = x1;
+ gtk_canvas_item_set (marker_drag_line, "points", marker_drag_line_points, NULL);
+ }
+ else {
+ gtk_canvas_item_set (range_marker_drag_rect, "x1", x1, "x2", x2, NULL);
+ }
+}
+
+void
+Editor::start_marker_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ Marker* marker;
+
+ if ((marker = static_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ bool is_start;
+
+ Location *location = find_location_from_marker (marker, is_start);
+
+ drag_info.item = item;
+ drag_info.data = marker;
+ drag_info.motion_callback = &Editor::marker_drag_motion_callback;
+ drag_info.finished_callback = &Editor::marker_drag_finished_callback;
+
+ start_grab (event);
+
+ drag_info.copied_location = new Location (*location);
+ drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end());
+
+ update_marker_drag_item (location);
+
+ if (location->is_mark()) {
+ gtk_canvas_item_show (marker_drag_line);
+ gtk_canvas_item_raise_to_top (marker_drag_line);
+ }
+ else {
+ gtk_canvas_item_show (range_marker_drag_rect);
+ gtk_canvas_item_raise_to_top (range_marker_drag_rect);
+ }
+
+ if (is_start) show_verbose_time_cursor (location->start(), 10);
+ else show_verbose_time_cursor (location->end(), 10);
+}
+
+void
+Editor::marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ jack_nframes_t f_delta;
+ Marker* marker = (Marker *) drag_info.data;
+ Location *real_location;
+ Location *copy_location;
+ bool is_start;
+ bool move_both = false;
+
+ jack_nframes_t newframe;
+ if (drag_info.pointer_frame_offset <= (long) drag_info.current_pointer_frame) {
+ newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ newframe = 0;
+ }
+
+ jack_nframes_t next = newframe;
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (newframe, 0, true);
+ }
+
+ if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return;
+
+ /* call this to find out if its the start or end */
+
+ real_location = find_location_from_marker (marker, is_start);
+
+ /* use the copy that we're "dragging" around */
+
+ copy_location = drag_info.copied_location;
+
+ f_delta = copy_location->end() - copy_location->start();
+
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+ move_both = true;
+ }
+
+ if (is_start) { // start marker
+
+ if (move_both) {
+ copy_location->set_start (newframe);
+ copy_location->set_end (newframe + f_delta);
+ } else if (newframe < copy_location->end()) {
+ copy_location->set_start (newframe);
+ } else {
+ snap_to (next, 1, true);
+ copy_location->set_end (next);
+ copy_location->set_start (newframe);
+ }
+
+ } else { // end marker
+
+ if (move_both) {
+ copy_location->set_end (newframe);
+ copy_location->set_start (newframe - f_delta);
+ } else if (newframe > copy_location->start()) {
+ copy_location->set_end (newframe);
+
+ } else if (newframe > 0) {
+ snap_to (next, -1, true);
+ copy_location->set_start (next);
+ copy_location->set_end (newframe);
+ }
+ }
+
+ drag_info.last_pointer_frame = drag_info.current_pointer_frame;
+ drag_info.first_move = false;
+
+ update_marker_drag_item (copy_location);
+
+ LocationMarkers* lm = find_location_markers (real_location);
+ lm->set_position (copy_location->start(), copy_location->end());
+
+ show_verbose_time_cursor (newframe, 10);
+}
+
+void
+Editor::marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (drag_info.first_move) {
+ marker_drag_motion_callback (item, event);
+
+ }
+
+ Marker* marker = (Marker *) drag_info.data;
+ bool is_start;
+ Location * location = find_location_from_marker (marker, is_start);
+ if (location) {
+ location->set (drag_info.copied_location->start(), drag_info.copied_location->end());
+ }
+
+ gtk_canvas_item_hide (marker_drag_line);
+ gtk_canvas_item_hide (range_marker_drag_rect);
+}
+
+void
+Editor::start_meter_marker_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ Marker* marker;
+ MeterMarker* meter_marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ meter_marker = dynamic_cast<MeterMarker*> (marker);
+
+ MetricSection& section (meter_marker->meter());
+
+ if (!section.movable()) {
+ return;
+ }
+
+ drag_info.item = item;
+ drag_info.data = marker;
+ drag_info.motion_callback = &Editor::meter_marker_drag_motion_callback;
+ drag_info.finished_callback = &Editor::meter_marker_drag_finished_callback;
+
+ start_grab (event);
+
+ drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame();
+
+ show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
+}
+
+void
+Editor::meter_marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ MeterMarker* marker = (MeterMarker *) drag_info.data;
+ jack_nframes_t adjusted_frame;
+
+ if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+ adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ adjusted_frame = 0;
+ }
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (adjusted_frame);
+ }
+
+ if (adjusted_frame == drag_info.last_pointer_frame) return;
+
+ marker->set_position (adjusted_frame);
+
+
+ drag_info.last_pointer_frame = adjusted_frame;
+ drag_info.first_move = false;
+
+ show_verbose_time_cursor (adjusted_frame, 10);
+}
+
+void
+Editor::meter_marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (drag_info.first_move) return;
+
+ meter_marker_drag_motion_callback (item, event);
+
+ MeterMarker* marker = (MeterMarker *) drag_info.data;
+ BBT_Time when;
+
+ TempoMap& map (session->tempo_map());
+ map.bbt_time (drag_info.last_pointer_frame, when);
+
+ begin_reversible_command (_("move meter mark"));
+ session->add_undo (map.get_memento());
+ map.move_meter (marker->meter(), when);
+ session->add_redo_no_execute (map.get_memento());
+ commit_reversible_command ();
+}
+
+void
+Editor::start_tempo_marker_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ Marker* marker;
+ TempoMarker* tempo_marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "tempo_marker"))) == 0) {
+ fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((tempo_marker = dynamic_cast<TempoMarker *> (marker)) == 0) {
+ fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ MetricSection& section (tempo_marker->tempo());
+
+ if (!section.movable()) {
+ return;
+ }
+
+ drag_info.item = item;
+ drag_info.data = marker;
+ drag_info.motion_callback = &Editor::tempo_marker_drag_motion_callback;
+ drag_info.finished_callback = &Editor::tempo_marker_drag_finished_callback;
+
+ start_grab (event);
+
+ drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame();
+ show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
+}
+
+void
+Editor::tempo_marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ TempoMarker* marker = (TempoMarker *) drag_info.data;
+ jack_nframes_t adjusted_frame;
+
+ if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+ adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ adjusted_frame = 0;
+ }
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (adjusted_frame);
+ }
+
+ if (adjusted_frame == drag_info.last_pointer_frame) return;
+
+ /* OK, we've moved far enough to make it worth actually move the thing. */
+
+ marker->set_position (adjusted_frame);
+
+ show_verbose_time_cursor (adjusted_frame, 10);
+
+ drag_info.last_pointer_frame = adjusted_frame;
+ drag_info.first_move = false;
+}
+
+void
+Editor::tempo_marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (drag_info.first_move) return;
+
+ tempo_marker_drag_motion_callback (item, event);
+
+ TempoMarker* marker = (TempoMarker *) drag_info.data;
+ BBT_Time when;
+
+ TempoMap& map (session->tempo_map());
+ map.bbt_time (drag_info.last_pointer_frame, when);
+
+ begin_reversible_command (_("move tempo mark"));
+ session->add_undo (map.get_memento());
+ map.move_tempo (marker->tempo(), when);
+ session->add_redo_no_execute (map.get_memento());
+ commit_reversible_command ();
+}
+
+void
+Editor::remove_gain_control_point (GtkCanvasItem*item, GdkEvent* event)
+{
+ ControlPoint* control_point;
+
+ if ((control_point = reinterpret_cast<ControlPoint *> (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) {
+ fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ // We shouldn't remove the first or last gain point
+ if (control_point->line.is_last_point(*control_point) ||
+ control_point->line.is_first_point(*control_point)) {
+ return;
+ }
+
+ control_point->line.remove_point (*control_point);
+}
+
+void
+Editor::remove_control_point (GtkCanvasItem*item, GdkEvent* event)
+{
+ ControlPoint* control_point;
+
+ if ((control_point = reinterpret_cast<ControlPoint *> (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) {
+ fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ control_point->line.remove_point (*control_point);
+}
+
+void
+Editor::start_control_point_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ ControlPoint* control_point;
+
+ if ((control_point = reinterpret_cast<ControlPoint *> (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) {
+ fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ drag_info.item = item;
+ drag_info.data = control_point;
+ drag_info.motion_callback = &Editor::control_point_drag_motion_callback;
+ drag_info.finished_callback = &Editor::control_point_drag_finished_callback;
+
+ start_grab (event, fader_cursor);
+
+ control_point->line.start_drag (control_point, 0);
+
+ float fraction = 1.0 - (control_point->get_y() / control_point->line.height());
+ set_verbose_canvas_cursor (control_point->line.get_verbose_cursor_string (fraction),
+ drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20);
+
+ show_verbose_canvas_cursor ();
+}
+
+void
+Editor::control_point_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ ControlPoint* cp = reinterpret_cast<ControlPoint *> (drag_info.data);
+
+ double cx = drag_info.current_pointer_x;
+ double cy = drag_info.current_pointer_y;
+
+ drag_info.cumulative_x_drag = cx - drag_info.grab_x ;
+ drag_info.cumulative_y_drag = cy - drag_info.grab_y ;
+
+ bool x_constrained = false;
+
+ if (drag_info.x_constrained) {
+ if (fabs(drag_info.cumulative_x_drag) < fabs(drag_info.cumulative_y_drag)) {
+ cx = drag_info.grab_x;
+ x_constrained = true;
+
+ } else {
+ cy = drag_info.grab_y;
+ }
+
+ }
+
+ gtk_canvas_item_w2i (cp->line.parent_group(), &cx, &cy);
+
+ cx = max (0.0, cx);
+ cy = max (0.0, cy);
+ cy = min ((double) cp->line.height(), cy);
+
+ //translate cx to frames
+ jack_nframes_t cx_frames = (jack_nframes_t) floor (cx * frames_per_unit);
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && !x_constrained) {
+ snap_to (cx_frames);
+ }
+
+ float fraction = 1.0 - (cy / cp->line.height());
+
+ bool push;
+
+ if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+ push = true;
+ } else {
+ push = false;
+ }
+
+ cp->line.point_drag (*cp, cx_frames , fraction, push);
+
+ set_verbose_canvas_cursor_text (cp->line.get_verbose_cursor_string (fraction));
+}
+
+void
+Editor::control_point_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ ControlPoint* cp = reinterpret_cast<ControlPoint *> (drag_info.data);
+ control_point_drag_motion_callback (item, event);
+ cp->line.end_drag (cp);
+}
+
+void
+Editor::start_line_grab_from_regionview (GtkCanvasItem* item, GdkEvent* event)
+{
+ switch (mouse_mode) {
+ case MouseGain:
+ start_line_grab (clicked_regionview->get_gain_line(), event);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+Editor::start_line_grab_from_line (GtkCanvasItem* item, GdkEvent* event)
+{
+ AutomationLine* al;
+
+ if ((al = reinterpret_cast<AutomationLine*> (gtk_object_get_data (GTK_OBJECT(item), "line"))) == 0) {
+ fatal << _("programming error: line canvas item has no line pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ start_line_grab (al, event);
+}
+
+void
+Editor::start_line_grab (AutomationLine* line, GdkEvent* event)
+{
+ double cx;
+ double cy;
+ jack_nframes_t frame_within_region;
+
+ /* need to get x coordinate in terms of parent (TimeAxisItemView)
+ origin.
+ */
+
+ cx = event->button.x;
+ cy = event->button.y;
+ gtk_canvas_item_w2i (line->parent_group(), &cx, &cy);
+ frame_within_region = (jack_nframes_t) floor (cx * frames_per_unit);
+
+ if (!line->control_points_adjacent (frame_within_region, current_line_drag_info.before,
+ current_line_drag_info.after)) {
+ /* no adjacent points */
+ return;
+ }
+
+ drag_info.item = line->grab_item();
+ drag_info.data = line;
+ drag_info.motion_callback = &Editor::line_drag_motion_callback;
+ drag_info.finished_callback = &Editor::line_drag_finished_callback;
+
+ start_grab (event, fader_cursor);
+
+ double fraction = 1.0 - (cy / line->height());
+
+ line->start_drag (0, fraction);
+
+ set_verbose_canvas_cursor (line->get_verbose_cursor_string (fraction),
+ drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20);
+ show_verbose_canvas_cursor ();
+}
+
+void
+Editor::line_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ AutomationLine* line = reinterpret_cast<AutomationLine *> (drag_info.data);
+ double cx = drag_info.current_pointer_x;
+ double cy = drag_info.current_pointer_y;
+
+ gtk_canvas_item_w2i (line->parent_group(), &cx, &cy);
+
+ double fraction;
+ fraction = 1.0 - (cy / line->height());
+
+ bool push;
+
+ if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) {
+ push = false;
+ } else {
+ push = true;
+ }
+
+ line->line_drag (current_line_drag_info.before, current_line_drag_info.after, fraction, push);
+
+ set_verbose_canvas_cursor_text (line->get_verbose_cursor_string (fraction));
+}
+
+void
+Editor::line_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ AutomationLine* line = reinterpret_cast<AutomationLine *> (drag_info.data);
+ line_drag_motion_callback (item, event);
+ line->end_drag (0);
+}
+
+void
+Editor::start_region_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (selection->audio_regions.empty() || clicked_regionview == 0) {
+ return;
+ }
+
+ 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;
+
+ start_grab (event);
+
+ double speed = 1.0;
+ TimeAxisView* tvp = clicked_trackview;
+ AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+
+ if (tv && tv->is_audio_track()) {
+ speed = tv->get_diskstream()->speed();
+ }
+
+ drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
+ drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
+ drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
+ // we want a move threshold
+ drag_info.want_move_threshold = true;
+
+ show_verbose_time_cursor (drag_info.last_frame_position, 10);
+
+ begin_reversible_command (_("move region(s)"));
+}
+
+void
+Editor::start_region_copy_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (selection->audio_regions.empty() || clicked_regionview == 0) {
+ return;
+ }
+
+ /* this is committed in the grab finished callback. */
+
+ begin_reversible_command (_("Drag region copy"));
+
+ /* duplicate the region(s) */
+
+ vector<AudioRegionView*> new_regionviews;
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+ AudioRegionView* rv;
+
+ rv = (*i);
+
+ Playlist* to_playlist = rv->region.playlist();
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view());
+
+ session->add_undo (to_playlist->get_memento ());
+ latest_regionview = 0;
+
+ SigC::Connection c = atv->view->AudioRegionViewAdded.connect (slot (*this, &Editor::collect_new_region_view));
+
+ /* create a new region with the same name.
+ */
+
+ AudioRegion* newregion = new AudioRegion (rv->region);
+
+ /* if the original region was locked, we don't care */
+
+ newregion->set_locked (false);
+
+ to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region.position() * atv->get_diskstream()->speed()));
+
+ c.disconnect ();
+
+ if (latest_regionview) {
+ new_regionviews.push_back (latest_regionview);
+ }
+
+ }
+
+ if (new_regionviews.empty()) {
+ return;
+ }
+
+ /* reset selection to new regionviews */
+
+ selection->set (new_regionviews);
+
+ drag_info.item = new_regionviews.front()->get_canvas_group ();
+ drag_info.copy = true;
+ drag_info.data = new_regionviews.front();
+ drag_info.motion_callback = &Editor::region_drag_motion_callback;
+ drag_info.finished_callback = &Editor::region_drag_finished_callback;
+
+ start_grab(event);
+
+ TimeAxisView* tv = &clicked_regionview->get_time_axis_view();
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(tv);
+ double speed = 1.0;
+
+ if (atv && atv->is_audio_track()) {
+ speed = atv->get_diskstream()->speed();
+ }
+
+ drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
+ drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
+ drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
+ // we want a move threshold
+ drag_info.want_move_threshold = true;
+
+ show_verbose_time_cursor (drag_info.last_frame_position, 10);
+
+ begin_reversible_command (_("copy region(s)"));
+}
+
+void
+Editor::start_region_brush_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (selection->audio_regions.empty() || clicked_regionview == 0) {
+ return;
+ }
+
+ 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;
+
+ start_grab (event);
+
+ double speed = 1.0;
+ TimeAxisView* tvp = clicked_trackview;
+ AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+
+ if (tv && tv->is_audio_track()) {
+ speed = tv->get_diskstream()->speed();
+ }
+
+ drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed);
+ drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
+ drag_info.last_trackview = &clicked_regionview->get_time_axis_view();
+ // we want a move threshold
+ drag_info.want_move_threshold = true;
+ drag_info.brushing = true;
+
+ begin_reversible_command (_("Drag region brush"));
+}
+
+void
+Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ double x_delta;
+ double y_delta = 0;
+ AudioRegionView *rv = reinterpret_cast<AudioRegionView*> (drag_info.data);
+ jack_nframes_t pending_region_position = 0;
+ int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order;
+ int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen
+ bool clamp_y_axis = false;
+ vector<int32_t> height_list(512) ;
+ vector<int32_t>::iterator j;
+
+ /* Which trackview is this ? */
+
+ TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y);
+ AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+
+ /* The region motion is only processed if the pointer is over
+ an audio track.
+ */
+
+ if (!tv || !tv->is_audio_track()) {
+ /* To make sure we hide the verbose canvas cursor when the mouse is
+ not held over and audiotrack.
+ */
+ hide_verbose_canvas_cursor ();
+ return;
+ }
+
+ original_pointer_order = drag_info.last_trackview->order;
+
+ /************************************************************
+ Y-Delta Computation
+ ************************************************************/
+
+ if (drag_info.brushing) {
+ clamp_y_axis = true;
+ 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;
+ bitset <512> tracks (0x00);
+ /* get a bitmask representing the visible tracks */
+
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ TimeAxisView *tracklist_timeview;
+ tracklist_timeview = (*i);
+ AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tracklist_timeview);
+ list<TimeAxisView*> children_list;
+
+ /* zeroes are audio tracks. ones are other types. */
+
+ if (!atv2->hidden()) {
+
+ if (visible_y_high < atv2->order) {
+ visible_y_high = atv2->order;
+ }
+ if (visible_y_low > atv2->order) {
+ visible_y_low = atv2->order;
+ }
+
+ if (!atv2->is_audio_track()) {
+ tracks = tracks |= (0x01 << atv2->order);
+ }
+
+ height_list[atv2->order] = (*i)->height;
+ children = 1;
+ if ((children_list = atv2->get_child_list()).size() > 0) {
+ for (list<TimeAxisView*>::iterator j = children_list.begin(); j != children_list.end(); ++j) {
+ tracks = tracks |= (0x01 << (atv2->order + children));
+ height_list[atv2->order + children] = (*j)->height;
+ numtracks++;
+ children++;
+ }
+ }
+ numtracks++;
+ }
+ }
+ /* find the actual span according to the canvas */
+
+ canvas_pointer_y_span = pointer_y_span;
+ if (drag_info.last_trackview->order >= tv->order) {
+ int32_t y;
+ for (y = tv->order; y < drag_info.last_trackview->order; y++) {
+ if (height_list[y] == 0 ) {
+ canvas_pointer_y_span--;
+ }
+ }
+ } else {
+ int32_t y;
+ for (y = drag_info.last_trackview->order;y <= tv->order; y++) {
+ if ( height_list[y] == 0 ) {
+ canvas_pointer_y_span++;
+ }
+ }
+ }
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+ AudioRegionView* rv2;
+ rv2 = (*i);
+ double ix1, ix2, iy1, iy2;
+ int32_t n = 0;
+
+ gtk_canvas_item_get_bounds (rv2->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2);
+ gtk_canvas_item_i2w (rv2->get_canvas_group(), &ix1, &iy1);
+ TimeAxisView* tvp2 = trackview_by_y_position (iy1);
+ AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
+
+ if (atv2->order != original_pointer_order) {
+ /* this isn't the pointer track */
+
+ if (canvas_pointer_y_span > 0) {
+
+ /* moving up the canvas */
+ if ((atv2->order - canvas_pointer_y_span) >= visible_y_low) {
+
+ int32_t visible_tracks = 0;
+ while (visible_tracks < canvas_pointer_y_span ) {
+ visible_tracks++;
+
+ while (height_list[atv2->order - (visible_tracks - n)] == 0) {
+ /* we're passing through a hidden track */
+ n--;
+ }
+ }
+
+ if (tracks[atv2->order - (canvas_pointer_y_span - n)] != 0x00) {
+ clamp_y_axis = true;
+ }
+
+ } else {
+ clamp_y_axis = true;
+ }
+
+ } else if (canvas_pointer_y_span < 0) {
+
+ /*moving down the canvas*/
+
+ if ((atv2->order - (canvas_pointer_y_span - n)) <= visible_y_high) { // we will overflow
+
+
+ int32_t visible_tracks = 0;
+
+ while (visible_tracks > canvas_pointer_y_span ) {
+ visible_tracks--;
+
+ while (height_list[atv2->order - (visible_tracks - n)] == 0) {
+ n++;
+ }
+ }
+ if ( tracks[atv2->order - ( canvas_pointer_y_span - n)] != 0x00) {
+ clamp_y_axis = true;
+
+ }
+ } else {
+
+ clamp_y_axis = true;
+ }
+ }
+
+ } else {
+
+ /* this is the pointer's track */
+ if ((atv2->order - pointer_y_span) > visible_y_high) { // we will overflow
+ clamp_y_axis = true;
+ } else if ((atv2->order - pointer_y_span) < visible_y_low) { // we will underflow
+ clamp_y_axis = true;
+ }
+ }
+ if (clamp_y_axis) {
+ break;
+ }
+ }
+
+ } else if (drag_info.last_trackview == tv) {
+ clamp_y_axis = true;
+ }
+
+ y_axis_done:
+ if (!clamp_y_axis) {
+ drag_info.last_trackview = tv;
+ }
+
+ /************************************************************
+ X DELTA COMPUTATION
+ ************************************************************/
+
+ /* compute the amount of pointer motion in frames, and where
+ the region would be if we moved it by that much.
+ */
+
+ if (drag_info.move_threshold_passsed) {
+
+ if ((int32_t)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+
+ jack_nframes_t sync_frame;
+ jack_nframes_t sync_offset;
+ int32_t sync_dir;
+
+ pending_region_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+
+ sync_offset = rv->region.sync_offset (sync_dir);
+ sync_frame = rv->region.adjust_to_sync (pending_region_position);
+
+ /* we snap if the snap modifier is not enabled.
+ */
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (sync_frame);
+ }
+
+ if (sync_frame - sync_offset <= sync_frame) {
+ pending_region_position = sync_frame - (sync_dir*sync_offset);
+ } else {
+ pending_region_position = 0;
+ }
+
+ } else {
+ pending_region_position = 0;
+ }
+
+ if (pending_region_position > max_frames - rv->region.length()) {
+ pending_region_position = drag_info.last_frame_position;
+ }
+
+ // printf ("3: pending_region_position= %lu %lu\n", pending_region_position, drag_info.last_frame_position );
+
+ 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
+ to make it appear at the new location.
+ */
+
+ if (pending_region_position > drag_info.last_frame_position) {
+ x_delta = ((double) (pending_region_position - drag_info.last_frame_position) / frames_per_unit);
+ } else {
+ x_delta = -((double) (drag_info.last_frame_position - pending_region_position) / frames_per_unit);
+ }
+
+ drag_info.last_frame_position = pending_region_position;
+
+ } else {
+ x_delta = 0;
+ }
+
+ } else {
+ /* threshold not passed */
+
+ x_delta = 0;
+ }
+
+ /*************************************************************
+ PREPARE TO MOVE
+ ************************************************************/
+
+ if (x_delta == 0 && (pointer_y_span == 0)) {
+ /* haven't reached next snap point, and we're not switching
+ trackviews. nothing to do.
+ */
+ return;
+ }
+
+ if (x_delta < 0) {
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+
+ AudioRegionView* rv2;
+ rv2 = (*i);
+
+ /* if any regionview is at zero, we need to know so we can
+ stop further leftward motion.
+ */
+
+ double ix1, ix2, iy1, iy2;
+ gtk_canvas_item_get_bounds (rv2->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2);
+ gtk_canvas_item_i2w (rv2->get_canvas_group(), &ix1, &iy1);
+
+ if (ix1 <= 1) {
+ x_delta = 0;
+ break;
+ }
+ }
+ }
+
+ /*************************************************************
+ MOTION
+ ************************************************************/
+
+ pair<set<Playlist*>::iterator,bool> insert_result;
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+
+ AudioRegionView* rv;
+ rv = (*i);
+ double ix1, ix2, iy1, iy2;
+ int32_t temp_pointer_y_span = pointer_y_span;
+
+ /* get item BBox, which will be relative to parent. so we have
+ to query on a child, then convert to world coordinates using
+ the parent.
+ */
+
+ gtk_canvas_item_get_bounds (rv->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2);
+ gtk_canvas_item_i2w (rv->get_canvas_group(), &ix1, &iy1);
+ TimeAxisView* tvp2 = trackview_by_y_position (iy1);
+ AudioTimeAxisView* canvas_atv = dynamic_cast<AudioTimeAxisView*>(tvp2);
+ AudioTimeAxisView* temp_atv;
+
+ if ((pointer_y_span != 0) && !clamp_y_axis) {
+ y_delta = 0;
+ int32_t x = 0;
+ for (j = height_list.begin(); j!= height_list.end(); j++) {
+ if (x == canvas_atv->order) {
+ /* we found the track the region is on */
+ if (x != original_pointer_order) {
+ /*this isn't from the same track we're dragging from */
+ temp_pointer_y_span = canvas_pointer_y_span;
+ }
+ while (temp_pointer_y_span > 0) {
+ /* we're moving up canvas-wise,
+ so we need to find the next track height
+ */
+ if (j != height_list.begin()) {
+ j--;
+ }
+ if (x != original_pointer_order) {
+ /* we're not from the dragged track, so ignore hidden tracks. */
+ if ((*j) == 0) {
+ temp_pointer_y_span++;
+ }
+ }
+ y_delta -= (*j);
+ temp_pointer_y_span--;
+ }
+ while (temp_pointer_y_span < 0) {
+ y_delta += (*j);
+ if (x != original_pointer_order) {
+ if ((*j) == 0) {
+ temp_pointer_y_span--;
+ }
+ }
+
+ if (j != height_list.end()) {
+ j++;
+ }
+ temp_pointer_y_span++;
+ }
+ /* find out where we'll be when we move and set height accordingly */
+
+ tvp2 = trackview_by_y_position (iy1 + y_delta);
+ temp_atv = dynamic_cast<AudioTimeAxisView*>(tvp2);
+ rv->set_height (temp_atv->height);
+
+ /* if you un-comment the following, the region colours will follow the track colours whilst dragging,
+ personally, i think this can confuse things, but never mind.
+ */
+
+ //const GdkColor& col (temp_atv->view->get_region_color());
+ //rv->set_color (const_cast<GdkColor&>(col));
+ break;
+ }
+ x++;
+ }
+ }
+
+ /* prevent the regionview from being moved to before
+ the zero position on the canvas.
+ */
+ /* clamp */
+
+ if (x_delta < 0) {
+ if (-x_delta > ix1) {
+ x_delta = -ix1;
+ }
+ } else if ((x_delta > 0) &&(rv->region.last_frame() > max_frames - x_delta)) {
+ x_delta = max_frames - rv->region.last_frame();
+ }
+
+ if (drag_info.first_move) {
+
+ /* hide any dependent views */
+
+// rv->get_time_axis_view().hide_dependent_views (*rv);
+
+ /* this is subtle. raising the regionview itself won't help,
+ because raise_to_top() just puts the item on the top of
+ its parent's stack. so, we need to put the trackview canvas_display group
+ on the top, since its parent is the whole canvas.
+ */
+
+ gtk_canvas_item_raise_to_top (rv->get_canvas_group());
+ gtk_canvas_item_raise_to_top (rv->get_time_axis_view().canvas_display);
+ gtk_canvas_item_raise_to_top (cursor_group);
+
+ /* freeze the playlists from notifying till
+ the motion is done.
+ */
+
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&rv->get_time_axis_view());
+ if (atv && atv->is_audio_track()) {
+ AudioPlaylist* pl = atv->get_diskstream()->playlist();
+ if (pl) {
+ /* only freeze and capture state once */
+
+ insert_result = motion_frozen_playlists.insert (pl);
+ if (insert_result.second) {
+ pl->freeze();
+ session->add_undo(pl->get_memento());
+ }
+ }
+ }
+ }
+
+ if (drag_info.brushing) {
+ mouse_brush_insert_region (rv, pending_region_position);
+ } else {
+ rv->move (x_delta, y_delta);
+ }
+ }
+
+ if (drag_info.first_move) {
+ gtk_canvas_item_raise_to_top (cursor_group);
+ }
+
+ drag_info.first_move = false;
+
+ if (x_delta != 0 && !drag_info.brushing) {
+ show_verbose_time_cursor (drag_info.last_frame_position, 10);
+ }
+
+}
+
+void
+Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ jack_nframes_t where;
+ AudioRegionView* rv = reinterpret_cast<AudioRegionView *> (drag_info.data);
+ pair<set<Playlist*>::iterator,bool> insert_result;
+ bool nocommit = true;
+ double speed;
+ AudioTimeAxisView* atv;
+ bool regionview_y_movement;
+ bool regionview_x_movement;
+
+ /* first_move is set to false if the regionview has been moved in the
+ motion handler.
+ */
+
+ if (drag_info.first_move) {
+ /* just a click */
+ goto out;
+ }
+
+ nocommit = false;
+
+ /* The regionview has been moved at some stage during the grab so we need
+ to account for any mouse movement between this event and the last one.
+ */
+
+ region_drag_motion_callback (item, event);
+
+ if (drag_info.brushing) {
+ /* all changes were made during motion event handlers */
+ goto out;
+ }
+
+ /* adjust for track speed */
+ speed = 1.0;
+
+ atv = dynamic_cast<AudioTimeAxisView*> (drag_info.last_trackview);
+ if (atv && atv->get_diskstream()) {
+ speed = atv->get_diskstream()->speed();
+ }
+
+ regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region.position()/speed));
+ regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view());
+
+ //printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed);
+ //printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str());
+
+ if (regionview_y_movement) {
+
+ /* motion between tracks */
+
+ list<AudioRegionView*> new_selection;
+
+ /* moved to a different audio track. */
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ) {
+
+ AudioRegionView* rv2 = (*i);
+
+ /* the region that used to be in the old playlist is not
+ moved to the new one - we make a copy of it. as a result,
+ any existing editor for the region should no longer be
+ visible.
+ */
+
+ if (!drag_info.copy) {
+ rv2->hide_region_editor();
+ }
+ new_selection.push_back (rv2);
+ i++;
+ }
+
+ /* first, freeze the target tracks */
+
+ for (list<AudioRegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
+
+ Playlist* from_playlist;
+ Playlist* to_playlist;
+
+ double ix1, ix2, iy1, iy2;
+
+ gtk_canvas_item_get_bounds ((*i)->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2);
+ gtk_canvas_item_i2w ((*i)->get_canvas_group(), &ix1, &iy1);
+ TimeAxisView* tvp2 = trackview_by_y_position (iy1);
+ AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
+
+ from_playlist = (*i)->region.playlist();
+ to_playlist = atv2->playlist();
+
+ /* the from_playlist was frozen in the "first_move" case
+ of the motion handler. the insert can fail,
+ but that doesn't matter. it just means
+ we already have the playlist in the list.
+ */
+
+ motion_frozen_playlists.insert (from_playlist);
+
+ /* only freeze the to_playlist once */
+
+ insert_result = motion_frozen_playlists.insert(to_playlist);
+ if (insert_result.second) {
+ to_playlist->freeze();
+ session->add_undo(to_playlist->get_memento());
+ }
+
+ }
+
+ /* now do it again with the actual operations */
+
+ for (list<AudioRegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
+
+ Playlist* from_playlist;
+ Playlist* to_playlist;
+
+ double ix1, ix2, iy1, iy2;
+
+ gtk_canvas_item_get_bounds ((*i)->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2);
+ gtk_canvas_item_i2w ((*i)->get_canvas_group(), &ix1, &iy1);
+ TimeAxisView* tvp2 = trackview_by_y_position (iy1);
+ AudioTimeAxisView* atv2 = dynamic_cast<AudioTimeAxisView*>(tvp2);
+
+ from_playlist = (*i)->region.playlist();
+ to_playlist = atv2->playlist();
+
+ latest_regionview = 0;
+
+ where = (jack_nframes_t) (unit_to_frame (ix1) * speed);
+ Region* new_region = createRegion ((*i)->region);
+
+ from_playlist->remove_region (&((*i)->region));
+
+ SigC::Connection c = atv2->view->AudioRegionViewAdded.connect (slot (*this, &Editor::collect_new_region_view));
+ to_playlist->add_region (*new_region, where);
+ c.disconnect ();
+
+ if (latest_regionview) {
+ selection->add (latest_regionview);
+ }
+ }
+
+ } else {
+
+ /* motion within a single track */
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+
+ rv = (*i);
+
+ if (rv->region.locked()) {
+ continue;
+ }
+
+ if (regionview_x_movement) {
+ double ownspeed = 1.0;
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&(rv->get_time_axis_view()));
+
+ if (atv && atv->get_diskstream()) {
+ ownspeed = atv->get_diskstream()->speed();
+ }
+
+ /* base the new region position on the current position of the regionview.*/
+
+ double ix1, ix2, iy1, iy2;
+
+ gtk_canvas_item_get_bounds (rv->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2);
+ gtk_canvas_item_i2w (rv->get_canvas_group(), &ix1, &iy1);
+ where = (jack_nframes_t) (unit_to_frame (ix1) * ownspeed);
+
+ } else {
+
+ where = rv->region.position();
+ }
+
+ rv->get_time_axis_view().reveal_dependent_views (*rv);
+
+ session->add_undo (rv->region.playlist()->get_memento());
+ rv->region.set_position (where, (void *) this);
+ }
+ }
+
+ out:
+ for (set<Playlist*>::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
+ (*p)->thaw ();
+ session->add_redo_no_execute ((*p)->get_memento());
+ }
+
+ motion_frozen_playlists.clear ();
+
+ if (!nocommit) {
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
+{
+ /* Either add to or set the set the region selection, unless
+ this is an alignment click (control used)
+ */
+
+ if (Keyboard::modifier_state_contains (event->state, Keyboard::Control)) {
+ TimeAxisView* tv = &rv.get_time_axis_view();
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(tv);
+ double speed = 1.0;
+ if (atv && atv->is_audio_track()) {
+ speed = atv->get_diskstream()->speed();
+ }
+
+ if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
+
+ align_region (rv.region, SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed));
+
+ } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+
+ align_region (rv.region, End, (jack_nframes_t) (edit_cursor->current_frame * speed));
+
+ } else {
+
+ align_region (rv.region, Start, (jack_nframes_t) (edit_cursor->current_frame * speed));
+ }
+ }
+}
+
+void
+Editor::show_verbose_time_cursor (jack_nframes_t frame, double offset, double xpos, double ypos)
+{
+ char buf[128];
+ SMPTE_Time smpte;
+ BBT_Time bbt;
+ float secs;
+
+ if (session == 0) {
+ return;
+ }
+
+ switch (ARDOUR_UI::instance()->secondary_clock.mode ()) {
+ case AudioClock::BBT:
+ session->bbt_time (frame, bbt);
+ snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, bbt.bars, bbt.beats, bbt.ticks);
+ break;
+
+ case AudioClock::SMPTE:
+ session->smpte_time (frame, smpte);
+ snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ break;
+
+ case AudioClock::MinSec:
+ /* XXX fix this to compute min/sec properly */
+ session->smpte_time (frame, smpte);
+ secs = smpte.seconds + ((float) smpte.frames / session->smpte_frames_per_second);
+ snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", smpte.hours, smpte.minutes, secs);
+ break;
+
+ default:
+ snprintf (buf, sizeof(buf), "%u", frame);
+ break;
+ }
+
+ if (xpos >= 0 && ypos >=0) {
+ set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset);
+ }
+ else {
+ set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset, drag_info.current_pointer_y + offset);
+ }
+ show_verbose_canvas_cursor ();
+}
+
+void
+Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, double offset, double xpos, double ypos)
+{
+ char buf[128];
+ SMPTE_Time smpte;
+ BBT_Time sbbt;
+ BBT_Time ebbt;
+ float secs;
+ Meter meter_at_start(session->tempo_map().meter_at(start));
+
+ if (session == 0) {
+ return;
+ }
+
+ switch (ARDOUR_UI::instance()->secondary_clock.mode ()) {
+ case AudioClock::BBT:
+ session->bbt_time (start, sbbt);
+ session->bbt_time (end, ebbt);
+
+ /* subtract */
+ /* XXX this computation won't work well if the
+ user makes a selection that spans any meter changes.
+ */
+
+ ebbt.bars -= sbbt.bars;
+ if (ebbt.beats >= sbbt.beats) {
+ ebbt.beats -= sbbt.beats;
+ } else {
+ ebbt.bars--;
+ ebbt.beats = int(meter_at_start.beats_per_bar()) + ebbt.beats - sbbt.beats;
+ }
+ if (ebbt.ticks >= sbbt.ticks) {
+ ebbt.ticks -= sbbt.ticks;
+ } else {
+ ebbt.beats--;
+ ebbt.ticks = int(Meter::ticks_per_beat) + ebbt.ticks - sbbt.ticks;
+ }
+
+ snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, ebbt.bars, ebbt.beats, ebbt.ticks);
+ break;
+
+ case AudioClock::SMPTE:
+ session->smpte_duration (end - start, smpte);
+ snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ break;
+
+ case AudioClock::MinSec:
+ /* XXX fix this to compute min/sec properly */
+ session->smpte_duration (end - start, smpte);
+ secs = smpte.seconds + ((float) smpte.frames / session->smpte_frames_per_second);
+ snprintf (buf, sizeof (buf), "%02ld:%02ld:%.4f", smpte.hours, smpte.minutes, secs);
+ break;
+
+ default:
+ snprintf (buf, sizeof(buf), "%u", end - start);
+ break;
+ }
+
+ if (xpos >= 0 && ypos >=0) {
+ set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset);
+ }
+ else {
+ set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset, drag_info.current_pointer_y + offset);
+ }
+ show_verbose_canvas_cursor ();
+}
+
+void
+Editor::collect_new_region_view (AudioRegionView* rv)
+{
+ latest_regionview = rv;
+}
+
+void
+Editor::start_selection_grab (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (clicked_regionview == 0) {
+ return;
+ }
+
+ /* lets try to create new Region for the selection */
+
+ vector<AudioRegion*> new_regions;
+ create_region_from_selection (new_regions);
+
+ if (new_regions.empty()) {
+ return;
+ }
+
+ /* XXX fix me one day to use all new regions */
+
+ Region* region = new_regions.front();
+
+ /* add it to the current stream/playlist.
+
+ tricky: the streamview for the track will add a new regionview. we will
+ catch the signal it sends when it creates the regionview to
+ set the regionview we want to then drag.
+ */
+
+ latest_regionview = 0;
+ SigC::Connection c = clicked_audio_trackview->view->AudioRegionViewAdded.connect (slot (*this, &Editor::collect_new_region_view));
+
+ /* A selection grab currently creates two undo/redo operations, one for
+ creating the new region and another for moving it.
+ */
+
+ begin_reversible_command (_("selection grab"));
+
+ Playlist* playlist = clicked_trackview->playlist();
+
+ session->add_undo (playlist->get_memento ());
+ clicked_trackview->playlist()->add_region (*region, selection->time[clicked_selection].start);
+ session->add_redo_no_execute (playlist->get_memento ());
+
+ commit_reversible_command ();
+
+ c.disconnect ();
+
+ if (latest_regionview == 0) {
+ /* 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);
+
+ drag_info.item = latest_regionview->get_canvas_group();
+ drag_info.data = latest_regionview;
+ 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_trackview;
+ drag_info.last_frame_position = latest_regionview->region.position();
+ drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position;
+
+ show_verbose_time_cursor (drag_info.last_frame_position, 10);
+}
+
+void
+Editor::cancel_selection ()
+{
+ for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ (*i)->hide_selection ();
+ }
+ selection->clear ();
+ clicked_selection = 0;
+}
+
+void
+Editor::start_selection_op (GtkCanvasItem* item, GdkEvent* event, SelectionOp op)
+{
+ jack_nframes_t start = 0;
+ jack_nframes_t end = 0;
+
+ if (session == 0) {
+ return;
+ }
+
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::drag_selection;
+ drag_info.finished_callback = &Editor::end_selection_op;
+
+ selection_op = op;
+
+ switch (op) {
+ case CreateSelection:
+
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
+ drag_info.copy = true;
+ } else {
+ drag_info.copy = false;
+ }
+ start_grab (event, selector_cursor);
+ break;
+
+ case SelectionStartTrim:
+ clicked_trackview->order_selection_trims (item, true);
+ start_grab (event, trimmer_cursor);
+ start = selection->time[clicked_selection].start;
+ drag_info.pointer_frame_offset = drag_info.grab_frame - start;
+ break;
+
+ case SelectionEndTrim:
+ clicked_trackview->order_selection_trims (item, false);
+ start_grab (event, trimmer_cursor);
+ end = selection->time[clicked_selection].end;
+ drag_info.pointer_frame_offset = drag_info.grab_frame - end;
+ break;
+
+ case SelectionMove:
+ start = selection->time[clicked_selection].start;
+ start_grab (event);
+ drag_info.pointer_frame_offset = drag_info.grab_frame - start;
+ break;
+ }
+
+ if (selection_op == SelectionMove) {
+ show_verbose_time_cursor(start, 10);
+ } else {
+ show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
+ }
+}
+
+void
+Editor::drag_selection (GtkCanvasItem* item, GdkEvent* event)
+{
+ jack_nframes_t start = 0;
+ jack_nframes_t end = 0;
+ jack_nframes_t length;
+ jack_nframes_t pending_position;
+
+ if ((int32_t) drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
+ pending_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
+ }
+ else {
+ pending_position = 0;
+ }
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (pending_position);
+ }
+
+ /* only alter selection if the current frame is
+ different from the last frame position (adjusted)
+ */
+
+ if (pending_position == drag_info.last_pointer_frame) return;
+
+ switch (selection_op) {
+ case CreateSelection:
+
+ if (drag_info.first_move) {
+ snap_to (drag_info.grab_frame);
+ }
+
+ if (pending_position < drag_info.grab_frame) {
+ start = pending_position;
+ end = drag_info.grab_frame;
+ } else {
+ end = pending_position;
+ start = drag_info.grab_frame;
+ }
+
+ /* first drag: Either add to the selection
+ or create a new selection->
+ */
+
+ if (drag_info.first_move) {
+
+ begin_reversible_command (_("range selection"));
+
+ if (drag_info.copy) {
+ /* adding to the selection */
+ clicked_selection = selection->add (start, end);
+ drag_info.copy = false;
+ } else {
+ /* new selection-> */
+ clicked_selection = selection->set (clicked_trackview, start, end);
+ }
+ }
+ break;
+
+ case SelectionStartTrim:
+
+ if (drag_info.first_move) {
+ begin_reversible_command (_("trim selection start"));
+ }
+
+ start = selection->time[clicked_selection].start;
+ end = selection->time[clicked_selection].end;
+
+ if (pending_position > end) {
+ start = end;
+ } else {
+ start = pending_position;
+ }
+ break;
+
+ case SelectionEndTrim:
+
+ if (drag_info.first_move) {
+ begin_reversible_command (_("trim selection end"));
+ }
+
+ start = selection->time[clicked_selection].start;
+ end = selection->time[clicked_selection].end;
+
+ if (pending_position < start) {
+ end = start;
+ } else {
+ end = pending_position;
+ }
+
+ break;
+
+ case SelectionMove:
+
+ if (drag_info.first_move) {
+ begin_reversible_command (_("move selection"));
+ }
+
+ start = selection->time[clicked_selection].start;
+ end = selection->time[clicked_selection].end;
+
+ length = end - start;
+
+ start = pending_position;
+ snap_to (start);
+
+ end = start + length;
+
+ break;
+ }
+
+
+ if (event->button.x >= track_canvas_scroller.get_hadjustment()->get_value() + canvas_width) {
+ start_canvas_autoscroll (1);
+ }
+
+ if (start != end) {
+ selection->replace (clicked_selection, start, end);
+ }
+
+ drag_info.last_pointer_frame = pending_position;
+ drag_info.first_move = false;
+
+ if (selection_op == SelectionMove) {
+ show_verbose_time_cursor(start, 10);
+ } else {
+ show_verbose_time_cursor(pending_position, 10);
+ }
+}
+
+void
+Editor::end_selection_op (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (!drag_info.first_move) {
+ drag_selection (item, event);
+ /* XXX this is not object-oriented programming at all. ick */
+ if (selection->time.consolidate()) {
+ selection->TimeChanged ();
+ }
+ commit_reversible_command ();
+ } else {
+ /* just a click, no pointer movement.*/
+
+ if (Keyboard::no_modifier_keys_pressed (&event->button)) {
+
+ selection->clear_time();
+
+ }
+ }
+
+ /* XXX what happens if its a music selection? */
+ session->set_audio_range (selection->time);
+ stop_canvas_autoscroll ();
+}
+
+void
+Editor::start_trim (GtkCanvasItem* item, GdkEvent* event)
+{
+ double speed = 1.0;
+ TimeAxisView* tvp = clicked_trackview;
+ AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+
+ if (tv && tv->is_audio_track()) {
+ speed = tv->get_diskstream()->speed();
+ }
+
+ jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region.position() / speed);
+ jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region.last_frame() / speed);
+ jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region.length() / speed);
+
+ //drag_info.item = clicked_regionview->get_name_highlight();
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::trim_motion_callback;
+ drag_info.finished_callback = &Editor::trim_finished_callback;
+
+ start_grab (event, trimmer_cursor);
+
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+ trim_op = ContentsTrim;
+ } else {
+ /* These will get overridden for a point trim.*/
+ if (drag_info.current_pointer_frame < (region_start + region_length/2)) {
+ /* closer to start */
+ trim_op = StartTrim;
+ } else if (drag_info.current_pointer_frame > (region_end - region_length/2)) {
+ /* closer to end */
+ trim_op = EndTrim;
+ }
+ }
+
+ switch (trim_op) {
+ case StartTrim:
+ show_verbose_time_cursor(region_start, 10);
+ break;
+ case EndTrim:
+ show_verbose_time_cursor(region_end, 10);
+ break;
+ case ContentsTrim:
+ show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
+ break;
+ }
+
+ flush_track_canvas ();
+}
+
+void
+Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ AudioRegionView* rv = clicked_regionview;
+ jack_nframes_t frame_delta = 0;
+ bool left_direction;
+ bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier());
+
+ /* snap modifier works differently here..
+ its' current state has to be passed to the
+ various trim functions in order to work properly
+ */
+
+ double speed = 1.0;
+ TimeAxisView* tvp = clicked_trackview;
+ AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+
+ if (tv && tv->is_audio_track()) {
+ speed = tv->get_diskstream()->speed();
+ }
+
+ if (drag_info.last_pointer_frame > drag_info.current_pointer_frame) {
+ left_direction = true;
+ } else {
+ left_direction = false;
+ }
+
+ if (obey_snap) {
+ snap_to (drag_info.current_pointer_frame);
+ }
+
+ if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) {
+ return;
+ }
+
+ if (drag_info.first_move) {
+
+ string trim_type;
+
+ switch (trim_op) {
+ case StartTrim:
+ trim_type = "Region start trim";
+ break;
+ case EndTrim:
+ trim_type = "Region end trim";
+ break;
+ case ContentsTrim:
+ trim_type = "Region content trim";
+ break;
+ }
+
+ begin_reversible_command (trim_type);
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+ (*i)->region.freeze ();
+ (*i)->temporarily_hide_envelope ();
+ session->add_undo ((*i)->region.playlist()->get_memento());
+ }
+ }
+
+ if (left_direction) {
+ frame_delta = (drag_info.last_pointer_frame - drag_info.current_pointer_frame);
+ } else {
+ frame_delta = (drag_info.current_pointer_frame - drag_info.last_pointer_frame);
+ }
+
+ switch (trim_op) {
+ case StartTrim:
+ if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region.first_frame()/speed)) {
+ break;
+ } else {
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+ single_start_trim (**i, frame_delta, left_direction, obey_snap);
+ }
+ break;
+ }
+
+ case EndTrim:
+ if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region.last_frame()/speed))) {
+ break;
+ } else {
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) {
+ single_end_trim (**i, frame_delta, left_direction, obey_snap);
+ }
+ break;
+ }
+
+ case ContentsTrim:
+ {
+ bool swap_direction = false;
+
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) {
+ swap_direction = true;
+ }
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
+ i != selection->audio_regions.by_layer().end(); ++i)
+ {
+ single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap);
+ }
+ }
+ break;
+ }
+
+ switch (trim_op) {
+ case StartTrim:
+ show_verbose_time_cursor((jack_nframes_t) (rv->region.position()/speed), 10);
+ break;
+ case EndTrim:
+ show_verbose_time_cursor((jack_nframes_t) (rv->region.last_frame()/speed), 10);
+ break;
+ case ContentsTrim:
+ show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
+ break;
+ }
+
+ drag_info.last_pointer_frame = drag_info.current_pointer_frame;
+ drag_info.first_move = false;
+}
+
+void
+Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap)
+{
+ Region& region (rv.region);
+
+ if (region.locked()) {
+ return;
+ }
+
+ jack_nframes_t new_bound;
+
+ double speed = 1.0;
+ TimeAxisView* tvp = clicked_trackview;
+ AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+
+ if (tv && tv->is_audio_track()) {
+ speed = tv->get_diskstream()->speed();
+ }
+
+ if (left_direction) {
+ if (swap_direction) {
+ new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta;
+ } else {
+ new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta;
+ }
+ } else {
+ if (swap_direction) {
+ new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta;
+ } else {
+ new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta;
+ }
+ }
+
+ if (obey_snap) {
+ snap_to (new_bound);
+ }
+ region.trim_start ((jack_nframes_t) (new_bound * speed), this);
+ rv.region_changed (StartChanged);
+}
+
+void
+Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
+{
+ Region& region (rv.region);
+
+ if (region.locked()) {
+ return;
+ }
+
+ jack_nframes_t new_bound;
+
+ double speed = 1.0;
+ TimeAxisView* tvp = clicked_trackview;
+ AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+
+ if (tv && tv->is_audio_track()) {
+ speed = tv->get_diskstream()->speed();
+ }
+
+ if (left_direction) {
+ new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta;
+ } else {
+ new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta;
+ }
+
+ if (obey_snap) {
+ snap_to (new_bound, (left_direction ? 0 : 1));
+ }
+
+ region.trim_front ((jack_nframes_t) (new_bound * speed), this);
+
+ rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged));
+}
+
+void
+Editor::single_end_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap)
+{
+ Region& region (rv.region);
+
+ if (region.locked()) {
+ return;
+ }
+
+ jack_nframes_t new_bound;
+
+ double speed = 1.0;
+ TimeAxisView* tvp = clicked_trackview;
+ AudioTimeAxisView* tv = dynamic_cast<AudioTimeAxisView*>(tvp);
+
+ if (tv && tv->is_audio_track()) {
+ speed = tv->get_diskstream()->speed();
+ }
+
+ if (left_direction) {
+ new_bound = (jack_nframes_t) ((region.last_frame() + 1)/speed) - frame_delta;
+ } else {
+ new_bound = (jack_nframes_t) ((region.last_frame() + 1)/speed) + frame_delta;
+ }
+
+ if (obey_snap) {
+ snap_to (new_bound);
+ }
+ region.trim_end ((jack_nframes_t) (new_bound * speed), this);
+ rv.region_changed (LengthChanged);
+}
+
+void
+Editor::trim_finished_callback (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (!drag_info.first_move) {
+ trim_motion_callback (item, event);
+
+ if (!clicked_regionview->get_selected()) {
+ thaw_region_after_trim (*clicked_regionview);
+ } else {
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
+ i != selection->audio_regions.by_layer().end(); ++i)
+ {
+ thaw_region_after_trim (**i);
+ }
+ }
+ commit_reversible_command();
+ } else {
+ /* no mouse movement */
+ point_trim (event);
+ }
+
+ flush_track_canvas ();
+}
+
+void
+Editor::point_trim (GdkEvent* event)
+{
+ AudioRegionView* rv = clicked_regionview;
+ jack_nframes_t new_bound = drag_info.current_pointer_frame;
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (new_bound);
+ }
+
+ /* Choose action dependant on which button was pressed */
+ switch (event->button.button) {
+ case 1:
+ trim_op = StartTrim;
+ begin_reversible_command (_("Start point trim"));
+
+ if (rv->get_selected()) {
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin();
+ i != selection->audio_regions.by_layer().end(); ++i)
+ {
+ if (!(*i)->region.locked()) {
+ session->add_undo ((*i)->region.playlist()->get_memento());
+ (*i)->region.trim_front (new_bound, this);
+ session->add_redo_no_execute ((*i)->region.playlist()->get_memento());
+ }
+ }
+
+ } else {
+
+ if (!rv->region.locked()) {
+ session->add_undo (rv->region.playlist()->get_memento());
+ rv->region.trim_front (new_bound, this);
+ session->add_redo_no_execute (rv->region.playlist()->get_memento());
+ }
+ }
+
+ commit_reversible_command();
+
+ break;
+ case 2:
+ trim_op = EndTrim;
+ begin_reversible_command (_("End point trim"));
+
+ if (rv->get_selected()) {
+
+ for (list<AudioRegionView*>::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i)
+ {
+ if (!(*i)->region.locked()) {
+ session->add_undo ((*i)->region.playlist()->get_memento());
+ (*i)->region.trim_end (new_bound, this);
+ session->add_redo_no_execute ((*i)->region.playlist()->get_memento());
+ }
+ }
+
+ } else {
+
+ if (!rv->region.locked()) {
+ session->add_undo (rv->region.playlist()->get_memento());
+ rv->region.trim_end (new_bound, this);
+ session->add_redo_no_execute (rv->region.playlist()->get_memento());
+ }
+ }
+
+ commit_reversible_command();
+
+ break;
+ default:
+ break;
+ }
+}
+
+void
+Editor::thaw_region_after_trim (AudioRegionView& rv)
+{
+ Region& region (rv.region);
+
+ if (region.locked()) {
+ return;
+ }
+
+ region.thaw (_("trimmed region"));
+ session->add_redo_no_execute (region.playlist()->get_memento());
+
+ rv.unhide_envelope ();
+}
+
+void
+Editor::hide_marker (GtkCanvasItem* item, GdkEvent* event)
+{
+ Marker* marker;
+ bool is_start;
+
+ if ((marker = static_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* location = find_location_from_marker (marker, is_start);
+ location->set_hidden (true, this);
+}
+
+
+void
+Editor::start_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event, RangeMarkerOp op)
+{
+
+ if (session == 0) {
+ return;
+ }
+
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::drag_range_markerbar_op;
+ drag_info.finished_callback = &Editor::end_range_markerbar_op;
+
+ range_marker_op = op;
+
+ if (!temp_location) {
+ temp_location = new Location;
+ }
+
+ switch (op) {
+ case CreateRangeMarker:
+ case CreateTransportMarker:
+
+ if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) {
+ drag_info.copy = true;
+ } else {
+ drag_info.copy = false;
+ }
+ start_grab (event, selector_cursor);
+ break;
+ }
+
+ show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
+
+}
+
+void
+Editor::drag_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event)
+{
+ jack_nframes_t start = 0;
+ jack_nframes_t end = 0;
+
+ GtkCanvasItem * crect = (range_marker_op == CreateRangeMarker) ? range_bar_drag_rect: transport_bar_drag_rect;
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (drag_info.current_pointer_frame);
+ }
+
+ /* only alter selection if the current frame is
+ different from the last frame position.
+ */
+
+ if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return;
+
+ switch (range_marker_op) {
+ case CreateRangeMarker:
+ case CreateTransportMarker:
+ if (drag_info.first_move) {
+ snap_to (drag_info.grab_frame);
+ }
+
+ if (drag_info.current_pointer_frame < drag_info.grab_frame) {
+ start = drag_info.current_pointer_frame;
+ end = drag_info.grab_frame;
+ } else {
+ end = drag_info.current_pointer_frame;
+ start = drag_info.grab_frame;
+ }
+
+ /* first drag: Either add to the selection
+ or create a new selection->
+ */
+
+ if (drag_info.first_move) {
+
+ temp_location->set (start, end);
+
+ gtk_canvas_item_show (crect);
+
+ update_marker_drag_item (temp_location);
+ gtk_canvas_item_show (range_marker_drag_rect);
+ gtk_canvas_item_raise_to_top (range_marker_drag_rect);
+
+ }
+ break;
+ }
+
+
+ if (event->button.x >= track_canvas_scroller.get_hadjustment()->get_value() + canvas_width) {
+ start_canvas_autoscroll (1);
+ }
+
+ if (start != end) {
+ temp_location->set (start, end);
+
+ double x1 = frame_to_pixel (start);
+ double x2 = frame_to_pixel (end);
+ gtk_canvas_item_set (crect, "x1", x1, "x2", x2, NULL);
+
+ update_marker_drag_item (temp_location);
+ }
+
+ drag_info.last_pointer_frame = drag_info.current_pointer_frame;
+ drag_info.first_move = false;
+
+ show_verbose_time_cursor(drag_info.current_pointer_frame, 10);
+
+}
+
+void
+Editor::end_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event)
+{
+ Location * newloc = 0;
+
+ if (!drag_info.first_move) {
+ drag_range_markerbar_op (item, event);
+
+ switch (range_marker_op)
+ {
+ case CreateRangeMarker:
+ begin_reversible_command (_("new range marker"));
+ session->add_undo (session->locations()->get_memento());
+ newloc = new Location(temp_location->start(), temp_location->end(), "unnamed");
+ session->locations()->add (newloc, true);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ commit_reversible_command ();
+
+ gtk_canvas_item_hide (range_bar_drag_rect);
+ gtk_canvas_item_hide (range_marker_drag_rect);
+ break;
+
+ case CreateTransportMarker:
+ // popup menu to pick loop or punch
+ new_transport_marker_context_menu (&event->button, item);
+
+ break;
+ }
+ } else {
+ /* just a click, no pointer movement.*/
+
+ if (Keyboard::no_modifier_keys_pressed (&event->button)) {
+
+ // nothing yet
+
+ }
+ }
+
+ stop_canvas_autoscroll ();
+}
+
+
+
+void
+Editor::start_mouse_zoom (GtkCanvasItem* item, GdkEvent* event)
+{
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::drag_mouse_zoom;
+ drag_info.finished_callback = &Editor::end_mouse_zoom;
+
+ start_grab (event, zoom_cursor);
+
+ show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
+}
+
+void
+Editor::drag_mouse_zoom (GtkCanvasItem* item, GdkEvent* event)
+{
+ jack_nframes_t start;
+ jack_nframes_t end;
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (drag_info.current_pointer_frame);
+
+ if (drag_info.first_move) {
+ snap_to (drag_info.grab_frame);
+ }
+ }
+
+ if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return;
+
+ /* base start and end on initial click position */
+ if (drag_info.current_pointer_frame < drag_info.grab_frame) {
+ start = drag_info.current_pointer_frame;
+ end = drag_info.grab_frame;
+ } else {
+ end = drag_info.current_pointer_frame;
+ start = drag_info.grab_frame;
+ }
+
+ if (start != end) {
+
+ if (drag_info.first_move) {
+ gtk_canvas_item_show (zoom_rect);
+ gtk_canvas_item_raise_to_top (zoom_rect);
+ }
+
+ reposition_zoom_rect(start, end);
+
+ drag_info.last_pointer_frame = drag_info.current_pointer_frame;
+ drag_info.first_move = false;
+
+ show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
+ }
+}
+
+void
+Editor::end_mouse_zoom (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (!drag_info.first_move) {
+ drag_mouse_zoom (item, event);
+
+ if (drag_info.grab_frame < drag_info.last_pointer_frame) {
+ temporal_zoom_by_frame (drag_info.grab_frame, drag_info.last_pointer_frame, "mouse zoom");
+ } else {
+ temporal_zoom_by_frame (drag_info.last_pointer_frame, drag_info.grab_frame, "mouse zoom");
+ }
+ } else {
+ temporal_zoom_to_frame (false, drag_info.grab_frame);
+ /*
+ temporal_zoom_step (false);
+ center_screen (drag_info.grab_frame);
+ */
+ }
+
+ gtk_canvas_item_hide (zoom_rect);
+}
+
+void
+Editor::reposition_zoom_rect (jack_nframes_t start, jack_nframes_t end)
+{
+ double x1 = frame_to_pixel (start);
+ double x2 = frame_to_pixel (end);
+ double y2 = canvas_height - 2;
+
+ gtk_object_set (GTK_OBJECT(zoom_rect),
+ "x1", x1,
+ "y1", 1.0,
+ "x2", x2,
+ "y2", y2,
+ NULL);
+}
+
+void
+Editor::start_rubberband_select (GtkCanvasItem* item, GdkEvent* event)
+{
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::drag_rubberband_select;
+ drag_info.finished_callback = &Editor::end_rubberband_select;
+
+ start_grab (event, cross_hair_cursor);
+
+ show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
+}
+
+void
+Editor::drag_rubberband_select (GtkCanvasItem* item, GdkEvent* event)
+{
+ jack_nframes_t start;
+ jack_nframes_t end;
+ double y1;
+ double y2;
+
+ /* use a bigger drag threshold than the default */
+
+ if (abs ((int) (drag_info.current_pointer_frame - drag_info.grab_frame)) < 8) {
+ return;
+ }
+
+// if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+// snap_to (drag_info.current_pointer_frame);
+
+// if (drag_info.first_move) {
+// snap_to (drag_info.grab_frame);
+// }
+// }
+
+
+ /* base start and end on initial click position */
+ if (drag_info.current_pointer_frame < drag_info.grab_frame) {
+ start = drag_info.current_pointer_frame;
+ end = drag_info.grab_frame;
+ } else {
+ end = drag_info.current_pointer_frame;
+ start = drag_info.grab_frame;
+ }
+
+ if (drag_info.current_pointer_y < drag_info.grab_y) {
+ y1 = drag_info.current_pointer_y;
+ y2 = drag_info.grab_y;
+ }
+ else {
+ y2 = drag_info.current_pointer_y;
+ y1 = drag_info.grab_y;
+ }
+
+
+ if (start != end || y1 != y2) {
+
+ double x1 = frame_to_pixel (start);
+ double x2 = frame_to_pixel (end);
+
+ gtk_object_set (GTK_OBJECT(rubberband_rect),
+ "x1", x1,
+ "y1", y1,
+ "x2", x2,
+ "y2", y2,
+ NULL);
+
+ gtk_canvas_item_show (rubberband_rect);
+ gtk_canvas_item_raise_to_top (rubberband_rect);
+
+ drag_info.last_pointer_frame = drag_info.current_pointer_frame;
+ drag_info.first_move = false;
+
+ show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
+ }
+}
+
+void
+Editor::end_rubberband_select (GtkCanvasItem* item, GdkEvent* event)
+{
+ if (!drag_info.first_move) {
+
+ drag_rubberband_select (item, event);
+
+ double y1,y2;
+ if (drag_info.current_pointer_y < drag_info.grab_y) {
+ y1 = drag_info.current_pointer_y;
+ y2 = drag_info.grab_y;
+ }
+ else {
+ y2 = drag_info.current_pointer_y;
+ y1 = drag_info.grab_y;
+ }
+
+
+ bool add = Keyboard::modifier_state_contains (event->button.state, Keyboard::Shift);
+ bool commit;
+
+ begin_reversible_command (_("select regions"));
+
+ if (drag_info.grab_frame < drag_info.last_pointer_frame) {
+ commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, add);
+ } else {
+ commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, add);
+ }
+
+ if (commit) {
+ commit_reversible_command ();
+ }
+
+ } else {
+ selection->clear_audio_regions();
+ selection->clear_points ();
+ selection->clear_lines ();
+ }
+
+ gtk_canvas_item_hide (rubberband_rect);
+}
+
+
+gint
+Editor::mouse_rename_region (GtkCanvasItem* item, GdkEvent* event)
+{
+ using namespace Gtkmmext;
+
+ ArdourPrompter prompter (false);
+
+ prompter.set_prompt (_("Name for region:"));
+ prompter.set_initial_text (clicked_regionview->region.name());
+ prompter.show_all ();
+ prompter.done.connect (Main::quit.slot());
+
+ Main::run ();
+
+ if (prompter.status == Prompter::cancelled) {
+ return TRUE;
+ }
+
+ string str;
+
+ prompter.get_result(str);
+ clicked_regionview->region.set_name (str);
+
+ return TRUE;
+}
+
+void
+Editor::start_time_fx (GtkCanvasItem* item, GdkEvent* event)
+{
+ drag_info.item = item;
+ drag_info.motion_callback = &Editor::time_fx_motion;
+ drag_info.finished_callback = &Editor::end_time_fx;
+
+ start_grab (event);
+
+ show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
+}
+
+void
+Editor::time_fx_motion (GtkCanvasItem *item, GdkEvent* event)
+{
+ AudioRegionView* rv = clicked_regionview;
+
+ if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+ snap_to (drag_info.current_pointer_frame);
+ }
+
+ if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) {
+ return;
+ }
+
+ if (drag_info.current_pointer_frame > rv->region.position()) {
+ rv->get_time_axis_view().show_timestretch (rv->region.position(), drag_info.current_pointer_frame);
+ }
+
+ drag_info.last_pointer_frame = drag_info.current_pointer_frame;
+ drag_info.first_move = false;
+
+ show_verbose_time_cursor (drag_info.current_pointer_frame, 10);
+}
+
+void
+Editor::end_time_fx (GtkCanvasItem* item, GdkEvent* event)
+{
+ clicked_regionview->get_time_axis_view().hide_timestretch ();
+
+ if (drag_info.first_move) {
+ return;
+ }
+
+ jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region.position();
+ float percentage = (float) ((double) newlen - (double) clicked_regionview->region.length()) / ((double) newlen) * 100.0f;
+
+ begin_reversible_command (_("timestretch"));
+
+ if (run_timestretch (selection->audio_regions, percentage) == 0) {
+ session->commit_reversible_command ();
+ }
+}
+
+void
+Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos)
+{
+ /* no brushing without a useful snap setting */
+
+ switch (snap_mode) {
+ case SnapMagnetic:
+ return; /* can't work because it allows region to be placed anywhere */
+ default:
+ break; /* OK */
+ }
+
+ switch (snap_type) {
+ case SnapToFrame:
+ case SnapToMark:
+ case SnapToEditCursor:
+ return;
+
+ default:
+ break;
+ }
+
+ /* don't brush a copy over the original */
+
+ if (pos == rv->region.position()) {
+ return;
+ }
+
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&rv->get_time_axis_view());
+
+ if (atv == 0 || !atv->is_audio_track()) {
+ return;
+ }
+
+ Playlist* playlist = atv->playlist();
+ double speed = atv->get_diskstream()->speed();
+
+ session->add_undo (playlist->get_memento());
+ playlist->add_region (*(new AudioRegion (rv->region)), (jack_nframes_t) (pos * speed));
+ session->add_redo_no_execute (playlist->get_memento());
+
+ // playlist is frozen, so we have to update manually
+
+ playlist->StateChanged (Change (~0)); /* EMIT SIGNAL */
+}
+
+gint
+Editor::track_height_step_timeout ()
+{
+ struct timeval now;
+ struct timeval delta;
+
+ gettimeofday (&now, 0);
+ timersub (&now, &last_track_height_step_timestamp, &delta);
+
+ if (delta.tv_sec * 1000000 + delta.tv_usec > 250000) { /* milliseconds */
+ current_stepping_trackview = 0;
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/gtk2_ardour/editor_nudge.cc b/gtk2_ardour/editor_nudge.cc
new file mode 100644
index 0000000000..f7203d93b8
--- /dev/null
+++ b/gtk2_ardour/editor_nudge.cc
@@ -0,0 +1,30 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+
+#include "editor.h"
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
new file mode 100644
index 0000000000..756e2ea8ba
--- /dev/null
+++ b/gtk2_ardour/editor_ops.cc
@@ -0,0 +1,3627 @@
+/*
+ Copyright (C) 2000-2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <unistd.h>
+
+#include <cstdlib>
+#include <cmath>
+#include <string>
+#include <map>
+
+#include <sndfile.h>
+
+#include <pbd/error.h>
+#include <pbd/basename.h>
+#include <pbd/pthread_utils.h>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/choice.h>
+
+#include <ardour/audioengine.h>
+#include <ardour/session.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/audioregion.h>
+#include <ardour/diskstream.h>
+#include <ardour/filesource.h>
+#include <ardour/sndfilesource.h>
+#include <ardour/utils.h>
+#include <ardour/location.h>
+#include <ardour/named_selection.h>
+#include <ardour/audio_track.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/region_factory.h>
+#include <ardour/reverse.h>
+
+#include "ardour_ui.h"
+#include "editor.h"
+#include "time_axis_view.h"
+#include "audio_time_axis.h"
+#include "automation_time_axis.h"
+#include "streamview.h"
+#include "regionview.h"
+#include "rgb_macros.h"
+#include "extra_bind.h"
+#include "selection_templates.h"
+#include "selection.h"
+#include "library_ui.h"
+#include "editing.h"
+#include "gtk-custom-hruler.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace SigC;
+using namespace Gtk;
+using namespace Editing;
+
+/***********************************************************************
+ Editor operations
+ ***********************************************************************/
+
+void
+Editor::undo (uint32_t n)
+{
+ if (session) {
+ session->undo (n);
+ }
+}
+
+void
+Editor::redo (uint32_t n)
+{
+ if (session) {
+ session->redo (n);
+ }
+}
+
+int
+Editor::ensure_cursor (jack_nframes_t *pos)
+{
+ *pos = edit_cursor->current_frame;
+ return 0;
+}
+
+void
+Editor::split_region ()
+{
+ split_region_at (edit_cursor->current_frame);
+}
+
+void
+Editor::split_region_at (jack_nframes_t where)
+{
+ split_regions_at (where, selection->audio_regions);
+}
+
+void
+Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions)
+{
+ begin_reversible_command (_("split"));
+
+ snap_to (where);
+ for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
+
+ AudioRegionSelection::iterator tmp;
+
+ tmp = a;
+ ++tmp;
+
+ Playlist* pl = (*a)->region.playlist();
+
+ _new_regionviews_show_envelope = (*a)->envelope_visible();
+
+ if (pl) {
+ session->add_undo (pl->get_memento());
+ pl->split_region ((*a)->region, where);
+ session->add_redo_no_execute (pl->get_memento());
+ }
+
+ a = tmp;
+ }
+
+ commit_reversible_command ();
+ _new_regionviews_show_envelope = false;
+}
+
+void
+Editor::remove_clicked_region ()
+{
+ if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
+ return;
+ }
+
+ Playlist* playlist = clicked_audio_trackview->playlist();
+
+ begin_reversible_command (_("remove region"));
+ session->add_undo (playlist->get_memento());
+ playlist->remove_region (&clicked_regionview->region);
+ session->add_redo_no_execute (playlist->get_memento());
+ commit_reversible_command ();
+}
+
+void
+Editor::destroy_clicked_region ()
+{
+ int32_t selected = selection->audio_regions.size();
+
+ if (!session || clicked_regionview == 0 && selected == 0) {
+ return;
+ }
+
+ vector<string> choices;
+ string prompt;
+
+ prompt = compose (_(" This is destructive, will possibly delete audio files\n\
+It cannot be undone\n\
+Do you really want to destroy %1 ?"),
+ (selected > 1 ?
+ _("these regions") : _("this region")));
+
+ if (selected > 1) {
+ choices.push_back (_("Yes, destroy them."));
+ } else {
+ choices.push_back (_("Yes, destroy it."));
+ }
+
+ choices.push_back (_("No, do nothing."));
+
+ Gtkmmext::Choice prompter (prompt, choices);
+
+ prompter.chosen.connect (Gtk::Main::quit.slot());
+ prompter.show_all ();
+
+ Gtk::Main::run ();
+
+ if (prompter.get_choice() != 0) {
+ return;
+ }
+
+ if (selected > 0) {
+ list<Region*> r;
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ r.push_back (&(*i)->region);
+ }
+
+ session->destroy_regions (r);
+
+ } else if (clicked_regionview) {
+ session->destroy_region (&clicked_regionview->region);
+ }
+}
+
+AudioRegion *
+Editor::select_region_for_operation (int dir, TimeAxisView **tv)
+{
+ AudioRegionView* rv;
+ AudioRegion *region;
+ jack_nframes_t start = 0;
+
+ if (selection->time.start () == selection->time.end_frame ()) {
+
+ /* no current selection-> is there a selected regionview? */
+
+ if (selection->audio_regions.empty()) {
+ return 0;
+ }
+
+ }
+
+ region = 0;
+
+ if (!selection->audio_regions.empty()) {
+
+ rv = *(selection->audio_regions.begin());
+ (*tv) = &rv->get_time_axis_view();
+ region = &rv->region;
+
+ } else if (!selection->tracks.empty()) {
+
+ (*tv) = selection->tracks.front();
+
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
+ Playlist *pl;
+
+ if ((pl = atv->playlist()) == 0) {
+ return 0;
+ }
+
+ region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
+ }
+ }
+
+ return region;
+}
+
+void
+Editor::extend_selection_to_end_of_region (bool next)
+{
+ TimeAxisView *tv;
+ Region *region;
+ jack_nframes_t start;
+
+ if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
+ return;
+ }
+
+ if (region && selection->time.start () == selection->time.end_frame ()) {
+ start = region->position();
+ } else {
+ start = selection->time.start ();
+ }
+
+ /* Try to leave the selection with the same route if possible */
+
+ if ((tv = selection->time.track) == 0) {
+ return;
+ }
+
+ begin_reversible_command (_("extend selection"));
+ selection->set (tv, start, region->position() + region->length());
+ commit_reversible_command ();
+}
+
+void
+Editor::extend_selection_to_start_of_region (bool previous)
+{
+ TimeAxisView *tv;
+ Region *region;
+ jack_nframes_t end;
+
+ if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
+ return;
+ }
+
+ if (region && selection->time.start () == selection->time.end_frame ()) {
+ end = region->position() + region->length();
+ } else {
+ end = selection->time.end_frame ();
+ }
+
+ /* Try to leave the selection with the same route if possible */
+
+ if ((tv = selection->time.track) == 0) {
+ return;
+ }
+
+ begin_reversible_command (_("extend selection"));
+ selection->set (tv, region->position(), end);
+ commit_reversible_command ();
+}
+
+
+void
+Editor::nudge_forward (bool next)
+{
+ jack_nframes_t distance;
+ jack_nframes_t next_distance;
+
+ if (!session) return;
+
+ if (!selection->audio_regions.empty()) {
+
+ begin_reversible_command (_("nudge forward"));
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ AudioRegion& r ((*i)->region);
+
+ distance = get_nudge_distance (r.position(), next_distance);
+
+ if (next) {
+ distance = next_distance;
+ }
+
+ session->add_undo (r.playlist()->get_memento());
+ r.set_position (r.position() + distance, this);
+ session->add_redo_no_execute (r.playlist()->get_memento());
+ }
+
+ commit_reversible_command ();
+
+ } else {
+ distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
+ session->request_locate (playhead_cursor->current_frame + distance);
+ }
+}
+
+void
+Editor::nudge_backward (bool next)
+{
+ jack_nframes_t distance;
+ jack_nframes_t next_distance;
+
+ if (!session) return;
+
+ if (!selection->audio_regions.empty()) {
+
+ begin_reversible_command (_("nudge forward"));
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ AudioRegion& r ((*i)->region);
+
+ distance = get_nudge_distance (r.position(), next_distance);
+
+ if (next) {
+ distance = next_distance;
+ }
+
+ session->add_undo (r.playlist()->get_memento());
+
+ if (r.position() > distance) {
+ r.set_position (r.position() - distance, this);
+ } else {
+ r.set_position (0, this);
+ }
+ session->add_redo_no_execute (r.playlist()->get_memento());
+ }
+
+ commit_reversible_command ();
+
+ } else {
+
+ distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
+
+ if (playhead_cursor->current_frame > distance) {
+ session->request_locate (playhead_cursor->current_frame - distance);
+ } else {
+ session->request_locate (0);
+ }
+ }
+}
+
+void
+Editor::nudge_forward_capture_offset ()
+{
+ jack_nframes_t distance;
+
+ if (!session) return;
+
+ if (!selection->audio_regions.empty()) {
+
+ begin_reversible_command (_("nudge forward"));
+
+ distance = session->worst_output_latency();
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ AudioRegion& r ((*i)->region);
+
+ session->add_undo (r.playlist()->get_memento());
+ r.set_position (r.position() + distance, this);
+ session->add_redo_no_execute (r.playlist()->get_memento());
+ }
+
+ commit_reversible_command ();
+
+ }
+}
+
+void
+Editor::nudge_backward_capture_offset ()
+{
+ jack_nframes_t distance;
+
+ if (!session) return;
+
+ if (!selection->audio_regions.empty()) {
+
+ begin_reversible_command (_("nudge forward"));
+
+ distance = session->worst_output_latency();
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ AudioRegion& r ((*i)->region);
+
+ session->add_undo (r.playlist()->get_memento());
+
+ if (r.position() > distance) {
+ r.set_position (r.position() - distance, this);
+ } else {
+ r.set_position (0, this);
+ }
+ session->add_redo_no_execute (r.playlist()->get_memento());
+ }
+
+ commit_reversible_command ();
+ }
+}
+
+/* DISPLAY MOTION */
+
+void
+Editor::move_to_start ()
+{
+ session->request_locate (0);
+}
+
+void
+Editor::move_to_end ()
+{
+
+ session->request_locate (session->current_end_frame());
+}
+
+void
+Editor::build_region_boundary_cache ()
+{
+ jack_nframes_t pos = 0;
+ RegionPoint point;
+ Region *r;
+ TrackViewList tracks;
+
+ region_boundary_cache.clear ();
+
+ if (session == 0) {
+ return;
+ }
+
+ switch (snap_type) {
+ case SnapToRegionStart:
+ point = Start;
+ break;
+ case SnapToRegionEnd:
+ point = End;
+ break;
+ case SnapToRegionSync:
+ point = SyncPoint;
+ break;
+ case SnapToRegionBoundary:
+ point = Start;
+ break;
+ default:
+ fatal << compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
+ /*NOTREACHED*/
+ return;
+ }
+
+ TimeAxisView *ontrack = 0;
+
+ while (pos < session->current_end_frame()) {
+
+ if (!selection->tracks.empty()) {
+
+ if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
+ break;
+ }
+
+ } else if (clicked_trackview) {
+
+ TrackViewList t;
+ t.push_back (clicked_trackview);
+
+ if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
+ break;
+ }
+
+ } else {
+
+ if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
+ break;
+ }
+ }
+
+ jack_nframes_t rpos;
+
+ switch (snap_type) {
+ case SnapToRegionStart:
+ rpos = r->first_frame();
+ break;
+ case SnapToRegionEnd:
+ rpos = r->last_frame();
+ break;
+ case SnapToRegionSync:
+ rpos = r->adjust_to_sync (r->first_frame());
+ break;
+
+ case SnapToRegionBoundary:
+ rpos = r->last_frame();
+ break;
+ default:
+ break;
+ }
+
+ float speed = 1.0f;
+ AudioTimeAxisView *atav;
+
+ if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
+ if (atav->get_diskstream() != 0) {
+ speed = atav->get_diskstream()->speed();
+ }
+ }
+
+ rpos = (jack_nframes_t) floor ( (float) rpos / speed );
+
+ if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
+ if (snap_type == SnapToRegionBoundary) {
+ region_boundary_cache.push_back (r->first_frame());
+ }
+ region_boundary_cache.push_back (rpos);
+ }
+
+ pos = rpos + 1;
+ }
+}
+
+Region*
+Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
+{
+ TrackViewList::iterator i;
+ jack_nframes_t closest = max_frames;
+ Region* ret = 0;
+ jack_nframes_t rpos = 0;
+
+ float track_speed;
+ jack_nframes_t track_frame;
+ AudioTimeAxisView *atav;
+
+ for (i = tracks.begin(); i != tracks.end(); ++i) {
+
+ jack_nframes_t distance;
+ Region* r;
+
+ track_speed = 1.0f;
+ if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
+ if (atav->get_diskstream()!=0)
+ track_speed = atav->get_diskstream()->speed();
+ }
+
+ track_frame = (jack_nframes_t) floor ( (float) frame * track_speed );
+
+ if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
+ continue;
+ }
+
+ switch (point) {
+ 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;
+ }
+ // rpos is a "track frame", converting it to "time frame"
+ rpos = (jack_nframes_t) floor ( (float) rpos / track_speed );
+
+ if (rpos > frame) {
+ distance = rpos - frame;
+ } else {
+ distance = frame - rpos;
+ }
+
+ if (distance < closest) {
+ closest = distance;
+ if (ontrack != 0)
+ *ontrack = (*i);
+ ret = r;
+ }
+ }
+
+ return ret;
+}
+
+void
+Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
+{
+ Region* r;
+ jack_nframes_t pos = cursor->current_frame;
+
+ if (!session) {
+ return;
+ }
+
+ TimeAxisView *ontrack = 0;
+
+ // so we don't find the current region again..
+ if (dir>0 || pos>0)
+ pos+=dir;
+
+ if (!selection->tracks.empty()) {
+
+ r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
+
+ } else if (clicked_trackview) {
+
+ TrackViewList t;
+ t.push_back (clicked_trackview);
+
+ r = find_next_region (pos, point, dir, t, &ontrack);
+
+ } else {
+
+ r = find_next_region (pos, point, dir, track_views, &ontrack);
+ }
+
+ if (r == 0) {
+ return;
+ }
+
+ switch (point){
+ case Start:
+ pos = r->first_frame ();
+ break;
+
+ case End:
+ pos = r->last_frame ();
+ break;
+
+ case SyncPoint:
+ pos = r->adjust_to_sync (r->first_frame());
+ break;
+ }
+
+ float speed = 1.0f;
+ AudioTimeAxisView *atav;
+
+ if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
+ if (atav->get_diskstream() != 0) {
+ speed = atav->get_diskstream()->speed();
+ }
+ }
+
+ pos = (jack_nframes_t) floor ( (float) pos / speed );
+
+
+ if (cursor == playhead_cursor) {
+ session->request_locate (pos);
+ } else {
+ cursor->set_position (pos);
+ }
+}
+
+void
+Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
+{
+ cursor_to_region_point (cursor, point, 1);
+}
+
+void
+Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
+{
+ cursor_to_region_point (cursor, point, -1);
+}
+
+void
+Editor::cursor_to_selection_start (Cursor *cursor)
+{
+ jack_nframes_t pos = 0;
+ switch (mouse_mode) {
+ case MouseObject:
+ if (!selection->audio_regions.empty()) {
+ pos = selection->audio_regions.start();
+ }
+ break;
+
+ case MouseRange:
+ if (!selection->time.empty()) {
+ pos = selection->time.start ();
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (cursor == playhead_cursor) {
+ session->request_locate (pos);
+ } else {
+ cursor->set_position (pos);
+ }
+}
+
+void
+Editor::cursor_to_selection_end (Cursor *cursor)
+{
+ jack_nframes_t pos = 0;
+
+ switch (mouse_mode) {
+ case MouseObject:
+ if (!selection->audio_regions.empty()) {
+ pos = selection->audio_regions.end_frame();
+ }
+ break;
+
+ case MouseRange:
+ if (!selection->time.empty()) {
+ pos = selection->time.end_frame ();
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (cursor == playhead_cursor) {
+ session->request_locate (pos);
+ } else {
+ cursor->set_position (pos);
+ }
+}
+
+void
+Editor::playhead_backward ()
+{
+ jack_nframes_t pos;
+ jack_nframes_t cnt;
+ float prefix;
+ bool was_floating;
+
+ if (get_prefix (prefix, was_floating)) {
+ cnt = 1;
+ } else {
+ if (was_floating) {
+ cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
+ } else {
+ cnt = (jack_nframes_t) prefix;
+ }
+ }
+
+ pos = playhead_cursor->current_frame;
+
+ if ((jack_nframes_t) pos < cnt) {
+ pos = 0;
+ } else {
+ pos -= cnt;
+ }
+
+ /* XXX this is completely insane. with the current buffering
+ design, we'll force a complete track buffer flush and
+ reload, just to move 1 sample !!!
+ */
+
+ session->request_locate (pos);
+}
+
+void
+Editor::playhead_forward ()
+{
+ jack_nframes_t pos;
+ jack_nframes_t cnt;
+ bool was_floating;
+ float prefix;
+
+ if (get_prefix (prefix, was_floating)) {
+ cnt = 1;
+ } else {
+ if (was_floating) {
+ cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
+ } else {
+ cnt = (jack_nframes_t) floor (prefix);
+ }
+ }
+
+ pos = playhead_cursor->current_frame;
+
+ /* XXX this is completely insane. with the current buffering
+ design, we'll force a complete track buffer flush and
+ reload, just to move 1 sample !!!
+ */
+
+ session->request_locate (pos+cnt);
+}
+
+void
+Editor::cursor_align (bool playhead_to_edit)
+{
+ if (playhead_to_edit) {
+ if (session) {
+ session->request_locate (edit_cursor->current_frame);
+ }
+ } else {
+ edit_cursor->set_position (playhead_cursor->current_frame);
+ }
+}
+
+void
+Editor::edit_cursor_backward ()
+{
+ jack_nframes_t pos;
+ jack_nframes_t cnt;
+ float prefix;
+ bool was_floating;
+
+ if (get_prefix (prefix, was_floating)) {
+ cnt = 1;
+ } else {
+ if (was_floating) {
+ cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
+ } else {
+ cnt = (jack_nframes_t) prefix;
+ }
+ }
+
+ pos = edit_cursor->current_frame;
+
+ if ((jack_nframes_t) pos < cnt) {
+ pos = 0;
+ } else {
+ pos -= cnt;
+ }
+
+ edit_cursor->set_position (pos);
+}
+
+void
+Editor::edit_cursor_forward ()
+{
+ jack_nframes_t pos;
+ jack_nframes_t cnt;
+ bool was_floating;
+ float prefix;
+
+ if (get_prefix (prefix, was_floating)) {
+ cnt = 1;
+ } else {
+ if (was_floating) {
+ cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
+ } else {
+ cnt = (jack_nframes_t) floor (prefix);
+ }
+ }
+
+ pos = edit_cursor->current_frame;
+ edit_cursor->set_position (pos+cnt);
+}
+
+void
+Editor::goto_frame ()
+{
+ float prefix;
+ bool was_floating;
+ jack_nframes_t frame;
+
+ if (get_prefix (prefix, was_floating)) {
+ return;
+ }
+
+ if (was_floating) {
+ frame = (jack_nframes_t) floor (prefix * session->frame_rate());
+ } else {
+ frame = (jack_nframes_t) floor (prefix);
+ }
+
+ session->request_locate (frame);
+}
+
+void
+Editor::scroll_backward (float pages)
+{
+ jack_nframes_t frame;
+ jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
+ bool was_floating;
+ float prefix;
+ jack_nframes_t cnt;
+
+ if (get_prefix (prefix, was_floating)) {
+ cnt = (jack_nframes_t) floor (pages * one_page);
+ } else {
+ if (was_floating) {
+ cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
+ } else {
+ cnt = (jack_nframes_t) floor (prefix * one_page);
+ }
+ }
+
+ if (leftmost_frame < cnt) {
+ frame = 0;
+ } else {
+ frame = leftmost_frame - cnt;
+ }
+
+ reposition_x_origin (frame);
+}
+
+void
+Editor::scroll_forward (float pages)
+{
+ jack_nframes_t frame;
+ jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
+ bool was_floating;
+ float prefix;
+ jack_nframes_t cnt;
+
+ if (get_prefix (prefix, was_floating)) {
+ cnt = (jack_nframes_t) floor (pages * one_page);
+ } else {
+ if (was_floating) {
+ cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
+ } else {
+ cnt = (jack_nframes_t) floor (prefix * one_page);
+ }
+ }
+
+ if (ULONG_MAX - cnt < leftmost_frame) {
+ frame = ULONG_MAX - cnt;
+ } else {
+ frame = leftmost_frame + cnt;
+ }
+
+ reposition_x_origin (frame);
+}
+
+void
+Editor::scroll_tracks_down ()
+{
+ float prefix;
+ bool was_floating;
+ int cnt;
+
+ if (get_prefix (prefix, was_floating)) {
+ cnt = 1;
+ } else {
+ cnt = (int) floor (prefix);
+ }
+
+ Gtk::Adjustment *adj = track_canvas_scroller.get_vadjustment();
+ adj->set_value (adj->get_value() + (cnt * adj->get_page_size()));
+}
+
+void
+Editor::scroll_tracks_up ()
+{
+ float prefix;
+ bool was_floating;
+ int cnt;
+
+ if (get_prefix (prefix, was_floating)) {
+ cnt = 1;
+ } else {
+ cnt = (int) floor (prefix);
+ }
+
+ Gtk::Adjustment *adj = track_canvas_scroller.get_vadjustment();
+ adj->set_value (adj->get_value() - (cnt * adj->get_page_size()));
+}
+
+void
+Editor::scroll_tracks_down_line ()
+{
+ edit_vscrollbar.default_vmotion (0, 10);
+}
+
+void
+Editor::scroll_tracks_up_line ()
+{
+ edit_vscrollbar.default_vmotion (0, -10);
+}
+
+/* ZOOM */
+
+void
+Editor::temporal_zoom_step (bool coarser)
+{
+ double nfpu;
+
+ nfpu = frames_per_unit;
+
+ if (coarser) {
+ nfpu *= 2.0;
+ } else {
+ nfpu = max(1.0,(nfpu/2.0));
+ }
+
+ temporal_zoom (nfpu);
+}
+
+void
+Editor::temporal_zoom (gdouble fpu)
+{
+ if (!session) return;
+
+ jack_nframes_t current_page = current_page_frames();
+ jack_nframes_t current_leftmost = leftmost_frame;
+ jack_nframes_t current_rightmost;
+ jack_nframes_t current_center;
+ jack_nframes_t new_page;
+ jack_nframes_t leftmost_after_zoom = 0;
+ double nfpu;
+
+ nfpu = fpu;
+
+ new_page = (jack_nframes_t) floor (canvas_width * nfpu);
+
+ switch (zoom_focus) {
+ case ZoomFocusLeft:
+ leftmost_after_zoom = current_leftmost;
+ break;
+
+ case ZoomFocusRight:
+ current_rightmost = leftmost_frame + current_page;
+ if (current_rightmost > new_page) {
+ leftmost_after_zoom = current_rightmost - new_page;
+ } else {
+ leftmost_after_zoom = 0;
+ }
+ 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 {
+ leftmost_after_zoom = 0;
+ }
+ 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 {
+ leftmost_after_zoom = 0;
+ }
+ break;
+
+ case ZoomFocusEdit:
+ /* try to keep the edit cursor in the center */
+ if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
+ leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
+ } else {
+ leftmost_after_zoom = 0;
+ }
+ break;
+
+ }
+
+ // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
+
+// begin_reversible_command (_("zoom"));
+// session->add_undo (bind (slot (*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
+// session->add_redo (bind (slot (*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
+// commit_reversible_command ();
+
+ reposition_and_zoom (leftmost_after_zoom, nfpu);
+}
+
+void
+Editor::temporal_zoom_selection ()
+{
+ if (!selection) return;
+
+ if (selection->time.empty()) {
+ return;
+ }
+
+ jack_nframes_t start = selection->time[clicked_selection].start;
+ jack_nframes_t end = selection->time[clicked_selection].end;
+
+ temporal_zoom_by_frame (start, end, "zoom to selection");
+}
+
+void
+Editor::temporal_zoom_session ()
+{
+ if (session) {
+ temporal_zoom_by_frame (0, session->current_end_frame(), "zoom to session");
+ }
+}
+
+void
+Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, string op)
+{
+ if (!session) return;
+
+ if ((start == 0 && end == 0) || end < start) {
+ return;
+ }
+
+ jack_nframes_t range = end - start;
+
+ double new_fpu = (double)range / (double)canvas_width;
+// double p2 = 1.0;
+
+// while (p2 < new_fpu) {
+// p2 *= 2.0;
+// }
+// new_fpu = p2;
+
+ jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
+ jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
+ jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
+
+ if (new_leftmost > middle) new_leftmost = 0;
+
+// begin_reversible_command (op);
+// session->add_undo (bind (slot (*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
+// session->add_redo (bind (slot (*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
+// commit_reversible_command ();
+
+ reposition_and_zoom (new_leftmost, new_fpu);
+}
+
+void
+Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
+{
+ if (!session) return;
+
+ jack_nframes_t range_before = frame - leftmost_frame;
+ double new_fpu;
+
+ new_fpu = frames_per_unit;
+
+ if (coarser) {
+ new_fpu *= 2.0;
+ range_before *= 2;
+ } else {
+ new_fpu = max(1.0,(new_fpu/2.0));
+ range_before /= 2;
+ }
+
+ if (new_fpu == frames_per_unit) return;
+
+ jack_nframes_t new_leftmost = frame - range_before;
+
+ if (new_leftmost > frame) new_leftmost = 0;
+
+// begin_reversible_command (_("zoom to frame"));
+// session->add_undo (bind (slot (*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
+// session->add_redo (bind (slot (*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
+// commit_reversible_command ();
+
+ reposition_and_zoom (new_leftmost, new_fpu);
+}
+
+void
+Editor::select_all_in_track (bool add)
+{
+ list<Selectable *> touched;
+
+ if (!clicked_trackview) {
+ return;
+ }
+
+ clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
+
+ if (add) {
+ selection->add (touched);
+ } else {
+ selection->set (touched);
+ }
+}
+
+void
+Editor::select_all (bool add)
+{
+ list<Selectable *> touched;
+
+ for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+ if ((*iter)->hidden()) {
+ continue;
+ }
+ (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
+ }
+
+ if (add) {
+ selection->add (touched);
+ } else {
+ selection->set (touched);
+ }
+
+}
+
+void
+Editor::invert_selection_in_track ()
+{
+ list<Selectable *> touched;
+
+ if (!clicked_trackview) {
+ return;
+ }
+
+ clicked_trackview->get_inverted_selectables (*selection, touched);
+ selection->set (touched);
+}
+
+void
+Editor::invert_selection ()
+{
+ list<Selectable *> touched;
+
+ for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+ if ((*iter)->hidden()) {
+ continue;
+ }
+ (*iter)->get_inverted_selectables (*selection, touched);
+ }
+
+ selection->set (touched);
+}
+
+bool
+Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, bool add)
+{
+ list<Selectable *> touched;
+
+ for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+ if ((*iter)->hidden()) {
+ continue;
+ }
+ (*iter)->get_selectables (start, end, top, bot, touched);
+ }
+
+ if (add) {
+ selection->add (touched);
+ } else {
+ selection->set (touched);
+ }
+
+ return !touched.empty();
+}
+
+void
+Editor::set_selection_from_punch()
+{
+ Location* location;
+
+ if ((location = session->locations()->auto_punch_location()) == 0) {
+ return;
+ }
+
+ set_selection_from_range (*location);
+}
+
+void
+Editor::set_selection_from_loop()
+{
+ Location* location;
+
+ if ((location = session->locations()->auto_loop_location()) == 0) {
+ return;
+ }
+
+ set_selection_from_range (*location);
+}
+
+void
+Editor::set_selection_from_range (Location& range)
+{
+ if (clicked_trackview == 0) {
+ return;
+ }
+
+ begin_reversible_command (_("set selection from range"));
+ selection->set (0, range.start(), range.end());
+ commit_reversible_command ();
+}
+
+void
+Editor::amplitude_zoom_step (bool in)
+{
+ gdouble zoom = 1.0;
+
+ if (in) {
+ zoom *= 2.0;
+ } else {
+ if (zoom > 2.0) {
+ zoom /= 2.0;
+ } else {
+ zoom = 1.0;
+ }
+ }
+
+#ifdef FIX_FOR_CANVAS
+ /* XXX DO SOMETHING */
+#endif
+}
+
+
+/* DELETION */
+
+
+void
+Editor::delete_sample_forward ()
+{
+}
+
+void
+Editor::delete_sample_backward ()
+{
+}
+
+void
+Editor::delete_screen ()
+{
+}
+
+/* SEARCH */
+
+void
+Editor::search_backwards ()
+{
+ /* what ? */
+}
+
+void
+Editor::search_forwards ()
+{
+ /* what ? */
+}
+
+/* MARKS */
+
+void
+Editor::jump_forward_to_mark ()
+{
+ if (!session) {
+ return;
+ }
+
+ Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
+
+ if (location) {
+ session->request_locate (location->start(), session->transport_rolling());
+ } else {
+ session->request_locate (session->current_end_frame());
+ }
+}
+
+void
+Editor::jump_backward_to_mark ()
+{
+ if (!session) {
+ return;
+ }
+
+ Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
+
+ if (location) {
+ session->request_locate (location->start(), session->transport_rolling());
+ } else {
+ session->request_locate (0);
+ }
+}
+
+void
+Editor::set_mark ()
+{
+ jack_nframes_t pos;
+ float prefix;
+ bool was_floating;
+
+ if (get_prefix (prefix, was_floating)) {
+ pos = session->audible_frame ();
+ } else {
+ if (was_floating) {
+ pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
+ } else {
+ pos = (jack_nframes_t) floor (prefix);
+ }
+ }
+
+ session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
+}
+
+void
+Editor::clear_markers ()
+{
+ if (session) {
+ session->begin_reversible_command (_("clear markers"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->clear_markers ();
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+ }
+}
+
+void
+Editor::clear_ranges ()
+{
+ if (session) {
+ session->begin_reversible_command (_("clear ranges"));
+ session->add_undo (session->locations()->get_memento());
+
+ Location * looploc = session->locations()->auto_loop_location();
+ Location * punchloc = session->locations()->auto_punch_location();
+
+ session->locations()->clear_ranges ();
+ // re-add these
+ if (looploc) session->locations()->add (looploc);
+ if (punchloc) session->locations()->add (punchloc);
+
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+ }
+}
+
+void
+Editor::clear_locations ()
+{
+ session->begin_reversible_command (_("clear locations"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->clear ();
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+ session->locations()->clear ();
+}
+
+/* INSERT/REPLACE */
+
+void
+Editor::insert_region_list_drag (AudioRegion& region)
+{
+ gint x, y;
+ double wx, wy;
+ double cx, cy;
+ TimeAxisView *tv;
+ jack_nframes_t where;
+ AudioTimeAxisView *atv = 0;
+ Playlist *playlist;
+
+ track_canvas->get_pointer (x, y);
+
+ gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), x, y, &wx, &wy);
+
+ GdkEvent event;
+ event.type = GDK_BUTTON_RELEASE;
+ event.button.x = wx;
+ event.button.y = wy;
+
+ where = event_frame (&event, &cx, &cy);
+
+ if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
+ /* clearly outside canvas area */
+ return;
+ }
+
+ if ((tv = trackview_by_y_position (cy)) == 0) {
+ return;
+ }
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
+ return;
+ }
+
+ if ((playlist = atv->playlist()) == 0) {
+ return;
+ }
+
+ snap_to (where);
+
+ begin_reversible_command (_("insert dragged region"));
+ session->add_undo (playlist->get_memento());
+ playlist->add_region (*(new AudioRegion (region)), where, 1.0);
+ session->add_redo_no_execute (playlist->get_memento());
+ commit_reversible_command ();
+}
+
+void
+Editor::insert_region_list_selection (float times)
+{
+ AudioTimeAxisView *tv = 0;
+ Playlist *playlist;
+
+ if (clicked_audio_trackview != 0) {
+ tv = clicked_audio_trackview;
+ } else if (!selection->tracks.empty()) {
+ if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
+ return;
+ }
+ } else {
+ return;
+ }
+
+ if ((playlist = tv->playlist()) == 0) {
+ return;
+ }
+
+ Gtk::CTree_Helpers::SelectionList& selected = region_list_display.selection();
+
+ if (selected.empty()) {
+ return;
+ }
+
+ Region* region = reinterpret_cast<Region *> (selected.front().get_data ());
+
+ begin_reversible_command (_("insert region"));
+ session->add_undo (playlist->get_memento());
+ playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
+ session->add_redo_no_execute (playlist->get_memento());
+ commit_reversible_command ();
+}
+
+
+/* BUILT-IN EFFECTS */
+
+void
+Editor::reverse_selection ()
+{
+
+}
+
+/* GAIN ENVELOPE EDITING */
+
+void
+Editor::edit_envelope ()
+{
+}
+
+/* PLAYBACK */
+
+void
+Editor::toggle_playback (bool with_abort)
+{
+ if (!session) {
+ return;
+ }
+
+ switch (session->slave_source()) {
+ case Session::None:
+ case Session::JACK:
+ break;
+ default:
+ /* transport controlled by the master */
+ return;
+ }
+
+ if (session->is_auditioning()) {
+ session->cancel_audition ();
+ return;
+ }
+
+ if (session->transport_rolling()) {
+ session->request_stop (with_abort);
+ if (session->get_auto_loop()) {
+ session->request_auto_loop (false);
+ }
+ } else {
+ session->request_transport_speed (1.0f);
+ }
+}
+
+void
+Editor::play_from_start ()
+{
+ session->request_locate (0, true);
+}
+
+void
+Editor::play_selection ()
+{
+ if (selection->time.empty()) {
+ return;
+ }
+
+ session->request_play_range (true);
+}
+
+void
+Editor::play_selected_region ()
+{
+ if (!selection->audio_regions.empty()) {
+ AudioRegionView *rv = *(selection->audio_regions.begin());
+
+ session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
+ }
+}
+
+void
+Editor::toggle_loop_playback ()
+{
+ if (session) {
+ session->request_auto_loop (true);
+ }
+}
+
+void
+Editor::loop_selected_region ()
+{
+ if (!selection->audio_regions.empty()) {
+ AudioRegionView *rv = *(selection->audio_regions.begin());
+ Location* tll;
+
+ if ((tll = transport_loop_location()) != 0) {
+
+ tll->set (rv->region.position(), rv->region.last_frame());
+
+ // enable looping, reposition and start rolling
+
+ session->request_auto_loop (true);
+ session->request_locate (tll->start(), false);
+ session->request_transport_speed (1.0f);
+ }
+ }
+}
+
+void
+Editor::play_location (Location& location)
+{
+ if (location.start() <= location.end()) {
+ return;
+ }
+
+ session->request_bounded_roll (location.start(), location.end());
+}
+
+void
+Editor::loop_location (Location& location)
+{
+ if (location.start() <= location.end()) {
+ return;
+ }
+
+ Location* tll;
+
+ if ((tll = transport_loop_location()) != 0) {
+ tll->set (location.start(), location.end());
+
+ // enable looping, reposition and start rolling
+ session->request_auto_loop (true);
+ session->request_locate (tll->start(), true);
+ }
+}
+
+void
+Editor::toggle_region_mute ()
+{
+ if (clicked_regionview) {
+ clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
+ } else if (!selection->audio_regions.empty()) {
+ bool yn = ! (*selection->audio_regions.begin())->region.muted();
+ selection->foreach_audio_region (&AudioRegion::set_muted, yn);
+ }
+}
+
+void
+Editor::toggle_region_opaque ()
+{
+ if (clicked_regionview) {
+ clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
+ } else if (!selection->audio_regions.empty()) {
+ bool yn = ! (*selection->audio_regions.begin())->region.opaque();
+ selection->foreach_audio_region (&Region::set_opaque, yn);
+ }
+}
+
+void
+Editor::raise_region ()
+{
+ selection->foreach_audio_region (&Region::raise);
+}
+
+void
+Editor::raise_region_to_top ()
+{
+ selection->foreach_audio_region (&Region::raise_to_top);
+}
+
+void
+Editor::lower_region ()
+{
+ selection->foreach_audio_region (&Region::lower);
+}
+
+void
+Editor::lower_region_to_bottom ()
+{
+ selection->foreach_audio_region (&Region::lower_to_bottom);
+}
+
+void
+Editor::edit_region ()
+{
+ if (clicked_regionview == 0) {
+ return;
+ }
+
+ clicked_regionview->show_region_editor ();
+}
+
+void
+Editor::rename_region ()
+{
+ Dialog dialog;
+ Entry entry;
+ Button ok_button (_("OK"));
+ Button cancel_button (_("Cancel"));
+
+ if (selection->audio_regions.empty()) {
+ return;
+ }
+
+ dialog.set_title (_("ardour: rename region"));
+ dialog.set_name ("RegionRenameWindow");
+ dialog.set_usize (300, -1);
+ dialog.set_position (GTK_WIN_POS_MOUSE);
+ dialog.set_modal (true);
+
+ 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);
+
+ entry.set_name ("RegionNameDisplay");
+ ok_button.set_name ("EditorGTKButton");
+ cancel_button.set_name ("EditorGTKButton");
+
+ region_renamed = false;
+
+ entry.activate.connect (bind (slot (*this, &Editor::rename_region_finished), true));
+ ok_button.clicked.connect (bind (slot (*this, &Editor::rename_region_finished), true));
+ cancel_button.clicked.connect (bind (slot (*this, &Editor::rename_region_finished), false));
+
+ /* recurse */
+
+ dialog.show_all ();
+ ARDOUR_UI::instance()->allow_focus (true);
+ Main::run ();
+ ARDOUR_UI::instance()->allow_focus (false);
+
+ if (region_renamed) {
+ (*selection->audio_regions.begin())->region.set_name (entry.get_text());
+ redisplay_regions ();
+ }
+}
+
+void
+Editor::rename_region_finished (bool status)
+
+{
+ region_renamed = status;
+ Main::quit ();
+}
+
+void
+Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
+{
+ if (session->is_auditioning()) {
+ session->cancel_audition ();
+ }
+
+ // note: some potential for creativity here, because region doesn't
+ // have to belong to the playlist that Route is handling
+
+ // bool was_soloed = route.soloed();
+
+ route.set_solo (true, this);
+
+ session->request_bounded_roll (region.position(), region.position() + region.length());
+
+ /* XXX how to unset the solo state ? */
+}
+
+void
+Editor::audition_selected_region ()
+{
+ if (!selection->audio_regions.empty()) {
+ AudioRegionView* rv = *(selection->audio_regions.begin());
+ session->audition_region (rv->region);
+ }
+}
+
+void
+Editor::audition_playlist_region_standalone (AudioRegion& region)
+{
+ session->audition_region (region);
+}
+
+void
+Editor::build_interthread_progress_window ()
+{
+ interthread_progress_window = new ArdourDialog (X_("interthread progress"));
+
+ interthread_progress_bar.set_orientation (GTK_PROGRESS_LEFT_TO_RIGHT);
+
+ interthread_progress_vbox.set_border_width (10);
+ interthread_progress_vbox.set_spacing (5);
+ interthread_progress_vbox.pack_start (interthread_progress_label, false, false);
+ interthread_progress_vbox.pack_start (interthread_progress_bar,false, false);
+ interthread_progress_vbox.pack_start (interthread_cancel_button,false, false);
+
+ interthread_cancel_button.add (interthread_cancel_label);
+
+ interthread_cancel_button.clicked.connect (slot (*this, &Editor::interthread_cancel_clicked));
+
+ interthread_progress_window->set_modal (true);
+ interthread_progress_window->set_default_size (200, 100);
+ interthread_progress_window->add (interthread_progress_vbox);
+}
+
+void
+Editor::interthread_cancel_clicked ()
+{
+ if (current_interthread_info) {
+ current_interthread_info->cancel = true;
+ }
+}
+
+void *
+Editor::_import_thread (void *arg)
+{
+ PBD::ThreadCreated (pthread_self(), X_("Import"));
+
+ Editor *ed = (Editor *) arg;
+ return ed->import_thread ();
+}
+
+void *
+Editor::import_thread ()
+{
+ session->import_audiofile (import_status);
+ return 0;
+}
+
+gint
+Editor::import_progress_timeout (void *arg)
+{
+ interthread_progress_label.set_text (import_status.doing_what);
+
+ if (import_status.freeze) {
+ interthread_cancel_button.set_sensitive(false);
+ } else {
+ interthread_cancel_button.set_sensitive(true);
+ }
+
+ if (import_status.doing_what == "building peak files") {
+ interthread_progress_bar.set_activity_mode (true);
+ return FALSE;
+ } else {
+ interthread_progress_bar.set_percentage (import_status.progress);
+ }
+
+ return !(import_status.done || import_status.cancel);
+}
+
+void
+Editor::import_audio (bool as_tracks)
+{
+ if (session == 0) {
+ warning << _("You can't import an audiofile until you have a session loaded.") << endmsg;
+ return;
+ }
+
+ SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window());
+ SigC::Connection c;
+ string str;
+
+ if (as_tracks) {
+ c = sfdb.Action.connect (bind (slot (*this, &Editor::do_import), true));
+ str =_("Import selected as tracks");
+ } else {
+ c = sfdb.Action.connect (bind (slot (*this, &Editor::do_import), false));
+ str = _("Import selected to region list");
+ }
+
+ sfdb.run (str, true);
+ c.disconnect ();
+}
+
+void
+Editor::catch_new_audio_region (AudioRegion* ar)
+{
+ last_audio_region = ar;
+}
+
+void
+Editor::do_import (vector<string> paths, bool split, bool as_tracks)
+{
+ SigC::Connection c;
+
+ /* SFDB sets "multichan" to true to indicate "split channels"
+ so reverse the setting to match the way libardour
+ interprets it.
+ */
+
+ import_status.multichan = !split;
+
+ if (interthread_progress_window == 0) {
+ build_interthread_progress_window ();
+ }
+
+ interthread_progress_window->set_title (_("ardour: audio import in progress"));
+ interthread_progress_window->set_position (GTK_WIN_POS_MOUSE);
+ interthread_progress_window->show_all ();
+ interthread_progress_bar.set_percentage (0.0f);
+ interthread_cancel_label.set_text (_("Cancel Import"));
+ current_interthread_info = &import_status;
+
+ c = session->AudioRegionAdded.connect (slot (*this, &Editor::catch_new_audio_region));
+
+ for (vector<string>::iterator i = paths.begin(); i != paths.end(); ++i ) {
+
+ interthread_progress_window->set_title (compose (_("ardour: importing %1"), (*i)));
+
+ import_status.pathname = (*i);
+ import_status.done = false;
+ import_status.cancel = false;
+ import_status.freeze = false;
+ import_status.done = 0.0;
+
+ interthread_progress_connection =
+ Gtk::Main::timeout.connect (bind (slot (*this, &Editor::import_progress_timeout), (gpointer) 0), 100);
+
+ last_audio_region = 0;
+
+ pthread_create_and_store ("import", &import_status.thread, 0, _import_thread, this);
+ pthread_detach (import_status.thread);
+
+ while (!(import_status.done || import_status.cancel)) {
+ gtk_main_iteration ();
+ }
+
+ import_status.done = true;
+ interthread_progress_connection.disconnect ();
+
+ if (as_tracks && last_audio_region != 0) {
+ uint32_t channels = last_audio_region->n_channels();
+
+ AudioTrack* at = session->new_audio_track (channels, channels);
+ AudioRegion* copy = new AudioRegion (*last_audio_region);
+ at->disk_stream().playlist()->add_region (*copy, 0);
+ }
+ }
+
+ c.disconnect ();
+ interthread_progress_window->hide_all ();
+}
+
+int
+Editor::reject_because_rate_differs (string path, SF_INFO& finfo, string action, bool multiple_pending)
+{
+ if (!session) {
+ return 1;
+ }
+
+ if (finfo.samplerate != (int) session->frame_rate()) {
+ vector<string> choices;
+
+ choices.push_back (compose (_("%1 it anyway"), action));
+
+ if (multiple_pending) {
+ /* XXX assumptions about sentence structure
+ here for translators. Sorry.
+ */
+ choices.push_back (compose (_("Don't %1 it"), action));
+ choices.push_back (compose (_("%1 all without questions"), action));
+ choices.push_back (_("Cancel entire import"));
+ } else {
+ choices.push_back (_("Cancel"));
+ }
+
+ Gtkmmext::Choice rate_choice (
+ compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
+ choices);
+
+ rate_choice.chosen.connect (Main::quit.slot());
+ rate_choice.show_all ();
+
+ Main::run ();
+
+ switch (rate_choice.get_choice()) {
+ case 0: /* do it anyway */
+ return 0;
+ case 1: /* don't import this one */
+ return 1;
+ case 2: /* do the rest without asking */
+ return -1;
+ case 3: /* stop a multi-file import */
+ default:
+ return -2;
+ }
+ }
+
+ return 0;
+}
+
+void
+Editor::embed_audio ()
+{
+ if (session == 0) {
+ warning << _("You can't embed an audiofile until you have a session loaded.") << endmsg;
+ return;
+ }
+
+ SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window());
+ SigC::Connection c = sfdb.Action.connect (slot (*this, &Editor::do_embed_sndfiles));
+
+ sfdb.run (_("Add to External Region list"), true);
+
+ c.disconnect ();
+}
+
+void
+Editor::do_embed_sndfiles (vector<string> paths, bool split)
+{
+ bool multiple_files = paths.size() > 1;
+ bool check_sample_rate = true;
+
+ for (vector<string>::iterator i = paths.begin(); i != paths.end(); ++i) {
+ embed_sndfile (*i, split, multiple_files, check_sample_rate);
+ }
+
+ session->save_state ("");
+}
+
+void
+Editor::embed_sndfile (string path, bool split, bool multiple_files, bool& check_sample_rate)
+{
+ SndFileSource *source = 0; /* keep g++ quiet */
+ AudioRegion::SourceList sources;
+ string idspec;
+ string linked_path;
+ SNDFILE *sf;
+ SF_INFO finfo;
+
+ /* lets see if we can link it into the session */
+
+ linked_path = session->sound_dir();
+ linked_path += PBD::basename (path);
+
+ if (link (path.c_str(), linked_path.c_str()) == 0) {
+
+ /* there are many reasons why link(2) might have failed.
+ but if it succeeds, we now have a link in the
+ session sound dir that will protect against
+ unlinking of the original path. nice.
+ */
+
+ path = linked_path;
+ }
+
+ memset (&finfo, 0, sizeof(finfo));
+
+ /* note that we temporarily truncated _id at the colon */
+
+ if ((sf = sf_open (path.c_str(), SFM_READ, &finfo)) == 0) {
+ char errbuf[256];
+ sf_error_str (0, errbuf, sizeof (errbuf) - 1);
+ error << compose(_("Editor: cannot open file \"%1\" (%2)"), selection, errbuf) << endmsg;
+ return;
+ }
+ sf_close (sf);
+ sf = 0;
+
+ if (check_sample_rate) {
+ switch (reject_because_rate_differs (path, finfo, "Embed", multiple_files)) {
+ case 0:
+ break;
+ case 1:
+ return;
+ case -1:
+ check_sample_rate = false;
+ break;
+
+ case -2:
+ default:
+ return;
+ }
+ }
+
+ track_canvas_scroller.get_window().set_cursor (GDK_WATCH);
+ ARDOUR_UI::instance()->flush_pending ();
+
+ /* make the proper number of channels in the region */
+
+ for (int n=0; n < finfo.channels; ++n)
+ {
+ idspec = path;
+ idspec += compose(":%1", n);
+
+ try {
+ source = new SndFileSource (idspec.c_str());
+ sources.push_back(source);
+ }
+
+ catch (failed_constructor& err) {
+ error << compose(_("could not open %1"), path) << endmsg;
+ goto out;
+ }
+
+ ARDOUR_UI::instance()->flush_pending ();
+ }
+
+ if (sources.size() > 0) {
+
+ string region_name = PBD::basename_nosuffix (path);
+ region_name += "-0";
+
+ /* The created region isn't dropped. It emits a signal
+ that is picked up by the session.
+ */
+
+ new AudioRegion (sources, 0, sources[0]->length(), region_name, 0,
+ Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External));
+
+ /* make sure we can see it in the list */
+
+ Gtk::CTree_Helpers::RowList::iterator external_node;
+ external_node = region_list_display.rows().begin();
+ ++external_node; /* its the second node, always */
+ external_node->expand_recursive ();
+
+ ARDOUR_UI::instance()->flush_pending ();
+ }
+
+ out:
+ track_canvas_scroller.get_window().set_cursor (current_canvas_cursor);
+}
+
+void
+Editor::insert_sndfile (bool as_tracks)
+{
+ SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window());
+ SigC::Connection c;
+ string str;
+
+ if (as_tracks) {
+
+ c = sfdb.Action.connect (slot (*this, &Editor::insert_paths_as_new_tracks));
+ str = _("Insert selected as new tracks");
+
+ } else {
+
+ jack_nframes_t pos;
+
+ if (clicked_audio_trackview == 0) {
+ return;
+ }
+
+ if (ensure_cursor (&pos)) {
+ return;
+ }
+
+ c = sfdb.Action.connect (bind (slot (*this, &Editor::do_insert_sndfile), pos));
+ str = _("Insert selected");
+ }
+
+ sfdb.run (str, false);
+ c.disconnect ();
+}
+
+void
+Editor::insert_paths_as_new_tracks (vector<string> paths, bool split)
+{
+ SNDFILE *sf;
+ SF_INFO finfo;
+ bool multiple_files;
+ bool check_sample_rate = true;
+
+ multiple_files = paths.size() > 1;
+
+ for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
+
+ memset (&finfo, 0, sizeof(finfo));
+
+ if ((sf = sf_open ((*p).c_str(), SFM_READ, &finfo)) == 0) {
+ char errbuf[256];
+ sf_error_str (0, errbuf, sizeof (errbuf) - 1);
+ error << compose(_("Editor: cannot open file \"%1\" (%2)"), (*p), errbuf) << endmsg;
+ continue;
+ }
+
+ sf_close (sf);
+ sf = 0;
+
+ /* add a new track */
+
+ if (check_sample_rate) {
+ switch (reject_because_rate_differs (*p, finfo, "Insert", multiple_files)) {
+ case 0:
+ break;
+ case 1:
+ continue;
+ case -1:
+ check_sample_rate = false;
+ break;
+
+ case -2:
+ return;
+ }
+ }
+
+ uint32_t input_chan = finfo.channels;
+ uint32_t output_chan;
+
+ if (session->get_output_auto_connect() & Session::AutoConnectMaster) {
+ output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
+ } else {
+ output_chan = input_chan;
+ }
+
+ (void) session->new_audio_track (input_chan, output_chan);
+
+
+ /* get the last (most recently added) track view */
+
+ AudioTimeAxisView* tv;
+
+ if ((tv = dynamic_cast<AudioTimeAxisView*>(track_views.back())) == 0) {
+ fatal << _("programming error: ")
+ << X_("last trackview after new_audio_track is not an audio track!")
+ << endmsg;
+ /*NOTREACHED*/
+ }
+
+ jack_nframes_t pos = 0;
+ insert_sndfile_into (*p, true, tv, pos, false);
+ }
+}
+
+void
+Editor::do_insert_sndfile (vector<string> paths, bool split, jack_nframes_t pos)
+{
+ for (vector<string>::iterator x = paths.begin(); x != paths.end(); ++x) {
+ insert_sndfile_into (*x, !split, clicked_audio_trackview, pos);
+ }
+}
+
+void
+Editor::insert_sndfile_into (string path, bool multi, AudioTimeAxisView* tv, jack_nframes_t& pos, bool prompt)
+{
+ SndFileSource *source = 0; /* keep g++ quiet */
+ AudioRegion::SourceList sources;
+ string idspec;
+ SNDFILE *sf;
+ SF_INFO finfo;
+
+ memset (&finfo, 0, sizeof(finfo));
+
+ /* note that we temporarily truncated _id at the colon */
+
+ if ((sf = sf_open (path.c_str(), SFM_READ, &finfo)) == 0) {
+ char errbuf[256];
+ sf_error_str (0, errbuf, sizeof (errbuf) - 1);
+ error << compose(_("Editor: cannot open file \"%1\" (%2)"), path, errbuf) << endmsg;
+ return;
+ }
+ sf_close (sf);
+ sf = 0;
+
+ if (prompt && (reject_because_rate_differs (path, finfo, "Insert", false) != 0)) {
+ return;
+ }
+
+ track_canvas_scroller.get_window().set_cursor (GDK_WATCH);
+ ARDOUR_UI::instance()->flush_pending ();
+
+ /* make the proper number of channels in the region */
+
+ for (int n=0; n < finfo.channels; ++n)
+ {
+ idspec = path;
+ idspec += compose(":%1", n);
+
+ try {
+ source = new SndFileSource (idspec.c_str());
+ sources.push_back(source);
+ }
+
+ catch (failed_constructor& err) {
+ error << compose(_("could not open %1"), path) << endmsg;
+ goto out;
+ }
+
+ ARDOUR_UI::instance()->flush_pending ();
+ }
+
+ if (sources.size() > 0) {
+
+ string region_name = region_name_from_path (PBD::basename (path));
+
+ AudioRegion *region = new AudioRegion (sources, 0, sources[0]->length(), region_name,
+ 0, /* irrelevant these days */
+ Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External));
+
+ begin_reversible_command (_("insert sndfile"));
+ session->add_undo (tv->playlist()->get_memento());
+ tv->playlist()->add_region (*region, pos);
+ session->add_redo_no_execute (tv->playlist()->get_memento());
+ commit_reversible_command ();
+
+ pos += sources[0]->length();
+
+ ARDOUR_UI::instance()->flush_pending ();
+ }
+
+ out:
+ track_canvas_scroller.get_window().set_cursor (current_canvas_cursor);
+ return;
+}
+
+void
+Editor::region_from_selection ()
+{
+ if (clicked_trackview == 0) {
+ return;
+ }
+
+ if (selection->time.empty()) {
+ return;
+ }
+
+ jack_nframes_t start = selection->time[clicked_selection].start;
+ jack_nframes_t end = selection->time[clicked_selection].end;
+
+ jack_nframes_t selection_cnt = end - start + 1;
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+
+ AudioRegion *region;
+ AudioRegion *current;
+ Region* current_r;
+ Playlist *pl;
+
+ jack_nframes_t internal_start;
+ string new_name;
+
+ if ((pl = (*i)->playlist()) == 0) {
+ continue;
+ }
+
+ if ((current_r = pl->top_region_at (start)) == 0) {
+ continue;
+ }
+
+ if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
+ internal_start = start - current->position();
+ session->region_name (new_name, current->name(), true);
+ region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
+ }
+ }
+}
+
+void
+Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
+{
+ if (selection->time.empty() || selection->tracks.empty()) {
+ return;
+ }
+
+ jack_nframes_t start = selection->time[clicked_selection].start;
+ jack_nframes_t end = selection->time[clicked_selection].end;
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+
+ AudioRegion* current;
+ Region* current_r;
+ Playlist* playlist;
+ jack_nframes_t internal_start;
+ string new_name;
+
+ if ((playlist = (*i)->playlist()) == 0) {
+ continue;
+ }
+
+ if ((current_r = playlist->top_region_at(start)) == 0) {
+ continue;
+ }
+
+ if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
+ continue;
+ }
+
+ internal_start = start - current->position();
+ session->region_name (new_name, current->name(), true);
+
+ new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
+ }
+}
+
+void
+Editor::split_multichannel_region ()
+{
+ vector<AudioRegion*> v;
+
+ if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
+ return;
+ }
+
+ clicked_regionview->region.separate_by_channel (*session, v);
+
+ /* nothing else to do, really */
+}
+
+void
+Editor::new_region_from_selection ()
+{
+ region_from_selection ();
+ cancel_selection ();
+}
+
+void
+Editor::separate_region_from_selection ()
+{
+ bool doing_undo = false;
+
+ if (selection->time.empty()) {
+ return;
+ }
+
+ Playlist *playlist;
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
+
+ if (atv->is_audio_track()) {
+
+ if ((playlist = atv->playlist()) != 0) {
+ if (!doing_undo) {
+ begin_reversible_command (_("separate"));
+ doing_undo = true;
+ }
+ if (doing_undo) session->add_undo ((playlist)->get_memento());
+
+ /* XXX need to consider musical time selections here at some point */
+
+ double speed = atv->get_diskstream()->speed();
+
+ for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
+ playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
+ }
+
+ if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
+ }
+ }
+ }
+ }
+
+ if (doing_undo) commit_reversible_command ();
+}
+
+void
+Editor::crop_region_to_selection ()
+{
+ if (selection->time.empty()) {
+ return;
+ }
+
+ vector<Playlist*> playlists;
+ Playlist *playlist;
+
+ if (clicked_trackview != 0) {
+
+ if ((playlist = clicked_trackview->playlist()) == 0) {
+ return;
+ }
+
+ playlists.push_back (playlist);
+
+ } else {
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
+
+ if (atv->is_audio_track()) {
+
+ if ((playlist = atv->playlist()) != 0) {
+ playlists.push_back (playlist);
+ }
+ }
+ }
+ }
+ }
+
+ if (!playlists.empty()) {
+
+ jack_nframes_t start;
+ jack_nframes_t end;
+ jack_nframes_t cnt;
+
+ begin_reversible_command (_("trim to selection"));
+
+ for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+
+ Region *region;
+
+ start = selection->time.start();
+
+ if ((region = (*i)->top_region_at(start)) == 0) {
+ continue;
+ }
+
+ /* now adjust lengths to that we do the right thing
+ if the selection extends beyond the region
+ */
+
+ start = max (start, region->position());
+ end = min (selection->time.end_frame(), start + region->length() - 1);
+ cnt = end - start + 1;
+
+ session->add_undo ((*i)->get_memento());
+ region->trim_to (start, cnt, this);
+ session->add_redo_no_execute ((*i)->get_memento());
+ }
+
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::region_fill_track ()
+{
+ jack_nframes_t end;
+
+ if (!session || selection->audio_regions.empty()) {
+ return;
+ }
+
+ end = session->current_end_frame ();
+
+ begin_reversible_command (_("region fill"));
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+
+ AudioRegion& region ((*i)->region);
+ Playlist* pl = region.playlist();
+
+ if (end <= region.last_frame()) {
+ return;
+ }
+
+ double times = (double) (end - region.last_frame()) / (double) region.length();
+
+ if (times == 0) {
+ return;
+ }
+
+ session->add_undo (pl->get_memento());
+ pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
+ session->add_redo_no_execute (pl->get_memento());
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::region_fill_selection ()
+{
+ if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
+ return;
+ }
+
+ if (selection->time.empty()) {
+ return;
+ }
+
+ Region *region;
+
+ Gtk::CTree_Helpers::SelectionList& selected = region_list_display.selection();
+
+ if (selected.empty()) {
+ return;
+ }
+
+ region = reinterpret_cast<Region *> (selected.front().get_data());
+
+ jack_nframes_t start = selection->time[clicked_selection].start;
+ jack_nframes_t end = selection->time[clicked_selection].end;
+
+ Playlist *playlist;
+
+ if (selection->tracks.empty()) {
+ return;
+ }
+
+ jack_nframes_t selection_length = end - start;
+ float times = (float)selection_length / region->length();
+
+ begin_reversible_command (_("fill selection"));
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+
+ if ((playlist = (*i)->playlist()) == 0) {
+ continue;
+ }
+
+ session->add_undo (playlist->get_memento());
+ playlist->add_region (*(createRegion (*region)), start, times);
+ session->add_redo_no_execute (playlist->get_memento());
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::set_region_sync_from_edit_cursor ()
+{
+ if (clicked_regionview == 0) {
+ return;
+ }
+
+ if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
+ error << _("Place the edit cursor at the desired sync point") << endmsg;
+ return;
+ }
+
+ Region& region (clicked_regionview->region);
+
+ begin_reversible_command (_("set sync from edit cursor"));
+ session->add_undo (region.playlist()->get_memento());
+ region.set_sync_position (edit_cursor->current_frame);
+ session->add_redo_no_execute (region.playlist()->get_memento());
+ commit_reversible_command ();
+}
+
+void
+Editor::remove_region_sync ()
+{
+ if (clicked_regionview) {
+ Region& region (clicked_regionview->region);
+ begin_reversible_command (_("remove sync"));
+ session->add_undo (region.playlist()->get_memento());
+ region.clear_sync_position ();
+ session->add_redo_no_execute (region.playlist()->get_memento());
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::naturalize ()
+{
+ if (selection->audio_regions.empty()) {
+ return;
+ }
+ begin_reversible_command (_("naturalize"));
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ session->add_undo ((*i)->region.get_memento());
+ (*i)->region.move_to_natural_position (this);
+ session->add_redo_no_execute ((*i)->region.get_memento());
+ }
+ commit_reversible_command ();
+}
+
+void
+Editor::align (RegionPoint what)
+{
+ align_selection (what, edit_cursor->current_frame);
+}
+
+void
+Editor::align_relative (RegionPoint what)
+{
+ align_selection_relative (what, edit_cursor->current_frame);
+}
+
+struct RegionSortByTime {
+ bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
+ return a->region.position() < b->region.position();
+ }
+};
+
+void
+Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
+{
+ if (selection->audio_regions.empty()) {
+ return;
+ }
+
+ jack_nframes_t distance;
+ jack_nframes_t pos = 0;
+ int dir;
+
+ list<AudioRegionView*> sorted;
+ selection->audio_regions.by_position (sorted);
+ Region& r ((*sorted.begin())->region);
+
+ switch (point) {
+ case Start:
+ pos = r.first_frame ();
+ break;
+
+ case End:
+ pos = r.last_frame();
+ break;
+
+ case SyncPoint:
+ pos = r.adjust_to_sync (r.first_frame());
+ break;
+ }
+
+ if (pos > position) {
+ distance = pos - position;
+ dir = -1;
+ } else {
+ distance = position - pos;
+ dir = 1;
+ }
+
+ begin_reversible_command (_("align selection (relative)"));
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+
+ Region& region ((*i)->region);
+
+ session->add_undo (region.playlist()->get_memento());
+
+ if (dir > 0) {
+ region.set_position (region.position() + distance, this);
+ } else {
+ region.set_position (region.position() - distance, this);
+ }
+
+ session->add_redo_no_execute (region.playlist()->get_memento());
+
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::align_selection (RegionPoint point, jack_nframes_t position)
+{
+ if (selection->audio_regions.empty()) {
+ return;
+ }
+
+ begin_reversible_command (_("align selection"));
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ align_region_internal ((*i)->region, point, position);
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
+{
+ begin_reversible_command (_("align region"));
+ align_region_internal (region, point, position);
+ commit_reversible_command ();
+}
+
+void
+Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
+{
+ session->add_undo (region.playlist()->get_memento());
+
+ switch (point) {
+ case SyncPoint:
+ region.set_position (region.adjust_to_sync (position), this);
+ break;
+
+ case End:
+ if (position > region.length()) {
+ region.set_position (position - region.length(), this);
+ }
+ break;
+
+ case Start:
+ region.set_position (position, this);
+ break;
+ }
+
+ session->add_redo_no_execute (region.playlist()->get_memento());
+}
+
+void
+Editor::trim_region_to_edit_cursor ()
+{
+ if (clicked_regionview == 0) {
+ return;
+ }
+
+ Region& region (clicked_regionview->region);
+
+ float speed = 1.0f;
+ AudioTimeAxisView *atav;
+
+ if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
+ if (atav->get_diskstream() != 0) {
+ speed = atav->get_diskstream()->speed();
+ }
+ }
+
+ begin_reversible_command (_("trim to edit"));
+ session->add_undo (region.playlist()->get_memento());
+ region.trim_end ( (jack_nframes_t) floor( (float)edit_cursor->current_frame * speed), this);
+ session->add_redo_no_execute (region.playlist()->get_memento());
+ commit_reversible_command ();
+}
+
+void
+Editor::trim_region_from_edit_cursor ()
+{
+ if (clicked_regionview == 0) {
+ return;
+ }
+
+ Region& region (clicked_regionview->region);
+
+ float speed = 1.0f;
+ AudioTimeAxisView *atav;
+
+ if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
+ if (atav->get_diskstream() != 0) {
+ speed = atav->get_diskstream()->speed();
+ }
+ }
+
+ begin_reversible_command (_("trim to edit"));
+ session->add_undo (region.playlist()->get_memento());
+ region.trim_front ( (jack_nframes_t) floor( (float)edit_cursor->current_frame * speed), this);
+ session->add_redo_no_execute (region.playlist()->get_memento());
+ commit_reversible_command ();
+}
+
+void
+Editor::unfreeze_route ()
+{
+ if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
+ return;
+ }
+
+ clicked_audio_trackview->audio_track()->unfreeze ();
+}
+
+void*
+Editor::_freeze_thread (void* arg)
+{
+ PBD::ThreadCreated (pthread_self(), X_("Freeze"));
+ return static_cast<Editor*>(arg)->freeze_thread ();
+}
+
+void*
+Editor::freeze_thread ()
+{
+ clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
+ return 0;
+}
+
+gint
+Editor::freeze_progress_timeout (void *arg)
+{
+ interthread_progress_bar.set_percentage (current_interthread_info->progress);
+ return !(current_interthread_info->done || current_interthread_info->cancel);
+}
+
+void
+Editor::freeze_route ()
+{
+ if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
+ return;
+ }
+
+ InterThreadInfo itt;
+
+ if (interthread_progress_window == 0) {
+ build_interthread_progress_window ();
+ }
+
+ interthread_progress_window->set_title (_("ardour: freeze"));
+ interthread_progress_window->set_position (GTK_WIN_POS_MOUSE);
+ interthread_progress_window->show_all ();
+ interthread_progress_bar.set_percentage (0.0f);
+ interthread_progress_label.set_text ("");
+ interthread_cancel_label.set_text (_("Cancel Freeze"));
+ current_interthread_info = &itt;
+
+ interthread_progress_connection =
+ Gtk::Main::timeout.connect (bind (slot (*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
+
+ itt.done = false;
+ itt.cancel = false;
+ itt.progress = 0.0f;
+
+ pthread_create (&itt.thread, 0, _freeze_thread, this);
+
+ track_canvas_scroller.get_window().set_cursor (GDK_WATCH);
+
+ while (!itt.done && !itt.cancel) {
+ gtk_main_iteration ();
+ }
+
+ interthread_progress_connection.disconnect ();
+ interthread_progress_window->hide_all ();
+ current_interthread_info = 0;
+ track_canvas_scroller.get_window().set_cursor (current_canvas_cursor);
+}
+
+void
+Editor::bounce_range_selection ()
+{
+ if (selection->time.empty()) {
+ return;
+ }
+
+ TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
+
+ jack_nframes_t start = selection->time[clicked_selection].start;
+ jack_nframes_t end = selection->time[clicked_selection].end;
+ jack_nframes_t cnt = end - start + 1;
+
+ begin_reversible_command (_("bounce range"));
+
+ for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
+
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
+ continue;
+ }
+
+ Playlist* playlist;
+
+ if ((playlist = atv->playlist()) == 0) {
+ return;
+ }
+
+ InterThreadInfo itt;
+
+ itt.done = false;
+ itt.cancel = false;
+ itt.progress = false;
+
+ session->add_undo (playlist->get_memento());
+ atv->audio_track()->bounce_range (start, cnt, itt);
+ session->add_redo_no_execute (playlist->get_memento());
+ }
+
+ commit_reversible_command ();
+
+ delete views;
+}
+
+void
+Editor::cut ()
+{
+ cut_copy (Cut);
+}
+
+void
+Editor::copy ()
+{
+ cut_copy (Copy);
+}
+
+void
+Editor::cut_copy (CutCopyOp op)
+{
+ /* only cancel selection if cut/copy is successful.*/
+
+ string opname;
+
+ switch (op) {
+ case Cut:
+ opname = _("cut");
+ break;
+ case Copy:
+ opname = _("copy");
+ break;
+ case Clear:
+ opname = _("clear");
+ break;
+ }
+
+ cut_buffer->clear ();
+
+ switch (current_mouse_mode()) {
+ case MouseObject:
+ if (!selection->audio_regions.empty() || !selection->points.empty()) {
+
+ begin_reversible_command (opname + _(" objects"));
+
+ if (!selection->audio_regions.empty()) {
+
+ cut_copy_regions (op);
+
+ if (op == Cut) {
+ selection->clear_audio_regions ();
+ }
+ }
+
+ if (!selection->points.empty()) {
+ cut_copy_points (op);
+
+ if (op == Cut) {
+ selection->clear_points ();
+ }
+ }
+
+ commit_reversible_command ();
+ }
+ break;
+
+ case MouseRange:
+ if (!selection->time.empty()) {
+
+ begin_reversible_command (opname + _(" range"));
+ cut_copy_ranges (op);
+ commit_reversible_command ();
+
+ if (op == Cut) {
+ selection->clear_time ();
+ }
+
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+Editor::cut_copy_points (CutCopyOp op)
+{
+ for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
+
+ AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
+
+ if (atv) {
+ atv->cut_copy_clear_objects (selection->points, op);
+ }
+ }
+}
+
+void
+Editor::cut_copy_regions (CutCopyOp op)
+{
+ typedef map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
+ PlaylistMapping pmap;
+ jack_nframes_t first_position = max_frames;
+ set<Playlist*> freezelist;
+ pair<set<Playlist*>::iterator,bool> insert_result;
+
+ for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
+ first_position = min ((*x)->region.position(), first_position);
+
+ if (op == Cut || op == Clear) {
+ AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
+ if (pl) {
+ insert_result = freezelist.insert (pl);
+ if (insert_result.second) {
+ pl->freeze ();
+ session->add_undo (pl->get_memento());
+ }
+ }
+ }
+ }
+
+ for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
+
+ AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
+ AudioPlaylist* npl;
+ AudioRegionSelection::iterator tmp;
+
+ tmp = x;
+ ++tmp;
+
+ if (pl) {
+
+ PlaylistMapping::iterator pi = pmap.find (pl);
+
+ if (pi == pmap.end()) {
+ npl = new AudioPlaylist (*session, "cutlist", true);
+ npl->freeze();
+ pmap[pl] = npl;
+ } else {
+ npl = pi->second;
+ }
+
+ switch (op) {
+ case Cut:
+ npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
+ pl->remove_region (&((*x)->region));
+ break;
+
+ case Copy:
+ npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
+ break;
+
+ case Clear:
+ pl->remove_region (&((*x)->region));
+ break;
+ }
+ }
+
+ x = tmp;
+ }
+
+ list<Playlist*> foo;
+
+ for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
+ foo.push_back (i->second);
+ }
+
+ if (!foo.empty()) {
+ cut_buffer->set (foo);
+ }
+
+ for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
+ (*pl)->thaw ();
+ session->add_redo_no_execute ((*pl)->get_memento());
+ }
+}
+
+void
+Editor::cut_copy_ranges (CutCopyOp op)
+{
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ (*i)->cut_copy_clear (*selection, op);
+ }
+}
+
+void
+Editor::paste (float times)
+{
+ paste_internal (edit_cursor->current_frame, times);
+}
+
+void
+Editor::mouse_paste ()
+{
+ gint x, y;
+ double wx, wy;
+ track_canvas->get_pointer (x, y);
+
+ gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), x, y, &wx, &wy);
+
+ GdkEvent event;
+ event.type = GDK_BUTTON_RELEASE;
+ event.button.x = wx;
+ event.button.y = wy;
+
+ jack_nframes_t where = event_frame (&event, 0, 0);
+ snap_to (where);
+ paste_internal (where, 1);
+}
+
+void
+Editor::paste_internal (jack_nframes_t position, float times)
+{
+ bool commit = false;
+
+ if (cut_buffer->empty() || selection->tracks.empty()) {
+ return;
+ }
+
+ if (position == max_frames) {
+ position = edit_cursor->current_frame;
+ }
+
+ begin_reversible_command (_("paste"));
+
+ TrackSelection::iterator i;
+ size_t nth;
+
+ for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
+
+ /* undo/redo is handled by individual tracks */
+
+ if ((*i)->paste (position, times, *cut_buffer, nth)) {
+ commit = true;
+ }
+ }
+
+ if (commit) {
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::paste_named_selection (float times)
+{
+ Gtk::CList_Helpers::SelectionList& selected = named_selection_display.selection();
+ TrackSelection::iterator i;
+
+ if (selected.empty() || selection->tracks.empty()) {
+ return;
+ }
+
+ NamedSelection* ns = static_cast<NamedSelection*> (selected.front()->get_data ());
+ list<Playlist*>::iterator chunk;
+ list<Playlist*>::iterator tmp;
+
+ chunk = ns->playlists.begin();
+
+ begin_reversible_command (_("paste chunk"));
+
+ for (i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+
+ AudioTimeAxisView* atv;
+ Playlist* pl;
+ AudioPlaylist* apl;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
+ continue;
+ }
+
+ if ((pl = atv->playlist()) == 0) {
+ continue;
+ }
+
+ if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
+ continue;
+ }
+
+ tmp = chunk;
+ ++tmp;
+
+ session->add_undo (apl->get_memento());
+ apl->paste (**chunk, edit_cursor->current_frame, times);
+ session->add_redo_no_execute (apl->get_memento());
+
+ if (tmp != ns->playlists.end()) {
+ chunk = tmp;
+ }
+ }
+
+ commit_reversible_command();
+}
+
+void
+Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
+{
+ Playlist *playlist;
+
+ begin_reversible_command (_("duplicate region"));
+
+ for (AudioRegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
+
+ Region& r ((*i)->region);
+
+ playlist = (*i)->region.playlist();
+ session->add_undo (playlist->get_memento());
+ playlist->duplicate (r, r.last_frame(), times);
+ session->add_redo_no_execute (playlist->get_memento());
+
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::duplicate_selection (float times)
+{
+ if (selection->time.empty() || selection->tracks.empty()) {
+ return;
+ }
+
+ Playlist *playlist;
+ vector<AudioRegion*> new_regions;
+ vector<AudioRegion*>::iterator ri;
+
+ create_region_from_selection (new_regions);
+
+ if (new_regions.empty()) {
+ return;
+ }
+
+ begin_reversible_command (_("duplicate selection"));
+
+ ri = new_regions.begin();
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ if ((playlist = (*i)->playlist()) == 0) {
+ continue;
+ }
+ session->add_undo (playlist->get_memento());
+ playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
+ session->add_redo_no_execute (playlist->get_memento());
+
+ ++ri;
+ if (ri == new_regions.end()) {
+ --ri;
+ }
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::center_playhead ()
+{
+ float page = canvas_width * frames_per_unit;
+
+ center_screen_internal (playhead_cursor->current_frame, page);
+}
+
+void
+Editor::center_edit_cursor ()
+{
+ float page = canvas_width * frames_per_unit;
+
+ center_screen_internal (edit_cursor->current_frame, page);
+}
+
+void
+Editor::clear_playlist (Playlist& playlist)
+{
+ begin_reversible_command (_("clear playlist"));
+ session->add_undo (playlist.get_memento());
+ playlist.clear ();
+ session->add_redo_no_execute (playlist.get_memento());
+ commit_reversible_command ();
+}
+
+void
+Editor::nudge_track (bool use_edit_cursor, bool forwards)
+{
+ Playlist *playlist;
+ jack_nframes_t distance;
+ jack_nframes_t next_distance;
+ jack_nframes_t start;
+
+ if (use_edit_cursor) {
+ start = edit_cursor->current_frame;
+ } else {
+ start = 0;
+ }
+
+ if ((distance = get_nudge_distance (start, next_distance)) == 0) {
+ return;
+ }
+
+ if (selection->tracks.empty()) {
+ return;
+ }
+
+ begin_reversible_command (_("nudge track"));
+
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+
+ if ((playlist = (*i)->playlist()) == 0) {
+ continue;
+ }
+
+ session->add_undo (playlist->get_memento());
+ playlist->nudge_after (start, distance, forwards);
+ session->add_redo_no_execute (playlist->get_memento());
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::toggle_xfades_active ()
+{
+ if (session) {
+ session->set_crossfades_active (!session->get_crossfades_active());
+ }
+}
+
+void
+Editor::toggle_follow_playhead ()
+{
+ set_follow_playhead (!_follow_playhead);
+}
+
+void
+Editor::set_xfade_visibility (bool yn)
+{
+
+}
+
+void
+Editor::toggle_xfade_visibility ()
+{
+ set_xfade_visibility (!xfade_visibility());
+}
+
+void
+Editor::remove_last_capture ()
+{
+ vector<string> choices;
+ string prompt;
+
+ if (!session) {
+ return;
+ }
+
+ if (Config->get_verify_remove_last_capture()) {
+ prompt = _("Do you really want to destroy the last capture?"
+ "\n(This is destructive and cannot be undone)");
+
+ choices.push_back (_("Yes, destroy it."));
+ choices.push_back (_("No, do nothing."));
+
+ Gtkmmext::Choice prompter (prompt, choices);
+
+ prompter.chosen.connect (Gtk::Main::quit.slot());
+ prompter.show_all ();
+
+ Gtk::Main::run ();
+
+ if (prompter.get_choice() == 0) {
+ session->remove_last_capture ();
+ }
+ } else {
+ session->remove_last_capture();
+ }
+}
+
+void
+Editor::normalize_region ()
+{
+ if (!session) {
+ return;
+ }
+
+ if (selection->audio_regions.empty()) {
+ return;
+ }
+
+ begin_reversible_command (_("normalize"));
+
+ track_canvas_scroller.get_window().set_cursor (wait_cursor);
+ gdk_flush ();
+
+ for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
+ session->add_undo ((*r)->region.get_memento());
+ (*r)->region.normalize_to (0.0f);
+ session->add_redo_no_execute ((*r)->region.get_memento());
+ }
+
+ commit_reversible_command ();
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor);
+}
+
+
+void
+Editor::denormalize_region ()
+{
+ if (!session) {
+ return;
+ }
+
+ if (selection->audio_regions.empty()) {
+ return;
+ }
+
+ begin_reversible_command ("denormalize");
+
+ for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
+ session->add_undo ((*r)->region.get_memento());
+ (*r)->region.set_scale_amplitude (1.0f);
+ session->add_redo_no_execute ((*r)->region.get_memento());
+ }
+
+ commit_reversible_command ();
+}
+
+
+void
+Editor::reverse_region ()
+{
+ if (!session) {
+ return;
+ }
+
+ Reverse rev (*session);
+ apply_filter (rev, _("reverse regions"));
+}
+
+void
+Editor::apply_filter (AudioFilter& filter, string command)
+{
+ if (selection->audio_regions.empty()) {
+ return;
+ }
+
+ begin_reversible_command (command);
+
+ track_canvas_scroller.get_window().set_cursor (wait_cursor);
+ gdk_flush ();
+
+ for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
+
+ AudioRegion& region ((*r)->region);
+ Playlist* playlist = region.playlist();
+
+ AudioRegionSelection::iterator tmp;
+
+ tmp = r;
+ ++tmp;
+
+ if (region.apply (filter) == 0) {
+
+ session->add_undo (playlist->get_memento());
+ playlist->replace_region (region, *(filter.results.front()), region.position());
+ session->add_redo_no_execute (playlist->get_memento());
+ } else {
+ goto out;
+ }
+
+ r = tmp;
+ }
+
+ commit_reversible_command ();
+ selection->audio_regions.clear ();
+
+ out:
+ gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor);
+}
+
+void
+Editor::region_selection_op (void (Region::*pmf)(void))
+{
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ ((*i)->region.*pmf)();
+ }
+}
+
+
+void
+Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
+{
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ ((*i)->region.*pmf)(arg);
+ }
+}
+
+void
+Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
+{
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ ((*i)->region.*pmf)(yn);
+ }
+}
+
+void
+Editor::external_edit_region ()
+{
+ if (!clicked_regionview) {
+ return;
+ }
+
+ /* more to come */
+}
+
+void
+Editor::brush (jack_nframes_t pos)
+{
+ AudioRegionSelection sel;
+ snap_to (pos);
+
+ if (selection->audio_regions.empty()) {
+ /* XXX get selection from region list */
+ } else {
+ sel = selection->audio_regions;
+ }
+
+ if (sel.empty()) {
+ return;
+ }
+
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ mouse_brush_insert_region ((*i), pos);
+ }
+}
+
+void
+Editor::toggle_gain_envelope_visibility ()
+{
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ (*i)->set_envelope_visible (!(*i)->envelope_visible());
+ }
+}
+
+void
+Editor::toggle_gain_envelope_active ()
+{
+ for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
+ AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
+ if (ar) {
+ ar->set_envelope_active (true);
+ }
+ }
+}
diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc
new file mode 100644
index 0000000000..cd7b1a5995
--- /dev/null
+++ b/gtk2_ardour/editor_region_list.cc
@@ -0,0 +1,925 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+#include <algorithm>
+#include <string>
+
+#include <pbd/basename.h>
+
+#include <ardour/audioregion.h>
+#include <ardour/session_region.h>
+
+#include <gtkmmext/stop_signal.h>
+
+#include "editor.h"
+#include "editing.h"
+#include "ardour_ui.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Editing;
+
+#define wave_cursor_width 43
+#define wave_cursor_height 61
+#define wave_cursor_x_hot 0
+#define wave_cursor_y_hot 25
+static const gchar wave_cursor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
+0x03,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x02,
+ 0x02, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x00, 0x04, 0x00,
+0x02,
+ 0x02, 0x04, 0x00, 0x04, 0x00, 0x02, 0x02, 0x0c, 0x08, 0x0c, 0x00,
+0x02,
+ 0x02, 0x1c, 0x08, 0x0c, 0x00, 0x02, 0x02, 0x1c, 0x08, 0x0c, 0x04,
+0x02,
+ 0x02, 0x3c, 0x18, 0x0c, 0x04, 0x02, 0x02, 0x7c, 0x18, 0x1c, 0x0c,
+0x02,
+ 0x82, 0xfc, 0x38, 0x1c, 0x0c, 0x02, 0xc2, 0xfc, 0x78, 0x3c, 0x1c,
+0x02,
+ 0xe2, 0xfd, 0xf9, 0x7d, 0x1c, 0x02, 0xf2, 0xff, 0xfb, 0xff, 0x1c,
+0x02,
+ 0xfa, 0xff, 0xfb, 0xff, 0x3f, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff,
+0x03,
+ 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfa, 0xff, 0xff, 0xff, 0x3f,
+0x02,
+ 0xf2, 0xff, 0xfb, 0xfd, 0x3c, 0x02, 0xe2, 0xfd, 0x7b, 0x7c, 0x1c,
+0x02,
+ 0xc2, 0xfc, 0x39, 0x3c, 0x1c, 0x02, 0x82, 0xfc, 0x18, 0x1c, 0x1c,
+0x02,
+ 0x02, 0xfc, 0x18, 0x1c, 0x0c, 0x02, 0x02, 0x7c, 0x18, 0x0c, 0x0c,
+0x02,
+ 0x02, 0x3c, 0x08, 0x0c, 0x04, 0x02, 0x02, 0x1c, 0x08, 0x0c, 0x04,
+0x02,
+ 0x02, 0x1c, 0x08, 0x0c, 0x00, 0x02, 0x02, 0x0c, 0x00, 0x04, 0x00,
+0x02,
+ 0x02, 0x04, 0x00, 0x04, 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00,
+0x02,
+ 0x02, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff,
+0x03,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+#define wave_cursor_mask_width 43
+#define wave_cursor_mask_height 61
+#define wave_cursor_mask_x_hot 0
+#define wave_cursor_mask_y_hot 25
+static const gchar wave_cursor_mask_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+0x00,
+ 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x08, 0x0c, 0x00,
+0x00,
+ 0x00, 0x1c, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x0c, 0x04,
+0x00,
+ 0x00, 0x3c, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x7c, 0x18, 0x1c, 0x0c,
+0x00,
+ 0x80, 0xfc, 0x38, 0x1c, 0x0c, 0x00, 0xc0, 0xfc, 0x78, 0x3c, 0x1c,
+0x00,
+ 0xe0, 0xfd, 0xf9, 0x7d, 0x1c, 0x00, 0xf0, 0xff, 0xfb, 0xff, 0x1c,
+0x00,
+ 0xf8, 0xff, 0xfb, 0xff, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x07,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0x3f,
+0x00,
+ 0xf0, 0xff, 0xfb, 0xfd, 0x3c, 0x00, 0xe0, 0xfd, 0x7b, 0x7c, 0x1c,
+0x00,
+ 0xc0, 0xfc, 0x39, 0x3c, 0x1c, 0x00, 0x80, 0xfc, 0x18, 0x1c, 0x1c,
+0x00,
+ 0x00, 0xfc, 0x18, 0x1c, 0x0c, 0x00, 0x00, 0x7c, 0x18, 0x0c, 0x0c,
+0x00,
+ 0x00, 0x3c, 0x08, 0x0c, 0x04, 0x00, 0x00, 0x1c, 0x08, 0x0c, 0x04,
+0x00,
+ 0x00, 0x1c, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00,
+0x00,
+ 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+GdkCursor *wave_cursor = 0;
+
+void
+Editor::handle_audio_region_removed (AudioRegion* ignored)
+{
+ redisplay_regions ();
+}
+
+void
+Editor::handle_new_audio_region (AudioRegion *region)
+{
+ /* don't copy region - the one we are being notified
+ about belongs to the session, and so it will
+ never be edited.
+ */
+ add_audio_region_to_region_display (region);
+}
+
+void
+Editor::region_hidden (Region* r)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::region_hidden), r));
+
+ redisplay_regions ();
+}
+
+void
+Editor::add_audio_region_to_region_display (AudioRegion *region)
+{
+ using namespace Gtk::CTree_Helpers;
+
+ vector<const char*> item;
+ RowList::iterator i;
+ RowList::iterator tmpi;
+ string str;
+
+ if (!show_automatic_regions_in_region_list && region->automatic()) {
+ return;
+ }
+
+ if (region->hidden()) {
+
+ if (region_list_hidden_node == region_list_display.rows().end()) {
+ item.clear ();
+ item.push_back (_("hidden"));
+ region_list_hidden_node = region_list_display.rows().insert (region_list_display.rows().end(),
+ Element (item));
+ (*region_list_hidden_node).set_data (0);
+ (*region_list_hidden_node).set_leaf (false);
+ }
+
+ item.clear ();
+ if (region->n_channels() > 1) {
+ str = compose("%1 [%2]", region->name(), region->n_channels());
+ item.push_back (str.c_str());
+ } else {
+ item.push_back (region->name().c_str());
+ }
+
+ tmpi = region_list_hidden_node->subtree().insert (region_list_hidden_node->subtree().end(),
+ Element (item));
+ (*tmpi).set_data (region);
+ return;
+
+ } else if (region->whole_file()) {
+
+ item.clear ();
+
+ if (region->source().name()[0] == '/') { // external file
+
+ if (region->whole_file()) {
+ str = ".../";
+ str += PBD::basename_nosuffix (region->source().name());
+ } else {
+ str = region->name();
+ }
+
+ } else {
+
+ str = region->name();
+
+ }
+
+ item.push_back (str.c_str());
+
+ tmpi = region_list_display.rows().insert (region_list_display.rows().end(),
+ Element (item));
+
+ (*tmpi).set_data (region);
+ (*tmpi).set_leaf (false);
+
+ return;
+
+ } else {
+
+ /* find parent node, add as new child */
+
+ for (i = region_list_display.rows().begin(); i != region_list_display.rows().end(); ++i) {
+
+ AudioRegion* r = static_cast<AudioRegion*> ((*i).get_data());
+
+ if (r && r->whole_file()) {
+
+ if (region->source_equivalent (*r)) {
+
+ item.clear ();
+
+ if (region->n_channels() > 1) {
+ str = compose("%1 [%2]", region->name(), region->n_channels());
+ item.push_back (str.c_str());
+ } else {
+ item.push_back (region->name().c_str());
+ }
+
+
+ tmpi = i->subtree().insert (i->subtree().end(), Element (item));
+ (*tmpi).set_data (region);
+
+ return;
+ }
+ }
+ }
+ }
+
+ item.clear ();
+
+ if (region->n_channels() > 1) {
+ str = compose("%1 [%2]", region->name(), region->n_channels());
+ item.push_back (str.c_str());
+ } else {
+ item.push_back (region->name().c_str());
+ }
+
+ tmpi = region_list_display.rows().insert (region_list_display.rows().end(), Element (item));
+ (*tmpi).set_data (region);
+ (*tmpi).set_leaf (true);
+}
+
+void
+Editor::insert_into_tmp_audio_regionlist(AudioRegion* region)
+{
+ /* keep all whole files at the beginning */
+
+ if (region->whole_file()) {
+ tmp_audio_region_list.push_front (region);
+ } else {
+ tmp_audio_region_list.push_back (region);
+ }
+}
+
+void
+Editor::redisplay_regions ()
+{
+ if (session) {
+ region_list_display.freeze ();
+ region_list_clear ();
+ region_list_hidden_node = region_list_display.rows().end();
+
+ /* now add everything we have, via a temporary list used to help with
+ sorting.
+ */
+
+ tmp_audio_region_list.clear();
+ session->foreach_audio_region (this, &Editor::insert_into_tmp_audio_regionlist);
+
+ for (list<AudioRegion*>::iterator r = tmp_audio_region_list.begin(); r != tmp_audio_region_list.end(); ++r) {
+ add_audio_region_to_region_display (*r);
+ }
+
+ region_list_display.sort ();
+ region_list_display.thaw ();
+ }
+}
+
+void
+Editor::region_list_clear ()
+{
+ /* ---------------------------------------- */
+ /* XXX MAKE ME A FUNCTION (no CTree::clear() in gtkmm 1.2) */
+
+ gtk_ctree_remove_node (region_list_display.gtkobj(), NULL);
+
+ /* ---------------------------------------- */
+}
+
+void
+Editor::region_list_column_click (gint col)
+{
+ bool sensitive;
+
+ if (region_list_menu == 0) {
+ build_region_list_menu ();
+ }
+
+ if (region_list_display.selection().size() != 0) {
+ sensitive = true;
+ } else {
+ sensitive = false;
+ }
+
+ for (vector<MenuItem*>::iterator i = rl_context_menu_region_items.begin(); i != rl_context_menu_region_items.end(); ++i) {
+ (*i)->set_sensitive (sensitive);
+ }
+
+ region_list_menu->popup (0, 0);
+}
+
+void
+Editor::build_region_list_menu ()
+{
+ using namespace Gtk::Menu_Helpers;
+
+ region_list_menu = new Menu;
+
+ MenuList& items = region_list_menu->items();
+ region_list_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Audition"), slot (*this, &Editor::audition_region_from_region_list)));
+ rl_context_menu_region_items.push_back (items.back());
+ items.push_back (MenuElem (_("Hide"), slot (*this, &Editor::hide_region_from_region_list)));
+ rl_context_menu_region_items.push_back (items.back());
+ items.push_back (MenuElem (_("Remove"), slot (*this, &Editor::remove_region_from_region_list)));
+ rl_context_menu_region_items.push_back (items.back());
+
+
+ items.push_back (SeparatorElem());
+
+
+ // items.push_back (MenuElem (_("Find")));
+ items.push_back (CheckMenuElem (_("Show all"), slot (*this, &Editor::toggle_full_region_list)));
+ toggle_full_region_list_item = static_cast<CheckMenuItem*> (items.back());
+
+ Gtk::Menu *sort_menu = manage (new Menu);
+ MenuList& sort_items = sort_menu->items();
+ sort_menu->set_name ("ArdourContextMenu");
+ RadioMenuItem::Group sort_order_group;
+ RadioMenuItem::Group sort_type_group;
+
+ sort_items.push_back (RadioMenuElem (sort_order_group, _("Ascending"),
+ bind (slot (*this, &Editor::reset_region_list_sort_direction), true)));
+ sort_items.push_back (RadioMenuElem (sort_order_group, _("Descending"),
+ bind (slot (*this, &Editor::reset_region_list_sort_direction), false)));
+ sort_items.push_back (SeparatorElem());
+
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Name"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), ByName)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Length"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), ByLength)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Position"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), ByPosition)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Timestamp"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), ByTimestamp)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Start in File"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), ByStartInFile)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region End in File"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), ByEndInFile)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Name"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), BySourceFileName)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Length"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), BySourceFileLength)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Creation Date"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), BySourceFileCreationDate)));
+ sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source Filesystem"),
+ bind (slot (*this, &Editor::reset_region_list_sort_type), BySourceFileFS)));
+
+ items.push_back (MenuElem (_("Sorting"), *sort_menu));
+ items.push_back (SeparatorElem());
+
+// items.push_back (CheckMenuElem (_("Display Automatic Regions"), slot (*this, &Editor::toggle_show_auto_regions)));
+// toggle_auto_regions_item = static_cast<CheckMenuItem*> (items.back());
+// toggle_auto_regions_item->set_active (show_automatic_regions_in_region_list);
+// items.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Import audio (copy)"), bind (slot (*this, &Editor::import_audio), false)));
+ import_audio_item = items.back();
+ if (!session) {
+ import_audio_item->set_sensitive (false);
+ }
+ items.push_back (MenuElem (_("Embed audio (link)"), slot (*this, &Editor::embed_audio)));
+ embed_audio_item = items.back();
+ if (!session) {
+ embed_audio_item->set_sensitive (false);
+ }
+}
+
+void
+Editor::toggle_show_auto_regions ()
+{
+ //show_automatic_regions_in_region_list = toggle_auto_regions_item->get_active();
+ show_automatic_regions_in_region_list = true;
+ redisplay_regions ();
+}
+
+void
+Editor::toggle_full_region_list ()
+{
+ region_list_display.freeze ();
+ if (toggle_full_region_list_item->get_active()) {
+ for (CTree_Helpers::RowIterator r = region_list_display.rows().begin(); r != region_list_display.rows().end(); ++r) {
+ r->expand_recursive ();
+ }
+ } else {
+ for (CTree_Helpers::RowIterator r = region_list_display.rows().begin(); r != region_list_display.rows().end(); ++r) {
+ r->collapse ();
+ }
+ }
+ region_list_display.thaw ();
+}
+
+gint
+Editor::region_list_display_key_press (GdkEventKey* ev)
+{
+ return FALSE;
+}
+
+gint
+Editor::region_list_display_key_release (GdkEventKey* ev)
+{
+ switch (ev->keyval) {
+ case GDK_Delete:
+ remove_selected_regions_from_region_list ();
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+
+}
+
+gint
+Editor::region_list_display_button_press (GdkEventButton *ev)
+{
+ int row, col;
+ AudioRegion *region;
+
+ if (Keyboard::is_delete_event (ev)) {
+ if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
+ if ((region = (AudioRegion *) region_list_display.row(row).get_data()) != 0) {
+ delete region;
+ }
+ }
+ return TRUE;
+ }
+
+ if (Keyboard::is_context_menu_event (ev)) {
+ region_list_column_click (-1);
+ return TRUE;
+ }
+
+ switch (ev->button) {
+ case 1:
+ if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
+ if ((region = (AudioRegion *) region_list_display.row(row).get_data()) != 0) {
+
+ if (wave_cursor == 0) {
+ GdkPixmap *source, *mask;
+ GdkColor fg = { 0, 65535, 0, 0 }; /* Red. */
+ GdkColor bg = { 0, 0, 0, 65535 }; /* Blue. */
+
+ source = gdk_bitmap_create_from_data (NULL, wave_cursor_bits,
+ wave_cursor_width, wave_cursor_height);
+ mask = gdk_bitmap_create_from_data (NULL, wave_cursor_mask_bits,
+ wave_cursor_mask_width, wave_cursor_mask_height);
+
+ wave_cursor = gdk_cursor_new_from_pixmap (source,
+ mask,
+ &fg,
+ &bg,
+ wave_cursor_x_hot,
+ wave_cursor_y_hot);
+ gdk_pixmap_unref (source);
+ gdk_pixmap_unref (mask);
+ }
+ region_list_display_drag_region = region;
+ need_wave_cursor = 1;
+
+ /* audition on double click */
+ if (ev->type == GDK_2BUTTON_PRESS) {
+ consider_auditioning (region);
+ }
+
+ return TRUE;
+ }
+
+ }
+ break;
+
+ case 2:
+ if (!Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
+ if ((region = (AudioRegion *) region_list_display.get_row_data (row)) != 0) {
+ if (consider_auditioning (region)) {
+ region_list_display.row(row).select();
+ }
+ else {
+ region_list_display.row(row).unselect();
+ }
+ return TRUE;
+ }
+ }
+ }
+
+ /* to prevent regular selection -- i dont think this is needed JLC */
+ return stop_signal (region_list_display, "button_press_event");
+ break;
+
+ case 3:
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+Editor::region_list_display_button_release (GdkEventButton *ev)
+{
+ int row, col;
+
+ if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
+ region_list_button_region = (AudioRegion *) region_list_display.get_row_data (row);
+ } else {
+ region_list_button_region = 0;
+ }
+
+ if (Keyboard::is_delete_event (ev)) {
+ remove_region_from_region_list ();
+ return TRUE;
+ }
+
+ switch (ev->button) {
+ case 1:
+ if (region_list_display_drag_region) {
+ insert_region_list_drag (*region_list_display_drag_region);
+ }
+
+ track_canvas_scroller.get_window().set_cursor (current_canvas_cursor);
+ region_list_display.get_window().set_cursor (0);
+
+ region_list_display_drag_region = 0;
+ need_wave_cursor = 0;
+
+ return TRUE;
+ break;
+
+ case 3:
+ if (!Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+
+ if (region_list_menu == 0) {
+ build_region_list_menu ();
+ }
+
+ bool sensitive;
+
+ if (region_list_display.selection().size() != 0) {
+ sensitive = true;
+ } else {
+ sensitive = false;
+ }
+
+ for (vector<MenuItem*>::iterator i = rl_context_menu_region_items.begin(); i != rl_context_menu_region_items.end(); ++i) {
+ (*i)->set_sensitive (sensitive);
+ }
+
+ region_list_menu->popup (0, 0);
+ }
+
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+gint
+Editor::region_list_display_motion (GdkEventMotion *ev)
+{
+ if (need_wave_cursor == 1) {
+ track_canvas_scroller.get_window().set_cursor (wave_cursor);
+ region_list_display.get_window().set_cursor (wave_cursor);
+ gdk_flush ();
+ need_wave_cursor = 2;
+ }
+ return FALSE;
+}
+
+void
+Editor::region_list_display_selected (gint row, gint col, GdkEvent *ev)
+{
+ AudioRegion* region = static_cast<AudioRegion *>(region_list_display.get_row_data (row));
+
+ if (session == 0 || region == 0) {
+ return;
+ }
+
+ set_selected_regionview_from_region_list (*region, false);
+}
+
+void
+Editor::region_list_display_unselected (gint row, gint col, GdkEvent *ev)
+{
+}
+
+bool
+Editor::consider_auditioning (AudioRegion *r)
+{
+ if (r == 0) {
+ session->cancel_audition ();
+ return false;
+ }
+
+ if (session->is_auditioning()) {
+ session->cancel_audition ();
+ if (r == last_audition_region) {
+ return false;
+ }
+ }
+
+ session->audition_region (*r);
+ last_audition_region = r;
+
+ return true;
+}
+
+gint
+Editor::region_list_display_enter_notify (GdkEventCrossing *ev)
+{
+ ARDOUR_UI::instance()->allow_focus (true);
+ region_list_display.grab_focus ();
+ return FALSE;
+}
+
+gint
+Editor::region_list_display_leave_notify (GdkEventCrossing *ev)
+{
+ ARDOUR_UI::instance()->allow_focus (false);
+ return FALSE;
+}
+
+gint
+Editor::_region_list_sorter (GtkCList* clist, gconstpointer a, gconstpointer b)
+{
+ Editor* editor = static_cast<Editor*> (gtk_object_get_data (GTK_OBJECT(clist), "editor"));
+ return editor->region_list_sorter (a, b);
+}
+
+gint
+Editor::region_list_sorter (gconstpointer a, gconstpointer b)
+{
+ GtkCListRow* row1 = (GtkCListRow *) a;
+ GtkCListRow* row2 = (GtkCListRow *) b;
+
+ AudioRegion* region1 = static_cast<AudioRegion*> (row1->data);
+ AudioRegion* region2 = static_cast<AudioRegion*> (row2->data);
+
+ if (region1 == 0 || region2 == 0) {
+ switch (region_list_sort_type) {
+ case ByName:
+ return true; /* XXX compare text in rows */
+ default:
+ return true;
+ }
+ }
+
+ switch (region_list_sort_type) {
+ case ByName:
+ return strcasecmp (region1->name().c_str(), region2->name().c_str());
+ break;
+
+ case ByLength:
+ return region1->length() - region2->length();
+ break;
+
+ case ByPosition:
+ return region1->position() - region2->position();
+ break;
+
+ case ByTimestamp:
+ return region1->source().timestamp() - region2->source().timestamp();
+ break;
+
+ case ByStartInFile:
+ return region1->start() - region2->start();
+ break;
+
+ case ByEndInFile:
+ return (region1->start() + region1->length()) - (region2->start() + region2->length());
+ break;
+
+ case BySourceFileName:
+ return strcasecmp (region1->source().name().c_str(), region2->source().name().c_str());
+ break;
+
+ case BySourceFileLength:
+ return region1->source().length() - region2->source().length();
+ break;
+
+ case BySourceFileCreationDate:
+ return region1->source().timestamp() - region2->source().timestamp();
+ break;
+
+ case BySourceFileFS:
+ if (region1->source().name() == region2->source().name()) {
+ return strcasecmp (region1->name().c_str(), region2->name().c_str());
+ } else {
+ return strcasecmp (region1->source().name().c_str(), region2->source().name().c_str());
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+void
+Editor::reset_region_list_sort_type (RegionListSortType type)
+{
+ if (type != region_list_sort_type) {
+ region_list_sort_type = type;
+
+ switch (type) {
+ case ByName:
+ region_list_display.set_column_title(0, _("Regions/name"));
+ break;
+
+ case ByLength:
+ region_list_display.set_column_title (0, _("Regions/length"));
+ break;
+
+ case ByPosition:
+ region_list_display.set_column_title (0, _("Regions/position"));
+ break;
+
+ case ByTimestamp:
+ region_list_display.set_column_title (0, _("Regions/creation"));
+ break;
+
+ case ByStartInFile:
+ region_list_display.set_column_title (0, _("Regions/start"));
+ break;
+
+ case ByEndInFile:
+ region_list_display.set_column_title (0, _("Regions/end"));
+ break;
+
+ case BySourceFileName:
+ region_list_display.set_column_title (0, _("Regions/file name"));
+ break;
+
+ case BySourceFileLength:
+ region_list_display.set_column_title (0, _("Regions/file size"));
+ break;
+
+ case BySourceFileCreationDate:
+ region_list_display.set_column_title (0, _("Regions/file date"));
+ break;
+
+ case BySourceFileFS:
+ region_list_display.set_column_title (0, _("Regions/file system"));
+ break;
+ }
+
+ region_list_display.sort ();
+ }
+}
+
+void
+Editor::reset_region_list_sort_direction (bool up)
+{
+ region_list_display.set_sort_type (up ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING);
+ region_list_display.sort ();
+}
+
+void
+Editor::audition_region_from_region_list ()
+{
+ if (region_list_button_region) {
+ consider_auditioning (dynamic_cast<AudioRegion*> (region_list_button_region));
+ }
+}
+
+void
+Editor::hide_region_from_region_list ()
+{
+ if (session == 0 || region_list_button_region == 0) {
+ return;
+ }
+
+ region_list_button_region->set_hidden (true);
+}
+
+void
+Editor::remove_region_from_region_list ()
+{
+ if (session == 0 || region_list_button_region == 0) {
+ return;
+ }
+
+ session->remove_region_from_region_list (*region_list_button_region);
+}
+
+void
+Editor::remove_selected_regions_from_region_list ()
+{
+ using namespace Gtk::CTree_Helpers;
+ SelectionList& selected = region_list_display.selection();
+
+ /* called from idle context to avoid snafus with the list
+ state.
+ */
+
+ if (selected.empty() || session == 0) {
+ return;
+ }
+
+ vector<Region*> to_be_deleted;
+
+ for (SelectionList::iterator i = selected.begin(); i != selected.end(); ++i) {
+ to_be_deleted.push_back (static_cast<Region*> ((*i).get_data()));
+ }
+
+ for (vector<Region*>::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) {
+ session->remove_region_from_region_list (**i);
+ }
+
+ return;
+}
+
+void
+Editor::region_list_display_drag_data_received (GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint info,
+ guint time)
+{
+ vector<string> paths;
+
+ if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) {
+ do_embed_sndfiles (paths, false);
+ }
+
+ gtk_drag_finish (context, TRUE, FALSE, time);
+}
diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc
new file mode 100644
index 0000000000..e0bf98f26f
--- /dev/null
+++ b/gtk2_ardour/editor_route_list.cc
@@ -0,0 +1,444 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+#include <cstdlib>
+#include <cmath>
+
+#include "editor.h"
+#include "ardour_ui.h"
+#include "audio_time_axis.h"
+#include "mixer_strip.h"
+#include "gui_thread.h"
+
+#include <ardour/route.h>
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+
+void
+Editor::handle_new_route_p (Route* route)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::handle_new_route_p), route));
+ handle_new_route (*route);
+}
+
+void
+Editor::handle_new_route (Route& route)
+{
+ TimeAxisView *tv;
+ AudioTimeAxisView *atv;
+ const gchar *rowdata[1];
+
+ if (route.hidden()) {
+ return;
+ }
+
+ tv = new AudioTimeAxisView (*this, *session, route, track_canvas);
+
+ track_views.push_back (tv);
+
+ rowdata[0] = route.name ().c_str();
+
+ ignore_route_list_reorder = true;
+ route_list.rows().push_back (rowdata);
+ route_list.rows().back().set_data (tv);
+ if (tv->marked_for_display()) {
+ route_list.rows().back().select();
+ }
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> (tv)) != 0) {
+ /* added a new fresh one at the end */
+ if (atv->route().order_key(N_("editor")) == -1) {
+ atv->route().set_order_key (N_("editor"), route_list.rows().size()-1);
+ }
+ }
+
+ ignore_route_list_reorder = false;
+
+ route.gui_changed.connect (slot (*this, &Editor::handle_gui_changes));
+
+ tv->GoingAway.connect (bind (slot (*this, &Editor::remove_route), tv));
+
+ editor_mixer_button.set_sensitive(true);
+
+}
+
+void
+Editor::handle_gui_changes (string what, void *src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::handle_gui_changes), what, src));
+
+ if (what == "track_height") {
+ route_list_reordered ();
+ }
+}
+
+void
+Editor::remove_route (TimeAxisView *tv)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::remove_route), tv));
+
+ TrackViewList::iterator i;
+ CList_Helpers::RowList::iterator ri;
+
+ if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
+ track_views.erase (i);
+ }
+
+ for (ri = route_list.rows().begin(); ri != route_list.rows().end(); ++ri) {
+ if (tv == ri->get_data()) {
+ route_list.rows().erase (ri);
+ break;
+ }
+ }
+ /* since the editor mixer goes away when you remove a route, set the
+ * button to inacttive
+ */
+ editor_mixer_button.set_active(false);
+
+ /* and disable if all tracks and/or routes are gone */
+
+ if (track_views.size() == 0) {
+ editor_mixer_button.set_sensitive(false);
+ }
+}
+
+void
+Editor::route_name_changed (TimeAxisView *tv)
+{
+ CList_Helpers::RowList::iterator i;
+ gint row;
+
+ for (row = 0, i = route_list.rows().begin(); i != route_list.rows().end(); ++i, ++row) {
+ if (tv == i->get_data()) {
+ route_list.cell (row, 0).set_text (tv->name());
+ break;
+ }
+ }
+}
+
+void
+Editor::route_list_selected (gint row, gint col, GdkEvent *ev)
+{
+ TimeAxisView *tv;
+ if ((tv = (TimeAxisView *) route_list.get_row_data (row)) != 0) {
+ tv->set_marked_for_display (true);
+ route_list_reordered ();
+ }
+}
+
+void
+Editor::route_list_unselected (gint row, gint col, GdkEvent *ev)
+{
+ TimeAxisView *tv;
+ AudioTimeAxisView *atv;
+
+ if ((tv = (TimeAxisView *) route_list.get_row_data (row)) != 0) {
+
+ tv->set_marked_for_display (false);
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
+ if (current_mixer_strip && &(atv->route()) == &(current_mixer_strip->route())) {
+ /* this will hide the mixer strip */
+ set_selected_mixer_strip(*atv);
+ }
+ }
+
+ route_list_reordered ();
+ }
+}
+
+void
+Editor::unselect_strip_in_display (TimeAxisView& tv)
+{
+ CList_Helpers::RowIterator i;
+
+ if ((i = route_list.rows().find_data (&tv)) != route_list.rows().end()) {
+ (*i).unselect ();
+ }
+}
+
+void
+Editor::select_strip_in_display (TimeAxisView& tv)
+{
+ CList_Helpers::RowIterator i;
+
+ if ((i = route_list.rows().find_data (&tv)) != route_list.rows().end()) {
+ (*i).select ();
+ }
+}
+
+void
+Editor::queue_route_list_reordered (gint arg1, gint arg2)
+
+{
+ /* the problem here is that we are called *before* the
+ list has been reordered. so just queue up
+ the actual re-drawer to happen once the re-ordering
+ is complete.
+ */
+
+ Main::idle.connect (slot (*this, &Editor::route_list_reordered));
+}
+
+void
+Editor::redisplay_route_list ()
+{
+ route_list_reordered ();
+}
+
+gint
+Editor::route_list_reordered ()
+{
+ CList_Helpers::RowList::iterator i;
+ gdouble y;
+ int n;
+
+ for (n = 0, y = 0, i = route_list.rows().begin(); i != route_list.rows().end(); ++i) {
+
+ TimeAxisView *tv = (TimeAxisView *) (*i)->get_data ();
+
+ AudioTimeAxisView* at;
+
+ if (!ignore_route_list_reorder) {
+
+ /* this reorder is caused by user action, so reassign sort order keys
+ to tracks.
+ */
+
+ if ((at = dynamic_cast<AudioTimeAxisView*> (tv)) != 0) {
+ at->route().set_order_key (N_("editor"), n);
+ }
+ }
+
+ if (tv->marked_for_display()) {
+ y += tv->show_at (y, n, &edit_controls_vbox);
+ y += track_spacing;
+ } else {
+ tv->hide ();
+ }
+
+ n++;
+ }
+
+ edit_controls_scroller.queue_resize ();
+ reset_scrolling_region ();
+
+ //gtk_canvas_item_raise_to_top (time_line_group);
+ gtk_canvas_item_raise_to_top (cursor_group);
+
+ return FALSE;
+}
+
+void
+Editor::hide_all_tracks (bool with_select)
+{
+ Gtk::CList_Helpers::RowList::iterator i;
+ Gtk::CList_Helpers::RowList& rowlist = route_list.rows();
+
+ route_list.freeze ();
+
+ for (i = rowlist.begin(); i != rowlist.end(); ++i) {
+ TimeAxisView *tv = (TimeAxisView *) i->get_data ();
+
+ if (with_select) {
+ i->unselect ();
+ } else {
+ tv->set_marked_for_display (false);
+ tv->hide();
+ }
+ }
+
+ route_list.thaw ();
+
+ reset_scrolling_region ();
+}
+
+void
+Editor::route_list_column_click (gint col)
+{
+ if (route_list_menu == 0) {
+ build_route_list_menu ();
+ }
+
+ route_list_menu->popup (0, 0);
+}
+
+void
+Editor::build_route_list_menu ()
+{
+ using namespace Gtk::Menu_Helpers;
+
+ route_list_menu = new Menu;
+
+ MenuList& items = route_list_menu->items();
+ route_list_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Show All"), slot (*this, &Editor::select_all_routes)));
+ items.push_back (MenuElem (_("Hide All"), slot (*this, &Editor::unselect_all_routes)));
+ items.push_back (MenuElem (_("Show All AbstractTracks"), slot (*this, &Editor::select_all_audiotracks)));
+ items.push_back (MenuElem (_("Hide All AbstractTracks"), slot (*this, &Editor::unselect_all_audiotracks)));
+ items.push_back (MenuElem (_("Show All AudioBus"), slot (*this, &Editor::select_all_audiobus)));
+ items.push_back (MenuElem (_("Hide All AudioBus"), slot (*this, &Editor::unselect_all_audiobus)));
+
+}
+
+void
+Editor::unselect_all_routes ()
+{
+ hide_all_tracks (true);
+}
+
+void
+Editor::select_all_routes ()
+
+{
+ CList_Helpers::RowList::iterator i;
+
+ for (i = route_list.rows().begin(); i != route_list.rows().end(); ++i) {
+ i->select ();
+ }
+}
+
+void
+Editor::select_all_audiotracks ()
+{
+ Gtk::CList_Helpers::RowList::iterator i;
+ Gtk::CList_Helpers::RowList& rowlist = route_list.rows();
+
+ route_list.freeze ();
+
+ for (i = rowlist.begin(); i != rowlist.end(); ++i) {
+ TimeAxisView *tv = (TimeAxisView *) i->get_data ();
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
+ if (atv->is_audio_track()) {
+ i->select ();
+ }
+ }
+ }
+
+ route_list.thaw ();
+
+}
+
+void
+Editor::unselect_all_audiotracks ()
+{
+ Gtk::CList_Helpers::RowList::iterator i;
+ Gtk::CList_Helpers::RowList& rowlist = route_list.rows();
+
+ route_list.freeze ();
+
+ for (i = rowlist.begin(); i != rowlist.end(); ++i) {
+ TimeAxisView *tv = (TimeAxisView *) i->get_data ();
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
+ if (atv->is_audio_track()) {
+ i->unselect ();
+ }
+ }
+ }
+
+ route_list.thaw ();
+
+}
+
+void
+Editor::select_all_audiobus ()
+{
+ Gtk::CList_Helpers::RowList::iterator i;
+ Gtk::CList_Helpers::RowList& rowlist = route_list.rows();
+
+ route_list.freeze ();
+
+ for (i = rowlist.begin(); i != rowlist.end(); ++i) {
+ TimeAxisView *tv = (TimeAxisView *) i->get_data ();
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
+ if (!atv->is_audio_track()) {
+ i->select ();
+ }
+ }
+ }
+
+ route_list.thaw ();
+
+}
+
+void
+Editor::unselect_all_audiobus ()
+{
+ Gtk::CList_Helpers::RowList::iterator i;
+ Gtk::CList_Helpers::RowList& rowlist = route_list.rows();
+
+ route_list.freeze ();
+
+ for (i = rowlist.begin(); i != rowlist.end(); ++i) {
+ TimeAxisView *tv = (TimeAxisView *) i->get_data ();
+ AudioTimeAxisView* atv;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
+ if (!atv->is_audio_track()) {
+ i->unselect ();
+ }
+ }
+ }
+
+ route_list.thaw ();
+
+}
+
+gint
+route_list_compare_func (GtkCList* clist, gconstpointer a, gconstpointer b)
+{
+ TimeAxisView *tv1;
+ TimeAxisView *tv2;
+ AudioTimeAxisView *atv1;
+ AudioTimeAxisView *atv2;
+ Route* ra;
+ Route* rb;
+
+ GtkCListRow *row1 = (GtkCListRow *) a;
+ GtkCListRow *row2 = (GtkCListRow *) b;
+
+ tv1 = static_cast<TimeAxisView*> (row1->data);
+ tv2 = static_cast<TimeAxisView*> (row2->data);
+
+ if ((atv1 = dynamic_cast<AudioTimeAxisView*>(tv1)) == 0 ||
+ (atv2 = dynamic_cast<AudioTimeAxisView*>(tv2)) == 0) {
+ return FALSE;
+ }
+
+ ra = &atv1->route();
+ rb = &atv2->route();
+
+ /* use of ">" forces the correct sort order */
+
+ return ra->order_key ("editor") > rb->order_key ("editor");
+}
+
diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc
new file mode 100644
index 0000000000..b8a236cb61
--- /dev/null
+++ b/gtk2_ardour/editor_rulers.cc
@@ -0,0 +1,1602 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdio> // for sprintf, grrr
+#include <cmath>
+
+#include <string>
+
+#include <ardour/tempo.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include "editor.h"
+#include "editing.h"
+#include "gtk-custom-hruler.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Editing;
+
+Editor *Editor::ruler_editor;
+
+/* the order here must match the "metric" enums in editor.h */
+
+GtkCustomMetric Editor::ruler_metrics[4] = {
+ {1, Editor::_metric_get_smpte },
+ {1, Editor::_metric_get_bbt },
+ {1, Editor::_metric_get_frames },
+ {1, Editor::_metric_get_minsec }
+};
+
+void
+Editor::initialize_rulers ()
+{
+ ruler_editor = this;
+ ruler_grabbed_widget = 0;
+
+ _smpte_ruler = gtk_custom_hruler_new ();
+ smpte_ruler = wrap (_smpte_ruler);
+ smpte_ruler->set_name ("SMPTERuler");
+ smpte_ruler->set_usize (-1, (int)timebar_height);
+ gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_smpte_ruler), &ruler_metrics[ruler_metric_smpte]);
+ ruler_shown[ruler_metric_smpte] = true;
+
+ _bbt_ruler = gtk_custom_hruler_new ();
+ bbt_ruler = wrap (_bbt_ruler);
+ bbt_ruler->set_name ("BBTRuler");
+ bbt_ruler->set_usize (-1, (int)timebar_height);
+ gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_bbt_ruler), &ruler_metrics[ruler_metric_bbt]);
+ ruler_shown[ruler_metric_bbt] = true;
+
+ _frames_ruler = gtk_custom_hruler_new ();
+ frames_ruler = wrap (_frames_ruler);
+ frames_ruler->set_name ("FramesRuler");
+ frames_ruler->set_usize (-1, (int)timebar_height);
+ gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_frames_ruler), &ruler_metrics[ruler_metric_frames]);
+
+ _minsec_ruler = gtk_custom_hruler_new ();
+ minsec_ruler = wrap (_minsec_ruler);
+ minsec_ruler->set_name ("MinSecRuler");
+ minsec_ruler->set_usize (-1, (int)timebar_height);
+ gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_minsec_ruler), &ruler_metrics[ruler_metric_minsec]);
+
+ ruler_shown[ruler_time_meter] = true;
+ ruler_shown[ruler_time_tempo] = true;
+ ruler_shown[ruler_time_marker] = true;
+ ruler_shown[ruler_time_range_marker] = true;
+ ruler_shown[ruler_time_transport_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->button_release_event.connect (slot (*this, &Editor::ruler_button_release));
+ bbt_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release));
+ frames_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release));
+ minsec_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release));
+
+ smpte_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press));
+ bbt_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press));
+ frames_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press));
+ minsec_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press));
+
+ smpte_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion));
+ bbt_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion));
+ frames_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion));
+ minsec_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion));
+
+ visible_timebars = 7; /* 4 here, 3 in time_canvas */
+ ruler_pressed_button = 0;
+}
+
+
+gint
+Editor::ruler_button_press (GdkEventButton* ev)
+{
+ if (session == 0) {
+ return FALSE;
+ }
+
+ ruler_pressed_button = ev->button;
+
+ // jlc: grab ev->window ?
+ //Gtk::Main::grab_add (*minsec_ruler);
+ Widget * grab_widget = 0;
+
+ if (smpte_ruler->is_realized() && ev->window == smpte_ruler->get_window()) grab_widget = smpte_ruler;
+ else if (bbt_ruler->is_realized() && ev->window == bbt_ruler->get_window()) grab_widget = bbt_ruler;
+ else if (frames_ruler->is_realized() && ev->window == frames_ruler->get_window()) grab_widget = frames_ruler;
+ else if (minsec_ruler->is_realized() && ev->window == minsec_ruler->get_window()) grab_widget = minsec_ruler;
+
+ if (grab_widget) {
+ Gtk::Main::grab_add (*grab_widget);
+ ruler_grabbed_widget = grab_widget;
+ }
+
+ return TRUE;
+}
+
+gint
+Editor::ruler_button_release (GdkEventButton* ev)
+{
+ gint x,y;
+ GdkModifierType state;
+
+ /* need to use the correct x,y, the event lies */
+ time_canvas_event_box.get_window().get_pointer (x, y, state);
+
+
+ ruler_pressed_button = 0;
+
+ if (session == 0) {
+ return FALSE;
+ }
+
+ hide_verbose_canvas_cursor();
+ stop_canvas_autoscroll();
+
+ jack_nframes_t where = leftmost_frame + pixel_to_frame (x);
+
+ switch (ev->button) {
+ case 1:
+ /* transport playhead */
+ snap_to (where);
+ session->request_locate (where);
+ break;
+
+ case 2:
+ /* edit cursor */
+ if (snap_type != Editing::SnapToEditCursor) {
+ snap_to (where);
+ }
+ edit_cursor->set_position (where);
+ edit_cursor_clock.set (where);
+ break;
+
+ case 3:
+ /* popup menu */
+ snap_to (where);
+ popup_ruler_menu (where);
+
+ break;
+ default:
+ break;
+ }
+
+
+ if (ruler_grabbed_widget) {
+ Gtk::Main::grab_remove (*ruler_grabbed_widget);
+ ruler_grabbed_widget = 0;
+ }
+
+ return TRUE;
+}
+
+gint
+Editor::ruler_label_button_release (GdkEventButton* ev)
+{
+ if (ev->button == 3)
+ {
+ popup_ruler_menu();
+ }
+
+ return TRUE;
+}
+
+
+gint
+Editor::ruler_mouse_motion (GdkEventMotion* ev)
+{
+ if (session == 0 || !ruler_pressed_button) {
+ return FALSE;
+ }
+
+ double wcx=0,wcy=0;
+ double cx=0,cy=0;
+
+ gint x,y;
+ GdkModifierType state;
+
+ /* need to use the correct x,y, the event lies */
+ time_canvas_event_box.get_window().get_pointer (x, y, state);
+
+
+ gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), x, y, &wcx, &wcy);
+ gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), wcx, wcy, &cx, &cy);
+
+ jack_nframes_t where = leftmost_frame + pixel_to_frame (x);
+
+ /// ripped from maybe_autoscroll
+ jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
+ jack_nframes_t rightmost_frame = leftmost_frame + one_page;
+
+ jack_nframes_t frame = pixel_to_frame (cx);
+
+ if (autoscroll_timeout_tag < 0) {
+ if (frame > rightmost_frame) {
+ if (rightmost_frame < max_frames) {
+ start_canvas_autoscroll (1);
+ }
+ } else if (frame < leftmost_frame) {
+ if (leftmost_frame > 0) {
+ start_canvas_autoscroll (-1);
+ }
+ }
+ } else {
+ if (frame >= leftmost_frame && frame < rightmost_frame) {
+ stop_canvas_autoscroll ();
+ }
+ }
+ //////
+
+ snap_to (where);
+
+ Cursor* cursor = 0;
+
+ switch (ruler_pressed_button) {
+ case 1:
+ /* transport playhead */
+ cursor = playhead_cursor;
+ break;
+
+ case 2:
+ /* edit cursor */
+ cursor = edit_cursor;
+ break;
+
+ default:
+ break;
+ }
+
+ if (cursor)
+ {
+ cursor->set_position (where);
+
+ if (cursor == edit_cursor) {
+ edit_cursor_clock.set (where);
+ }
+
+ show_verbose_time_cursor (where, 10, cx, 0);
+ }
+
+ return TRUE;
+}
+
+
+void
+Editor::popup_ruler_menu (jack_nframes_t where, ItemType t)
+{
+ using namespace Menu_Helpers;
+
+ if (editor_ruler_menu == 0) {
+ editor_ruler_menu = new Menu;
+ editor_ruler_menu->set_name ("ArdourContextMenu");
+ }
+
+ // always build from scratch
+ MenuList& ruler_items = editor_ruler_menu->items();
+ editor_ruler_menu->set_name ("ArdourContextMenu");
+ ruler_items.clear();
+
+ CheckMenuItem * mitem;
+
+ no_ruler_shown_update = true;
+
+ switch (t) {
+ case MarkerBarItem:
+ ruler_items.push_back (MenuElem (_("New location marker"), bind ( slot (*this, &Editor::mouse_add_new_marker), where)));
+ ruler_items.push_back (MenuElem (_("Clear all locations"), slot (*this, &Editor::clear_markers)));
+ ruler_items.push_back (SeparatorElem ());
+ break;
+ case RangeMarkerBarItem:
+ //ruler_items.push_back (MenuElem (_("New Range")));
+ ruler_items.push_back (MenuElem (_("Clear all ranges"), slot (*this, &Editor::clear_ranges)));
+ ruler_items.push_back (SeparatorElem ());
+
+ break;
+ case TransportMarkerBarItem:
+
+ break;
+
+ case TempoBarItem:
+ ruler_items.push_back (MenuElem (_("New Tempo"), bind ( slot (*this, &Editor::mouse_add_new_tempo_event), where)));
+ ruler_items.push_back (MenuElem (_("Clear tempo")));
+ ruler_items.push_back (SeparatorElem ());
+ break;
+
+ case MeterBarItem:
+ ruler_items.push_back (MenuElem (_("New Meter"), bind ( slot (*this, &Editor::mouse_add_new_meter_event), where)));
+ ruler_items.push_back (MenuElem (_("Clear meter")));
+ ruler_items.push_back (SeparatorElem ());
+ break;
+
+ default:
+ break;
+ }
+
+ ruler_items.push_back (CheckMenuElem (_("Min:Secs"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_metric_minsec)));
+ mitem = (CheckMenuItem *) ruler_items.back();
+ if (ruler_shown[ruler_metric_minsec]) {
+ mitem->set_active(true);
+ }
+
+ ruler_items.push_back (CheckMenuElem (X_("SMPTE"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_metric_smpte)));
+ mitem = (CheckMenuItem *) ruler_items.back();
+ if (ruler_shown[ruler_metric_smpte]) {
+ mitem->set_active(true);
+ }
+
+ ruler_items.push_back (CheckMenuElem (_("Frames"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_metric_frames)));
+ mitem = (CheckMenuItem *) ruler_items.back();
+ if (ruler_shown[ruler_metric_frames]) {
+ mitem->set_active(true);
+ }
+
+ ruler_items.push_back (CheckMenuElem (_("Bars:Beats"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_metric_bbt)));
+ mitem = (CheckMenuItem *) ruler_items.back();
+ if (ruler_shown[ruler_metric_bbt]) {
+ mitem->set_active(true);
+ }
+
+ ruler_items.push_back (SeparatorElem ());
+
+ ruler_items.push_back (CheckMenuElem (_("Meter"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_meter)));
+ mitem = (CheckMenuItem *) ruler_items.back();
+ if (ruler_shown[ruler_time_meter]) {
+ mitem->set_active(true);
+ }
+
+ ruler_items.push_back (CheckMenuElem (_("Tempo"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_tempo)));
+ mitem = (CheckMenuItem *) ruler_items.back();
+ if (ruler_shown[ruler_time_tempo]) {
+ mitem->set_active(true);
+ }
+
+ ruler_items.push_back (CheckMenuElem (_("Location Markers"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_marker)));
+ mitem = (CheckMenuItem *) ruler_items.back();
+ if (ruler_shown[ruler_time_marker]) {
+ mitem->set_active(true);
+ }
+
+ ruler_items.push_back (CheckMenuElem (_("Range Markers"), bind (slot (*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 (_("Loop/Punch Ranges"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_transport_marker)));
+ mitem = (CheckMenuItem *) ruler_items.back();
+ if (ruler_shown[ruler_time_transport_marker]) {
+ mitem->set_active(true);
+ }
+
+ editor_ruler_menu->popup (1, 0);
+
+ no_ruler_shown_update = false;
+}
+
+void
+Editor::ruler_toggled (int ruler)
+{
+ if (!session) return;
+ if (ruler < 0 || ruler >= (int) sizeof(ruler_shown)) return;
+
+ if (no_ruler_shown_update) return;
+
+ if (ruler_shown[ruler]) {
+ if (visible_timebars <= 1) {
+ // must always have 1 visible
+ return;
+ }
+ }
+
+ ruler_shown[ruler] = !ruler_shown[ruler];
+
+ update_ruler_visibility ();
+
+ // update session extra RulerVisibility
+ store_ruler_visibility ();
+}
+
+void
+Editor::store_ruler_visibility ()
+{
+ XMLNode* node = new XMLNode(X_("RulerVisibility"));
+
+ node->add_property (X_("smpte"), ruler_shown[ruler_metric_smpte] ? "yes": "no");
+ node->add_property (X_("bbt"), ruler_shown[ruler_metric_bbt] ? "yes": "no");
+ node->add_property (X_("frames"), ruler_shown[ruler_metric_frames] ? "yes": "no");
+ node->add_property (X_("minsec"), ruler_shown[ruler_metric_minsec] ? "yes": "no");
+ node->add_property (X_("tempo"), ruler_shown[ruler_time_tempo] ? "yes": "no");
+ node->add_property (X_("meter"), ruler_shown[ruler_time_meter] ? "yes": "no");
+ 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");
+
+ session->add_extra_xml (*node);
+ session->set_dirty ();
+}
+
+void
+Editor::restore_ruler_visibility ()
+{
+ XMLProperty* prop;
+ XMLNode * node = session->extra_xml (X_("RulerVisibility"));
+
+ if (node) {
+ if ((prop = node->property ("smpte")) != 0) {
+ if (prop->value() == "yes")
+ ruler_shown[ruler_metric_smpte] = true;
+ else
+ ruler_shown[ruler_metric_smpte] = false;
+ }
+ if ((prop = node->property ("bbt")) != 0) {
+ if (prop->value() == "yes")
+ ruler_shown[ruler_metric_bbt] = true;
+ else
+ ruler_shown[ruler_metric_bbt] = false;
+ }
+ if ((prop = node->property ("frames")) != 0) {
+ if (prop->value() == "yes")
+ ruler_shown[ruler_metric_frames] = true;
+ else
+ ruler_shown[ruler_metric_frames] = false;
+ }
+ if ((prop = node->property ("minsec")) != 0) {
+ if (prop->value() == "yes")
+ ruler_shown[ruler_metric_minsec] = true;
+ else
+ ruler_shown[ruler_metric_minsec] = false;
+ }
+ if ((prop = node->property ("tempo")) != 0) {
+ if (prop->value() == "yes")
+ ruler_shown[ruler_time_tempo] = true;
+ else
+ ruler_shown[ruler_time_tempo] = false;
+ }
+ if ((prop = node->property ("meter")) != 0) {
+ if (prop->value() == "yes")
+ ruler_shown[ruler_time_meter] = true;
+ else
+ ruler_shown[ruler_time_meter] = false;
+ }
+ if ((prop = node->property ("marker")) != 0) {
+ if (prop->value() == "yes")
+ ruler_shown[ruler_time_marker] = true;
+ else
+ ruler_shown[ruler_time_marker] = false;
+ }
+ if ((prop = node->property ("rangemarker")) != 0) {
+ if (prop->value() == "yes")
+ ruler_shown[ruler_time_range_marker] = true;
+ 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;
+ else
+ ruler_shown[ruler_time_transport_marker] = false;
+ }
+
+ }
+
+ update_ruler_visibility ();
+}
+
+
+void
+Editor::update_ruler_visibility ()
+{
+ using namespace Box_Helpers;
+ BoxList & lab_children = time_button_vbox.children();
+ BoxList & ruler_children = time_canvas_vbox.children();
+
+ visible_timebars = 0;
+
+ lab_children.clear();
+
+ // leave the last one (the time_canvas_scroller) intact
+ while (ruler_children.size() > 1) {
+ ruler_children.pop_front();
+ }
+
+ BoxList::iterator canvaspos = ruler_children.begin();
+
+ _smpte_ruler = gtk_custom_hruler_new ();
+ smpte_ruler = wrap (_smpte_ruler);
+ smpte_ruler->set_name ("SMPTERuler");
+ smpte_ruler->set_usize (-1, (int)timebar_height);
+ gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_smpte_ruler), &ruler_metrics[ruler_metric_smpte]);
+
+ _bbt_ruler = gtk_custom_hruler_new ();
+ bbt_ruler = wrap (_bbt_ruler);
+ bbt_ruler->set_name ("BBTRuler");
+ bbt_ruler->set_usize (-1, (int)timebar_height);
+ gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_bbt_ruler), &ruler_metrics[ruler_metric_bbt]);
+
+ _frames_ruler = gtk_custom_hruler_new ();
+ frames_ruler = wrap (_frames_ruler);
+ frames_ruler->set_name ("FramesRuler");
+ frames_ruler->set_usize (-1, (int)timebar_height);
+ gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_frames_ruler), &ruler_metrics[ruler_metric_frames]);
+
+ _minsec_ruler = gtk_custom_hruler_new ();
+ minsec_ruler = wrap (_minsec_ruler);
+ minsec_ruler->set_name ("MinSecRuler");
+ minsec_ruler->set_usize (-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->button_release_event.connect (slot (*this, &Editor::ruler_button_release));
+ bbt_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release));
+ frames_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release));
+ minsec_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release));
+
+ smpte_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press));
+ bbt_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press));
+ frames_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press));
+ minsec_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press));
+
+ smpte_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion));
+ bbt_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion));
+ frames_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion));
+ minsec_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion));
+
+
+ if (ruler_shown[ruler_metric_minsec]) {
+ lab_children.push_back (Element(minsec_label, false, false));
+ ruler_children.insert (canvaspos, Element(*minsec_ruler, false, false));
+ visible_timebars++;
+ }
+
+ if (ruler_shown[ruler_metric_smpte]) {
+ lab_children.push_back (Element(smpte_label, false, false));
+ ruler_children.insert (canvaspos, Element(*smpte_ruler, false, false));
+ visible_timebars++;
+ }
+
+ if (ruler_shown[ruler_metric_frames]) {
+ lab_children.push_back (Element(frame_label, false, false));
+ ruler_children.insert (canvaspos, Element(*frames_ruler, false, false));
+ visible_timebars++;
+ }
+
+ if (ruler_shown[ruler_metric_bbt]) {
+ lab_children.push_back (Element(bbt_label, false, false));
+ ruler_children.insert (canvaspos, Element(*bbt_ruler, false, false));
+ visible_timebars++;
+ }
+
+ double tbpos = 0.0;
+ double old_unit_pos ;
+ GtkArg args[1] ;
+ args[0].name = "y";
+
+ if (ruler_shown[ruler_time_meter]) {
+ lab_children.push_back (Element(meter_label, false, false));
+
+ gtk_object_getv (GTK_OBJECT(meter_group), 1, args) ;
+ old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ;
+ if (tbpos != old_unit_pos) {
+ gtk_canvas_item_move (meter_group, 0.0, tbpos - old_unit_pos) ;
+ }
+
+ //gtk_canvas_item_set (meter_group, "y", tbpos, NULL);
+ gtk_canvas_item_show (meter_group);
+ tbpos += timebar_height;
+ visible_timebars++;
+ }
+ else {
+ gtk_canvas_item_hide (meter_group);
+ }
+
+ if (ruler_shown[ruler_time_tempo]) {
+ lab_children.push_back (Element(tempo_label, false, false));
+ gtk_object_getv (GTK_OBJECT(tempo_group), 1, args) ;
+ old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ;
+ if (tbpos != old_unit_pos) {
+ gtk_canvas_item_move (tempo_group, 0.0, tbpos - old_unit_pos) ;
+ }
+ //gtk_canvas_item_set (tempo_group, "y", tbpos, NULL);
+ gtk_canvas_item_show (tempo_group);
+ tbpos += timebar_height;
+ visible_timebars++;
+ }
+ else {
+ gtk_canvas_item_hide (tempo_group);
+ }
+
+ if (ruler_shown[ruler_time_marker]) {
+ lab_children.push_back (Element(mark_label, false, false));
+ gtk_object_getv (GTK_OBJECT(marker_group), 1, args) ;
+ old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ;
+ if (tbpos != old_unit_pos) {
+ gtk_canvas_item_move (marker_group, 0.0, tbpos - old_unit_pos) ;
+ }
+ //gtk_canvas_item_set (marker_group, "y", tbpos, NULL);
+ gtk_canvas_item_show (marker_group);
+ tbpos += timebar_height;
+ visible_timebars++;
+ }
+ else {
+ gtk_canvas_item_hide (marker_group);
+ }
+
+ if (ruler_shown[ruler_time_range_marker]) {
+ lab_children.push_back (Element(range_mark_label, false, false));
+ gtk_object_getv (GTK_OBJECT(range_marker_group), 1, args) ;
+ old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ;
+ if (tbpos != old_unit_pos) {
+ gtk_canvas_item_move (range_marker_group, 0.0, tbpos - old_unit_pos) ;
+ }
+ //gtk_canvas_item_set (marker_group, "y", tbpos, NULL);
+ gtk_canvas_item_show (range_marker_group);
+ tbpos += timebar_height;
+ visible_timebars++;
+ }
+ else {
+ gtk_canvas_item_hide (range_marker_group);
+ }
+
+ if (ruler_shown[ruler_time_transport_marker]) {
+ lab_children.push_back (Element(transport_mark_label, false, false));
+ gtk_object_getv (GTK_OBJECT(transport_marker_group), 1, args) ;
+ old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ;
+ if (tbpos != old_unit_pos) {
+ gtk_canvas_item_move (transport_marker_group, 0.0, tbpos - old_unit_pos) ;
+ }
+ //gtk_canvas_item_set (marker_group, "y", tbpos, NULL);
+ gtk_canvas_item_show (transport_marker_group);
+ tbpos += timebar_height;
+ visible_timebars++;
+ }
+ else {
+ gtk_canvas_item_hide (transport_marker_group);
+ }
+
+ time_canvas_vbox.set_usize (-1, (int)(timebar_height * visible_timebars));
+ time_canvas_event_box.queue_resize();
+
+ update_fixed_rulers();
+ //update_tempo_based_rulers();
+ tempo_map_changed(Change (0));
+
+ time_canvas_event_box.show_all();
+ time_button_event_box.show_all();
+}
+
+void
+Editor::update_just_smpte ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &Editor::update_just_smpte));
+
+ if (session == 0) {
+ return;
+ }
+
+ /* XXX Note the potential loss of accuracy here as we convert from
+ an uint32_t (or larger) to a float ... what to do ?
+ */
+
+ jack_nframes_t page = (jack_nframes_t) floor (canvas_width * frames_per_unit);
+ jack_nframes_t rightmost_frame = leftmost_frame + page;
+
+ if (ruler_shown[ruler_metric_smpte]) {
+ gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_smpte_ruler), leftmost_frame, rightmost_frame,
+ leftmost_frame, session->current_end_frame());
+ }
+}
+
+void
+Editor::update_fixed_rulers ()
+{
+ jack_nframes_t rightmost_frame;
+
+ if (session == 0) {
+ return;
+ }
+
+ /* XXX Note the potential loss of accuracy here as we convert from
+ an uint32_t (or larger) to a float ... what to do ?
+ */
+
+ jack_nframes_t page = (jack_nframes_t) floor (canvas_width * frames_per_unit);
+
+ ruler_metrics[ruler_metric_smpte].units_per_pixel = frames_per_unit;
+ ruler_metrics[ruler_metric_frames].units_per_pixel = frames_per_unit;
+ ruler_metrics[ruler_metric_minsec].units_per_pixel = frames_per_unit;
+
+ rightmost_frame = leftmost_frame + page;
+
+ /* these force a redraw, which in turn will force execution of the metric callbacks
+ to compute the relevant ticks to display.
+ */
+
+ if (ruler_shown[ruler_metric_smpte]) {
+ gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_smpte_ruler), leftmost_frame, rightmost_frame,
+ leftmost_frame, session->current_end_frame());
+ }
+
+ if (ruler_shown[ruler_metric_frames]) {
+ gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_frames_ruler), leftmost_frame, rightmost_frame,
+ leftmost_frame, session->current_end_frame());
+ }
+
+ if (ruler_shown[ruler_metric_minsec]) {
+ gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_minsec_ruler), leftmost_frame, rightmost_frame,
+ leftmost_frame, session->current_end_frame());
+ }
+}
+
+void
+Editor::update_tempo_based_rulers ()
+{
+ if (session == 0) {
+ return;
+ }
+
+ /* XXX Note the potential loss of accuracy here as we convert from
+ an uint32_t (or larger) to a float ... what to do ?
+ */
+
+ jack_nframes_t page = (jack_nframes_t) floor (canvas_width * frames_per_unit);
+ ruler_metrics[ruler_metric_bbt].units_per_pixel = frames_per_unit;
+
+ if (ruler_shown[ruler_metric_bbt]) {
+ gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_bbt_ruler), leftmost_frame, leftmost_frame+page,
+ leftmost_frame, session->current_end_frame());
+ }
+}
+
+/* Mark generation */
+
+gint
+Editor::_metric_get_smpte (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ return ruler_editor->metric_get_smpte (marks, lower, upper, maxchars);
+}
+
+gint
+Editor::_metric_get_bbt (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ return ruler_editor->metric_get_bbt (marks, lower, upper, maxchars);
+}
+
+gint
+Editor::_metric_get_frames (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ return ruler_editor->metric_get_frames (marks, lower, upper, maxchars);
+}
+
+gint
+Editor::_metric_get_minsec (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ return ruler_editor->metric_get_minsec (marks, lower, upper, maxchars);
+}
+
+gint
+Editor::metric_get_smpte (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ jack_nframes_t range;
+ jack_nframes_t pos;
+ jack_nframes_t spacer;
+ jack_nframes_t fr;
+ SMPTE_Time smpte;
+ gchar buf[16];
+ gint nmarks = 0;
+ gint n;
+ bool show_bits = false;
+ bool show_frames = false;
+ bool show_seconds = false;
+ bool show_minutes = false;
+ bool show_hours = false;
+ int mark_modulo;
+
+ if (session == 0) {
+ return 0;
+ }
+
+ fr = session->frame_rate();
+
+ if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) {
+ lower = lower - spacer;
+ } else {
+ upper = upper + spacer - lower;
+ lower = 0;
+ }
+ range = upper - lower;
+
+ if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */
+ show_bits = true;
+ mark_modulo = 20;
+ nmarks = 1 + 160;
+ } else if (range <= (fr / 4)) { /* 2 frames - 0.250 second */
+ show_frames = true;
+ mark_modulo = 1;
+ nmarks = 1 + (range / (jack_nframes_t)session->frames_per_smpte_frame());
+ } else if (range <= (fr / 2)) { /* 0.25-0.5 second */
+ show_frames = true;
+ mark_modulo = 2;
+ nmarks = 1 + (range / (jack_nframes_t)session->frames_per_smpte_frame());
+ } else if (range <= fr) { /* 0.5-1 second */
+ show_frames = true;
+ mark_modulo = 5;
+ nmarks = 1 + (range / (jack_nframes_t)session->frames_per_smpte_frame());
+ } else if (range <= 2 * fr) { /* 1-2 seconds */
+ show_frames = true;
+ mark_modulo = 10;
+ nmarks = 1 + (range / (jack_nframes_t)session->frames_per_smpte_frame());
+ } else if (range <= 8 * fr) { /* 2-8 seconds */
+ show_seconds = true;
+ mark_modulo = 1;
+ nmarks = 1 + (range / fr);
+ } else if (range <= 16 * fr) { /* 8-16 seconds */
+ show_seconds = true;
+ mark_modulo = 2;
+ nmarks = 1 + (range / fr);
+ } else if (range <= 30 * fr) { /* 16-30 seconds */
+ show_seconds = true;
+ mark_modulo = 5;
+ nmarks = 1 + (range / fr);
+ } else if (range <= 60 * fr) { /* 30-60 seconds */
+ show_seconds = true;
+ mark_modulo = 5;
+ nmarks = 1 + (range / fr);
+ } else if (range <= 2 * 60 * fr) { /* 1-2 minutes */
+ show_seconds = true;
+ mark_modulo = 20;
+ nmarks = 1 + (range / fr);
+ } else if (range <= 4 * 60 * fr) { /* 2-4 minutes */
+ show_seconds = true;
+ mark_modulo = 30;
+ nmarks = 1 + (range / fr);
+ } else if (range <= 10 * 60 * fr) { /* 4-10 minutes */
+ show_minutes = true;
+ mark_modulo = 2;
+ nmarks = 1 + 10;
+ } else if (range <= 30 * 60 * fr) { /* 10-30 minutes */
+ show_minutes = true;
+ mark_modulo = 5;
+ nmarks = 1 + 30;
+ } else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */
+ show_minutes = true;
+ mark_modulo = 10;
+ nmarks = 1 + 60;
+ } else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/
+ show_minutes = true;
+ mark_modulo = 30;
+ nmarks = 1 + (60 * 4);
+ } else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/
+ show_hours = true;
+ mark_modulo = 1;
+ nmarks = 1 + 8;
+ } else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/
+ show_hours = true;
+ mark_modulo = 1;
+ nmarks = 1 + 24;
+ } else {
+
+ /* not possible if jack_nframes_t is a 32 bit quantity */
+
+ show_hours = true;
+ mark_modulo = 4;
+ nmarks = 1 + 24;
+ }
+
+ pos = lower;
+
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+
+ if (show_bits) {
+ // Find smpte time of this sample (pos) with subframe accuracy
+ session->sample_to_smpte(pos, smpte, true /* use_offset */, true /* use_subframes */ );
+
+ for (n = 0; n < nmarks; n++) {
+ session->smpte_to_sample(smpte, pos, true /* use_offset */, true /* use_subframes */ );
+ if ((smpte.subframes % mark_modulo) == 0) {
+ if (smpte.subframes == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ snprintf (buf, sizeof(buf), ".%02ld", smpte.subframes);
+ }
+ } else {
+ snprintf (buf, sizeof(buf)," ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = pos;
+
+ // Increment subframes by one
+ session->smpte_increment_subframes( smpte );
+ }
+ } else if (show_seconds) {
+ // Find smpte time of this sample (pos)
+ session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
+ // Go to next whole second down
+ session->smpte_seconds_floor( smpte );
+
+ for (n = 0; n < nmarks; n++) {
+ session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
+ if ((smpte.seconds % mark_modulo) == 0) {
+ if (smpte.seconds == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ (*marks)[n].position = pos;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ (*marks)[n].position = pos;
+ }
+ snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ } else {
+ snprintf (buf, sizeof(buf)," ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ (*marks)[n].position = pos;
+
+ }
+ (*marks)[n].label = g_strdup (buf);
+ session->smpte_increment_seconds( smpte );
+ }
+ } else if (show_minutes) {
+ // Find smpte time of this sample (pos)
+ session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
+ // Go to next whole minute down
+ session->smpte_minutes_floor( smpte );
+
+ for (n = 0; n < nmarks; n++) {
+ session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
+ if ((smpte.minutes % mark_modulo) == 0) {
+ if (smpte.minutes == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ }
+ snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ } else {
+ snprintf (buf, sizeof(buf)," ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = pos;
+ session->smpte_increment_minutes( smpte );
+ }
+ } else if (show_hours) {
+ // Find smpte time of this sample (pos)
+ session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
+ // Go to next whole hour down
+ session->smpte_hours_floor( smpte );
+
+ for (n = 0; n < nmarks; n++) {
+ session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
+ if ((smpte.hours % mark_modulo) == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ } else {
+ snprintf (buf, sizeof(buf)," ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = pos;
+
+ session->smpte_increment_hours( smpte );
+ }
+ } else { // show_frames
+ // Find smpte time of this sample (pos)
+ session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ );
+ // Go to next whole frame down
+ session->smpte_frames_floor( smpte );
+
+ for (n = 0; n < nmarks; n++) {
+ session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ );
+ if ((smpte.frames % mark_modulo) == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ (*marks)[n].position = pos;
+ snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames);
+ } else {
+ snprintf (buf, sizeof(buf)," ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ (*marks)[n].position = pos;
+
+ }
+ (*marks)[n].label = g_strdup (buf);
+ session->smpte_increment( smpte );
+ }
+ }
+
+ return nmarks;
+}
+
+
+gint
+Editor::metric_get_bbt (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ if (session == 0) {
+ return 0;
+ }
+
+ TempoMap::BBTPointList::iterator i;
+ TempoMap::BBTPointList *zoomed_bbt_points;
+ uint32_t beats = 0;
+ uint32_t bars = 0;
+ uint32_t tick = 0;
+ uint32_t skip;
+ uint32_t t;
+ uint32_t zoomed_beats = 0;
+ uint32_t zoomed_bars = 0;
+ uint32_t desirable_marks;
+ uint32_t magic_accent_number = 1;
+ gint nmarks;
+ char buf[64];
+ gint n;
+ jack_nframes_t pos;
+ jack_nframes_t frame_one_beats_worth;
+ jack_nframes_t frame_skip;
+ double frame_skip_error;
+ double accumulated_error;
+ bool bar_helper_on = true;
+
+
+ BBT_Time previous_beat;
+ BBT_Time next_beat;
+ jack_nframes_t next_beat_pos;
+
+ if ((desirable_marks = maxchars / 6) == 0) {
+ return 0;
+ }
+
+ /* align the tick marks to whatever we're snapping to... */
+
+ if (snap_type == SnapToAThirdBeat) {
+ bbt_beat_subdivision = 3;
+ } else if (snap_type == SnapToAQuarterBeat) {
+ bbt_beat_subdivision = 4;
+ } else if (snap_type == SnapToAEighthBeat) {
+ bbt_beat_subdivision = 8;
+ magic_accent_number = 2;
+ } else if (snap_type == SnapToASixteenthBeat) {
+ bbt_beat_subdivision = 16;
+ magic_accent_number = 4;
+ } else if (snap_type == SnapToAThirtysecondBeat) {
+ bbt_beat_subdivision = 32;
+ magic_accent_number = 8;
+ } else {
+ bbt_beat_subdivision = 4;
+ }
+
+ /* First find what a beat's distance is, so we can start plotting stuff before the beginning of the ruler */
+
+ session->bbt_time(lower,previous_beat);
+ previous_beat.ticks = 0;
+ next_beat = previous_beat;
+
+ if (session->tempo_map().meter_at(lower).beats_per_bar() < (next_beat.beats + 1)) {
+ next_beat.bars += 1;
+ next_beat.beats = 1;
+ } else {
+ next_beat.beats += 1;
+ }
+
+ frame_one_beats_worth = session->tempo_map().frame_time(next_beat) - session->tempo_map().frame_time(previous_beat);
+
+
+ zoomed_bbt_points = session->tempo_map().get_points((lower >= frame_one_beats_worth) ? lower - frame_one_beats_worth : 0, upper);
+
+ if (current_bbt_points == 0 || zoomed_bbt_points == 0 || zoomed_bbt_points->empty()) {
+ return 0;
+ }
+
+ for (i = current_bbt_points->begin(); i != current_bbt_points->end(); i++) {
+ if ((*i).type == TempoMap::Beat) {
+ beats++;
+ } else if ((*i).type == TempoMap::Bar) {
+ bars++;
+ }
+ }
+ /*Only show the bar helper if there aren't many bars on the screen */
+ if (bars > 1) {
+ bar_helper_on = false;
+ }
+
+ for (i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end(); i++) {
+ if ((*i).type == TempoMap::Beat) {
+ zoomed_beats++;
+ } else if ((*i).type == TempoMap::Bar) {
+ zoomed_bars++;
+ }
+ }
+
+ if (desirable_marks > (beats / 4)) {
+
+ /* we're in beat land...*/
+
+ double position_of_helper;
+ bool i_am_accented = false;
+ bool we_need_ticks = false;
+
+ position_of_helper = lower + (30 * Editor::get_current_zoom ());
+
+ if (desirable_marks >= (beats * 2)) {
+ nmarks = (zoomed_beats * bbt_beat_subdivision) + 1;
+ we_need_ticks = true;
+ } else {
+ nmarks = zoomed_beats + 1;
+ }
+
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+
+ (*marks)[0].label = g_strdup(" ");
+ (*marks)[0].position = lower;
+ (*marks)[0].style = GtkCustomRulerMarkMicro;
+
+ for (n = 1, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) {
+
+ if ((*i).frame <= lower && (bar_helper_on)) {
+
+ snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat);
+ (*marks)[0].label = g_strdup (buf);
+ } else {
+
+
+ if ((*i).type == TempoMap::Bar) {
+ tick = 0;
+ (((*i).frame < position_of_helper) && bar_helper_on) ?
+ snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ n++;
+
+ } else if (((*i).type == TempoMap::Beat) && ((*i).beat > 1)) {
+ tick = 0;
+ ((((*i).frame < position_of_helper) && bar_helper_on) || !we_need_ticks) ?
+ snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat);
+ if (((*i).beat % 2 == 1) || we_need_ticks) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+
+ }
+ /* Find the next beat */
+
+ session->bbt_time((*i).frame, next_beat);
+
+ if (session->tempo_map().meter_at((*i).frame).beats_per_bar() > (next_beat.beats + 1)) {
+ next_beat.beats += 1;
+ } else {
+ next_beat.bars += 1;
+ next_beat.beats = 1;
+ }
+
+ next_beat_pos = session->tempo_map().frame_time(next_beat);
+
+ /* Add the tick marks */
+
+ if (we_need_ticks) {
+
+ frame_skip = (jack_nframes_t) floor ((session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute()));
+ frame_skip_error = ((session->frame_rate() * 60.0f) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())) - frame_skip;
+ skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision);
+
+ pos = (*i).frame + frame_skip;
+ accumulated_error = frame_skip_error;
+
+ tick += skip;
+
+ for (t = 0; tick < Meter::ticks_per_beat && pos <= next_beat_pos ; pos += frame_skip, tick += skip, ++t) {
+
+ if (t % magic_accent_number == (magic_accent_number - 1)) {
+ i_am_accented = true;
+ }
+ if (Editor::get_current_zoom () > 32) {
+ snprintf (buf, sizeof(buf), " ");
+ } else if ((Editor::get_current_zoom () > 8) && !i_am_accented) {
+ snprintf (buf, sizeof(buf), " ");
+ } else if (bar_helper_on && (pos < position_of_helper)) {
+ snprintf (buf, sizeof(buf), " ");
+ } else {
+ snprintf (buf, sizeof(buf), "%" PRIu32, tick);
+ }
+
+ (*marks)[n].label = g_strdup (buf);
+
+ /* Error compensation for float to jack_nframes_t*/
+ accumulated_error += frame_skip_error;
+ if (accumulated_error > 1) {
+ pos += 1;
+ accumulated_error -= 1.0f;
+ }
+
+ (*marks)[n].position = pos;
+
+ if ((bbt_beat_subdivision > 4) && i_am_accented) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ i_am_accented = false;
+ n++;
+
+ }
+ }
+ }
+ delete zoomed_bbt_points;
+ return n; //return the actual number of marks made, since we might have skipped some fro fractional time signatures
+
+ } else {
+
+ /* we're in bar land */
+
+ if (desirable_marks < (uint32_t) (zoomed_bars / 256)) {
+ nmarks = 1;
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+ snprintf (buf, sizeof(buf), "too many bars... (currently %" PRIu32 ")", zoomed_bars );
+ (*marks)[0].style = GtkCustomRulerMarkMajor;
+ (*marks)[0].label = g_strdup (buf);
+ (*marks)[0].position = lower;
+ } else if (desirable_marks < (uint32_t) (nmarks = (gint) (zoomed_bars / 64))) {
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+ for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
+ if ((*i).type == TempoMap::Bar) {
+ if ((*i).bar % 64 == 1) {
+ if ((*i).bar % 256 == 1) {
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ if ((*i).bar % 256 == 129) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+ }
+ }
+ } else if (desirable_marks < (uint32_t) (nmarks = (gint)(zoomed_bars / 16))) {
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+ for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
+ if ((*i).type == TempoMap::Bar) {
+ if ((*i).bar % 16 == 1) {
+ if ((*i).bar % 64 == 1) {
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ if ((*i).bar % 64 == 33) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+ }
+ }
+ } else if (desirable_marks < (uint32_t) (nmarks = (gint)(zoomed_bars / 4))){
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+ for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) {
+ if ((*i).type == TempoMap::Bar) {
+ if ((*i).bar % 4 == 1) {
+ if ((*i).bar % 16 == 1) {
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ if ((*i).bar % 16 == 9) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+ }
+ }
+ } else {
+ nmarks = zoomed_bars;
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+ for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) {
+ if ((*i).type == TempoMap::Bar) {
+ if ((*i).bar % 4 == 1) {
+ snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar);
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ if ((*i).bar % 4 == 3) {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = (*i).frame;
+ n++;
+ }
+ }
+ }
+ delete zoomed_bbt_points;
+ return nmarks;
+ }
+}
+
+gint
+Editor::metric_get_frames (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ jack_nframes_t mark_interval;
+ jack_nframes_t pos;
+ gchar buf[16];
+ gint nmarks;
+ gint n;
+
+ if (session == 0) {
+ return 0;
+ }
+
+ mark_interval = (upper - lower) / 5;
+ if (mark_interval > session->frame_rate()) {
+ mark_interval -= mark_interval % session->frame_rate();
+ } else {
+ mark_interval = session->frame_rate() / (session->frame_rate() / mark_interval ) ;
+ }
+ nmarks = 5;
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+ for (n = 0, pos = lower; n < nmarks; pos += mark_interval, ++n) {
+ snprintf (buf, sizeof(buf), "%u", pos);
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = pos;
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ }
+
+ return nmarks;
+}
+
+static void
+sample_to_clock_parts ( jack_nframes_t sample,
+ jack_nframes_t sample_rate,
+ long *hrs_p,
+ long *mins_p,
+ long *secs_p,
+ long *millisecs_p)
+
+{
+ jack_nframes_t left;
+ long hrs;
+ long mins;
+ long secs;
+ long millisecs;
+
+ left = sample;
+ hrs = left / (sample_rate * 60 * 60);
+ left -= hrs * sample_rate * 60 * 60;
+ mins = left / (sample_rate * 60);
+ left -= mins * sample_rate * 60;
+ secs = left / sample_rate;
+ left -= secs * sample_rate;
+ millisecs = left * 1000 / sample_rate;
+
+ *millisecs_p = millisecs;
+ *secs_p = secs;
+ *mins_p = mins;
+ *hrs_p = hrs;
+
+ return;
+}
+
+gint
+Editor::metric_get_minsec (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ jack_nframes_t range;
+ jack_nframes_t fr;
+ jack_nframes_t mark_interval;
+ jack_nframes_t pos;
+ jack_nframes_t spacer;
+ long hrs, mins, secs, millisecs;
+ gchar buf[16];
+ gint nmarks;
+ gint n;
+ gint mark_modulo = 100;
+ bool show_seconds = false;
+ bool show_minutes = false;
+ bool show_hours = false;
+
+ if (session == 0) {
+ return 0;
+ }
+
+ fr = session->frame_rate();
+
+ /* to prevent 'flashing' */
+ if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) {
+ lower = lower - spacer;
+ } else {
+ upper = upper + spacer;
+ lower = 0;
+ }
+ range = upper - lower;
+
+ if (range < (fr / 50)) {
+ mark_interval = fr / 100; /* show 1/100 seconds */
+ mark_modulo = 10;
+ } else if (range <= (fr / 10)) { /* 0-0.1 second */
+ mark_interval = fr / 50; /* show 1/50 seconds */
+ mark_modulo = 20;
+ } else if (range <= (fr / 2)) { /* 0-0.5 second */
+ mark_interval = fr / 20; /* show 1/20 seconds */
+ mark_modulo = 100;
+ } else if (range <= fr) { /* 0-1 second */
+ mark_interval = fr / 10; /* show 1/10 seconds */
+ mark_modulo = 200;
+ } else if (range <= 2 * fr) { /* 1-2 seconds */
+ mark_interval = fr / 2; /* show 1/2 seconds */
+ mark_modulo = 500;
+ } else if (range <= 8 * fr) { /* 2-5 seconds */
+ mark_interval = fr / 5; /* show 2 seconds */
+ mark_modulo = 1000;
+ } else if (range <= 16 * fr) { /* 8-16 seconds */
+ mark_interval = fr; /* show 1 seconds */
+ show_seconds = true;
+ mark_modulo = 5;
+ } else if (range <= 30 * fr) { /* 10-30 seconds */
+ mark_interval = fr; /* show 10 seconds */
+ show_seconds = true;
+ mark_modulo = 5;
+ } else if (range <= 60 * fr) { /* 30-60 seconds */
+ mark_interval = 5 * fr; /* show 5 seconds */
+ show_seconds = true;
+ mark_modulo = 3;
+ } else if (range <= 2 * 60 * fr) { /* 1-2 minutes */
+ mark_interval = 5 * fr; /* show 5 seconds */
+ show_seconds = true;
+ mark_modulo = 3;
+ } else if (range <= 4 * 60 * fr) { /* 4 minutes */
+ mark_interval = 10 * fr; /* show 10 seconds */
+ show_seconds = true;
+ mark_modulo = 30;
+ } else if (range <= 10 * 60 * fr) { /* 10 minutes */
+ mark_interval = 30 * fr; /* show 30 seconds */
+ show_seconds = true;
+ mark_modulo = 60;
+ } else if (range <= 30 * 60 * fr) { /* 10-30 minutes */
+ mark_interval = 60 * fr; /* show 1 minute */
+ show_minutes = true;
+ mark_modulo = 5;
+ } else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */
+ mark_interval = 2 * 60 * fr; /* show 2 minutes */
+ show_minutes = true;
+ mark_modulo = 10;
+ } else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/
+ mark_interval = 5 * 60 * fr; /* show 10 minutes */
+ show_minutes = true;
+ mark_modulo = 30;
+ } else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/
+ mark_interval = 20 * 60 * fr; /* show 20 minutes */
+ show_minutes = true;
+ mark_modulo = 60;
+ } else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/
+ mark_interval = 60 * 60 * fr; /* show 60 minutes */
+ show_hours = true;
+ mark_modulo = 2;
+ } else {
+
+ /* not possible if jack_nframes_t is a 32 bit quantity */
+
+ mark_interval = 4 * 60 * 60 * fr; /* show 4 hrs */
+ }
+
+ nmarks = 1 + (range / mark_interval);
+ *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks);
+ pos = ((lower + (mark_interval/2))/mark_interval) * mark_interval;
+
+ if (show_seconds) {
+ for (n = 0; n < nmarks; pos += mark_interval, ++n) {
+ sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
+ if (secs % mark_modulo == 0) {
+ if (secs == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ }
+ snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs);
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = pos;
+ }
+ } else if (show_minutes) {
+ for (n = 0; n < nmarks; pos += mark_interval, ++n) {
+ sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
+ if (mins % mark_modulo == 0) {
+ if (mins == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ }
+ snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs);
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = pos;
+ }
+ } else if (show_hours) {
+ for (n = 0; n < nmarks; pos += mark_interval, ++n) {
+ sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
+ if (hrs % mark_modulo == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs);
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = pos;
+ }
+ } else {
+ for (n = 0; n < nmarks; pos += mark_interval, ++n) {
+ sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs);
+ if (millisecs % mark_modulo == 0) {
+ if (millisecs == 0) {
+ (*marks)[n].style = GtkCustomRulerMarkMajor;
+ } else {
+ (*marks)[n].style = GtkCustomRulerMarkMinor;
+ }
+ snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs);
+ } else {
+ snprintf (buf, sizeof(buf), " ");
+ (*marks)[n].style = GtkCustomRulerMarkMicro;
+ }
+ (*marks)[n].label = g_strdup (buf);
+ (*marks)[n].position = pos;
+ }
+ }
+
+ return nmarks;
+}
diff --git a/gtk2_ardour/editor_scrub.cc b/gtk2_ardour/editor_scrub.cc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/gtk2_ardour/editor_scrub.cc
diff --git a/gtk2_ardour/editor_selection_list.cc b/gtk2_ardour/editor_selection_list.cc
new file mode 100644
index 0000000000..36d9e858f6
--- /dev/null
+++ b/gtk2_ardour/editor_selection_list.cc
@@ -0,0 +1,185 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+#include <vector>
+
+#include <gtk--.h>
+
+#include <ardour/named_selection.h>
+#include <ardour/session_selection.h>
+#include <ardour/playlist.h>
+
+#include <gtkmmext/stop_signal.h>
+
+#include "editor.h"
+#include "selection.h"
+#include "time_axis_view.h"
+#include "ardour_ui.h"
+#include "prompter.h"
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+
+void
+Editor::handle_new_named_selection ()
+{
+ ARDOUR_UI::instance()->call_slot (slot (*this, &Editor::redisplay_named_selections));
+}
+
+void
+Editor::add_named_selection_to_named_selection_display (NamedSelection& selection)
+{
+ const gchar *row[1];
+
+ row[0] = selection.name.c_str();
+ named_selection_display.rows().push_back (row);
+ named_selection_display.rows().back().set_data (&selection);
+}
+
+void
+Editor::redisplay_named_selections ()
+{
+ named_selection_display.freeze ();
+ named_selection_display.clear ();
+ session->foreach_named_selection (*this, &Editor::add_named_selection_to_named_selection_display);
+ named_selection_display.thaw ();
+}
+
+gint
+Editor::named_selection_display_button_press (GdkEventButton *ev)
+{
+ NamedSelection* named_selection;
+ gint row;
+ gint col;
+
+ switch (ev->button) {
+ case 1:
+ if (Keyboard::is_delete_event (ev)) {
+ if (named_selection_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
+ if ((named_selection = reinterpret_cast<NamedSelection *> (named_selection_display.get_row_data (row))) != 0) {
+ session->remove_named_selection (named_selection);
+ return stop_signal (named_selection_display, "button_press_event");
+ }
+ }
+ }
+ break;
+
+ case 2:
+ break;
+
+ case 3:
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+
+void
+Editor::named_selection_display_selected (gint row, gint col, GdkEvent *ev)
+{
+}
+
+void
+Editor::named_selection_display_unselected (gint row, gint col, GdkEvent *ev)
+{
+}
+
+void
+Editor::name_selection ()
+{
+ ArdourPrompter p;
+
+ p.set_prompt (_("name for chunk:"));
+ p.done.connect (slot (*this, &Editor::named_selection_name_chosen));
+ p.change_labels (_("Create chunk"), _("Forget it"));
+ p.show_all ();
+
+ Gtk::Main::run ();
+
+ if (p.status == Prompter::entered) {
+ string name;
+ p.get_result (name);
+
+ if (name.length()){
+ create_named_selection (name);
+ }
+ }
+}
+
+void
+Editor::named_selection_name_chosen ()
+{
+ Gtk::Main::quit ();
+}
+
+void
+Editor::create_named_selection (string name)
+{
+ if (session == 0) {
+ return;
+ }
+
+ /* check for a range-based selection */
+
+ if (selection->time.empty()) {
+ return;
+ }
+
+
+ TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
+
+ if (views->empty()) {
+ delete views;
+ return;
+ }
+
+ Playlist* what_we_found;
+ list<Playlist*> thelist;
+
+ for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
+
+ Playlist *pl = (*i)->playlist();
+
+ if (pl) {
+
+ if ((what_we_found = pl->copy (selection->time, false)) != 0) {
+
+ thelist.push_back (what_we_found);
+ }
+ }
+ }
+
+ NamedSelection* ns;
+
+ ns = new NamedSelection (name, thelist);
+
+ /* make the one we just added be selected */
+
+ named_selection_display.rows().back().select ();
+}
+
diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc
new file mode 100644
index 0000000000..2f2dac1ae7
--- /dev/null
+++ b/gtk2_ardour/editor_tempodisplay.cc
@@ -0,0 +1,493 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdio> // for sprintf, grrr
+#include <cstdlib>
+#include <cmath>
+#include <string>
+#include <climits>
+
+#include <gtk-canvas.h>
+
+#include <pbd/error.h>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include <ardour/session.h>
+#include <ardour/tempo.h>
+#include <gtkmmext/doi.h>
+
+#include "editor.h"
+#include "marker.h"
+#include "canvas-simpleline.h"
+#include "tempo_dialog.h"
+#include "rgb_macros.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Editing;
+
+void
+Editor::remove_metric_marks ()
+{
+ /* don't delete these while handling events, just punt till the GUI is idle */
+
+ for (Marks::iterator x = metric_marks.begin(); x != metric_marks.end(); ++x) {
+ delete_when_idle (*x);
+ }
+ metric_marks.clear ();
+}
+
+void
+Editor::draw_metric_marks (const Metrics& metrics)
+{
+ for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
+ const MeterSection *ms;
+ const TempoSection *ts;
+ char buf[64];
+
+ if ((ms = dynamic_cast<const MeterSection*>(*i)) != 0) {
+ snprintf (buf, sizeof(buf), "%g/%g", ms->beats_per_bar(), ms->note_divisor ());
+ metric_marks.push_back (new MeterMarker (*this, GTK_CANVAS_GROUP(meter_group), color_map[cMeterMarker], buf,
+ *(const_cast<MeterSection*>(ms)), PublicEditor::canvas_meter_marker_event));
+ } else if ((ts = dynamic_cast<const TempoSection*>(*i)) != 0) {
+ snprintf (buf, sizeof (buf), "%.2f", ts->beats_per_minute());
+ metric_marks.push_back (new TempoMarker (*this, GTK_CANVAS_GROUP(tempo_group), color_map[cTempoMarker], buf,
+ *(const_cast<TempoSection*>(ts)), PublicEditor::canvas_tempo_marker_event));
+ }
+
+ }
+}
+
+void
+Editor::tempo_map_changed (Change ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Editor::tempo_map_changed), ignored));
+
+ if (current_bbt_points) {
+ delete current_bbt_points;
+ current_bbt_points = 0;
+ }
+
+ if (session) {
+ current_bbt_points = session->tempo_map().get_points (leftmost_frame, leftmost_frame + current_page_frames());
+ } else {
+ current_bbt_points = 0;
+ }
+
+ redisplay_tempo ();
+}
+
+void
+Editor::redisplay_tempo ()
+{
+ update_tempo_based_rulers ();
+
+ remove_metric_marks ();
+ hide_measures ();
+
+ if (session && current_bbt_points) {
+ session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
+ draw_measures ();
+ }
+
+}
+
+void
+Editor::hide_measures ()
+{
+ for (TimeLineList::iterator i = used_measure_lines.begin(); i != used_measure_lines.end(); ++i) {
+ gtk_canvas_item_hide (*i);
+ free_measure_lines.push_back (*i);
+ }
+ used_measure_lines.clear ();
+}
+
+GtkCanvasItem *
+Editor::get_time_line ()
+{
+ GtkCanvasItem *line;
+
+ if (free_measure_lines.empty()) {
+ line = gtk_canvas_item_new (GTK_CANVAS_GROUP(time_line_group),
+ gtk_canvas_simpleline_get_type(),
+ NULL);
+ // cerr << "measure line @ " << line << endl;
+ used_measure_lines.push_back (line);
+ } else {
+ line = free_measure_lines.front();
+ free_measure_lines.erase (free_measure_lines.begin());
+ used_measure_lines.push_back (line);
+ }
+
+ return line;
+}
+
+void
+Editor::draw_measures ()
+{
+ if (session == 0 || _show_measures == false) {
+ return;
+ }
+
+ TempoMap::BBTPointList::iterator i;
+ TempoMap::BBTPointList *all_bbt_points;
+ GtkCanvasItem *line;
+ gdouble xpos, last_xpos;
+ uint32_t cnt;
+ uint32_t color;
+
+ if (current_bbt_points == 0 || current_bbt_points->empty()) {
+ return;
+ }
+
+ all_bbt_points = session->tempo_map().get_points (leftmost_frame, leftmost_frame + current_page_frames());
+
+ cnt = 0;
+ last_xpos = 0;
+
+ /* get the first bar spacing */
+
+ gdouble last_beat = DBL_MAX;
+ gdouble beat_spacing = 0;
+
+ for (i = all_bbt_points->begin(); i != all_bbt_points->end() && beat_spacing == 0; ++i) {
+ TempoMap::BBTPoint& p = (*i);
+
+ switch (p.type) {
+ case TempoMap::Bar:
+ break;
+
+ case TempoMap::Beat:
+ xpos = p.frame / (gdouble) frames_per_unit;
+ if (last_beat < xpos) {
+ beat_spacing = xpos - last_beat;
+ }
+ last_beat = xpos;
+ }
+ }
+
+ for (i = all_bbt_points->begin(); i != all_bbt_points->end(); ++i) {
+
+ TempoMap::BBTPoint& p = (*i);
+
+ switch (p.type) {
+ case TempoMap::Bar:
+ break;
+
+ case TempoMap::Beat:
+ xpos = p.frame / (gdouble) frames_per_unit;
+
+ if (p.beat == 1) {
+ color = color_map[cMeasureLineBeat];
+ } else {
+ color = color_map[cMeasureLineBar];
+
+ /* only draw beat lines if the gaps between beats
+ are large.
+ */
+
+ if (beat_spacing < 25.0) {
+ break;
+ }
+ }
+
+ if (cnt == 0 || xpos - last_xpos > 4.0) {
+ line = get_time_line ();
+ gtk_object_set (GTK_OBJECT(line),
+ "x1", xpos,
+ "x2", xpos,
+ "y2", (gdouble) canvas_height,
+ "color_rgba", color,
+ NULL);
+ gtk_canvas_item_raise_to_top (line);
+ gtk_canvas_item_show (line);
+ last_xpos = xpos;
+ ++cnt;
+ }
+ break;
+ }
+ }
+
+ delete all_bbt_points;
+
+ /* the cursors are always on top of everything */
+
+ gtk_canvas_item_raise_to_top (cursor_group);
+ gtk_canvas_item_lower_to_bottom (time_line_group);
+}
+
+void
+Editor::mouse_add_new_tempo_event (jack_nframes_t frame)
+{
+ if (session == 0) {
+ return;
+ }
+
+
+ TempoMap& map(session->tempo_map());
+ TempoDialog tempo_dialog (map, frame, _("add"));
+
+ tempo_dialog.bpm_entry.activate.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), 0));
+ tempo_dialog.ok_button.clicked.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), 0));
+ tempo_dialog.cancel_button.clicked.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), -1));
+
+ tempo_dialog.set_position (GTK_WIN_POS_MOUSE);
+ tempo_dialog.realize ();
+ tempo_dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ ensure_float (tempo_dialog);
+
+ tempo_dialog.run();
+
+ if (tempo_dialog.run_status() == 0) {
+
+ double bpm = 0;
+ BBT_Time requested;
+
+ bpm = tempo_dialog.get_bpm ();
+ bpm = max (0.01, bpm);
+
+ tempo_dialog.get_bbt_time (requested);
+
+ begin_reversible_command (_("add tempo mark"));
+ session->add_undo (map.get_memento());
+ map.add_tempo (Tempo (bpm), requested);
+ session->add_redo_no_execute (map.get_memento());
+ commit_reversible_command ();
+
+ map.dump (cerr);
+ }
+}
+
+void
+Editor::mouse_add_new_meter_event (jack_nframes_t frame)
+{
+ if (session == 0) {
+ return;
+ }
+
+
+ TempoMap& map(session->tempo_map());
+ MeterDialog meter_dialog (map, frame, _("add"));
+
+ meter_dialog.ok_button.clicked.connect (bind (slot (meter_dialog, &ArdourDialog::stop), 0));
+ meter_dialog.cancel_button.clicked.connect (bind (slot (meter_dialog, &ArdourDialog::stop), -1));
+
+ meter_dialog.set_position (GTK_WIN_POS_MOUSE);
+ meter_dialog.realize ();
+ meter_dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ ensure_float (meter_dialog);
+
+ meter_dialog.run ();
+
+ if (meter_dialog.run_status() == 0) {
+
+ double bpb = meter_dialog.get_bpb ();
+ bpb = max (1.0, bpb); // XXX is this a reasonable limit?
+
+ double note_type = meter_dialog.get_note_type ();
+ BBT_Time requested;
+
+ meter_dialog.get_bbt_time (requested);
+
+ begin_reversible_command (_("add meter mark"));
+ session->add_undo (map.get_memento());
+ map.add_meter (Meter (bpb, note_type), requested);
+ session->add_redo_no_execute (map.get_memento());
+ commit_reversible_command ();
+
+ map.dump (cerr);
+ }
+}
+
+void
+Editor::remove_tempo_marker (GtkCanvasItem* item)
+{
+ Marker* marker;
+ TempoMarker* tempo_marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((tempo_marker = dynamic_cast<TempoMarker*> (marker)) == 0) {
+ fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if (tempo_marker->tempo().movable()) {
+ Gtk::Main::idle.connect (bind (slot (*this, &Editor::real_remove_tempo_marker), &tempo_marker->tempo()));
+ }
+}
+
+void
+Editor::edit_meter_section (MeterSection* section)
+{
+ MeterDialog meter_dialog (*section, _("done"));
+
+ meter_dialog.ok_button.clicked.connect (bind (slot (meter_dialog, &ArdourDialog::stop), 0));
+ meter_dialog.cancel_button.clicked.connect (bind (slot (meter_dialog, &ArdourDialog::stop), -1));
+
+ meter_dialog.set_position (GTK_WIN_POS_MOUSE);
+ meter_dialog.realize ();
+ meter_dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ ensure_float (meter_dialog);
+
+ meter_dialog.run ();
+
+ if (meter_dialog.run_status() == 0) {
+
+ double bpb = meter_dialog.get_bpb ();
+ bpb = max (1.0, bpb); // XXX is this a reasonable limit?
+
+ double note_type = meter_dialog.get_note_type ();
+
+ begin_reversible_command (_("replace tempo mark"));
+ session->add_undo (session->tempo_map().get_memento());
+ session->tempo_map().replace_meter (*section, Meter (bpb, note_type));
+ session->add_redo_no_execute (session->tempo_map().get_memento());
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::edit_tempo_section (TempoSection* section)
+{
+ TempoDialog tempo_dialog (*section, _("done"));
+
+ tempo_dialog.bpm_entry.activate.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), 0));
+ tempo_dialog.ok_button.clicked.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), 0));
+ tempo_dialog.cancel_button.clicked.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), -1));
+
+ tempo_dialog.set_position (GTK_WIN_POS_MOUSE);
+ tempo_dialog.realize ();
+ tempo_dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ ensure_float (tempo_dialog);
+
+ tempo_dialog.run ();
+
+ if (tempo_dialog.run_status() == 0) {
+
+ double bpm = tempo_dialog.get_bpm ();
+ BBT_Time when;
+ tempo_dialog.get_bbt_time(when);
+ bpm = max (0.01, bpm);
+
+ begin_reversible_command (_("replace tempo mark"));
+ session->add_undo (session->tempo_map().get_memento());
+ session->tempo_map().replace_tempo (*section, Tempo (bpm));
+ session->tempo_map().move_tempo (*section, when);
+ session->add_redo_no_execute (session->tempo_map().get_memento());
+ commit_reversible_command ();
+ }
+}
+
+void
+Editor::edit_tempo_marker (GtkCanvasItem *item)
+{
+ Marker* marker;
+ TempoMarker* tempo_marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((tempo_marker = dynamic_cast<TempoMarker*> (marker)) == 0) {
+ fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ edit_tempo_section (&tempo_marker->tempo());
+}
+
+void
+Editor::edit_meter_marker (GtkCanvasItem *item)
+{
+ Marker* marker;
+ MeterMarker* meter_marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((meter_marker = dynamic_cast<MeterMarker*> (marker)) == 0) {
+ fatal << _("programming error: marker for meter is not a meter marker!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ edit_meter_section (&meter_marker->meter());
+}
+
+gint
+Editor::real_remove_tempo_marker (TempoSection *section)
+{
+ begin_reversible_command (_("remove tempo mark"));
+ session->add_undo (session->tempo_map().get_memento());
+ session->tempo_map().remove_tempo (*section);
+ session->add_redo_no_execute (session->tempo_map().get_memento());
+ commit_reversible_command ();
+
+ return FALSE;
+}
+
+void
+Editor::remove_meter_marker (GtkCanvasItem* item)
+{
+ Marker* marker;
+ MeterMarker* meter_marker;
+
+ if ((marker = reinterpret_cast<Marker *> (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) {
+ fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if ((meter_marker = dynamic_cast<MeterMarker*> (marker)) == 0) {
+ fatal << _("programming error: marker for meter is not a meter marker!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ if (meter_marker->meter().movable()) {
+ Gtk::Main::idle.connect (bind (slot (*this, &Editor::real_remove_meter_marker), &meter_marker->meter()));
+ }
+}
+
+gint
+Editor::real_remove_meter_marker (MeterSection *section)
+{
+ begin_reversible_command (_("remove tempo mark"));
+ session->add_undo (session->tempo_map().get_memento());
+ session->tempo_map().remove_meter (*section);
+ session->add_redo_no_execute (session->tempo_map().get_memento());
+ commit_reversible_command ();
+ return FALSE;
+}
diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc
new file mode 100644
index 0000000000..70cac67d03
--- /dev/null
+++ b/gtk2_ardour/editor_timefx.cc
@@ -0,0 +1,239 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+
+#include <string>
+
+#include <pbd/error.h>
+#include <pbd/pthread_utils.h>
+
+#include "editor.h"
+#include "audio_time_axis.h"
+#include "regionview.h"
+#include "region_selection.h"
+
+#include <ardour/session.h>
+#include <ardour/region.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/audio_track.h>
+#include <ardour/audioregion.h>
+#include <ardour/diskstream.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+using namespace Gtk;
+
+Editor::TimeStretchDialog::TimeStretchDialog (Editor& e)
+ : ArdourDialog ("time stretch dialog"),
+ editor (e),
+ quick_button (_("Quick but Ugly")),
+ antialias_button (_("Skip Anti-aliasing")),
+ cancel_button (_("Cancel")),
+ action_button (_("Stretch/Shrink it"))
+{
+ set_modal (true);
+ set_position (GTK_WIN_POS_MOUSE);
+ set_title (_("ardour: timestretch"));
+ set_name (N_("TimeStretchDialog"));
+
+ set_hide_on_stop (false);
+
+ add (packer);
+
+ packer.set_spacing (5);
+ packer.set_border_width (5);
+ packer.pack_start (upper_button_box);
+ packer.pack_start (progress_bar);
+ packer.pack_start (lower_button_box);
+
+ 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);
+
+ lower_button_box.set_homogeneous (true);
+ lower_button_box.set_spacing (5);
+ lower_button_box.set_border_width (5);
+ lower_button_box.pack_start (action_button, true, true);
+ lower_button_box.pack_start (cancel_button, true, true);
+
+ action_button.set_name (N_("TimeStretchButton"));
+ cancel_button.set_name (N_("TimeStretchButton"));
+ quick_button.set_name (N_("TimeStretchButton"));
+ antialias_button.set_name (N_("TimeStretchButton"));
+ progress_bar.set_name (N_("TimeStretchProgress"));
+
+ action_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 1));
+}
+
+gint
+Editor::TimeStretchDialog::update_progress ()
+{
+ progress_bar.set_percentage (request.progress);
+ return request.running;
+}
+
+void
+Editor::TimeStretchDialog::cancel_timestretch_in_progress ()
+{
+ status = -2;
+ request.running = false;
+}
+
+gint
+Editor::TimeStretchDialog::delete_timestretch_in_progress (GdkEventAny* ev)
+{
+ status = -2;
+ request.running = false;
+ return TRUE;
+}
+
+int
+Editor::run_timestretch (AudioRegionSelection& regions, float fraction)
+{
+ pthread_t thread;
+
+ if (current_timestretch == 0) {
+ current_timestretch = new TimeStretchDialog (*this);
+ }
+
+ current_timestretch->progress_bar.set_percentage (0.0f);
+ current_timestretch->first_cancel = current_timestretch->cancel_button.clicked.connect (bind (slot (*current_timestretch, &ArdourDialog::stop), -1));
+ current_timestretch->first_delete = current_timestretch->delete_event.connect (slot (*current_timestretch, &ArdourDialog::wm_close_event));
+
+ current_timestretch->run ();
+
+ if (current_timestretch->run_status() != 1) {
+ current_timestretch->close ();
+ return 1; /* no error, but we did nothing */
+ }
+
+ 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.running = true;
+
+ /* re-connect the cancel button and delete events */
+
+ current_timestretch->first_cancel.disconnect();
+ current_timestretch->first_delete.disconnect();
+
+ current_timestretch->cancel_button.clicked.connect (slot (current_timestretch, &TimeStretchDialog::cancel_timestretch_in_progress));
+ current_timestretch->delete_event.connect (slot (current_timestretch, &TimeStretchDialog::delete_timestretch_in_progress));
+
+ if (pthread_create_and_store ("timestretch", &thread, 0, timestretch_thread, current_timestretch)) {
+ current_timestretch->close ();
+ error << _("timestretch cannot be started - thread creation error") << endmsg;
+ return -1;
+ }
+
+ pthread_detach (thread);
+
+ SigC::Connection c = Main::timeout.connect (slot (current_timestretch, &TimeStretchDialog::update_progress), 100);
+
+ while (current_timestretch->request.running) {
+ gtk_main_iteration ();
+ }
+
+ c.disconnect ();
+
+ current_timestretch->close ();
+ return current_timestretch->status;
+}
+
+void
+Editor::do_timestretch (TimeStretchDialog& dialog)
+{
+ AudioTrack* at;
+ Playlist* playlist;
+ AudioRegion* new_region;
+
+ for (AudioRegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) {
+
+ AudioRegion& aregion ((*i)->region);
+ TimeAxisView* tv = &(*i)->get_time_axis_view();
+ AudioTimeAxisView* atv;
+ AudioRegionSelection::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ if ((atv = dynamic_cast<AudioTimeAxisView*> (tv)) == 0) {
+ i = tmp;
+ continue;
+ }
+
+ if ((at = dynamic_cast<AudioTrack*> (&atv->route())) == 0) {
+ i = tmp;
+ continue;
+ }
+
+ if ((playlist = at->disk_stream().playlist()) == 0) {
+ i = tmp;
+ continue;
+ }
+
+ dialog.request.region = &aregion;
+
+ if (!dialog.request.running) {
+ /* we were cancelled */
+ dialog.status = 1;
+ return;
+ }
+
+ if ((new_region = session->tempoize_region (dialog.request)) == 0) {
+ dialog.status = -1;
+ dialog.request.running = false;
+ return;
+ }
+
+ session->add_undo (playlist->get_memento());
+ playlist->replace_region (aregion, *new_region, aregion.position());
+ session->add_redo_no_execute (playlist->get_memento());
+
+ i = tmp;
+ }
+
+ dialog.status = 0;
+ dialog.request.running = false;
+}
+
+void*
+Editor::timestretch_thread (void *arg)
+{
+ PBD::ThreadCreated (pthread_self(), X_("TimeFX"));
+
+ TimeStretchDialog* tsd = static_cast<TimeStretchDialog*>(arg);
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+
+ tsd->editor.do_timestretch (*tsd);
+
+ return 0;
+}
+
diff --git a/gtk2_ardour/editor_xpms b/gtk2_ardour/editor_xpms
new file mode 100644
index 0000000000..880ac9ab6f
--- /dev/null
+++ b/gtk2_ardour/editor_xpms
@@ -0,0 +1,195 @@
+/* Created with The GIMP */
+#define hand_width 16
+#define hand_height 16
+#define hand_x_hot 3
+#define hand_y_hot 0
+static const gchar hand_bits[] = {
+ 0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0xe4, 0x36, 0x24, 0x49,
+ 0x27, 0x49, 0x25, 0x49, 0x25, 0x49, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40,
+ 0x02, 0x40, 0x04, 0x60, 0xfc, 0x3f, 0xfc, 0x3f };
+
+/* Created with The GIMP */
+#define handmask_width 16
+#define handmask_height 16
+static const gchar handmask_bits[] = {
+ 0x18, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0xfc, 0x36, 0xfc, 0x7f,
+ 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f,
+ 0xfe, 0x7f, 0xfc, 0x7f, 0xfc, 0x3f, 0xfc, 0x3f };
+
+#define mag_width 16
+#define mag_height 16
+#define mag_x_hot 9
+#define mag_y_hot 5
+static const gchar mag_bits[] = {
+ 0x7f, 0xe0, 0x3f, 0xc0, 0x1f, 0x8f, 0x8f, 0x9f, 0xcf, 0x3f, 0xcf, 0x3f,
+ 0xcf, 0x3f, 0xcf, 0x3f, 0x8f, 0x1f, 0x1f, 0x8f, 0x0f, 0xc0, 0x47, 0xe0,
+ 0xe3, 0xff, 0xf1, 0xff, 0xf8, 0xff, 0xfc, 0xff };
+
+static const gchar magmask_bits[] = {
+ 0x80, 0x1f, 0xc0, 0x3f, 0xe0, 0x70, 0x70, 0x66, 0x30, 0xc6, 0xb0, 0xdf,
+ 0xb0, 0xdf, 0x30, 0xc6, 0x70, 0xe6, 0xe0, 0x70, 0xf0, 0x3f, 0xb8, 0x1f,
+ 0x1c, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x03, 0x00 };
+
+/* Created with The GIMP */
+#define fader_cursor_width 25
+#define fader_cursor_height 25
+#define fader_cursor_x_hot 3
+#define fader_cursor_y_hot 21
+static const gchar fader_cursor_bits[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x02, 0x01,
+ 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x01,
+ 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x01,
+ 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0xfe, 0x01,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00,
+ 0x3e, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+
+/* Created with The GIMP */
+static const gchar fader_cursor_mask_bits[] = {
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00,
+ 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01,
+ 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01,
+ 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01,
+ 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01,
+ 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00,
+ 0x08, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x78, 0x00, 0x3e, 0x00, 0x78, 0x00,
+ 0x7f, 0x00, 0x78, 0x00, 0x3e, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x78, 0x00,
+ 0x08, 0x00, 0x30, 0x00 };
+
+
+#define speaker_cursor_width 16
+#define speaker_cursor_height 26
+#define speaker_cursor_x_hot 0
+#define speaker_cursor_y_hot 0
+static const gchar speaker_cursor_bits[] = {
+ 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xcc, 0x00, 0xcc,
+ 0xff, 0xc3, 0xff, 0xc3, 0x03, 0xc0, 0x03, 0xc0, 0xc3, 0xc0, 0xc3, 0xc0,
+ 0xc3, 0xc0, 0xc3, 0xc0, 0xc3, 0xc0, 0xc3, 0xc0, 0x03, 0xc0, 0x03, 0xc0,
+ 0xff, 0xc3, 0xff, 0xc3, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xf0, 0x00, 0xf0,
+ 0x00, 0xc0, 0x00, 0xc0 };
+
+#define speaker_cursor_mask_width 16
+#define speaker_cursor_mask_height 26
+#define speaker_cursor_mask_x_hot 0
+#define speaker_cursor_mask_y_hot 0
+static const gchar speaker_cursor_mask_bits[] = {
+ 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0xfc,
+ 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x3f, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xf0, 0x00, 0xf0,
+ 0x00, 0xc0, 0x00, 0xc0 };
+
+/* XPM */
+static const gchar * zoom_in_button_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ....... ",
+" .+++++++. ",
+" .+++++++++. ",
+" .+++.....+++. ",
+" .+++. + .+++.",
+" .++. +.+ .++.",
+" .++. ++.++ .++.",
+" .++.+.....+.++.",
+" .++. ++.++ .++.",
+" .++. +.+ .++.",
+" .+++. + .+++.",
+" .+++.....+++. ",
+" .+++++++++++. ",
+".+++.+++++++. ",
+".++. ....... ",
+"... "};
+
+/* XPM */
+static const gchar * zoom_out_button_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ....... ",
+" .+++++++. ",
+" .+++++++++. ",
+" .+++.....+++. ",
+" .+++. .+++.",
+" .++. .++.",
+" .++. +++++ .++.",
+" .++.+.....+.++.",
+" .++. +++++ .++.",
+" .++. .++.",
+" .+++. .+++.",
+" .+++.....+++. ",
+" .+++++++++++. ",
+".+++.+++++++. ",
+".++. ....... ",
+"... "};
+
+/* XPM */
+static const gchar * zoom_out_full_button_xpm[] = {
+"16 16 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ",
+" ",
+" ",
+" ",
+".... ....",
+".++. .++.",
+".++..........++.",
+".++++++++++++++.",
+".++++++++++++++.",
+".++++++++++++++.",
+".++..........++.",
+".++. .++.",
+".... ....",
+" ",
+" ",
+" "};
+
+/* XPM */
+static const gchar * right_arrow_xpm[] = {
+"12 15 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" .+.. ",
+" .++.. ",
+" .+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" .+++.. ",
+" .++.. ",
+" .+.. "};
+
+/* XPM */
+static const gchar * left_arrow_xpm[] = {
+"12 15 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ..+. ",
+" ..++. ",
+" ..+++. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" .+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++.. ",
+" ..+++. ",
+" ..++. ",
+" ..+. "};
diff --git a/gtk2_ardour/enums.h b/gtk2_ardour/enums.h
new file mode 100644
index 0000000000..514a821662
--- /dev/null
+++ b/gtk2_ardour/enums.h
@@ -0,0 +1,26 @@
+#ifndef __ardour_gtk_enums_h__
+#define __ardour_gtk_enums_h__
+
+#include <ardour/types.h>
+
+enum WaveformShape {
+ Traditional,
+ Rectified
+};
+
+
+enum Width {
+ Wide,
+ Narrow,
+};
+
+#include <gtk-canvas/gtk-canvas.h>
+
+struct SelectionRect {
+ GtkCanvasItem *rect;
+ GtkCanvasItem *end_trim;
+ GtkCanvasItem *start_trim;
+ uint32_t id;
+};
+
+#endif /* __ardour_gtk_enums_h__ */
diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc
new file mode 100644
index 0000000000..8a76e6c794
--- /dev/null
+++ b/gtk2_ardour/export_dialog.cc
@@ -0,0 +1,1391 @@
+/*
+ Copyright (C) 1999-2003 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 <unistd.h>
+#include <utility>
+
+#include <fstream>
+
+
+#include <samplerate.h>
+#include <pbd/pthread_utils.h>
+#include <pbd/xml++.h>
+
+#include <gtk--.h>
+#include <gtkmmext/utils.h>
+#include <ardour/export.h>
+#include <ardour/sndfile_helpers.h>
+#include <ardour/audio_track.h>
+#include <ardour/audioregion.h>
+#include <ardour/audioengine.h>
+#include <ardour/gdither.h>
+#include <ardour/utils.h>
+
+#include "export_dialog.h"
+#include "check_mark.h"
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "keyboard.h"
+
+#include "i18n.h"
+
+#define FRAME_SHADOW_STYLE GTK_SHADOW_IN
+#define FRAME_NAME "BaseFrame"
+
+GdkPixmap* ExportDialog::check_pixmap = 0;
+GdkPixmap* ExportDialog::check_mask = 0;
+GdkPixmap* ExportDialog::empty_pixmap = 0;
+GdkPixmap* ExportDialog::empty_mask = 0;
+
+using namespace std;
+
+using namespace ARDOUR;
+using namespace SigC;
+using namespace Gtk;
+
+static const gchar *sample_rates[] = {
+ N_("22.05kHz"),
+ N_("44.1kHz"),
+ N_("48kHz"),
+ N_("88.2kHz"),
+ N_("96kHz"),
+ N_("192kHz"),
+ 0
+};
+
+static const gchar *src_qualities[] = {
+ N_("best"),
+ N_("fastest"),
+ N_("linear"),
+ N_("better"),
+ N_("intermediate"),
+ 0
+};
+
+static const gchar *dither_types[] = {
+ N_("None"),
+ N_("Rectangular"),
+ N_("Shaped Noise"),
+ N_("Triangular"),
+ 0
+};
+
+static const gchar* channel_strings[] = {
+ N_("stereo"),
+ N_("mono"),
+ 0
+};
+
+static const gchar* cue_file_types[] = {
+ N_("None"),
+ N_("CUE"),
+ N_("TOC"),
+ 0
+};
+
+ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r)
+ : ArdourDialog ("export dialog"),
+ editor (e),
+ format_table (9, 2),
+ format_frame (_("FORMAT")),
+ sample_rate_label (_("SAMPLE RATE")),
+ src_quality_label (_("CONVERSION QUALITY")),
+ dither_type_label (_("DITHER TYPE")),
+ cue_file_label (_("CD MARKER FILE TYPE")),
+ channel_count_label (_("CHANNELS")),
+ header_format_label (_("FILE TYPE")),
+ bitdepth_format_label (_("SAMPLE FORMAT")),
+ endian_format_label (_("SAMPLE ENDIANNESS")),
+ cuefile_only_checkbox (_("EXPORT CD MARKER FILE ONLY")),
+ file_frame (_("EXPORT TO FILE")),
+ file_browse_button (_("Browse")),
+ ok_button (_("Export")),
+ track_selector_button (_("Specific tracks ...")),
+ track_selector (3),
+ master_selector (3)
+{
+ guint32 n;
+ guint32 len;
+ guint32 maxlen;
+
+ audio_region = r;
+
+ session = 0;
+
+ set_title (_("ardour: export"));
+ set_wmclass (_("ardour_export"), "Ardour");
+ set_name ("ExportWindow");
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ add (vpacker);
+
+ vpacker.set_border_width (10);
+ vpacker.set_spacing (10);
+
+ file_selector = 0;
+ spec.running = false;
+
+ file_entry.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event));
+ file_entry.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event));
+
+ file_entry.set_name ("ExportFileNameEntry");
+
+ master_selector.set_name ("ExportTrackSelector");
+ master_selector.set_usize (-1, 100);
+ master_selector.set_column_min_width (0, 100);
+ master_selector.set_column_min_width (1, 40);
+ master_selector.set_column_auto_resize(1, true);
+ master_selector.set_column_min_width (2, 40);
+ master_selector.set_column_auto_resize(2, true);
+ master_selector.set_column_title (0, _("Output"));
+ master_selector.column_titles_show ();
+ master_selector.set_selection_mode (GTK_SELECTION_MULTIPLE);
+ master_selector.button_press_event.connect (slot (*this, &ExportDialog::master_selector_button_press_event));
+
+ track_selector.set_name ("ExportTrackSelector");
+ track_selector.set_usize (-1, 130);
+ track_selector.set_column_min_width (0, 100);
+ track_selector.set_column_min_width (1, 40);
+ track_selector.set_column_auto_resize(1, true);
+ track_selector.set_column_min_width (2, 40);
+ track_selector.set_column_auto_resize(2, true);
+ track_selector.set_column_title (0, _("Track"));
+ track_selector.column_titles_show ();
+ track_selector.set_selection_mode (GTK_SELECTION_MULTIPLE);
+ track_selector.button_press_event.connect (slot (*this, &ExportDialog::track_selector_button_press_event));
+
+ check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
+ gtk_widget_get_colormap(GTK_WIDGET(track_selector.gtkobj())),
+ &check_mask, NULL, (gchar**) check_xpm);
+ empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
+ gtk_widget_get_colormap(GTK_WIDGET(track_selector.gtkobj())),
+ &empty_mask, NULL, (gchar**) empty_xpm);
+
+ progress_bar.set_show_text (false);
+ progress_bar.set_orientation (GTK_PROGRESS_LEFT_TO_RIGHT);
+ progress_bar.set_name ("ExportProgress");
+
+ format_frame.add (format_table);
+ format_frame.set_name (FRAME_NAME);
+
+ track_scroll.set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ master_scroll.set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ vpacker.pack_start (file_frame, false, false);
+
+ hpacker.set_spacing (5);
+ hpacker.set_border_width (5);
+ hpacker.pack_start (format_frame, false, false);
+
+ if (!audio_region) {
+
+ master_scroll.add (master_selector);
+ track_scroll.add (track_selector);
+
+ master_scroll.set_usize (220, 100);
+ track_scroll.set_usize (220, 100);
+
+
+
+ /* we may hide some of these later */
+ track_vpacker.pack_start (master_scroll, true, true);
+ track_vpacker.pack_start (track_scroll, true, true);
+ track_vpacker.pack_start (track_selector_button, false);
+
+ hpacker.pack_start (track_vpacker, true, true);
+ }
+
+ vpacker.pack_start (hpacker, true, true);
+
+ track_selector_button.set_name ("EditorGTKButton");
+ track_selector_button.clicked.connect (slot (*this, &ExportDialog::track_selector_button_click));
+
+ vpacker.pack_start (button_box, false, false);
+ vpacker.pack_start (progress_bar, false, false);
+
+ Gtkmmext::set_usize_to_display_given_text (file_entry, X_("Kg/quite/a/reasonable/size/for/files/i/think"), 5, 8);
+
+ file_hbox.set_spacing (5);
+ file_hbox.set_border_width (5);
+ file_hbox.pack_start (file_entry, true, true);
+ file_hbox.pack_start (file_browse_button, false, false);
+
+ file_frame.add (file_hbox);
+ file_frame.set_border_width (5);
+ file_frame.set_name (FRAME_NAME);
+
+ sample_rate_combo.set_popdown_strings (internationalize(sample_rates));
+ src_quality_combo.set_popdown_strings (internationalize (src_qualities));
+ dither_type_combo.set_popdown_strings (internationalize (dither_types));
+ channel_count_combo.set_popdown_strings (internationalize (channel_strings));
+ header_format_combo.set_popdown_strings (internationalize ((const char **) sndfile_header_formats_strings));
+ bitdepth_format_combo.set_popdown_strings (internationalize ((const char **) sndfile_bitdepth_formats_strings));
+ endian_format_combo.set_popdown_strings (internationalize ((const char **) sndfile_endian_formats_strings));
+ cue_file_combo.set_popdown_strings (internationalize (cue_file_types));
+
+ /* this will re-sensitized as soon as a non RIFF/WAV
+ header format is chosen.
+ */
+
+ endian_format_combo.set_sensitive (false);
+
+ /* determine longest strings at runtime */
+
+ const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
+
+ maxlen = 0;
+ const char *longest = "gl";
+ string longest_str;
+
+ for (n = 0; n < SNDFILE_HEADER_FORMATS; ++n) {
+ if ((len = strlen (sndfile_header_formats_strings[n])) > maxlen) {
+ maxlen = len;
+ longest = sndfile_header_formats_strings[n];
+ }
+ }
+
+ for (n = 0; n < SNDFILE_BITDEPTH_FORMATS; ++n) {
+ if ((len = strlen (sndfile_bitdepth_formats_strings[n])) > maxlen) {
+ maxlen = len;
+ longest = sndfile_bitdepth_formats_strings[n];
+ }
+ }
+
+ for (n = 0; n < SNDFILE_ENDIAN_FORMATS; ++n) {
+ if ((len = strlen (sndfile_endian_formats_strings[n])) > maxlen) {
+ maxlen = len;
+ longest = sndfile_endian_formats_strings[n];
+ }
+ }
+
+ longest_str = longest;
+
+ /* force ascender + descender */
+
+ longest_str[0] = 'g';
+ longest_str[1] = 'l';
+
+ Gtkmmext::set_usize_to_display_given_text (*header_format_combo.get_entry(), longest_str.c_str(), 5+FUDGE, 5);
+
+ // TRANSLATORS: "slereg" is "stereo" with ascender and descender substituted
+ Gtkmmext::set_usize_to_display_given_text (*channel_count_combo.get_entry(), _("slereg"), 5+FUDGE, 5);
+
+ header_format_combo.set_use_arrows_always (true);
+ bitdepth_format_combo.set_use_arrows_always (true);
+ endian_format_combo.set_use_arrows_always (true);
+ channel_count_combo.set_use_arrows_always (true);
+ src_quality_combo.set_use_arrows_always (true);
+ dither_type_combo.set_use_arrows_always (true);
+ sample_rate_combo.set_use_arrows_always (true);
+ cue_file_combo.set_use_arrows_always (true);
+
+ header_format_combo.set_value_in_list (true, false);
+ bitdepth_format_combo.set_value_in_list (true, false);
+ endian_format_combo.set_value_in_list (true, false);
+ channel_count_combo.set_value_in_list (true, false);
+ src_quality_combo.set_value_in_list (true, false);
+ dither_type_combo.set_value_in_list (true, false);
+ sample_rate_combo.set_value_in_list (true, false);
+ cue_file_combo.set_value_in_list (true, false);
+
+ header_format_combo.get_entry()->set_editable (false);
+ bitdepth_format_combo.get_entry()->set_editable (false);
+ endian_format_combo.get_entry()->set_editable (false);
+ channel_count_combo.get_entry()->set_editable (false);
+ src_quality_combo.get_entry()->set_editable (false);
+ dither_type_combo.get_entry()->set_editable (false);
+ sample_rate_combo.get_entry()->set_editable (false);
+ cue_file_combo.get_entry()->set_editable (false);
+
+ dither_type_label.set_name ("ExportFormatLabel");
+ sample_rate_label.set_name ("ExportFormatLabel");
+ src_quality_label.set_name ("ExportFormatLabel");
+ channel_count_label.set_name ("ExportFormatLabel");
+ header_format_label.set_name ("ExportFormatLabel");
+ bitdepth_format_label.set_name ("ExportFormatLabel");
+ endian_format_label.set_name ("ExportFormatLabel");
+ cue_file_label.set_name ("ExportFormatLabel");
+
+ header_format_combo.get_entry()->set_name ("ExportFormatDisplay");
+ bitdepth_format_combo.get_entry()->set_name ("ExportFormatDisplay");
+ endian_format_combo.get_entry()->set_name ("ExportFormatDisplay");
+ channel_count_combo.get_entry()->set_name ("ExportFormatDisplay");
+ dither_type_combo.get_entry()->set_name ("ExportFormatDisplay");
+ src_quality_combo.get_entry()->set_name ("ExportFormatDisplay");
+ sample_rate_combo.get_entry()->set_name ("ExportFormatDisplay");
+ cue_file_combo.get_entry()->set_name ("ExportFormatDisplay");
+
+ cuefile_only_checkbox.set_name ("ExportCheckbox");
+
+ format_table.set_homogeneous (true);
+ format_table.set_border_width (5);
+ format_table.set_col_spacings (5);
+ format_table.set_row_spacings (5);
+
+ if (!audio_region) {
+ format_table.attach (channel_count_label, 0, 1, 0, 1);
+ format_table.attach (channel_count_combo, 0, 1, 1, 2);
+ }
+
+ format_table.attach (header_format_label, 1, 2, 0, 1);
+ format_table.attach (header_format_combo, 1, 2, 1, 2);
+
+ format_table.attach (bitdepth_format_label, 0, 1, 2, 3);
+ format_table.attach (bitdepth_format_combo, 0, 1, 3, 4);
+
+ format_table.attach (endian_format_label, 1, 2, 2, 3);
+ format_table.attach (endian_format_combo, 1, 2, 3, 4);
+
+ format_table.attach (sample_rate_label, 0, 1, 4, 5);
+ format_table.attach (sample_rate_combo, 0, 1, 5, 6);
+
+ format_table.attach (src_quality_label, 1, 2, 4, 5);
+ format_table.attach (src_quality_combo, 1, 2, 5, 6);
+
+ format_table.attach (dither_type_label, 0, 1, 6, 7);
+ format_table.attach (dither_type_combo, 0, 1, 7, 8);
+
+ format_table.attach (cue_file_label, 1, 2, 6, 7);
+ format_table.attach (cue_file_combo, 1, 2, 7, 8);
+ format_table.attach (cuefile_only_checkbox, 1, 2, 8, 9);
+
+
+ button_box.set_spacing (10);
+ button_box.set_homogeneous (true);
+
+ cancel_button.add (cancel_label);
+
+ button_box.pack_start (ok_button, false, true);
+ button_box.pack_start (cancel_button, false, true);
+
+ ok_button.set_name ("EditorGTKButton");
+ cancel_button.set_name ("EditorGTKButton");
+ file_entry.set_name ("ExportFileDisplay");
+
+ delete_event.connect (slot (*this, &ExportDialog::window_closed));
+ ok_button.clicked.connect (slot (*this, &ExportDialog::do_export));
+ cancel_button.clicked.connect (slot (*this, &ExportDialog::end_dialog));
+
+ file_browse_button.set_name ("EditorGTKButton");
+ file_browse_button.clicked.connect (slot (*this, &ExportDialog::initiate_browse));
+
+ channel_count_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::channels_chosen));
+ bitdepth_format_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::bitdepth_chosen));
+ header_format_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::header_chosen));
+ sample_rate_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::sample_rate_chosen));
+ cue_file_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::cue_file_type_chosen));
+}
+
+ExportDialog::~ExportDialog()
+{
+ if (file_selector) {
+ delete file_selector;
+ }
+}
+
+void
+ExportDialog::connect_to_session (Session *s)
+{
+ session = s;
+ session->going_away.connect (slot (*this, &Window::hide_all));
+
+ switch (session->frame_rate()) {
+ case 22050:
+ sample_rate_combo.get_entry()->set_text (N_("22.05kHz"));
+ break;
+ case 44100:
+ sample_rate_combo.get_entry()->set_text (N_("44.1kHz"));
+ break;
+ case 48000:
+ sample_rate_combo.get_entry()->set_text (N_("48kHz"));
+ break;
+ case 88200:
+ sample_rate_combo.get_entry()->set_text (N_("88.2kHz"));
+ break;
+ case 96000:
+ sample_rate_combo.get_entry()->set_text (N_("96kHz"));
+ break;
+ case 192000:
+ sample_rate_combo.get_entry()->set_text (N_("192kHz"));
+ break;
+ default:
+ sample_rate_combo.get_entry()->set_text (N_("44.1kHz"));
+ break;
+ }
+
+ src_quality_combo.set_sensitive (false);
+
+ set_state();
+}
+
+void
+ExportDialog::set_state()
+{
+ XMLNode* node = session->instant_xml(X_("ExportDialog"), session->path());
+ XMLProperty* prop;
+
+ if (node) {
+
+ if ((prop = node->property (X_("sample_rate"))) != 0) {
+ sample_rate_combo.get_entry()->set_text(prop->value());
+ }
+ if ((prop = node->property (X_("src_quality"))) != 0) {
+ src_quality_combo.get_entry()->set_text(prop->value());
+ }
+ if ((prop = node->property (X_("dither_type"))) != 0) {
+ dither_type_combo.get_entry()->set_text(prop->value());
+ }
+ if ((prop = node->property (X_("channel_count"))) != 0) {
+ channel_count_combo.get_entry()->set_text(prop->value());
+ }
+ if ((prop = node->property (X_("header_format"))) != 0) {
+ header_format_combo.get_entry()->set_text(prop->value());
+ }
+ if ((prop = node->property (X_("bitdepth_format"))) != 0) {
+ bitdepth_format_combo.get_entry()->set_text(prop->value());
+ }
+ if ((prop = node->property (X_("endian_format"))) != 0) {
+ endian_format_combo.get_entry()->set_text(prop->value());
+ }
+ if ((prop = node->property (X_("filename"))) != 0) {
+ file_entry.set_text(prop->value());
+ }
+ if ((prop = node->property (X_("cue_file_type"))) != 0) {
+ cue_file_combo.get_entry()->set_text(prop->value());
+ }
+ }
+
+ header_chosen (0);
+ bitdepth_chosen(0);
+ channels_chosen(0);
+ sample_rate_chosen(0);
+
+ if (session->master_out()) {
+ track_scroll.hide ();
+ } else {
+ master_scroll.hide ();
+ track_selector_button.hide ();
+ }
+
+ if (!node) {
+ return;
+ }
+
+ if (session->master_out()) {
+ XMLNode* master = find_named_node(*node, (X_("Master")));
+ int nchns;
+
+ if (!master) {
+
+ /* default is to use all */
+ if (channel_count_combo.get_entry()->get_text() == _("mono")) {
+ nchns = 1;
+ } else {
+ nchns = 2;
+ }
+
+ for (uint32_t r = 0; r < session->master_out()->n_outputs(); ++r) {
+ if (nchns == 2) {
+ if (r % 2) {
+ master_selector.cell (r, 2).set_pixmap (check_pixmap, check_mask);
+ } else {
+ master_selector.cell (r, 1).set_pixmap (check_pixmap, check_mask);
+ }
+ } else {
+ master_selector.cell (r, 1).set_pixmap (check_pixmap, check_mask);
+ }
+ }
+
+ } else {
+ /* XXX use XML state */
+ }
+ }
+
+ XMLNode* tracks = find_named_node(*node, (X_("Tracks")));
+ if (!tracks) {
+ return;
+ }
+
+ XMLNodeList track_list = tracks->children(X_("Track"));
+ CList_Helpers::RowIterator ri = track_selector.rows().begin();
+ uint32_t n = 0;
+ for (XMLNodeIterator it = track_list.begin(); it != track_list.end(); ++it, ++ri, ++n) {
+ if (ri == track_selector.rows().end()) {
+ break;
+ }
+
+ XMLNode* track = *it;
+
+ if ((prop = track->property(X_("channel1"))) != 0) {
+ if (prop->value() == X_("on")) {
+ track_selector.cell (n,1).set_pixmap (check_pixmap, check_mask);
+ } else {
+ track_selector.cell (n,1).set_pixmap (empty_pixmap, empty_mask);
+ }
+ }
+
+ if ((prop = track->property(X_("channel2"))) != 0) {
+ if (prop->value() == X_("on")) {
+ track_selector.cell (n,2).set_pixmap (check_pixmap, check_mask);
+ } else {
+ track_selector.cell (n,2).set_pixmap (empty_pixmap, empty_mask);
+ }
+ }
+ }
+ }
+
+void
+ExportDialog::save_state()
+{
+ if (!session) {
+ return;
+ }
+
+ XMLNode* node = new XMLNode(X_("ExportDialog"));
+
+ node->add_property(X_("sample_rate"), sample_rate_combo.get_entry()->get_text());
+ node->add_property(X_("src_quality"), src_quality_combo.get_entry()->get_text());
+ node->add_property(X_("dither_type"), dither_type_combo.get_entry()->get_text());
+ node->add_property(X_("channel_count"), channel_count_combo.get_entry()->get_text());
+ node->add_property(X_("header_format"), header_format_combo.get_entry()->get_text());
+ node->add_property(X_("bitdepth_format"), bitdepth_format_combo.get_entry()->get_text());
+ node->add_property(X_("endian_format"), endian_format_combo.get_entry()->get_text());
+ node->add_property(X_("filename"), file_entry.get_text());
+ node->add_property(X_("cue_file_type"), cue_file_combo.get_entry()->get_text());
+
+ XMLNode* tracks = new XMLNode(X_("Tracks"));
+
+ uint32_t n = 0;
+ for (CList_Helpers::RowIterator ri = track_selector.rows().begin(); ri != track_selector.rows().end(); ++ri, ++n) {
+ XMLNode* track = new XMLNode(X_("Track"));
+
+ Gdk_Pixmap left_pixmap = track_selector.cell (n, 1).get_pixmap ();
+ track->add_property(X_("channel1"), left_pixmap.gdkobj() == check_pixmap ? X_("on") : X_("off"));
+
+ Gdk_Pixmap right_pixmap = track_selector.cell (n, 2).get_pixmap ();
+ track->add_property(X_("channel2"), right_pixmap.gdkobj() == check_pixmap ? X_("on") : X_("off"));
+
+ tracks->add_child_nocopy(*track);
+ }
+ node->add_child_nocopy(*tracks);
+
+ session->add_instant_xml(*node, session->path());
+}
+
+void
+ExportDialog::set_range (jack_nframes_t start, jack_nframes_t end)
+{
+ spec.start_frame = start;
+ spec.end_frame = end;
+
+ if (!audio_region) {
+ // XXX: this is a hack until we figure out what is really wrong
+ session->request_locate (spec.start_frame, false);
+ }
+}
+
+gint
+ExportDialog::progress_timeout ()
+{
+ progress_bar.set_percentage (spec.progress);
+ return TRUE;
+}
+
+void*
+ExportDialog::_export_region_thread (void *arg)
+{
+ PBD::ThreadCreated (pthread_self(), X_("Export Region"));
+
+ static_cast<ExportDialog*>(arg)->export_region ();
+ return 0;
+}
+
+void
+ExportDialog::export_region ()
+{
+ audio_region->exportme (*session, spec);
+}
+
+void
+frames_to_cd_frames_string (char* buf, jack_nframes_t when, jack_nframes_t fr)
+{
+
+ long unsigned int remainder;
+ int mins, secs, frames;
+
+ mins = when / (60 * fr);
+ remainder = when - (mins * 60 * fr);
+ secs = remainder / fr;
+ remainder -= secs * fr;
+ frames = remainder / (fr / 75);
+ sprintf (buf, " %02d:%02d:%02d", mins, secs, frames);
+
+}
+
+struct LocationSortByStart {
+ bool operator() (Location *a, Location *b) {
+ return a->start() < b->start();
+ }
+};
+
+void
+ExportDialog::export_toc_file (Locations::LocationList& locations, const string& path)
+{
+
+ 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) {
+ error << compose(_("Editor: cannot open \"%1\" as export file for CD toc file"), filepath) << endmsg;
+ return;
+ }
+ out << "CD_DA" << endl;
+ out << "CD_TEXT {" << endl << " LANGUAGE_MAP {" << endl << " 0 : EN" << endl << " }" << endl;
+ out << " LANGUAGE 0 {" << endl << " TITLE \"" << session->name() << "\"" << endl << " }" << endl << "}" << endl;
+
+ Locations::LocationList::iterator i;
+ 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 (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()) {
+ LocationSortByStart cmp;
+ temp.sort (cmp);
+
+ 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;
+ }
+
+ 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("composer") != (*i)->cd_info.end()) {
+ out << " COMPOSER \"" << (*i)->cd_info["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;
+
+ 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;
+ }
+ }
+ }
+
+}
+
+void
+ExportDialog::export_cue_file (Locations::LocationList& locations, const string& path)
+{
+ string filepath = path + ".cue";
+ ofstream out (filepath.c_str());
+ gchar buf[18];
+ long unsigned int last_track_end = spec.start_frame;
+ int numtracks = 0, tracknum = 0, indexnum = 0;
+
+ if (!out) {
+ error << compose(_("Editor: cannot open \"%1\" as export file for CD cue file"), filepath) << endmsg;
+ return;
+ }
+
+ Locations::LocationList::iterator i;
+ 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++;
+ }
+ }
+ }
+
+ out << "REM Cue file generated by Ardour" << endl;
+ out << "TITLE \"" << session->name() << "\"" << endl;
+
+ if ((header_format_combo.get_entry()->get_text() == N_("WAV"))) {
+ out << "FILE " << path << " WAVE" << endl;
+ } else {
+ out << "FILE " << path << ' ' << (header_format_combo.get_entry()->get_text()) << endl;
+ }
+
+ if (numtracks == 0) {
+ /* the user has supplied no track markers.
+ the entire export is treated as one track.
+ */
+
+ numtracks++;
+ tracknum++;
+ indexnum = 0;
+ out << endl << "TRACK " << tracknum << " AUDIO" << endl;
+ out << "FLAGS " ;
+
+ out << "DCP " << endl;
+
+ /* use the session name*/
+
+ if (session->name() != "") {
+ out << "TITLE \"" << session->name() << "\"" << endl;
+ }
+
+ /* no pregap in this case */
+
+ out << "INDEX 00 00:00:00" << endl;
+ indexnum++;
+ out << "INDEX 01 00:00:00" << endl;
+ indexnum++;
+ last_track_end = spec.end_frame;
+ }
+
+ if (temp.size()) {
+ LocationSortByStart cmp;
+ temp.sort (cmp);
+
+ 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("composer") != (*i)->cd_info.end()) {
+ out << "SONGWRITER \"" << (*i)->cd_info["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++;
+ }
+ }
+ }
+
+}
+
+void
+ExportDialog::do_export_cd_markers (const string& path,const string& cuefile_type)
+{
+ if (cuefile_type == "TOC") {
+ session->locations()->apply (*this, &ExportDialog::export_toc_file, path);
+ } else {
+ session->locations()->apply (*this, &ExportDialog::export_cue_file, path);
+ }
+}
+
+
+void
+ExportDialog::do_export ()
+{
+ using namespace CList_Helpers;
+
+ ok_button.set_sensitive(false);
+ save_state();
+
+ if (cue_file_combo.get_entry()->get_text () != _("None")) {
+ do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_entry()->get_text ());
+ }
+
+ if (cuefile_only_checkbox.get_active()) {
+ end_dialog ();
+ return;
+ }
+
+ set_modal (true);
+
+ spec.path = file_entry.get_text();
+ spec.progress = 0;
+ spec.running = true;
+ spec.stop = false;
+ spec.port_map.clear();
+
+ if (channel_count_combo.get_entry()->get_text() == _("mono")) {
+ spec.channels = 1;
+ } else {
+ spec.channels = 2;
+ }
+
+ spec.format = 0;
+
+ spec.format |= sndfile_header_format_from_string (header_format_combo.get_entry()->get_text ());
+
+ if ((spec.format & SF_FORMAT_WAV) == 0) {
+ /* RIFF/WAV specifies endianess */
+ spec.format |= sndfile_endian_format_from_string (endian_format_combo.get_entry()->get_text ());
+ }
+
+ spec.format |= sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_entry()->get_text ());
+
+ string sr_str = sample_rate_combo.get_entry()->get_text();
+ if (sr_str == N_("22.05kHz")) {
+ spec.sample_rate = 22050;
+ } else if (sr_str == N_("44.1kHz")) {
+ spec.sample_rate = 44100;
+ } else if (sr_str == N_("48kHz")) {
+ spec.sample_rate = 48000;
+ } else if (sr_str == N_("88.2kHz")) {
+ spec.sample_rate = 88200;
+ } else if (sr_str == N_("96kHz")) {
+ spec.sample_rate = 96000;
+ } else if (sr_str == N_("192kHz")) {
+ spec.sample_rate = 192000;
+ } else {
+ spec.sample_rate = session->frame_rate();
+ }
+
+ string src_str = src_quality_combo.get_entry()->get_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_entry()->get_text();
+ if (dither_str == _("None")) {
+ spec.dither_type = GDitherNone;
+ } else if (dither_str == _("Rectangular")) {
+ spec.dither_type = GDitherRect;
+ } else if (dither_str == _("Triangular")) {
+ spec.dither_type = GDitherTri;
+ } else {
+ spec.dither_type = GDitherShaped;
+ }
+
+ if (!audio_region) {
+
+ uint32_t n = 0;
+ uint32_t chan=0;
+ Port *last_port = 0;
+
+ for (RowIterator ri = master_selector.rows().begin(); ri != master_selector.rows().end(); ++ri, ++n) {
+
+ Port* port = static_cast<Port*> ((*ri)->get_data ());
+
+ if (last_port != port) {
+ chan = 0;
+ }
+
+ Gdk_Pixmap left_pixmap = master_selector.cell (n, 1).get_pixmap ();
+
+ if (left_pixmap.gdkobj() == check_pixmap) {
+ spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
+ }
+
+ if (spec.channels == 2) {
+
+ Gdk_Pixmap right_pixmap = master_selector.cell (n, 2).get_pixmap ();
+
+ if (right_pixmap.gdkobj() == check_pixmap) {
+ spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
+ }
+
+ }
+ }
+
+ chan = 0;
+ n = 0;
+
+ for (RowIterator ri = track_selector.rows().begin(); ri != track_selector.rows().end(); ++ri, ++n) {
+
+ Port* port = static_cast<Port*> ((*ri)->get_data ());
+
+ if (last_port != port) {
+ chan = 0;
+ }
+
+ Gdk_Pixmap left_pixmap = track_selector.cell (n, 1).get_pixmap ();
+
+ if (left_pixmap.gdkobj() == check_pixmap) {
+ spec.port_map[0].push_back (std::pair<Port*,uint32_t>(port, chan));
+ }
+
+ if (spec.channels == 2) {
+
+ Gdk_Pixmap right_pixmap = track_selector.cell (n, 2).get_pixmap ();
+
+ if (right_pixmap.gdkobj() == check_pixmap) {
+ spec.port_map[1].push_back (std::pair<Port*,uint32_t>(port, chan));
+ }
+
+ }
+
+ last_port = port;
+ ++chan;
+ }
+ }
+
+ progress_connection = Main::timeout.connect (slot (*this, &ExportDialog::progress_timeout), 100);
+ cancel_label.set_text (_("Stop Export"));
+
+ if (!audio_region) {
+ if (session->start_audio_export (spec)) {
+ goto out;
+ }
+ } else {
+ pthread_t thr;
+ pthread_create_and_store ("region export", &thr, 0, ExportDialog::_export_region_thread, this);
+ }
+
+ gtk_main_iteration ();
+ while (spec.running) {
+ if (gtk_events_pending()) {
+ gtk_main_iteration ();
+ } else {
+ usleep (10000);
+ }
+ }
+
+ out:
+ progress_connection.disconnect ();
+ end_dialog ();
+}
+
+
+void
+ExportDialog::end_dialog ()
+{
+
+ if (spec.running) {
+ spec.stop = true;
+
+ while (spec.running) {
+ if (gtk_events_pending()) {
+ gtk_main_iteration ();
+ } else {
+ usleep (10000);
+ }
+ }
+ }
+
+ session->engine().freewheel (false);
+
+ hide_all ();
+
+ if (file_selector) {
+ file_selector->hide_all ();
+ }
+
+ set_modal (false);
+ ok_button.set_sensitive(true);
+}
+
+void
+ExportDialog::start_export ()
+{
+ if (session == 0) {
+ return;
+ }
+
+ /* If it the filename hasn't been set before, use the
+ directory above the current session as a default
+ location for the export.
+ */
+
+ if (file_entry.get_text().length() == 0) {
+ string dir = session->path();
+ string::size_type last_slash;
+
+ if ((last_slash = dir.find_last_of ('/')) != string::npos) {
+ dir = dir.substr (0, last_slash+1);
+ }
+
+ file_entry.set_text (dir);
+ }
+
+ progress_bar.set_percentage (0);
+ cancel_label.set_text (_("Cancel"));
+
+ show_all ();
+
+ if (session->master_out()) {
+ track_scroll.hide ();
+ } else {
+ master_scroll.hide ();
+ track_selector_button.hide ();
+ }
+}
+
+gint
+ExportDialog::header_chosen (GdkEventAny* ignored)
+{
+ if (sndfile_header_format_from_string (header_format_combo.get_entry()->get_text ()) == SF_FORMAT_WAV) {
+ endian_format_combo.set_sensitive (false);
+ } else {
+ endian_format_combo.set_sensitive (true);
+ }
+ return FALSE;
+}
+
+gint
+ExportDialog::bitdepth_chosen (GdkEventAny* ignored)
+{
+ int format = sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_entry()->get_text ());
+ switch (format) {
+ case SF_FORMAT_PCM_24:
+ case SF_FORMAT_PCM_32:
+ case SF_FORMAT_FLOAT:
+ dither_type_combo.set_sensitive (false);
+ break;
+
+ default:
+ dither_type_combo.set_sensitive (true);
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+ExportDialog::cue_file_type_chosen (GdkEventAny* ignored)
+{
+ if (cue_file_combo.get_entry()->get_text () != "None") {
+ cuefile_only_checkbox.set_sensitive (true);
+ } else {
+ cuefile_only_checkbox.set_active (false);
+ cuefile_only_checkbox.set_sensitive (false);
+ }
+ return FALSE;
+}
+
+gint
+ExportDialog::sample_rate_chosen (GdkEventAny* ignored)
+{
+ string sr_str = sample_rate_combo.get_entry()->get_text();
+ jack_nframes_t rate;
+
+ if (sr_str == N_("22.05kHz")) {
+ rate = 22050;
+ } else if (sr_str == N_("44.1kHz")) {
+ rate = 44100;
+ } else if (sr_str == N_("48kHz")) {
+ rate = 48000;
+ } else if (sr_str == N_("88.2kHz")) {
+ rate = 88200;
+ } else if (sr_str == N_("96kHz")) {
+ rate = 96000;
+ } else if (sr_str == N_("192kHz")) {
+ rate = 192000;
+ } else {
+ rate = session->frame_rate();
+ }
+
+ if (rate != session->frame_rate()) {
+ src_quality_combo.set_sensitive (true);
+ } else {
+ src_quality_combo.set_sensitive (false);
+ }
+
+ return FALSE;
+}
+
+gint
+ExportDialog::channels_chosen (GdkEventAny* ignored)
+{
+ bool mono;
+
+ mono = (channel_count_combo.get_entry()->get_text() == _("mono"));
+
+ if (mono) {
+ track_selector.set_column_visibility (2, false);
+ track_selector.set_column_title (1, _("Export"));
+
+ if (session->master_out()) {
+ master_selector.set_column_visibility (2, false);
+ master_selector.set_column_title (1, _("Export"));
+ }
+
+ } else {
+ track_selector.set_column_visibility (2, true);
+ track_selector.set_column_title (1, _("Left"));
+ track_selector.set_column_title (2, _("Right"));
+
+ if (session->master_out()) {
+ master_selector.set_column_visibility (2, true);
+ master_selector.set_column_title (1, _("Left"));
+ master_selector.set_column_title (2, _("Right"));
+ }
+ }
+
+ track_selector.column_titles_show ();
+ track_selector.clear ();
+ master_selector.column_titles_show ();
+ master_selector.clear ();
+
+ Session::RouteList routes = session->get_routes ();
+
+ for (Session::RouteList::iterator ri = routes.begin(); ri != routes.end(); ++ri) {
+
+ Route* route = (*ri);
+
+ if (route->hidden()) {
+ continue;
+ }
+
+ for (uint32_t i=0; i < route->n_outputs(); ++i) {
+
+ list<string> stupid_list;
+
+ if (route->n_outputs() == 1) {
+ stupid_list.push_back (route->name());
+ } else {
+ stupid_list.push_back (compose("%1: out-%2", route->name(), i+1));
+ }
+
+ stupid_list.push_back ("");
+ stupid_list.push_back ("");
+
+ if (route == session->master_out()) {
+ master_selector.rows().push_back (stupid_list);
+ CList_Helpers::Row row = master_selector.rows().back();
+ row.set_data (route->output (i));
+ master_selector.cell (row.get_row_num(), 1).set_pixmap (empty_pixmap, empty_mask);
+ master_selector.cell (row.get_row_num(), 2).set_pixmap (empty_pixmap, empty_mask);
+ } else {
+ track_selector.rows().push_back (stupid_list);
+ CList_Helpers::Row row = track_selector.rows().back();
+ row.set_data (route->output (i));
+ track_selector.cell (row.get_row_num(), 1).set_pixmap (empty_pixmap, empty_mask);
+ track_selector.cell (row.get_row_num(), 2).set_pixmap (empty_pixmap, empty_mask);
+ }
+ }
+ }
+
+ track_selector.select_all ();
+ master_selector.select_all ();
+
+ return FALSE;
+}
+
+gint
+ExportDialog::track_selector_button_press_event (GdkEventButton* ev)
+{
+ gint row, col;
+
+ if (track_selector.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) {
+ return FALSE;
+ }
+
+ gtk_signal_emit_stop_by_name (GTK_OBJECT(track_selector.gtkobj()), "button_press_event");
+
+ Gdk_Pixmap pixmap = track_selector.cell (row,col).get_pixmap ();
+
+ if (col != 0) {
+ if (pixmap.gdkobj() == check_pixmap) {
+ track_selector.cell (row,col).set_pixmap (empty_pixmap, empty_mask);
+ } else {
+ track_selector.cell (row,col).set_pixmap (check_pixmap, check_mask);
+ }
+ }
+
+ return TRUE;
+}
+
+gint
+ExportDialog::master_selector_button_press_event (GdkEventButton* ev)
+{
+ gint row, col;
+
+ if (master_selector.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) {
+ return FALSE;
+ }
+
+ gtk_signal_emit_stop_by_name (GTK_OBJECT(master_selector.gtkobj()), "button_press_event");
+
+ if (col != 0) {
+ Gdk_Pixmap pixmap = master_selector.cell (row,col).get_pixmap ();
+
+ if (pixmap.gdkobj() == check_pixmap) {
+ master_selector.cell (row,col).set_pixmap (empty_pixmap, empty_mask);
+ } else {
+ master_selector.cell (row,col).set_pixmap (check_pixmap, check_mask);
+ }
+ }
+
+ return TRUE;
+}
+
+gint
+ExportDialog::window_closed (GdkEventAny *ignored)
+{
+ end_dialog ();
+ return TRUE;
+}
+void
+ExportDialog::initiate_browse ()
+{
+ if (file_selector == 0) {
+ file_selector = new FileSelection;
+ file_selector->set_modal (true);
+
+ file_selector->get_cancel_button()->clicked.connect (bind (slot (*this, &ExportDialog::finish_browse), -1));
+ file_selector->get_ok_button()->clicked.connect (bind (slot (*this, &ExportDialog::finish_browse), 1));
+ file_selector->map_event.connect (bind (slot (*this, &ExportDialog::change_focus_policy), true));
+ file_selector->unmap_event.connect (bind (slot (*this, &ExportDialog::change_focus_policy), false));
+ }
+ file_selector->show_all ();
+}
+
+gint
+ExportDialog::change_focus_policy (GdkEventAny *ev, bool yn)
+{
+ Keyboard::the_keyboard().allow_focus (yn);
+ return FALSE;
+}
+
+void
+ExportDialog::finish_browse (int status)
+{
+ if (file_selector) {
+ if (status > 0) {
+ string result = file_selector->get_filename();
+
+ if (result.length()) {
+ file_entry.set_text (result);
+ }
+ }
+ file_selector->hide_all();
+ }
+}
+
+void
+ExportDialog::track_selector_button_click ()
+{
+ if (track_scroll.is_visible ()) {
+ track_scroll.hide ();
+ } else {
+ track_scroll.show_all ();
+ }
+}
diff --git a/gtk2_ardour/export_dialog.h b/gtk2_ardour/export_dialog.h
new file mode 100644
index 0000000000..f974af26a1
--- /dev/null
+++ b/gtk2_ardour/export_dialog.h
@@ -0,0 +1,132 @@
+/*
+ Copyright (C) 1999-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_export_dialog_h__
+#define __ardour_export_dialog_h__
+
+#include <gtk--.h>
+
+#include <ardour/export.h>
+#include "ardour_dialog.h"
+#include <ardour/location.h>
+
+
+class PublicEditor;
+
+namespace ARDOUR {
+ class Session;
+ class AudioRegion;
+}
+
+class ExportDialog : public ArdourDialog
+{
+ public:
+ ExportDialog (PublicEditor&, ARDOUR::AudioRegion* r = 0);
+ ~ExportDialog ();
+
+ void connect_to_session (ARDOUR::Session*);
+ void set_range (jack_nframes_t start, jack_nframes_t end);
+ void start_export ();
+
+ private:
+ PublicEditor& editor;
+ ARDOUR::Session* session;
+ ARDOUR::AudioRegion* audio_region;
+ Gtk::VBox vpacker;
+ Gtk::VBox track_vpacker;
+ Gtk::HBox hpacker;
+ Gtk::HBox button_box;
+
+ Gtk::Table format_table;
+ Gtk::Frame format_frame;
+
+ Gtk::Label sample_rate_label;
+ Gtk::Combo sample_rate_combo;
+ Gtk::Label src_quality_label;
+ Gtk::Combo src_quality_combo;
+ Gtk::Label dither_type_label;
+ Gtk::Combo dither_type_combo;
+ Gtk::Label cue_file_label;
+ Gtk::Combo cue_file_combo;
+ Gtk::Label channel_count_label;
+ Gtk::Combo channel_count_combo;
+ Gtk::Label header_format_label;
+ Gtk::Combo header_format_combo;
+ Gtk::Label bitdepth_format_label;
+ Gtk::Combo bitdepth_format_combo;
+ Gtk::Label endian_format_label;
+ Gtk::Combo endian_format_combo;
+ Gtk::CheckButton cuefile_only_checkbox;
+
+ Gtk::Frame file_frame;
+ Gtk::Entry file_entry;
+ Gtk::HBox file_hbox;
+ Gtk::Button file_browse_button;
+
+ Gtk::Button ok_button;
+ Gtk::Button cancel_button;
+ Gtk::Label cancel_label;
+ Gtk::ProgressBar progress_bar;
+ Gtk::ScrolledWindow track_scroll;
+ Gtk::ScrolledWindow master_scroll;
+ Gtk::Button track_selector_button;
+ Gtk::CList track_selector;
+ Gtk::CList master_selector;
+ Gtk::FileSelection *file_selector;
+ ARDOUR::AudioExportSpecification spec;
+
+ static GdkPixmap *check_pixmap;
+ static GdkBitmap *check_mask;
+ static GdkPixmap *empty_pixmap;
+ static GdkBitmap *empty_mask;
+
+ static void *_thread (void *arg);
+ gint progress_timeout ();
+ SigC::Connection progress_connection;
+ void build_window ();
+ void end_dialog();
+ gint header_chosen (GdkEventAny *ignored);
+ gint channels_chosen (GdkEventAny *ignored);
+ gint bitdepth_chosen (GdkEventAny *ignored);
+ gint sample_rate_chosen (GdkEventAny *ignored);
+ gint cue_file_type_chosen(GdkEventAny *ignored);
+ gint track_selector_button_press_event (GdkEventButton *ev);
+ gint master_selector_button_press_event (GdkEventButton *ev);
+
+ void do_export_cd_markers (const string& path, const string& cuefile_type);
+ void export_cue_file (ARDOUR::Locations::LocationList& locations, const string& path);
+ void export_toc_file (ARDOUR::Locations::LocationList& locations, const string& path);
+ void do_export ();
+ gint change_focus_policy (GdkEventAny *, bool);
+ gint window_closed (GdkEventAny *ignored);
+
+ void track_selector_button_click ();
+
+ void initiate_browse ();
+ void finish_browse (int status);
+
+ void set_state();
+ void save_state();
+
+ static void* _export_region_thread (void *);
+ void export_region ();
+};
+
+#endif // __ardour_export_dialog_h__
+
diff --git a/gtk2_ardour/extra_bind.h b/gtk2_ardour/extra_bind.h
new file mode 100644
index 0000000000..70e1c3e538
--- /dev/null
+++ b/gtk2_ardour/extra_bind.h
@@ -0,0 +1,138 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_extra_bind_h__
+#define __ardour_extra_bind_h__
+
+#include <sigc++/adaptor.h>
+#include <sigc++/scope.h>
+
+namespace SigC
+{
+
+/****************************************************************
+ ***** Adaptor Bind Slot 0 arguments, 3 hidden arguments
+ ****************************************************************/
+template <class R,
+ class C1, class C2, class C3>
+struct AdaptorBindSlot0_3: public AdaptorSlot_
+ {
+#ifdef SIGC_CXX_PARTIAL_SPEC
+ typedef R RType;
+#else
+ typedef typename Trait<R>::type RType;
+#endif
+ typedef Slot0<R> SlotType;
+ typedef Slot3<R,C1,C2,C3> InSlotType;
+
+ struct Node:public AdaptorNode
+ {
+ C1 c1_;
+ C2 c2_;
+ C3 c3_;
+ };
+
+ typedef CallDataObj2<typename SlotType::Func,Node> CallData;
+
+ static RType callback(void* d)
+ {
+ CallData* data=(CallData*)d;
+ Node* node=data->obj;
+ return ((typename InSlotType::Callback&)(node->data_))(
+ node->c1_,
+ node->c2_,
+ node->c3_);
+ }
+ static SlotData* create(SlotData *s,C1 c1, C2 c2, C3 c3)
+ {
+ SlotData* tmp=(SlotData*)s;
+ Node *node=new Node();
+ copy_callback(tmp,node);
+ node->c1_=c1;
+ node->c2_=c2;
+ node->c3_=c3;
+ CallData &data=reinterpret_cast<CallData&>(tmp->data_);
+ data.callback=&callback;
+ data.obj=node;
+ return tmp;
+ }
+ };
+
+
+#ifndef SIGC_CXX_VOID_RETURN
+#ifdef SIGC_CXX_PARTIAL_SPEC
+template <
+ class C1,C2,C3>
+struct AdaptorBindSlot0_3
+ <void,
+ C1,C2,C3> : public AdaptorSlot_
+ {
+ typedef void RType;
+ typedef Slot0<void> SlotType;
+ typedef Slot3<void,C1,C2,C3> InSlotType;
+
+ struct Node:public AdaptorNode
+ {
+ C1 c1_;
+ C2 c2_;
+ C3 c3_;
+ };
+
+ typedef CallDataObj2<typename SlotType::Func,Node> CallData;
+
+ static RType callback(void* d)
+ {
+ CallData* data=(CallData*)d;
+ Node* node=data->obj;
+ ((typename InSlotType::Callback&)(node->data_))(
+ node->c1_,
+ node->c2_,
+ node->c3);
+ }
+ static SlotData* create(SlotData *s,C1 c1, C2 c2, C3 c3)
+ {
+ SlotData* tmp=(SlotData*)s;
+ Node *node=new Node();
+ copy_callback(tmp,node);
+ node->c1_=c1;
+ node->c2_=c2;
+ node->c3_=c3;
+ CallData &data=reinterpret_cast<CallData&>(tmp->data_);
+ data.callback=&callback;
+ data.obj=node;
+ return tmp;
+ }
+ };
+
+#endif
+#endif
+
+template <class C1, class C2, class C3,
+ class R>
+Slot0<R>
+ bind(const Slot3<R,C1,C2,C3> &s,
+ C1 c1, C2 c2, C3 c3)
+ {return AdaptorBindSlot0_3<R,
+ C1,C2,C3>::create(s.data(),c1,c2,c3);
+ }
+
+} /* namespace */
+
+#endif /* __ardour_extra_bind_h__ */
diff --git a/gtk2_ardour/gain_automation_time_axis.cc b/gtk2_ardour/gain_automation_time_axis.cc
new file mode 100644
index 0000000000..2f739e0fad
--- /dev/null
+++ b/gtk2_ardour/gain_automation_time_axis.cc
@@ -0,0 +1,75 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/curve.h>
+#include <ardour/route.h>
+
+#include "gain_automation_time_axis.h"
+#include "automation_line.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+
+GainAutomationTimeAxisView::GainAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, Widget* p, std::string n, ARDOUR::Curve& c)
+
+ : AxisView (s),
+ AutomationTimeAxisView (s, r, e, parent, p, n, X_("gain"), ""),
+ curve (c)
+
+{
+}
+
+GainAutomationTimeAxisView::~GainAutomationTimeAxisView ()
+{
+}
+
+void
+GainAutomationTimeAxisView::add_automation_event (GtkCanvasItem* item, GdkEvent* event, jack_nframes_t when, double y)
+{
+ double x = 0;
+
+ gtk_canvas_item_w2i (canvas_display, &x, &y);
+
+ /* compute vertical fractional position */
+
+ y = 1.0 - (y / height);
+
+ /* map using line */
+
+ lines.front()->view_to_model_y (y);
+
+ _session.begin_reversible_command (_("add gain automation event"));
+
+ _session.add_undo (curve.get_memento());
+ curve.add (when, y);
+ _session.add_redo_no_execute (curve.get_memento());
+ _session.commit_reversible_command ();
+ _session.set_dirty ();
+}
+
+void
+GainAutomationTimeAxisView::set_automation_state (AutoState state)
+{
+ if (!ignore_state_request) {
+ route.set_gain_automation_state (state);
+ }
+}
diff --git a/gtk2_ardour/gain_automation_time_axis.h b/gtk2_ardour/gain_automation_time_axis.h
new file mode 100644
index 0000000000..b261e34d30
--- /dev/null
+++ b/gtk2_ardour/gain_automation_time_axis.h
@@ -0,0 +1,33 @@
+#ifndef __ardour_gtk_gain_automation_time_axis_h__
+#define __ardour_gtk_gain_automation_time_axis_h__
+
+#include "automation_time_axis.h"
+
+namespace ARDOUR {
+ class Redirect;
+ class Curve;
+}
+
+class GainAutomationTimeAxisView : public AutomationTimeAxisView
+{
+ public:
+ GainAutomationTimeAxisView (ARDOUR::Session&,
+ ARDOUR::Route&,
+ PublicEditor&,
+ TimeAxisView& parent_axis,
+ Gtk::Widget* parent,
+ std::string name,
+ ARDOUR::Curve&);
+
+ ~GainAutomationTimeAxisView();
+
+ void add_automation_event (GtkCanvasItem *item, GdkEvent *event, jack_nframes_t, double);
+
+ private:
+ ARDOUR::Curve& curve;
+
+ void automation_changed ();
+ void set_automation_state (ARDOUR::AutoState);
+};
+
+#endif /* __ardour_gtk_gain_automation_time_axis_h__ */
diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc
new file mode 100644
index 0000000000..0e7f3b77aa
--- /dev/null
+++ b/gtk2_ardour/gain_meter.cc
@@ -0,0 +1,762 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <limits.h>
+
+#include <ardour/io.h>
+#include <ardour/route.h>
+#include <ardour/route_group.h>
+#include <ardour/session.h>
+#include <ardour/session_route.h>
+#include <ardour/dB.h>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/pix.h>
+#include <gtkmmext/fastmeter.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/barcontroller.h>
+#include <midi++/manager.h>
+#include <pbd/fastlog.h>
+
+#include "ardour_ui.h"
+#include "gain_meter.h"
+#include "utils.h"
+#include "logmeter.h"
+#include "gui_thread.h"
+
+#include <ardour/session.h>
+#include <ardour/route.h>
+
+#include "i18n.h"
+#include "misc_xpms"
+
+using namespace ARDOUR;
+using namespace Gtkmmext;
+using namespace Gtk;
+using namespace SigC;
+
+Signal0<void> GainMeter::ResetAllPeakDisplays;
+Signal1<void,RouteGroup*> GainMeter::ResetGroupPeakDisplays;
+Pix* GainMeter::slider_pix = 0;
+
+int
+GainMeter::setup_slider_pix ()
+{
+ vector<const char **> xpms;
+
+ xpms.push_back (vslider_rail_xpm);
+ xpms.push_back (vslider_slider_xpm);
+
+ if ((slider_pix = get_pix ("sliders", xpms, false)) == 0) {
+ error << _("Cannot create slider pixmaps") << endmsg;
+ return -1;
+ }
+
+ slider_pix->ref ();
+ return 0;
+}
+
+GainMeter::GainMeter (IO& io, Session& s)
+ : _io (io),
+ _session (s),
+ gain_slider (0),
+ // 0.781787 is the value needed for gain to be set to 0.
+ gain_adjustment (0.781787, 0.0, 1.0, 0.01, 0.1),
+ gain_display (&gain_adjustment, "MixerStripGainDisplay"),
+ gain_unit_label (_("dbFS")),
+ meter_point_label (_("pre")),
+ top_table (1, 2)
+
+{
+ if (slider_pix == 0) {
+ setup_slider_pix ();
+ }
+
+ ignore_toggle = false;
+ meter_menu = 0;
+
+ gain_slider = manage (new VSliderController (slider_pix,
+ &gain_adjustment,
+ & _io.midi_gain_control(),
+ false));
+
+ gain_slider->button_press_event.connect (slot (*this, &GainMeter::start_gain_touch));
+ gain_slider->button_release_event.connect (slot (*this, &GainMeter::end_gain_touch));
+ gain_slider->set_name ("MixerGainMeter");
+
+ if (_session.midi_port()) {
+ _io.set_midi_to_gain_function (slider_position_to_gain);
+ _io.set_gain_to_midi_function (gain_to_slider_position);
+ }
+
+ gain_display.set_print_func (_gain_printer, this);
+ set_usize_to_display_given_text (gain_display, "-86.0", 2, 2);
+
+ gain_unit_button.add (gain_unit_label);
+ gain_unit_button.set_name ("MixerStripGainUnitButton");
+ gain_unit_label.set_name ("MixerStripGainUnitButton");
+
+ top_table.set_col_spacings (2);
+ top_table.set_homogeneous (true);
+ top_table.attach (gain_unit_button, 0, 1, 0, 1);
+
+ Route* r;
+
+ if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+ r->meter_change.connect (slot (*this, &GainMeter::meter_changed));
+ meter_point_button.add (meter_point_label);
+ meter_point_button.set_name ("MixerStripMeterPreButton");
+ meter_point_label.set_name ("MixerStripMeterPreButton");
+
+ switch (r->meter_point()) {
+ case MeterInput:
+ meter_point_label.set_text (_("input"));
+ break;
+
+ case MeterPreFader:
+ meter_point_label.set_text (_("pre"));
+ break;
+
+ case MeterPostFader:
+ meter_point_label.set_text (_("post"));
+ break;
+ }
+
+ /* TRANSLATORS: this string should be longest of the strings
+ used to describe meter points. In english, its "input".
+ */
+
+ set_usize_to_display_given_text (meter_point_button, _("tupni"), 2, 2);
+
+ meter_point_button.button_press_event.connect (slot (*this, &GainMeter::meter_press));
+ meter_point_button.button_release_event.connect (slot (*this, &GainMeter::meter_release));
+
+ top_table.attach (meter_point_button, 1, 2, 0, 1);
+ }
+
+ gain_display_box.set_spacing (2);
+ gain_display_frame.set_shadow_type (GTK_SHADOW_IN);
+ gain_display_frame.set_name ("BaseFrame");
+ gain_display_frame.add (gain_display);
+ gain_display_box.pack_start (gain_display_frame, false, false);
+
+ peak_display.set_name ("MixerStripPeakDisplay");
+ set_usize_to_display_given_text (peak_display, "-86.0", 2, 2);
+ peak_display.add (peak_display_label);
+ peak_display_frame.set_shadow_type (GTK_SHADOW_IN);
+ peak_display_frame.set_name ("BaseFrame");
+ peak_display_frame.add (peak_display);
+ max_peak = minus_infinity();
+ peak_display_label.set_text (_("-inf"));
+
+ gain_display_box.pack_start (peak_display_frame, false, false);
+
+
+ meter_metric_area.set_usize (18, -1);
+ meter_metric_area.set_name ("MeterMetricsStrip");
+
+ meter_packer.show ();
+ gain_slider->show_all ();
+
+ meter_packer.set_spacing (2);
+ fader_box.set_spacing (2);
+
+ fader_box.pack_start (*gain_slider, false, false);
+
+ hbox.set_spacing (4);
+ hbox.pack_start (fader_box, false, false);
+ hbox.pack_start (meter_packer, false, false);
+
+ set_spacing (4);
+ pack_start (top_table, false, false);
+ pack_start (gain_display_box, false, false);
+ pack_start (hbox, false, false);
+
+ show_all ();
+
+ _io.gain_changed.connect (slot (*this, &GainMeter::gain_changed));
+
+ meter_metric_area.expose_event.connect (slot (*this, &GainMeter::meter_metrics_expose));
+ gain_adjustment.value_changed.connect (slot (*this, &GainMeter::gain_adjusted));
+ peak_display.button_release_event.connect (slot (*this, &GainMeter::peak_button_release));
+
+ _session.MeterHoldChanged.connect (slot (*this, &GainMeter::meter_hold_changed));
+
+ gain_changed (0);
+ update_gain_sensitive ();
+
+ ResetAllPeakDisplays.connect (slot (*this, &GainMeter::reset_peak_display));
+ ResetGroupPeakDisplays.connect (slot (*this, &GainMeter::reset_group_peak_display));
+}
+
+void
+GainMeter::set_width (Width w)
+{
+ switch (w) {
+ case Wide:
+ peak_display_frame.show_all();
+ break;
+ case Narrow:
+ peak_display_frame.hide_all();
+ break;
+ }
+
+ _width = w;
+ setup_meters ();
+}
+
+gint
+GainMeter::meter_metrics_expose (GdkEventExpose *ev)
+{
+ /* XXX optimize this so that it doesn't do it all everytime */
+
+ double fraction;
+
+ Gdk_Window win (meter_metric_area.get_window());
+ Gdk_GC fg_gc (meter_metric_area.get_style()->get_fg_gc (GTK_STATE_NORMAL));
+ Gdk_GC bg_gc (meter_metric_area.get_style()->get_bg_gc (GTK_STATE_NORMAL));
+ Gdk_Font font (meter_metric_area.get_style()->get_font());
+ gint x, y, width, height, depth;
+ gint pos;
+ int db_points[] = { -50, -10, -3, 0, 6 };
+ uint32_t i;
+ char buf[32];
+ GdkRectangle base_rect;
+ GdkRectangle draw_rect;
+
+ win.get_geometry (x, y, width, height, depth);
+
+ base_rect.width = width;
+ base_rect.height = height;
+ base_rect.x = 0;
+ base_rect.y = 0;
+
+ gdk_rectangle_intersect (&ev->area, &base_rect, &draw_rect);
+ win.draw_rectangle (bg_gc, true, draw_rect.x, draw_rect.y, draw_rect.width, draw_rect.height);
+
+ for (i = 0; i < sizeof (db_points)/sizeof (db_points[0]); ++i) {
+ fraction = log_meter (db_points[i]);
+ pos = height - (gint) floor (height * fraction);
+
+ snprintf (buf, sizeof (buf), "%d", db_points[i]);
+
+ gint twidth;
+ gint lbearing;
+ gint rbearing;
+ gint ascent;
+ gint descent;
+
+ gdk_string_extents (font,
+ buf,
+ &lbearing,
+ &rbearing,
+ &twidth,
+ &ascent,
+ &descent);
+
+ win.draw_text (font, fg_gc, width - twidth, pos + ascent, buf, strlen (buf));
+ }
+
+ return TRUE;
+}
+
+GainMeter::~GainMeter ()
+{
+
+ if (meter_menu) {
+ delete meter_menu;
+ }
+
+ for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); i++) {
+ if ((*i).meter) {
+ delete (*i).meter;
+ }
+ }
+}
+
+void
+GainMeter::update_meters ()
+{
+ vector<MeterInfo>::iterator i;
+ uint32_t n;
+ float peak;
+ char buf[32];
+
+
+ for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
+ if ((*i).packed) {
+ peak = _io.peak_input_power (n);
+
+ if (_session.meter_falloff() == 0.0f || peak > (*i).meter->get_user_level()) {
+ (*i).meter->set (log_meter (peak), peak);
+ }
+
+ if (peak > max_peak) {
+ max_peak = peak;
+ /* set peak display */
+ snprintf (buf, sizeof(buf), "%.1f", max_peak);
+ peak_display_label.set_text (buf);
+
+ if (max_peak >= 0.0f) {
+ peak_display.set_name ("MixerStripPeakDisplayPeak");
+ }
+ }
+ }
+ }
+
+}
+
+void
+GainMeter::update_meters_falloff ()
+{
+ vector<MeterInfo>::iterator i;
+ uint32_t n;
+ float dbpeak;
+
+ for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
+ if ((*i).packed) {
+ // just do falloff
+ //peak = (*i).meter->get_level() * _falloff_rate;
+ dbpeak = (*i).meter->get_user_level() - _session.meter_falloff();
+
+ dbpeak = std::max(dbpeak, -200.0f);
+
+ // cerr << "tmplevel: " << tmplevel << endl;
+ (*i).meter->set (log_meter (dbpeak), dbpeak);
+ }
+ }
+
+}
+
+
+void
+GainMeter::meter_hold_changed()
+{
+ ENSURE_GUI_THREAD(slot (*this, &GainMeter::meter_hold_changed));
+
+ vector<MeterInfo>::iterator i;
+ uint32_t n;
+
+ for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
+
+ (*i).meter->set_hold_count ((uint32_t) floor(_session.meter_hold()));
+ }
+}
+
+void
+GainMeter::hide_all_meters ()
+{
+ bool remove_metric_area = false;
+
+ for (vector<MeterInfo>::iterator i = meters.begin(); i != meters.end(); ++i) {
+ if ((*i).packed) {
+ remove_metric_area = true;
+ meter_packer.remove (*((*i).meter));
+ (*i).packed = false;
+ }
+ }
+
+ if (remove_metric_area) {
+ if (meter_metric_area.get_parent()) {
+ meter_packer.remove (meter_metric_area);
+ }
+ }
+}
+
+void
+GainMeter::setup_meters ()
+{
+ uint32_t nmeters = _io.n_outputs();
+ guint16 width;
+
+ hide_all_meters ();
+
+ Route* r;
+
+ if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+
+ switch (r->meter_point()) {
+ case MeterPreFader:
+ case MeterInput:
+ nmeters = r->n_inputs();
+ break;
+ case MeterPostFader:
+ nmeters = r->n_outputs();
+ break;
+ }
+
+ } else {
+
+ nmeters = _io.n_outputs();
+
+ }
+
+ if (nmeters == 0) {
+ return;
+ }
+
+ if (_width == Wide) {
+ meter_packer.pack_start (meter_metric_area, false, false);
+ meter_metric_area.show_all ();
+ }
+
+ if (nmeters <= 2) {
+ width = regular_meter_width;
+ } else {
+ width = thin_meter_width;
+ }
+
+ while (meters.size() < nmeters) {
+ meters.push_back (MeterInfo());
+ }
+
+ for (uint32_t n = 0; n < nmeters; ++n) {
+ if (meters[n].width != width) {
+ delete meters[n].meter;
+ meters[n].meter = new FastMeter ((uint32_t) floor (_session.meter_hold()), width, FastMeter::Vertical);
+ meters[n].width = width;
+
+ meters[n].meter->add_events (GDK_BUTTON_RELEASE_MASK);
+ meters[n].meter->button_release_event.connect
+ (bind (slot (*this, &GainMeter::meter_button_release), n));
+ meters[n].meter->button_release_event.connect_after (slot (do_not_propagate));
+ }
+
+ meter_packer.pack_start (*meters[n].meter, false, false);
+ meters[n].meter->show_all ();
+ meters[n].packed = true;
+ }
+}
+
+gint
+GainMeter::peak_button_release (GdkEventButton* ev)
+{
+ /* reset peak label */
+
+ if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control|Keyboard::Shift)) {
+ ResetAllPeakDisplays ();
+ } else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ Route* r;
+ if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+ ResetGroupPeakDisplays (r->mix_group());
+ }
+ } else {
+ reset_peak_display ();
+ }
+ return TRUE;
+}
+
+void
+GainMeter::reset_peak_display ()
+{
+ max_peak = minus_infinity();
+ peak_display_label.set_text (_("-inf"));
+ peak_display.set_name ("MixerStripPeakDisplay");
+}
+
+void
+GainMeter::reset_group_peak_display (RouteGroup* group)
+{
+ Route* r;
+ if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+ if (group == r->mix_group()) {
+ reset_peak_display ();
+ }
+ }
+}
+
+gint
+GainMeter::meter_button_release (GdkEventButton* ev, uint32_t which)
+{
+ switch (ev->button) {
+ case 1:
+ meters[which].meter->clear();
+ max_peak = minus_infinity();
+ peak_display_label.set_text (_("-inf"));
+ peak_display.set_name ("MixerStripPeakDisplay");
+ break;
+
+ case 3:
+ // popup_meter_menu (ev);
+ break;
+ };
+
+ return TRUE;
+}
+
+void
+GainMeter::popup_meter_menu (GdkEventButton *ev)
+{
+ using namespace Menu_Helpers;
+
+ if (meter_menu == 0) {
+ meter_menu = new Gtk::Menu;
+ MenuList& items = meter_menu->items();
+
+ items.push_back (MenuElem ("-inf .. +0dBFS"));
+ items.push_back (MenuElem ("-10dB .. +0dBFS"));
+ items.push_back (MenuElem ("-4 .. +0dBFS"));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem ("-inf .. -2dBFS"));
+ items.push_back (MenuElem ("-10dB .. -2dBFS"));
+ items.push_back (MenuElem ("-4 .. -2dBFS"));
+ }
+
+ meter_menu->popup (1, ev->time);
+}
+
+void
+GainMeter::_gain_printer (char buf[32], Gtk::Adjustment& adj, void *arg)
+{
+ static_cast<GainMeter *>(arg)->gain_printer (buf, adj);
+}
+
+void
+GainMeter::gain_printer (char buf[32], Gtk::Adjustment& adj)
+{
+ float v = adj.get_value();
+
+ if (v == 0.0) {
+ strcpy (buf, _("-inf"));
+ } else {
+ snprintf (buf, 32, "%.1f", coefficient_to_dB (slider_position_to_gain (v)));
+ }
+}
+
+void
+GainMeter::gain_adjusted ()
+{
+ if (!ignore_toggle) {
+ _io.set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
+ }
+}
+
+void
+GainMeter::effective_gain_display ()
+{
+ gfloat value = gain_to_slider_position (_io.effective_gain());
+
+ if (gain_adjustment.get_value() != value) {
+ ignore_toggle = true;
+ gain_adjustment.set_value (value);
+ ignore_toggle = false;
+ }
+}
+
+void
+GainMeter::gain_changed (void *src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &GainMeter::effective_gain_display));
+}
+
+gint
+GainMeter::entry_focus_event (GdkEventFocus* ev)
+{
+ if (ev->in) {
+ ARDOUR_UI::instance()->allow_focus (true);
+ } else {
+ ARDOUR_UI::instance()->allow_focus (false);
+ }
+ return TRUE;
+}
+
+
+void
+GainMeter::set_meter_strip_name (string name)
+{
+ meter_metric_area.set_name (name);
+}
+
+void
+GainMeter::set_fader_name (string name)
+{
+ gain_slider->set_name (name);
+}
+
+void
+GainMeter::update_gain_sensitive ()
+{
+ static_cast<Gtkmmext::SliderController*>(gain_slider)->set_sensitive (!(_io.gain_automation_state() & Play));
+}
+
+
+static MeterPoint
+next_meter_point (MeterPoint mp)
+{
+ switch (mp) {
+ case MeterInput:
+ return MeterPreFader;
+ break;
+
+ case MeterPreFader:
+ return MeterPostFader;
+ break;
+
+ case MeterPostFader:
+ return MeterInput;
+ break;
+ }
+ /*NOTREACHED*/
+ return MeterInput;
+}
+
+gint
+GainMeter::meter_press(GdkEventButton* ev)
+{
+ Route* _route;
+
+ wait_for_release = false;
+
+ if ((_route = dynamic_cast<Route*>(&_io)) == 0) {
+ return FALSE;
+ }
+
+ if (!ignore_toggle) {
+
+ if (Keyboard::is_context_menu_event (ev)) {
+
+ // no menu at this time.
+
+ } else {
+
+ if (ev->button == 2) {
+
+ // ctrl-button2 click is the midi binding click
+ // button2-click is "momentary"
+
+ if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
+ wait_for_release = true;
+ old_meter_point = _route->meter_point ();
+ }
+ }
+
+ if (ev->button == 1 || ev->button == 2) {
+
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+
+ /* ctrl-shift-click applies change to all routes */
+
+ _session.foreach_route (this, &GainMeter::set_meter_point, next_meter_point (_route->meter_point()));
+
+ } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+
+ /* ctrl-click: solo mix group.
+ ctrl-button2 is MIDI learn.
+ */
+
+ if (ev->button == 1) {
+ set_mix_group_meter_point (*_route, next_meter_point (_route->meter_point()));
+ }
+
+ } else {
+
+ /* click: solo this route */
+
+ _route->set_meter_point (next_meter_point (_route->meter_point()), this);
+ }
+ }
+ }
+ }
+
+ return stop_signal (meter_point_button, "button-press-event");
+
+}
+
+gint
+GainMeter::meter_release(GdkEventButton* ev)
+{
+ if(!ignore_toggle){
+ if (wait_for_release){
+ wait_for_release = false;
+ set_meter_point (*(dynamic_cast<Route*>(&_io)), old_meter_point);
+ stop_signal (meter_point_button, "button-release-event");
+ }
+ }
+ return TRUE;
+}
+
+void
+GainMeter::set_meter_point (Route& route, MeterPoint mp)
+{
+ route.set_meter_point (mp, this);
+}
+
+void
+GainMeter::set_mix_group_meter_point (Route& route, MeterPoint mp)
+{
+ RouteGroup* mix_group;
+
+ if((mix_group = route.mix_group()) != 0){
+ mix_group->apply (&Route::set_meter_point, mp, this);
+ } else {
+ route.set_meter_point (mp, this);
+ }
+}
+
+void
+GainMeter::meter_changed (void *src)
+{
+ Route* r;
+
+ ENSURE_GUI_THREAD (bind (slot (*this, &GainMeter::meter_changed), src));
+
+ if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+
+ switch (r->meter_point()) {
+ case MeterInput:
+ meter_point_label.set_text (_("input"));
+ break;
+
+ case MeterPreFader:
+ meter_point_label.set_text (_("pre"));
+ break;
+
+ case MeterPostFader:
+ meter_point_label.set_text (_("post"));
+ break;
+ }
+
+ setup_meters ();
+ }
+}
+
+void
+GainMeter::meter_point_clicked ()
+{
+ Route* r;
+
+ if ((r = dynamic_cast<Route*> (&_io)) != 0) {
+
+ }
+}
+
+gint
+GainMeter::start_gain_touch (GdkEventButton* ev)
+{
+ _io.start_gain_touch ();
+ return FALSE;
+}
+
+gint
+GainMeter::end_gain_touch (GdkEventButton* ev)
+{
+ _io.end_gain_touch ();
+ return FALSE;
+}
diff --git a/gtk2_ardour/gain_meter.h b/gtk2_ardour/gain_meter.h
new file mode 100644
index 0000000000..06ae0dafd9
--- /dev/null
+++ b/gtk2_ardour/gain_meter.h
@@ -0,0 +1,156 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_gain_meter_h__
+#define __ardour_gtk_gain_meter_h__
+
+#include <vector>
+
+#include <ardour/types.h>
+
+#include <gtk--.h>
+#include <gtkmmext/slider_controller.h>
+#include <gtkmmext/click_box.h>
+
+#include "enums.h"
+
+namespace ARDOUR {
+ class IO;
+ class Session;
+ class Route;
+ class RouteGroup;
+}
+namespace Gtkmmext {
+ class FastMeter;
+ class BarController;
+ class Pix;
+}
+
+class GainMeter : public Gtk::VBox
+{
+ public:
+ GainMeter (ARDOUR::IO&, ARDOUR::Session&);
+ ~GainMeter ();
+
+ void update_gain_sensitive ();
+
+ void update_meters ();
+ void update_meters_falloff ();
+
+ void effective_gain_display ();
+
+ void set_width (Width);
+ void setup_meters ();
+
+ void set_meter_strip_name (string name);
+ void set_fader_name (string name);
+
+ private:
+ ARDOUR::IO& _io;
+ ARDOUR::Session& _session;
+
+ bool ignore_toggle;
+
+ Gtkmmext::VSliderController *gain_slider;
+ Gtk::Adjustment gain_adjustment;
+ Gtk::Frame gain_display_frame;
+ Gtkmmext::ClickBox gain_display;
+ Gtk::Frame peak_display_frame;
+ Gtk::EventBox peak_display;
+ Gtk::Label peak_display_label;
+ Gtk::Button gain_unit_button;
+ Gtk::Label gain_unit_label;
+ Gtk::HBox gain_display_box;
+ Gtk::HBox fader_box;
+ Gtk::DrawingArea meter_metric_area;
+ Gtk::Button meter_point_button;
+ Gtk::Label meter_point_label;
+ Gtk::Table top_table;
+ Width _width;
+
+ gint meter_metrics_expose (GdkEventExpose *);
+
+ static void _gain_printer (char buf[32], Gtk::Adjustment&, void *);
+ void gain_printer (char buf[32], Gtk::Adjustment&);
+
+ struct MeterInfo {
+ Gtkmmext::FastMeter *meter;
+ gint16 width;
+ bool packed;
+
+ MeterInfo() {
+ meter = 0;
+ width = 0;
+ packed = false;
+ }
+ };
+
+ static const guint16 regular_meter_width = 5;
+ static const guint16 thin_meter_width = 2;
+ vector<MeterInfo> meters;
+ float max_peak;
+
+
+ Gtk::HBox hbox;
+ Gtk::HBox meter_packer;
+
+ void gain_adjusted ();
+ void gain_changed (void *);
+
+ void meter_point_clicked ();
+ void meter_changed (void *);
+ void gain_unit_changed ();
+
+ void hide_all_meters ();
+
+ gint meter_button_press (GdkEventButton*, uint32_t);
+ gint meter_button_release (GdkEventButton*, uint32_t);
+
+ gint peak_button_release (GdkEventButton*);
+
+ Gtk::Menu* meter_menu;
+ void popup_meter_menu (GdkEventButton*);
+
+ gint start_gain_touch (GdkEventButton*);
+ gint end_gain_touch (GdkEventButton*);
+
+ gint entry_focus_event (GdkEventFocus* ev);
+
+ void set_mix_group_meter_point (ARDOUR::Route&, ARDOUR::MeterPoint);
+ void set_meter_point (ARDOUR::Route&, ARDOUR::MeterPoint);
+ gint meter_release (GdkEventButton*);
+ gint meter_press (GdkEventButton*);
+ bool wait_for_release;
+ ARDOUR::MeterPoint old_meter_point;
+
+ void meter_hold_changed();
+
+ void reset_peak_display ();
+ void reset_group_peak_display (ARDOUR::RouteGroup*);
+
+ static SigC::Signal0<void> ResetAllPeakDisplays;
+ static SigC::Signal1<void,ARDOUR::RouteGroup*> ResetGroupPeakDisplays;
+
+ static Gtkmmext::Pix* slider_pix;
+ static int setup_slider_pix ();
+};
+
+#endif /* __ardour_gtk_gain_meter_h__ */
+
diff --git a/gtk2_ardour/gettext.h b/gtk2_ardour/gettext.h
new file mode 100644
index 0000000000..339c74ffe7
--- /dev/null
+++ b/gtk2_ardour/gettext.h
@@ -0,0 +1,82 @@
+/* Convenience header for conditional use of GNU <libintl.h>.
+ Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option. */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions. */
+# include <libintl.h>
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+ chokes if dcgettext is defined as a macro. So include it now, to make
+ later inclusions of <locale.h> a NOP. We don't include <libintl.h>
+ as well because people using "gettext.h" will not include <libintl.h>,
+ and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+ is OK. */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Disabled NLS.
+ The casts to 'const char *' serve the purpose of producing warnings
+ for invalid uses of the value returned from these functions.
+ On pre-ANSI systems without 'const', the config.h file is supposed to
+ contain "#define const". */
+
+/* other headers may have included libintl.h */
+
+# undef gettext
+# undef dgettext
+# undef dcgettext
+# undef ngettext
+# undef dngettext
+# undef dcngettext
+# undef textdomain
+# undef bindtextdomain
+# undef bind_textdomain_codeset
+
+# define gettext(Msgid) ((const char *) (Msgid))
+# define dgettext(Domainname, Msgid) ((const char *) (Msgid))
+# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid))
+# define ngettext(Msgid1, Msgid2, N) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2))
+# define textdomain(Domainname) ((const char *) (Domainname))
+# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
+# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
+
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+ extraction of messages, but does not call gettext(). The run-time
+ translation is done at a different place in the code.
+ The argument, String, should be a literal string. Concatenated strings
+ and other string expressions won't work.
+ The macro's expansion is not parenthesized, so that it is suitable as
+ initializer for static 'char[]' or 'const char[]' variables. */
+#define gettext_noop(String) String
+
+#endif /* _LIBGETTEXT_H */
diff --git a/gtk2_ardour/ghostregion.cc b/gtk2_ardour/ghostregion.cc
new file mode 100644
index 0000000000..8caacac3b3
--- /dev/null
+++ b/gtk2_ardour/ghostregion.cc
@@ -0,0 +1,68 @@
+#include "canvas-simplerect.h"
+#include "ghostregion.h"
+#include "automation_time_axis.h"
+#include "rgb_macros.h"
+
+using namespace Editing;
+
+GhostRegion::GhostRegion (AutomationTimeAxisView& atv, double initial_pos)
+ : trackview (atv)
+{
+ group = gtk_canvas_item_new (GTK_CANVAS_GROUP(trackview.canvas_display),
+ gtk_canvas_group_get_type(),
+ "x", initial_pos,
+ "y", 0.0,
+ NULL);
+
+ base_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", (double) 0.0,
+ "y1", (double) 0.0,
+ "y2", (double) trackview.height,
+ "outline_what", (guint32) 0,
+ "outline_color_rgba", color_map[cGhostTrackBaseOutline],
+ "fill_color_rgba", color_map[cGhostTrackBaseFill],
+ NULL);
+
+ gtk_canvas_item_lower_to_bottom (group);
+
+ atv.add_ghost (this);
+}
+
+GhostRegion::~GhostRegion ()
+{
+ GoingAway (this);
+ gtk_object_destroy (GTK_OBJECT(group));
+}
+
+void
+GhostRegion::set_samples_per_unit (double spu)
+{
+ for (vector<GtkCanvasItem*>::iterator i = waves.begin(); i != waves.end(); ++i) {
+ gtk_canvas_item_set ((*i), "samples_per_unit", spu, NULL);
+ }
+}
+
+void
+GhostRegion::set_duration (double units)
+{
+ gtk_canvas_item_set (base_rect, "x2", units, NULL);
+}
+
+void
+GhostRegion::set_height ()
+{
+ gdouble ht;
+ vector<GtkCanvasItem*>::iterator i;
+ uint32_t n;
+
+ gtk_canvas_item_set (base_rect, "y2", (double) trackview.height, NULL);
+
+ ht = ((trackview.height) / (double) waves.size());
+
+ for (n = 0, i = waves.begin(); i != waves.end(); ++i, ++n) {
+ gdouble yoff = n * ht;
+ gtk_canvas_item_set ((*i), "height", ht, "y", yoff, NULL);
+ }
+}
+
diff --git a/gtk2_ardour/ghostregion.h b/gtk2_ardour/ghostregion.h
new file mode 100644
index 0000000000..0abb1b9b91
--- /dev/null
+++ b/gtk2_ardour/ghostregion.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_ghost_region_h__
+#define __ardour_gtk_ghost_region_h__
+
+#include <vector>
+#include <sigc++/signal_system.h>
+#include <gtk-canvas.h>
+
+class AutomationTimeAxisView;
+
+struct GhostRegion : public SigC::Object
+{
+ AutomationTimeAxisView& trackview;
+ GtkCanvasItem* group;
+ GtkCanvasItem* base_rect;
+ std::vector<GtkCanvasItem*> waves;
+
+ GhostRegion (AutomationTimeAxisView& tv, double initial_unit_pos);
+ ~GhostRegion ();
+
+ void set_samples_per_unit (double spu);
+ void set_duration (double units);
+ void set_height ();
+
+ SigC::Signal1<void,GhostRegion*> GoingAway;
+};
+
+#endif /* __ardour_gtk_ghost_region_h__ */
diff --git a/gtk2_ardour/gprofhelper.c b/gtk2_ardour/gprofhelper.c
new file mode 100644
index 0000000000..b806a073c6
--- /dev/null
+++ b/gtk2_ardour/gprofhelper.c
@@ -0,0 +1,117 @@
+/* gprof-helper.c -- preload library to profile pthread-enabled programs
+ *
+ * Authors: Sam Hocevar <sam at zoy dot org>
+ * Daniel Jönsson <danieljo at fagotten dot org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the Do What The Fuck You Want To
+ * Public License as published by Banlu Kemiyatorn. See
+ * http://sam.zoy.org/projects/COPYING.WTFPL for more details.
+ *
+ * Compilation example:
+ * gcc -shared -nostdlib -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl
+ *
+ * Usage example:
+ * LD_PRELOAD=./gprof-helper.so your_program
+ */
+
+#define _GNU_SOURCE
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <pthread.h>
+
+static void * wrapper_routine(void *);
+
+/* Original pthread function */
+static int (*pthread_create_orig)(pthread_t *__restrict,
+ __const pthread_attr_t *__restrict,
+ void *(*)(void *),
+ void *__restrict) = NULL;
+
+/* Library initialization function */
+void _init(void)
+{
+ pthread_create_orig = dlsym(RTLD_NEXT, "pthread_create");
+ fprintf(stderr, "pthreads: using profiling hooks for gprof\n");
+ if(pthread_create_orig == NULL)
+ {
+ char *error = dlerror();
+ if(error == NULL)
+ {
+ error = "pthread_create is NULL";
+ }
+ fprintf(stderr, "%s", error);
+ exit(EXIT_FAILURE);
+ }
+}
+
+/* Our data structure passed to the wrapper */
+typedef struct wrapper_s
+{
+ void * (*start_routine)(void *);
+ void * arg;
+
+ pthread_mutex_t lock;
+ pthread_cond_t wait;
+
+ struct itimerval itimer;
+
+} wrapper_t;
+
+/* The wrapper function in charge for setting the itimer value */
+static void * wrapper_routine(void * data)
+{
+ /* Put user data in thread-local variables */
+ void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine;
+ void * arg = ((wrapper_t*)data)->arg;
+
+ /* Set the profile timer value */
+ setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL);
+
+ /* Tell the calling thread that we don't need its data anymore */
+ pthread_mutex_lock(&((wrapper_t*)data)->lock);
+ pthread_cond_signal(&((wrapper_t*)data)->wait);
+ pthread_mutex_unlock(&((wrapper_t*)data)->lock);
+
+ /* Call the real function */
+ return start_routine(arg);
+}
+
+/* Our wrapper function for the real pthread_create() */
+int pthread_create(pthread_t *__restrict thread,
+ __const pthread_attr_t *__restrict attr,
+ void * (*start_routine)(void *),
+ void *__restrict arg)
+{
+ wrapper_t wrapper_data;
+ int i_return;
+
+ /* Initialize the wrapper structure */
+ wrapper_data.start_routine = start_routine;
+ wrapper_data.arg = arg;
+ getitimer(ITIMER_PROF, &wrapper_data.itimer);
+ pthread_cond_init(&wrapper_data.wait, NULL);
+ pthread_mutex_init(&wrapper_data.lock, NULL);
+ pthread_mutex_lock(&wrapper_data.lock);
+
+ /* The real pthread_create call */
+ i_return = pthread_create_orig(thread,
+ attr,
+ &wrapper_routine,
+ &wrapper_data);
+
+ /* If the thread was successfully spawned, wait for the data
+ * to be released */
+ if(i_return == 0)
+ {
+ pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock);
+ }
+
+ pthread_mutex_unlock(&wrapper_data.lock);
+ pthread_mutex_destroy(&wrapper_data.lock);
+ pthread_cond_destroy(&wrapper_data.wait);
+
+ return i_return;
+}
diff --git a/gtk2_ardour/grouped_buttons.cc b/gtk2_ardour/grouped_buttons.cc
new file mode 100644
index 0000000000..544b3e1ed8
--- /dev/null
+++ b/gtk2_ardour/grouped_buttons.cc
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gtk--.h>
+
+#include "grouped_buttons.h"
+
+using namespace std;
+
+GroupedButtons::GroupedButtons (vector<Gtk::ToggleButton *>& buttonset)
+{
+ uint32_t n = 0;
+
+ buttons = buttonset;
+
+ for (vector<Gtk::ToggleButton *>::iterator i = buttons.begin(); i != buttons.end(); ++i, ++n) {
+ if ((*i)->get_active()) {
+ current_active = n;
+ }
+ (*i)->clicked.connect (bind (slot (*this, &GroupedButtons::one_clicked), n));
+ }
+}
+
+GroupedButtons::GroupedButtons (uint32_t nbuttons, uint32_t first_active)
+{
+ buttons.reserve (nbuttons);
+ current_active = first_active;
+
+ for (uint32_t n = 0; n < nbuttons; ++n) {
+
+ Gtk::ToggleButton *button;
+
+ button = manage (new (Gtk::ToggleButton));
+
+ if (n == current_active) {
+ button->set_active (true);
+ }
+
+ button->clicked.connect (bind (slot (*this, &GroupedButtons::one_clicked), n));
+ buttons.push_back (button);
+ }
+}
+
+static gint
+reactivate_button (void *arg)
+{
+ Gtk::ToggleButton *b = (Gtk::ToggleButton *) arg;
+ b->set_active (true);
+ return FALSE;
+}
+
+void
+GroupedButtons::one_clicked (uint32_t which)
+{
+ if (buttons[which]->get_active()) {
+
+ if (which != current_active) {
+ uint32_t old = current_active;
+ current_active = which;
+ buttons[old]->set_active (false);
+ }
+
+ } else if (which == current_active) {
+
+ /* Someobody tried to unset the current active
+ button by clicking on it. This caused
+ set_active (false) to be called. We don't
+ allow that, so just reactivate it.
+
+ Don't try this right here, because of some
+ design glitches with GTK+ toggle buttons.
+ Setting the button back to active from
+ within the signal emission that marked
+ it as inactive causes a segfault ...
+ */
+
+ gtk_idle_add (reactivate_button, buttons[which]);
+ }
+}
diff --git a/gtk2_ardour/grouped_buttons.h b/gtk2_ardour/grouped_buttons.h
new file mode 100644
index 0000000000..ff8051a120
--- /dev/null
+++ b/gtk2_ardour/grouped_buttons.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtkmmext_grouped_buttons_h__
+#define __gtkmmext_grouped_buttons_h__
+
+#include <stdint.h>
+
+#include <vector>
+#include <sigc++/signal_system.h>
+
+namespace Gtk {
+ class ToggleButton;
+};
+
+class GroupedButtons : public SigC::Object
+{
+ public:
+ GroupedButtons (uint32_t nbuttons, uint32_t first_active);
+ GroupedButtons (std::vector<Gtk::ToggleButton *>&);
+
+ Gtk::ToggleButton& button (uint32_t which) {
+ return *buttons[which];
+ }
+
+ private:
+ std::vector<Gtk::ToggleButton *> buttons;
+ uint32_t current_active;
+ void one_clicked (uint32_t which);
+};
+
+#endif /* __gtkmmext_grouped_buttons_h__ */
diff --git a/gtk2_ardour/gtk-custom-hruler.c b/gtk2_ardour/gtk-custom-hruler.c
new file mode 100644
index 0000000000..d028d6472e
--- /dev/null
+++ b/gtk2_ardour/gtk-custom-hruler.c
@@ -0,0 +1,239 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+/* modified by andreas meyer <hexx3000@gmx.de> */
+/* subsequently specialized for audio time displays by paul davis <paul@linuxaudiosystems.com> */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include "gtk-custom-hruler.h"
+
+#define RULER_HEIGHT 14
+#define MINIMUM_INCR 5
+#define MAXIMUM_SUBDIVIDE 5
+
+#define ROUND(x) ((int) ((x) + 0.5))
+
+static void gtk_custom_hruler_class_init (GtkCustomHRulerClass * klass);
+static void gtk_custom_hruler_init (GtkCustomHRuler * custom_hruler);
+static gint gtk_custom_hruler_motion_notify (GtkWidget * widget, GdkEventMotion * event);
+static void gtk_custom_hruler_draw_ticks (GtkCustomRuler * ruler);
+static void gtk_custom_hruler_draw_pos (GtkCustomRuler * ruler);
+
+guint gtk_custom_hruler_get_type (void)
+{
+ static guint custom_hruler_type = 0;
+
+ if (!custom_hruler_type) {
+ static const GtkTypeInfo custom_hruler_info = {
+ "GtkCustomHRuler",
+ sizeof (GtkCustomHRuler),
+ sizeof (GtkCustomHRulerClass),
+ (GtkClassInitFunc) gtk_custom_hruler_class_init,
+ (GtkObjectInitFunc) gtk_custom_hruler_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+ custom_hruler_type = gtk_type_unique (gtk_custom_ruler_get_type (), &custom_hruler_info);
+ }
+ return custom_hruler_type;
+}
+
+static void
+gtk_custom_hruler_class_init (GtkCustomHRulerClass * klass)
+{
+ GtkWidgetClass *widget_class;
+ GtkCustomRulerClass *ruler_class;
+
+ widget_class = (GtkWidgetClass *) klass;
+ ruler_class = (GtkCustomRulerClass *) klass;
+
+ widget_class->motion_notify_event = gtk_custom_hruler_motion_notify;
+
+ ruler_class->draw_ticks = gtk_custom_hruler_draw_ticks;
+ ruler_class->draw_pos = gtk_custom_hruler_draw_pos;
+}
+
+static void
+gtk_custom_hruler_init (GtkCustomHRuler * custom_hruler)
+{
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (custom_hruler);
+ widget->requisition.width = widget->style->klass->xthickness * 2 + 1;
+ widget->requisition.height = widget->style->klass->ythickness * 2 + RULER_HEIGHT;
+}
+
+
+GtkWidget *
+gtk_custom_hruler_new (void)
+{
+ return GTK_WIDGET (gtk_type_new (gtk_custom_hruler_get_type ()));
+}
+
+static gint
+gtk_custom_hruler_motion_notify (GtkWidget * widget, GdkEventMotion * event)
+{
+ GtkCustomRuler *ruler;
+ gint x;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CUSTOM_HRULER (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ ruler = GTK_CUSTOM_RULER (widget);
+
+ if (event->is_hint)
+ gdk_window_get_pointer (widget->window, &x, NULL, NULL);
+ else
+ x = event->x;
+
+ ruler->position = ruler->lower + ((ruler->upper - ruler->lower) * x) / widget->allocation.width;
+
+ /* Make sure the ruler has been allocated already */
+ if (ruler->backing_store != NULL)
+ gtk_custom_ruler_draw_pos (ruler);
+
+ return FALSE;
+}
+
+static void
+gtk_custom_hruler_draw_ticks (GtkCustomRuler * ruler)
+{
+ GtkWidget *widget;
+ GdkGC *gc, *bg_gc;
+ GdkFont *font;
+ gint i;
+ GtkCustomRulerMark *marks;
+ gint nmarks;
+ gint max_chars;
+
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_HRULER (ruler));
+
+ if (!GTK_WIDGET_DRAWABLE (ruler))
+ return;
+
+ widget = GTK_WIDGET (ruler);
+
+ gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+ bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
+ font = widget->style->font;
+
+ gtk_paint_box (widget->style, ruler->backing_store,
+ GTK_STATE_NORMAL, GTK_SHADOW_NONE,
+ NULL, widget, "custom_hruler", 0, 0, widget->allocation.width, widget->allocation.height);
+
+ gdk_draw_line (ruler->backing_store, gc, 0, widget->allocation.height - 1,
+ widget->allocation.width, widget->allocation.height - 1);
+
+ if ((ruler->upper - ruler->lower) == 0) {
+ return;
+ }
+
+ /* we have to assume a fixed width font here */
+
+ max_chars = widget->allocation.width / gdk_string_width (font, "8");
+
+ nmarks = ruler->metric->get_marks (&marks, ruler->lower, ruler->upper, max_chars);
+
+ for (i = 0; i < nmarks; i++) {
+ gint pos;
+ gint height;
+
+ pos = ROUND ((marks[i].position - ruler->lower) / ruler->metric->units_per_pixel);
+ height = widget->allocation.height;
+
+ switch (marks[i].style) {
+ case GtkCustomRulerMarkMajor:
+ gdk_draw_line (ruler->backing_store, gc, pos, height, pos, 0);
+ break;
+ case GtkCustomRulerMarkMinor:
+ gdk_draw_line (ruler->backing_store, gc, pos, height, pos, height - (height/2));
+ break;
+ case GtkCustomRulerMarkMicro:
+ gdk_draw_line (ruler->backing_store, gc, pos, height, pos, height - 3);
+ break;
+ }
+
+ gdk_draw_string (ruler->backing_store, font, gc, pos + 2, font->ascent - 1, marks[i].label);
+ g_free (marks[i].label);
+ }
+
+ if (nmarks) {
+ g_free (marks);
+ }
+}
+
+static void
+gtk_custom_hruler_draw_pos (GtkCustomRuler * ruler)
+{
+ GtkWidget *widget;
+ GdkGC *gc;
+ int i;
+ gint x, y;
+ gint width, height;
+ gint bs_width, bs_height;
+ gint xthickness;
+ gint ythickness;
+ gfloat increment;
+
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_HRULER (ruler));
+ if (GTK_WIDGET_DRAWABLE (ruler) && (ruler->upper - ruler->lower) > 0) {
+ widget = GTK_WIDGET (ruler);
+ gc = widget->style->fg_gc[GTK_STATE_NORMAL];
+ xthickness = widget->style->klass->xthickness;
+ ythickness = widget->style->klass->ythickness;
+ width = widget->allocation.width;
+ height = widget->allocation.height - ythickness * 2;
+
+ bs_width = height / 2;
+ bs_width |= 1; /* make sure it's odd */
+ bs_height = bs_width / 2 + 1;
+
+ if ((bs_width > 0) && (bs_height > 0)) {
+ /* If a backing store exists, restore the ruler */
+ if (ruler->backing_store && ruler->non_gr_exp_gc)
+ gdk_draw_pixmap (ruler->widget.window,
+ ruler->non_gr_exp_gc,
+ ruler->backing_store, ruler->xsrc, ruler->ysrc, ruler->xsrc, ruler->ysrc, bs_width, bs_height);
+
+ increment = (gfloat) width / (ruler->upper - ruler->lower);
+ x = ROUND ((ruler->position - ruler->lower) * increment) + (xthickness - bs_width) / 2 - 1;
+ y = (height + bs_height) / 2 + ythickness;
+
+ for (i = 0; i < bs_height; i++)
+ gdk_draw_line (widget->window, gc, x + i, y + i, x + bs_width - 1 - i, y + i);
+
+
+ ruler->xsrc = x;
+ ruler->ysrc = y;
+ }
+ }
+}
diff --git a/gtk2_ardour/gtk-custom-hruler.h b/gtk2_ardour/gtk-custom-hruler.h
new file mode 100644
index 0000000000..a8c3affeb1
--- /dev/null
+++ b/gtk2_ardour/gtk-custom-hruler.h
@@ -0,0 +1,70 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+/* modified by andreas meyer <hexx3000@gmx.de> */
+
+#ifndef __GTK_CUSTOM_HRULER_H__
+#define __GTK_CUSTOM_HRULER_H__
+
+
+#include <gdk/gdk.h>
+#include "gtk-custom-ruler.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_CUSTOM_HRULER(obj) GTK_CHECK_CAST (obj, gtk_custom_hruler_get_type (), GtkCustomHRuler)
+#define GTK_CUSTOM_HRULER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_custom_hruler_get_type (), GtkCustomHRulerClass)
+#define GTK_IS_CUSTOM_HRULER(obj) GTK_CHECK_TYPE (obj, gtk_custom_hruler_get_type ())
+
+
+typedef struct _GtkCustomHRuler GtkCustomHRuler;
+typedef struct _GtkCustomHRulerClass GtkCustomHRulerClass;
+
+struct _GtkCustomHRuler
+{
+ GtkCustomRuler ruler;
+};
+
+struct _GtkCustomHRulerClass
+{
+ GtkCustomRulerClass parent_class;
+};
+
+
+guint gtk_custom_hruler_get_type (void);
+GtkWidget* gtk_custom_hruler_new (void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_CUSTOM_HRULER_H__ */
diff --git a/gtk2_ardour/gtk-custom-ruler.c b/gtk2_ardour/gtk-custom-ruler.c
new file mode 100644
index 0000000000..8f63f82f01
--- /dev/null
+++ b/gtk2_ardour/gtk-custom-ruler.c
@@ -0,0 +1,367 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+/* modified by andreas meyer <hexx3000@gmx.de> */
+
+#include <stdio.h>
+#include "gtk-custom-ruler.h"
+
+enum
+{
+ ARG_0,
+ ARG_LOWER,
+ ARG_UPPER,
+ ARG_POSITION,
+ ARG_MAX_SIZE,
+ ARG_SHOW_POSITION
+};
+
+static void gtk_custom_ruler_class_init (GtkCustomRulerClass * klass);
+static void gtk_custom_ruler_init (GtkCustomRuler * ruler);
+static void gtk_custom_ruler_realize (GtkWidget * widget);
+static void gtk_custom_ruler_unrealize (GtkWidget * widget);
+static void gtk_custom_ruler_size_allocate (GtkWidget * widget, GtkAllocation * allocation);
+static gint gtk_custom_ruler_expose (GtkWidget * widget, GdkEventExpose * event);
+static void gtk_custom_ruler_make_pixmap (GtkCustomRuler * ruler);
+static void gtk_custom_ruler_set_arg (GtkObject * object, GtkArg * arg, guint arg_id);
+static void gtk_custom_ruler_get_arg (GtkObject * object, GtkArg * arg, guint arg_id);
+
+static gint
+default_metric_get_marks (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars)
+{
+ return 0;
+}
+
+static const GtkCustomMetric default_metric = {
+ 1.0,
+ default_metric_get_marks
+};
+
+static GtkWidgetClass *parent_class;
+
+GtkType gtk_custom_ruler_get_type (void)
+{
+ static GtkType ruler_type = 0;
+
+ if (!ruler_type) {
+ static const GtkTypeInfo ruler_info = {
+ "GtkCustomRuler",
+ sizeof (GtkCustomRuler),
+ sizeof (GtkCustomRulerClass),
+ (GtkClassInitFunc) gtk_custom_ruler_class_init,
+ (GtkObjectInitFunc) gtk_custom_ruler_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+ ruler_type = gtk_type_unique (GTK_TYPE_WIDGET, &ruler_info);
+ }
+ return ruler_type;
+}
+
+static void
+gtk_custom_ruler_class_init (GtkCustomRulerClass * class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+
+ parent_class = gtk_type_class (GTK_TYPE_WIDGET);
+
+ object_class->set_arg = gtk_custom_ruler_set_arg;
+ object_class->get_arg = gtk_custom_ruler_get_arg;
+
+ widget_class->realize = gtk_custom_ruler_realize;
+ widget_class->unrealize = gtk_custom_ruler_unrealize;
+ widget_class->size_allocate = gtk_custom_ruler_size_allocate;
+ widget_class->expose_event = gtk_custom_ruler_expose;
+
+ class->draw_ticks = NULL;
+ class->draw_pos = NULL;
+
+ gtk_object_add_arg_type ("GtkCustomRuler::lower", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_LOWER);
+ gtk_object_add_arg_type ("GtkCustomRuler::upper", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_UPPER);
+ gtk_object_add_arg_type ("GtkCustomRuler::position", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_POSITION);
+ gtk_object_add_arg_type ("GtkCustomRuler::max_size", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_MAX_SIZE);
+ gtk_object_add_arg_type ("GtkCustomRuler::show_position", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_POSITION);
+}
+
+static void
+gtk_custom_ruler_init (GtkCustomRuler * ruler)
+{
+ ruler->backing_store = NULL;
+ ruler->non_gr_exp_gc = NULL;
+ ruler->xsrc = 0;
+ ruler->ysrc = 0;
+ ruler->slider_size = 0;
+ ruler->lower = 0;
+ ruler->upper = 0;
+ ruler->position = 0;
+ ruler->max_size = 0;
+ ruler->show_position = FALSE;
+
+ gtk_custom_ruler_set_metric (ruler, NULL);
+}
+
+static void
+gtk_custom_ruler_set_arg (GtkObject * object, GtkArg * arg, guint arg_id)
+{
+ GtkCustomRuler *ruler = GTK_CUSTOM_RULER (object);
+
+ switch (arg_id) {
+ case ARG_LOWER:
+ gtk_custom_ruler_set_range (ruler, GTK_VALUE_ULONG (*arg), ruler->upper, ruler->position, ruler->max_size);
+ break;
+ case ARG_UPPER:
+ gtk_custom_ruler_set_range (ruler, ruler->lower, GTK_VALUE_ULONG (*arg), ruler->position, ruler->max_size);
+ break;
+ case ARG_POSITION:
+ gtk_custom_ruler_set_range (ruler, ruler->lower, ruler->upper, GTK_VALUE_ULONG (*arg), ruler->max_size);
+ break;
+ case ARG_MAX_SIZE:
+ gtk_custom_ruler_set_range (ruler, ruler->lower, ruler->upper, ruler->position, GTK_VALUE_ULONG (*arg));
+ break;
+ case ARG_SHOW_POSITION:
+ // gtk_customer_ruler_set_show_position (ruler, GTK_VALUE_BOOL (*arg));
+ break;
+ }
+}
+
+static void
+gtk_custom_ruler_get_arg (GtkObject * object, GtkArg * arg, guint arg_id)
+{
+ GtkCustomRuler *ruler = GTK_CUSTOM_RULER (object);
+
+ switch (arg_id) {
+ case ARG_LOWER:
+ GTK_VALUE_ULONG (*arg) = ruler->lower;
+ break;
+ case ARG_UPPER:
+ GTK_VALUE_ULONG (*arg) = ruler->upper;
+ break;
+ case ARG_POSITION:
+ GTK_VALUE_ULONG (*arg) = ruler->position;
+ break;
+ case ARG_MAX_SIZE:
+ GTK_VALUE_ULONG (*arg) = ruler->max_size;
+ break;
+ case ARG_SHOW_POSITION:
+ GTK_VALUE_BOOL (*arg) = ruler->show_position;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+void
+gtk_custom_ruler_set_metric (GtkCustomRuler * ruler, GtkCustomMetric * metric)
+{
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_RULER (ruler));
+
+ if (metric == NULL)
+ ruler->metric = (GtkCustomMetric *) & default_metric;
+ else
+ ruler->metric = metric;
+
+ if (GTK_WIDGET_DRAWABLE (ruler))
+ gtk_widget_queue_draw (GTK_WIDGET (ruler));
+}
+
+void
+gtk_custom_ruler_set_range (GtkCustomRuler * ruler, gulong lower, gulong upper, gulong position, gulong max_size)
+{
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_RULER (ruler));
+
+ ruler->lower = lower;
+ ruler->upper = upper;
+ ruler->position = position;
+ ruler->max_size = max_size;
+
+ if (GTK_WIDGET_DRAWABLE (ruler))
+ gtk_widget_queue_draw (GTK_WIDGET (ruler));
+}
+
+void
+gtk_custom_ruler_draw_ticks (GtkCustomRuler * ruler)
+{
+ GtkCustomRulerClass *klass;
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_RULER (ruler));
+
+ klass = GTK_CUSTOM_RULER_CLASS (GTK_OBJECT (ruler)->klass);
+ if (klass->draw_ticks)
+ klass->draw_ticks (ruler);
+}
+
+void
+gtk_custom_ruler_draw_pos (GtkCustomRuler * ruler)
+{
+ GtkCustomRulerClass *klass;
+ g_return_if_fail (ruler != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_RULER (ruler));
+
+ klass = GTK_CUSTOM_RULER_CLASS (GTK_OBJECT (ruler)->klass);
+ if (klass->draw_pos && ruler->show_position)
+ klass->draw_pos (ruler);
+}
+
+static void
+gtk_custom_ruler_realize (GtkWidget * widget)
+{
+ GtkCustomRuler *ruler;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_RULER (widget));
+
+ ruler = GTK_CUSTOM_RULER (widget);
+ GTK_WIDGET_SET_FLAGS (ruler, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, ruler);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
+
+ gtk_custom_ruler_make_pixmap (ruler);
+}
+
+static void
+gtk_custom_ruler_unrealize (GtkWidget * widget)
+{
+ GtkCustomRuler *ruler;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_RULER (widget));
+
+ ruler = GTK_CUSTOM_RULER (widget);
+
+ if (ruler->backing_store)
+ gdk_pixmap_unref (ruler->backing_store);
+ if (ruler->non_gr_exp_gc)
+ gdk_gc_destroy (ruler->non_gr_exp_gc);
+
+ ruler->backing_store = NULL;
+ ruler->non_gr_exp_gc = NULL;
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (*GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+gtk_custom_ruler_size_allocate (GtkWidget * widget, GtkAllocation * allocation)
+{
+ GtkCustomRuler *ruler;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_CUSTOM_RULER (widget));
+
+ ruler = GTK_CUSTOM_RULER (widget);
+ widget->allocation = *allocation;
+
+ if (GTK_WIDGET_REALIZED (widget)) {
+ gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height);
+
+ gtk_custom_ruler_make_pixmap (ruler);
+ }
+}
+
+static gint
+gtk_custom_ruler_expose (GtkWidget * widget, GdkEventExpose * event)
+{
+ GtkCustomRuler *ruler;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_CUSTOM_RULER (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_WIDGET_DRAWABLE (widget)) {
+ ruler = GTK_CUSTOM_RULER (widget);
+
+ gtk_custom_ruler_draw_ticks (ruler);
+
+ gdk_draw_pixmap (widget->window,
+ ruler->non_gr_exp_gc,
+ ruler->backing_store, 0, 0, 0, 0, widget->allocation.width, widget->allocation.height);
+
+ gtk_custom_ruler_draw_pos (ruler);
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_custom_ruler_make_pixmap (GtkCustomRuler * ruler)
+{
+ GtkWidget *widget;
+ gint width;
+ gint height;
+
+ widget = GTK_WIDGET (ruler);
+
+ if (ruler->backing_store) {
+ gdk_window_get_size (ruler->backing_store, &width, &height);
+ if ((width == widget->allocation.width) && (height == widget->allocation.height))
+ return;
+
+ gdk_pixmap_unref (ruler->backing_store);
+ }
+
+ ruler->backing_store = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, -1);
+
+ ruler->xsrc = 0;
+ ruler->ysrc = 0;
+
+ if (!ruler->non_gr_exp_gc) {
+ ruler->non_gr_exp_gc = gdk_gc_new (widget->window);
+ gdk_gc_set_exposures (ruler->non_gr_exp_gc, FALSE);
+ }
+}
+
+void
+gtk_custom_ruler_set_show_position (GtkCustomRuler * ruler, gboolean yn)
+{
+ ruler->show_position = yn;
+}
diff --git a/gtk2_ardour/gtk-custom-ruler.h b/gtk2_ardour/gtk-custom-ruler.h
new file mode 100644
index 0000000000..da280abed5
--- /dev/null
+++ b/gtk2_ardour/gtk-custom-ruler.h
@@ -0,0 +1,111 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+/* modified by andreas meyer <hexx3000@gmx.de> */
+
+#ifndef __GTK_CUSTOM_RULER_H__
+#define __GTK_CUSTOM_RULER_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GTK_TYPE_CUSTOM_RULER (gtk_custom_ruler_get_type ())
+#define GTK_CUSTOM_RULER(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CUSTOM_RULER, GtkCustomRuler))
+#define GTK_CUSTOM_RULER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CUSTOM_RULER, GtkCustomRulerClass))
+#define GTK_IS_CUSTOM_RULER(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CUSTOM_RULER))
+#define GTK_IS_CUSTOM_RULER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CUSTOM_RULER))
+
+typedef struct _GtkCustomRuler GtkCustomRuler;
+typedef struct _GtkCustomRulerClass GtkCustomRulerClass;
+typedef struct _GtkCustomMetric GtkCustomMetric;
+typedef struct _GtkCustomRulerMark GtkCustomRulerMark;
+
+struct _GtkCustomRuler {
+ GtkWidget widget;
+
+ GdkPixmap *backing_store;
+ GdkGC *non_gr_exp_gc;
+ GtkCustomMetric *metric;
+ gint xsrc, ysrc;
+ gint slider_size;
+ gboolean show_position;
+
+ /* The upper limit of the ruler (in points) */
+ gulong lower;
+ /* The lower limit of the ruler */
+ gulong upper;
+ /* The position of the mark on the ruler */
+ gulong position;
+ /* The maximum size of the ruler */
+ gulong max_size;
+};
+
+struct _GtkCustomRulerClass {
+ GtkWidgetClass parent_class;
+
+ void (* draw_ticks) (GtkCustomRuler *ruler);
+ void (* draw_pos) (GtkCustomRuler *ruler);
+};
+
+typedef enum {
+ GtkCustomRulerMarkMajor,
+ GtkCustomRulerMarkMinor,
+ GtkCustomRulerMarkMicro
+} GtkCustomRulerMarkStyle;
+
+struct _GtkCustomRulerMark {
+ gchar *label;
+ gulong position;
+ GtkCustomRulerMarkStyle style;
+};
+
+struct _GtkCustomMetric {
+ gfloat units_per_pixel;
+ gint (* get_marks) (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars);
+};
+
+GtkType gtk_custom_ruler_get_type (void);
+void gtk_custom_ruler_set_metric (GtkCustomRuler *ruler, GtkCustomMetric *metric);
+void gtk_custom_ruler_set_range (GtkCustomRuler *ruler,
+ gulong lower,
+ gulong upper,
+ gulong position,
+ gulong max_size);
+void gtk_custom_ruler_draw_ticks (GtkCustomRuler *ruler);
+void gtk_custom_ruler_draw_pos (GtkCustomRuler *ruler);
+void gtk_custom_ruler_set_show_position (GtkCustomRuler *rule, gboolean yn);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_CUSTOM_RULER_H__ */
diff --git a/gtk2_ardour/gtkscrolledwindow.c b/gtk2_ardour/gtkscrolledwindow.c
new file mode 100644
index 0000000000..329660c06e
--- /dev/null
+++ b/gtk2_ardour/gtkscrolledwindow.c
@@ -0,0 +1,972 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtksignal.h>
+
+
+/* scrolled window policy and size requisition handling:
+ *
+ * gtk size requisition works as follows:
+ * a widget upon size-request reports the width and height that it finds
+ * to be best suited to display its contents, including children.
+ * the width and/or height reported from a widget upon size requisition
+ * may be overidden by the user by specifying a width and/or height
+ * other than 0 through gtk_widget_set_usize().
+ *
+ * a scrolled window needs (for imlementing all three policy types) to
+ * request its width and height based on two different rationales.
+ * 1) the user wants the scrolled window to just fit into the space
+ * that it gets allocated for a specifc dimension.
+ * 1.1) this does not apply if the user specified a concrete value
+ * value for that specific dimension by either specifying usize for the
+ * scrolled window or for its child.
+ * 2) the user wants the scrolled window to take as much space up as
+ * is desired by the child for a specifc dimension (i.e. POLICY_NEVER).
+ *
+ * also, kinda obvious:
+ * 3) a user would certainly not have choosen a scrolled window as a container
+ * for the child, if the resulting allocation takes up more space than the
+ * child would have allocated without the scrolled window.
+ *
+ * conclusions:
+ * A) from 1) follows: the scrolled window shouldn't request more space for a
+ * specifc dimension than is required at minimum.
+ * B) from 1.1) follows: the requisition may be overidden by usize of the scrolled
+ * window (done automatically) or by usize of the child (needs to be checked).
+ * C) from 2) follows: for POLICY_NEVER, the scrolled window simply reports the
+ * child's dimension.
+ * D) from 3) follows: the scrolled window child's minimum width and minimum height
+ * under A) at least correspond to the space taken up by its scrollbars.
+ */
+
+#define SCROLLBAR_SPACING(w) (GTK_SCROLLED_WINDOW_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing)
+
+#define DEFAULT_SCROLLBAR_SPACING 3
+
+enum {
+ ARG_0,
+ ARG_HADJUSTMENT,
+ ARG_VADJUSTMENT,
+ ARG_HSCROLLBAR_POLICY,
+ ARG_VSCROLLBAR_POLICY,
+ ARG_WINDOW_PLACEMENT
+};
+
+
+static void gtk_scrolled_window_class_init (GtkScrolledWindowClass *klass);
+static void gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window);
+static void gtk_scrolled_window_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_scrolled_window_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id);
+static void gtk_scrolled_window_destroy (GtkObject *object);
+static void gtk_scrolled_window_finalize (GtkObject *object);
+static void gtk_scrolled_window_map (GtkWidget *widget);
+static void gtk_scrolled_window_unmap (GtkWidget *widget);
+static void gtk_scrolled_window_draw (GtkWidget *widget,
+ GdkRectangle *area);
+static void gtk_scrolled_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_scrolled_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_scrolled_window_add (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_scrolled_window_remove (GtkContainer *container,
+ GtkWidget *widget);
+static void gtk_scrolled_window_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
+static void gtk_scrolled_window_relative_allocation(GtkWidget *widget,
+ GtkAllocation *allocation);
+static void gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+
+
+static GtkContainerClass *parent_class = NULL;
+
+
+GtkType
+gtk_scrolled_window_get_type (void)
+{
+ static GtkType scrolled_window_type = 0;
+
+ if (!scrolled_window_type)
+ {
+ static const GtkTypeInfo scrolled_window_info =
+ {
+ "GtkScrolledWindow",
+ sizeof (GtkScrolledWindow),
+ sizeof (GtkScrolledWindowClass),
+ (GtkClassInitFunc) gtk_scrolled_window_class_init,
+ (GtkObjectInitFunc) gtk_scrolled_window_init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ scrolled_window_type = gtk_type_unique (GTK_TYPE_BIN, &scrolled_window_info);
+ }
+
+ return scrolled_window_type;
+}
+
+static void
+gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+ container_class = (GtkContainerClass*) class;
+ parent_class = gtk_type_class (GTK_TYPE_BIN);
+
+ gtk_object_add_arg_type ("GtkScrolledWindow::hadjustment",
+ GTK_TYPE_ADJUSTMENT,
+ GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
+ ARG_HADJUSTMENT);
+ gtk_object_add_arg_type ("GtkScrolledWindow::vadjustment",
+ GTK_TYPE_ADJUSTMENT,
+ GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT,
+ ARG_VADJUSTMENT);
+ gtk_object_add_arg_type ("GtkScrolledWindow::hscrollbar_policy",
+ GTK_TYPE_POLICY_TYPE,
+ GTK_ARG_READWRITE,
+ ARG_HSCROLLBAR_POLICY);
+ gtk_object_add_arg_type ("GtkScrolledWindow::vscrollbar_policy",
+ GTK_TYPE_POLICY_TYPE,
+ GTK_ARG_READWRITE,
+ ARG_VSCROLLBAR_POLICY);
+ gtk_object_add_arg_type ("GtkScrolledWindow::window_placement",
+ GTK_TYPE_CORNER_TYPE,
+ GTK_ARG_READWRITE,
+ ARG_WINDOW_PLACEMENT);
+
+ object_class->set_arg = gtk_scrolled_window_set_arg;
+ object_class->get_arg = gtk_scrolled_window_get_arg;
+ object_class->destroy = gtk_scrolled_window_destroy;
+ object_class->finalize = gtk_scrolled_window_finalize;
+
+ widget_class->map = gtk_scrolled_window_map;
+ widget_class->unmap = gtk_scrolled_window_unmap;
+ widget_class->draw = gtk_scrolled_window_draw;
+ widget_class->size_request = gtk_scrolled_window_size_request;
+ widget_class->size_allocate = gtk_scrolled_window_size_allocate;
+
+ container_class->add = gtk_scrolled_window_add;
+ container_class->remove = gtk_scrolled_window_remove;
+ container_class->forall = gtk_scrolled_window_forall;
+
+ class->scrollbar_spacing = DEFAULT_SCROLLBAR_SPACING;
+}
+
+static void
+gtk_scrolled_window_set_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ scrolled_window = GTK_SCROLLED_WINDOW (object);
+
+ switch (arg_id)
+ {
+ case ARG_HADJUSTMENT:
+ gtk_scrolled_window_set_hadjustment (scrolled_window, GTK_VALUE_POINTER (*arg));
+ break;
+ case ARG_VADJUSTMENT:
+ gtk_scrolled_window_set_vadjustment (scrolled_window, GTK_VALUE_POINTER (*arg));
+ break;
+ case ARG_HSCROLLBAR_POLICY:
+ gtk_scrolled_window_set_policy (scrolled_window,
+ GTK_VALUE_ENUM (*arg),
+ scrolled_window->vscrollbar_policy);
+ break;
+ case ARG_VSCROLLBAR_POLICY:
+ gtk_scrolled_window_set_policy (scrolled_window,
+ scrolled_window->hscrollbar_policy,
+ GTK_VALUE_ENUM (*arg));
+ break;
+ case ARG_WINDOW_PLACEMENT:
+ gtk_scrolled_window_set_placement (scrolled_window,
+ GTK_VALUE_ENUM (*arg));
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+gtk_scrolled_window_get_arg (GtkObject *object,
+ GtkArg *arg,
+ guint arg_id)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ scrolled_window = GTK_SCROLLED_WINDOW (object);
+
+ switch (arg_id)
+ {
+ case ARG_HADJUSTMENT:
+ GTK_VALUE_POINTER (*arg) = gtk_scrolled_window_get_hadjustment (scrolled_window);
+ break;
+ case ARG_VADJUSTMENT:
+ GTK_VALUE_POINTER (*arg) = gtk_scrolled_window_get_vadjustment (scrolled_window);
+ break;
+ case ARG_HSCROLLBAR_POLICY:
+ GTK_VALUE_ENUM (*arg) = scrolled_window->hscrollbar_policy;
+ break;
+ case ARG_VSCROLLBAR_POLICY:
+ GTK_VALUE_ENUM (*arg) = scrolled_window->vscrollbar_policy;
+ break;
+ case ARG_WINDOW_PLACEMENT:
+ GTK_VALUE_ENUM (*arg) = scrolled_window->window_placement;
+ break;
+ default:
+ arg->type = GTK_TYPE_INVALID;
+ break;
+ }
+}
+
+static void
+gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window)
+{
+ GTK_WIDGET_SET_FLAGS (scrolled_window, GTK_NO_WINDOW);
+
+ gtk_container_set_resize_mode (GTK_CONTAINER (scrolled_window), GTK_RESIZE_QUEUE);
+
+ scrolled_window->hscrollbar = NULL;
+ scrolled_window->vscrollbar = NULL;
+ scrolled_window->hscrollbar_policy = GTK_POLICY_ALWAYS;
+ scrolled_window->vscrollbar_policy = GTK_POLICY_ALWAYS;
+ scrolled_window->hscrollbar_visible = FALSE;
+ scrolled_window->vscrollbar_visible = FALSE;
+ scrolled_window->window_placement = GTK_CORNER_TOP_LEFT;
+}
+
+GtkWidget*
+gtk_scrolled_window_new (GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment)
+{
+ GtkWidget *scrolled_window;
+
+ if (hadjustment)
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadjustment), NULL);
+
+ if (vadjustment)
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadjustment), NULL);
+
+ scrolled_window = gtk_widget_new (GTK_TYPE_SCROLLED_WINDOW,
+ "hadjustment", hadjustment,
+ "vadjustment", vadjustment,
+ NULL);
+
+ return scrolled_window;
+}
+
+void
+gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window,
+ GtkAdjustment *hadjustment)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (scrolled_window != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
+ if (hadjustment)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (hadjustment));
+ else
+ hadjustment = (GtkAdjustment*) gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL);
+
+ bin = GTK_BIN (scrolled_window);
+
+ if (!scrolled_window->hscrollbar)
+ {
+ gtk_widget_push_composite_child ();
+ scrolled_window->hscrollbar = gtk_hscrollbar_new (hadjustment);
+ gtk_widget_set_composite_name (scrolled_window->hscrollbar, "hscrollbar");
+ gtk_widget_pop_composite_child ();
+
+ gtk_widget_set_parent (scrolled_window->hscrollbar, GTK_WIDGET (scrolled_window));
+ gtk_widget_ref (scrolled_window->hscrollbar);
+ gtk_widget_show (scrolled_window->hscrollbar);
+ }
+ else
+ {
+ GtkAdjustment *old_adjustment;
+
+ old_adjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
+ if (old_adjustment == hadjustment)
+ return;
+
+ gtk_signal_disconnect_by_func (GTK_OBJECT (old_adjustment),
+ GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed),
+ scrolled_window);
+ gtk_range_set_adjustment (GTK_RANGE (scrolled_window->hscrollbar),
+ hadjustment);
+ }
+ hadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar));
+ gtk_signal_connect (GTK_OBJECT (hadjustment),
+ "changed",
+ GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed),
+ scrolled_window);
+ gtk_scrolled_window_adjustment_changed (hadjustment, scrolled_window);
+
+ if (bin->child)
+ gtk_widget_set_scroll_adjustments (bin->child,
+ gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
+ gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)));
+}
+
+void
+gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window,
+ GtkAdjustment *vadjustment)
+{
+ GtkBin *bin;
+
+ g_return_if_fail (scrolled_window != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
+ if (vadjustment)
+ g_return_if_fail (GTK_IS_ADJUSTMENT (vadjustment));
+ else
+ vadjustment = (GtkAdjustment*) gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL);
+
+ bin = GTK_BIN (scrolled_window);
+
+ if (!scrolled_window->vscrollbar)
+ {
+ gtk_widget_push_composite_child ();
+ scrolled_window->vscrollbar = gtk_vscrollbar_new (vadjustment);
+ gtk_widget_set_composite_name (scrolled_window->vscrollbar, "vscrollbar");
+ gtk_widget_pop_composite_child ();
+
+ gtk_widget_set_parent (scrolled_window->vscrollbar, GTK_WIDGET (scrolled_window));
+ gtk_widget_ref (scrolled_window->vscrollbar);
+ gtk_widget_show (scrolled_window->vscrollbar);
+ }
+ else
+ {
+ GtkAdjustment *old_adjustment;
+
+ old_adjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
+ if (old_adjustment == vadjustment)
+ return;
+
+ gtk_signal_disconnect_by_func (GTK_OBJECT (old_adjustment),
+ GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed),
+ scrolled_window);
+ gtk_range_set_adjustment (GTK_RANGE (scrolled_window->vscrollbar),
+ vadjustment);
+ }
+ vadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar));
+ gtk_signal_connect (GTK_OBJECT (vadjustment),
+ "changed",
+ GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed),
+ scrolled_window);
+ gtk_scrolled_window_adjustment_changed (vadjustment, scrolled_window);
+
+ if (bin->child)
+ gtk_widget_set_scroll_adjustments (bin->child,
+ gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
+ gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)));
+}
+
+GtkAdjustment*
+gtk_scrolled_window_get_hadjustment (GtkScrolledWindow *scrolled_window)
+{
+ g_return_val_if_fail (scrolled_window != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL);
+
+ return (scrolled_window->hscrollbar ?
+ gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)) :
+ NULL);
+}
+
+GtkAdjustment*
+gtk_scrolled_window_get_vadjustment (GtkScrolledWindow *scrolled_window)
+{
+ g_return_val_if_fail (scrolled_window != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL);
+
+ return (scrolled_window->vscrollbar ?
+ gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)) :
+ NULL);
+}
+
+void
+gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window,
+ GtkPolicyType hscrollbar_policy,
+ GtkPolicyType vscrollbar_policy)
+{
+ g_return_if_fail (scrolled_window != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
+
+ if ((scrolled_window->hscrollbar_policy != hscrollbar_policy) ||
+ (scrolled_window->vscrollbar_policy != vscrollbar_policy))
+ {
+ scrolled_window->hscrollbar_policy = hscrollbar_policy;
+ scrolled_window->vscrollbar_policy = vscrollbar_policy;
+
+ gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
+ }
+}
+
+void
+gtk_scrolled_window_set_placement (GtkScrolledWindow *scrolled_window,
+ GtkCornerType window_placement)
+{
+ g_return_if_fail (scrolled_window != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
+
+ if (scrolled_window->window_placement != window_placement)
+ {
+ scrolled_window->window_placement = window_placement;
+
+ gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
+ }
+}
+
+static void
+gtk_scrolled_window_destroy (GtkObject *object)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (object));
+
+ scrolled_window = GTK_SCROLLED_WINDOW (object);
+
+ gtk_widget_unparent (scrolled_window->hscrollbar);
+ gtk_widget_unparent (scrolled_window->vscrollbar);
+ gtk_widget_destroy (scrolled_window->hscrollbar);
+ gtk_widget_destroy (scrolled_window->vscrollbar);
+
+ GTK_OBJECT_CLASS (parent_class)->destroy (object);
+}
+
+static void
+gtk_scrolled_window_finalize (GtkObject *object)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ scrolled_window = GTK_SCROLLED_WINDOW (object);
+
+ gtk_widget_unref (scrolled_window->hscrollbar);
+ gtk_widget_unref (scrolled_window->vscrollbar);
+
+ GTK_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gtk_scrolled_window_map (GtkWidget *widget)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ /* chain parent class handler to map self and child */
+ GTK_WIDGET_CLASS (parent_class)->map (widget);
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) &&
+ !GTK_WIDGET_MAPPED (scrolled_window->hscrollbar))
+ gtk_widget_map (scrolled_window->hscrollbar);
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) &&
+ !GTK_WIDGET_MAPPED (scrolled_window->vscrollbar))
+ gtk_widget_map (scrolled_window->vscrollbar);
+}
+
+static void
+gtk_scrolled_window_unmap (GtkWidget *widget)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ /* chain parent class handler to unmap self and child */
+ GTK_WIDGET_CLASS (parent_class)->unmap (widget);
+
+ if (GTK_WIDGET_MAPPED (scrolled_window->hscrollbar))
+ gtk_widget_unmap (scrolled_window->hscrollbar);
+
+ if (GTK_WIDGET_MAPPED (scrolled_window->vscrollbar))
+ gtk_widget_unmap (scrolled_window->vscrollbar);
+}
+
+static void
+gtk_scrolled_window_draw (GtkWidget *widget,
+ GdkRectangle *area)
+{
+ GtkScrolledWindow *scrolled_window;
+ GtkBin *bin;
+ GdkRectangle child_area;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+ g_return_if_fail (area != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+ bin = GTK_BIN (widget);
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child) &&
+ gtk_widget_intersect (bin->child, area, &child_area))
+ gtk_widget_draw (bin->child, &child_area);
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) &&
+ gtk_widget_intersect (scrolled_window->hscrollbar, area, &child_area))
+ gtk_widget_draw (scrolled_window->hscrollbar, &child_area);
+
+ if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) &&
+ gtk_widget_intersect (scrolled_window->vscrollbar, area, &child_area))
+ gtk_widget_draw (scrolled_window->vscrollbar, &child_area);
+}
+
+static void
+gtk_scrolled_window_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container));
+ g_return_if_fail (callback != NULL);
+
+ GTK_CONTAINER_CLASS (parent_class)->forall (container,
+ include_internals,
+ callback,
+ callback_data);
+ if (include_internals)
+ {
+ GtkScrolledWindow *scrolled_window;
+
+ scrolled_window = GTK_SCROLLED_WINDOW (container);
+
+ if (scrolled_window->vscrollbar)
+ callback (scrolled_window->vscrollbar, callback_data);
+ if (scrolled_window->hscrollbar)
+ callback (scrolled_window->hscrollbar, callback_data);
+ }
+}
+
+static void
+gtk_scrolled_window_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkScrolledWindow *scrolled_window;
+ GtkBin *bin;
+ gint extra_width;
+ gint extra_height;
+ GtkRequisition hscrollbar_requisition;
+ GtkRequisition vscrollbar_requisition;
+ GtkRequisition child_requisition;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+ g_return_if_fail (requisition != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+ bin = GTK_BIN (scrolled_window);
+
+ extra_width = 0;
+ extra_height = 0;
+ requisition->width = 0;
+ requisition->height = 0;
+
+ gtk_widget_size_request (scrolled_window->hscrollbar,
+ &hscrollbar_requisition);
+ gtk_widget_size_request (scrolled_window->vscrollbar,
+ &vscrollbar_requisition);
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ static guint quark_aux_info = 0;
+
+ if (!quark_aux_info)
+ quark_aux_info = g_quark_from_static_string ("gtk-aux-info");
+
+ gtk_widget_size_request (bin->child, &child_requisition);
+
+ if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER)
+ requisition->width += child_requisition.width;
+ else
+ {
+ GtkWidgetAuxInfo *aux_info;
+
+ aux_info = gtk_object_get_data_by_id (GTK_OBJECT (bin->child), quark_aux_info);
+ if (aux_info && aux_info->width > 0)
+ {
+ requisition->width += aux_info->width;
+ extra_width = -1;
+ }
+ else
+ requisition->width += vscrollbar_requisition.width;
+ }
+
+// if (scrolled_window->vscrollbar_policy == GTK_POLICY_NEVER)
+// requisition->height += child_requisition.height;
+// else
+ {
+ GtkWidgetAuxInfo *aux_info;
+
+ aux_info = gtk_object_get_data_by_id (GTK_OBJECT (bin->child), quark_aux_info);
+ if (aux_info && aux_info->height > 0)
+ {
+ requisition->height += aux_info->height;
+ extra_height = -1;
+ }
+ else
+ requisition->height += hscrollbar_requisition.height;
+ }
+ }
+
+ if (scrolled_window->hscrollbar_policy == GTK_POLICY_AUTOMATIC ||
+ scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
+ {
+ requisition->width = MAX (requisition->width, hscrollbar_requisition.width);
+ if (!extra_height || scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
+ extra_height = SCROLLBAR_SPACING (scrolled_window) + hscrollbar_requisition.height;
+ }
+
+ if (scrolled_window->vscrollbar_policy == GTK_POLICY_AUTOMATIC ||
+ scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
+ {
+ requisition->height = MAX (requisition->height, vscrollbar_requisition.height);
+ if (!extra_height || scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
+ extra_width = SCROLLBAR_SPACING (scrolled_window) + vscrollbar_requisition.width;
+ }
+
+ requisition->width += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_width);
+ requisition->height += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_height);
+}
+
+static void
+gtk_scrolled_window_relative_allocation (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkScrolledWindow *scrolled_window;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (allocation != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+
+ allocation->x = GTK_CONTAINER (widget)->border_width;
+ allocation->y = GTK_CONTAINER (widget)->border_width;
+ allocation->width = MAX (1, (gint)widget->allocation.width - allocation->x * 2);
+ allocation->height = MAX (1, (gint)widget->allocation.height - allocation->y * 2);
+
+ if (scrolled_window->vscrollbar_visible)
+ {
+ GtkRequisition vscrollbar_requisition;
+ gtk_widget_get_child_requisition (scrolled_window->vscrollbar,
+ &vscrollbar_requisition);
+
+ if (scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT ||
+ scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT)
+ allocation->x += (vscrollbar_requisition.width +
+ SCROLLBAR_SPACING (scrolled_window));
+
+ allocation->width = MAX (1, (gint)allocation->width -
+ ((gint)vscrollbar_requisition.width +
+ (gint)SCROLLBAR_SPACING (scrolled_window)));
+ }
+ if (scrolled_window->hscrollbar_visible)
+ {
+ GtkRequisition hscrollbar_requisition;
+ gtk_widget_get_child_requisition (scrolled_window->hscrollbar,
+ &hscrollbar_requisition);
+
+ if (scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT ||
+ scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT)
+ allocation->y += (hscrollbar_requisition.height +
+ SCROLLBAR_SPACING (scrolled_window));
+
+ allocation->height = MAX (1, (gint)allocation->height -
+ ((gint)hscrollbar_requisition.height +
+ (gint)SCROLLBAR_SPACING (scrolled_window)));
+ }
+}
+
+static void
+gtk_scrolled_window_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkScrolledWindow *scrolled_window;
+ GtkBin *bin;
+ GtkAllocation relative_allocation;
+ GtkAllocation child_allocation;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget));
+ g_return_if_fail (allocation != NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (widget);
+ bin = GTK_BIN (scrolled_window);
+
+ widget->allocation = *allocation;
+
+ if (scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS)
+ scrolled_window->hscrollbar_visible = TRUE;
+ else if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER)
+ scrolled_window->hscrollbar_visible = FALSE;
+ if (scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS)
+ scrolled_window->vscrollbar_visible = TRUE;
+ else if (scrolled_window->vscrollbar_policy == GTK_POLICY_NEVER)
+ scrolled_window->vscrollbar_visible = FALSE;
+
+ if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
+ {
+ gboolean previous_hvis;
+ gboolean previous_vvis;
+ guint count = 0;
+
+ do
+ {
+ gtk_scrolled_window_relative_allocation (widget, &relative_allocation);
+
+ child_allocation.x = relative_allocation.x + allocation->x;
+ child_allocation.y = relative_allocation.y + allocation->y;
+ child_allocation.width = relative_allocation.width;
+ child_allocation.height = relative_allocation.height;
+
+ previous_hvis = scrolled_window->hscrollbar_visible;
+ previous_vvis = scrolled_window->vscrollbar_visible;
+
+ gtk_widget_size_allocate (bin->child, &child_allocation);
+
+ /* If, after the first iteration, the hscrollbar and the
+ * vscrollbar flip visiblity, then we need both.
+ */
+ if (count &&
+ previous_hvis != scrolled_window->hscrollbar_visible &&
+ previous_vvis != scrolled_window->vscrollbar_visible)
+ {
+ scrolled_window->hscrollbar_visible = TRUE;
+ scrolled_window->vscrollbar_visible = TRUE;
+
+ /* a new resize is already queued at this point,
+ * so we will immediatedly get reinvoked
+ */
+ return;
+ }
+
+ count++;
+ }
+ while (previous_hvis != scrolled_window->hscrollbar_visible ||
+ previous_vvis != scrolled_window->vscrollbar_visible);
+ }
+ else
+ gtk_scrolled_window_relative_allocation (widget, &relative_allocation);
+
+ if (scrolled_window->hscrollbar_visible)
+ {
+ GtkRequisition hscrollbar_requisition;
+ gtk_widget_get_child_requisition (scrolled_window->hscrollbar,
+ &hscrollbar_requisition);
+
+ if (!GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar))
+ gtk_widget_show (scrolled_window->hscrollbar);
+
+ child_allocation.x = relative_allocation.x;
+ if (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT ||
+ scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT)
+ child_allocation.y = (relative_allocation.y +
+ relative_allocation.height +
+ SCROLLBAR_SPACING (scrolled_window));
+ else
+ child_allocation.y = GTK_CONTAINER (scrolled_window)->border_width;
+
+ child_allocation.width = relative_allocation.width;
+ child_allocation.height = hscrollbar_requisition.height;
+ child_allocation.x += allocation->x;
+ child_allocation.y += allocation->y;
+
+ gtk_widget_size_allocate (scrolled_window->hscrollbar, &child_allocation);
+ }
+ else if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar))
+ gtk_widget_hide (scrolled_window->hscrollbar);
+
+ if (scrolled_window->vscrollbar_visible)
+ {
+ GtkRequisition vscrollbar_requisition;
+ if (!GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar))
+ gtk_widget_show (scrolled_window->vscrollbar);
+
+ gtk_widget_get_child_requisition (scrolled_window->vscrollbar,
+ &vscrollbar_requisition);
+
+ if (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT ||
+ scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT)
+ child_allocation.x = (relative_allocation.x +
+ relative_allocation.width +
+ SCROLLBAR_SPACING (scrolled_window));
+ else
+ child_allocation.x = GTK_CONTAINER (scrolled_window)->border_width;
+
+ child_allocation.y = relative_allocation.y;
+ child_allocation.width = vscrollbar_requisition.width;
+ child_allocation.height = relative_allocation.height;
+ child_allocation.x += allocation->x;
+ child_allocation.y += allocation->y;
+
+ gtk_widget_size_allocate (scrolled_window->vscrollbar, &child_allocation);
+ }
+ else if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar))
+ gtk_widget_hide (scrolled_window->vscrollbar);
+}
+
+
+static void
+gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
+{
+ GtkScrolledWindow *scrolled_win;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ scrolled_win = GTK_SCROLLED_WINDOW (data);
+
+ if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->hscrollbar)))
+ {
+ if (scrolled_win->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+ {
+ gboolean visible;
+
+ visible = scrolled_win->hscrollbar_visible;
+ scrolled_win->hscrollbar_visible = (adjustment->upper - adjustment->lower >
+ adjustment->page_size);
+ if (scrolled_win->hscrollbar_visible != visible)
+ gtk_widget_queue_resize (GTK_WIDGET (scrolled_win));
+ }
+ }
+ else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->vscrollbar)))
+ {
+ if (scrolled_win->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+ {
+ gboolean visible;
+
+ visible = scrolled_win->vscrollbar_visible;
+ scrolled_win->vscrollbar_visible = (adjustment->upper - adjustment->lower >
+ adjustment->page_size);
+ if (scrolled_win->vscrollbar_visible != visible)
+ gtk_widget_queue_resize (GTK_WIDGET (scrolled_win));
+ }
+ }
+}
+
+static void
+gtk_scrolled_window_add (GtkContainer *container,
+ GtkWidget *child)
+{
+ GtkScrolledWindow *scrolled_window;
+ GtkBin *bin;
+
+ bin = GTK_BIN (container);
+ g_return_if_fail (bin->child == NULL);
+
+ scrolled_window = GTK_SCROLLED_WINDOW (container);
+
+ bin->child = child;
+ gtk_widget_set_parent (child, GTK_WIDGET (bin));
+
+ /* this is a temporary message */
+ if (!gtk_widget_set_scroll_adjustments (child,
+ gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)),
+ gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar))))
+ g_warning ("gtk_scrolled_window_add(): cannot add non scrollable widget "
+ "use gtk_scrolled_window_add_with_viewport() instead");
+
+ if (GTK_WIDGET_REALIZED (child->parent))
+ gtk_widget_realize (child);
+
+ if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child))
+ {
+ if (GTK_WIDGET_MAPPED (child->parent))
+ gtk_widget_map (child);
+
+ gtk_widget_queue_resize (child);
+ }
+}
+
+static void
+gtk_scrolled_window_remove (GtkContainer *container,
+ GtkWidget *child)
+{
+ g_return_if_fail (container != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_BIN (container)->child == child);
+
+ gtk_widget_set_scroll_adjustments (child, NULL, NULL);
+
+ /* chain parent class handler to remove child */
+ GTK_CONTAINER_CLASS (parent_class)->remove (container, child);
+}
+
+void
+gtk_scrolled_window_add_with_viewport (GtkScrolledWindow *scrolled_window,
+ GtkWidget *child)
+{
+ GtkBin *bin;
+ GtkWidget *viewport;
+
+ g_return_if_fail (scrolled_window != NULL);
+ g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
+ g_return_if_fail (child != NULL);
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ g_return_if_fail (child->parent == NULL);
+
+ bin = GTK_BIN (scrolled_window);
+
+ if (bin->child != NULL)
+ {
+ g_return_if_fail (GTK_IS_VIEWPORT (bin->child));
+ g_return_if_fail (GTK_BIN (bin->child)->child == NULL);
+
+ viewport = bin->child;
+ }
+ else
+ {
+ viewport =
+ gtk_viewport_new (gtk_scrolled_window_get_hadjustment (scrolled_window),
+ gtk_scrolled_window_get_vadjustment (scrolled_window));
+ gtk_container_add (GTK_CONTAINER (scrolled_window), viewport);
+ }
+
+ gtk_widget_show (viewport);
+ gtk_container_add (GTK_CONTAINER (viewport), child);
+}
diff --git a/gtk2_ardour/gui_thread.h b/gtk2_ardour/gui_thread.h
new file mode 100644
index 0000000000..7b09007d80
--- /dev/null
+++ b/gtk2_ardour/gui_thread.h
@@ -0,0 +1,10 @@
+#ifndef __ardour_gtk_gui_thread_h__
+#define __ardour_gtk_gui_thread_h__
+
+#define ENSURE_GUI_THREAD(slot) \
+ if (!Gtkmmext::UI::instance()->caller_is_gui_thread()) {\
+ Gtkmmext::UI::instance()->call_slot ((slot));\
+ return;\
+ }
+
+#endif /* __ardour_gtk_gui_thread_h__ */
diff --git a/gtk2_ardour/i18n.h b/gtk2_ardour/i18n.h
new file mode 100644
index 0000000000..3ace250419
--- /dev/null
+++ b/gtk2_ardour/i18n.h
@@ -0,0 +1,16 @@
+#ifndef __i18n_h__
+#define __i18n_h__
+
+#include <pbd/compose.h>
+#include "gettext.h"
+
+#include <vector>
+#include <string>
+
+std::vector<std::string> internationalize (const char **);
+
+#define _(Text) dgettext (PACKAGE,Text)
+#define N_(Text) gettext_noop (Text)
+#define X_(Text) Text
+
+#endif // __i18n_h__
diff --git a/gtk2_ardour/imageframe_socket_handler.cc b/gtk2_ardour/imageframe_socket_handler.cc
new file mode 100644
index 0000000000..938984c82f
--- /dev/null
+++ b/gtk2_ardour/imageframe_socket_handler.cc
@@ -0,0 +1,2353 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <cstdio>
+
+#include <sigc++/bind.h>
+
+#include <gtkmmext/gtk_ui.h>
+
+#include "imageframe_socket_handler.h"
+#include "imageframe_time_axis.h"
+#include "imageframe_time_axis_view.h"
+#include "imageframe_time_axis_group.h"
+#include "imageframe_view.h"
+#include "marker_time_axis.h"
+#include "marker_time_axis_view.h"
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "extra_bind.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+#include <ardour/session.h>
+
+#include <gtk--.h>
+#include <unistd.h>
+
+using namespace std;
+using namespace ardourvis ;
+using namespace SigC;
+
+ImageFrameSocketHandler* ImageFrameSocketHandler::_instance = 0 ;
+
+/**
+ * Constructs a new ImageFrameSocketHandler to handle communication between Ardour and the Image Compositor
+ *
+ * @param ed the PublicEditor
+ */
+ImageFrameSocketHandler::ImageFrameSocketHandler(PublicEditor& ed) : thePublicEditor(ed), theArdourToCompositorSocket(-1)
+{
+
+}
+
+/**
+ * Descructor
+ * this will shutdown the socket if open
+ */
+ImageFrameSocketHandler::~ImageFrameSocketHandler()
+{
+ close_connection() ;
+}
+
+
+/**
+ * Returns the instance of the ImageFrameSocketHandler
+ * the instance should first be created with createInstance
+ *
+ * @return the instance of the ImageFrameSocketHandler
+ */
+ImageFrameSocketHandler*
+ImageFrameSocketHandler::get_instance()
+{
+ return(_instance) ;
+}
+
+/**
+ * Create an new instance of the ImageFrameSocketHandler, if one does not already exist
+ *
+ * @param ed the Ardour PublicEditor
+ */
+ImageFrameSocketHandler*
+ImageFrameSocketHandler::create_instance(PublicEditor& ed)
+{
+ if(_instance)
+ {
+ return(_instance) ;
+ }
+ else
+ {
+ _instance = new ImageFrameSocketHandler(ed) ;
+ return(_instance) ;
+ }
+}
+
+/**
+ * call back to handle doing the processing work
+ * This method is added to the gdk main loop and called when there is data
+ * upon the socket.
+ *
+ */
+void
+ImageFrameSocketHandler::image_socket_callback(void *arg, int32_t fd, GdkInputCondition cond)
+{
+ char buf[ardourvis::MAX_MSG_SIZE + 1] ;
+ memset(buf, 0, (ardourvis::MAX_MSG_SIZE + 1)) ;
+ buf[ardourvis::MAX_MSG_SIZE] = '\0' ;
+
+ int retcode = ::recv(fd, buf, MAX_MSG_SIZE, 0) ;
+ if (retcode == 0)
+ {
+ //end-of-file, other end closed or shutdown?
+ ARDOUR_UI::instance()->popup_error(_("Image Compositor Socket has been shutdown/closed"));
+
+ // assume socket has been shutdown, tell, someone interested,
+ // and remove the socket from the event loop
+ ImageFrameSocketHandler* ifsh = ImageFrameSocketHandler::get_instance() ;
+ gdk_input_remove(ifsh->theGdkInputTag) ;
+ ifsh->close_connection() ;
+ ifsh->CompositorSocketShutdown() ; /* EMIT_SIGNAL */
+ }
+ if(retcode > 0)
+ {
+ //std::cout << "Received Msg [" << buf << "]\n" ;
+ ImageFrameSocketHandler* ifsh = ImageFrameSocketHandler::get_instance() ;
+
+ std::string mType = ifsh->get_message_part(0,2,buf) ;
+
+ if(mType == ardourvis::INSERT_ITEM)
+ {
+ ifsh->handle_insert_message(buf) ;
+ }
+ else if (mType == ardourvis::REMOVE_ITEM)
+ {
+ ifsh->handle_remove_message(buf) ;
+ }
+ else if (mType == ardourvis::RENAME_ITEM)
+ {
+ ifsh->handle_rename_message(buf) ;
+ }
+ else if (mType == ardourvis::ITEM_UPDATE)
+ {
+ ifsh->handle_item_update_message(buf) ;
+ }
+ else if (mType == ardourvis::REQUEST_DATA)
+ {
+ ifsh->handle_request_data(buf) ;
+ }
+ else if (mType == ardourvis::ITEM_SELECTED)
+ {
+ ifsh->handle_item_selected(buf) ;
+ }
+ else if(mType == ardourvis::SESSION_ACTION)
+ {
+ ifsh->handle_session_action(buf) ;
+ }
+ else
+ {
+ std::string errMsg = "Unknown Message type : " ;
+ errMsg.append(mType) ;
+ ifsh->send_return_failure(errMsg) ;
+ }
+ }
+}
+
+/**
+ * Attempt to connect to the image compositor on the specified host and port
+ *
+ * @param hostIp the ip address of the image compositor host
+ * @param port the oprt number to attemp the connection on
+ * @return true if the connection was a succees
+ * false otherwise
+ */
+bool
+ImageFrameSocketHandler::connect(std::string hostIp, int32_t port)
+{
+ if (is_connected())
+ {
+ //already connected...
+ return(true) ;
+ }
+
+ theArdourToCompositorSocket = socket(AF_INET, SOCK_STREAM, 0) ;
+ if(theArdourToCompositorSocket == -1)
+ {
+ return(false) ;
+ }
+
+ int on = 1 ;
+ setsockopt(theArdourToCompositorSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) ;
+
+ sockaddr_in m_addr ;
+ m_addr.sin_family = AF_INET ;
+ m_addr.sin_port = htons(port) ;
+ m_addr.sin_addr.s_addr = inet_addr(hostIp.c_str()) ;
+
+ int status = ::connect(theArdourToCompositorSocket, (sockaddr *) &m_addr, sizeof(m_addr)) ;
+
+ if(status == -1)
+ {
+ theArdourToCompositorSocket = -1 ;
+ return(false) ;
+ }
+
+ return(true) ;
+}
+
+/**
+ * Closes the connection to th Image Compositor
+ *
+ */
+ void
+ ImageFrameSocketHandler::close_connection()
+ {
+ if(is_connected())
+ {
+ ::close(theArdourToCompositorSocket) ;
+ theArdourToCompositorSocket = -1 ;
+ }
+ }
+
+/**
+ * Returns true if this ImagFrameSocketHandler is currently connected to rthe image compositor
+ *
+ * @return true if connected to the image compositor
+ */
+bool
+ImageFrameSocketHandler::is_connected()
+{
+ return(theArdourToCompositorSocket == -1 ? false : true) ;
+}
+
+/**
+ * Sets the tag used to describe this input within gtk
+ * this is returned when gdk_input_add is called and is required to remove the input
+ *
+ * @param tag the gdk input tag of this input
+ */
+void
+ImageFrameSocketHandler::set_gdk_input_tag(int tag)
+{
+ theGdkInputTag = tag ;
+}
+
+/**
+ * Returns the gdk input tag of this input
+ *
+ * @return the gdk input tag of this input
+ * @see setGdkInputTag
+ */
+int
+ImageFrameSocketHandler::get_gdk_input_tag()
+{
+ return(theGdkInputTag) ;
+}
+
+/**
+ * Returns the socket file descriptor
+ *
+ * @return the Sockt file descriptor
+ */
+int
+ImageFrameSocketHandler::get_socket_descriptor()
+{
+ return(theArdourToCompositorSocket) ;
+}
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// Handle Sending messages to the Image Compositor
+
+//----------------------------
+// ImageFrameTimeAxis Messages
+
+/**
+ * Sends a message stating that the named image frame time axis has been removed
+ *
+ * @param track_id the unique id of the removed image frame time axis
+ * @param src the identity of the object that initiated the change
+ */
+void
+ImageFrameSocketHandler::send_imageframe_time_axis_removed(std::string track_id, void* src)
+{
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_TIME_AXIS ;
+
+ // add the id length, and the id
+ msgBuffer << std::setw(3) << track_id.length() ;
+ msgBuffer << track_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+/**
+ * Sends a message indicating that an ImageFrameTimeAxis has been renamed
+ *
+ * @param new_id the new name, or Id, of the track
+ * @param old_id the old name, or Id, of the track
+ * @param src the identity of the object that initiated the change
+ * @param time_axis the time axis that has changed
+ */
+void
+ImageFrameSocketHandler::send_imageframe_time_axis_renamed(std::string new_id, std::string old_id, void* src, ImageFrameTimeAxis* time_axis)
+{
+ // ENSURE_GUI_THREAD(SigC::bind (slot (*this, &ImageFrameSocketHandler::send_imageframe_time_axis_renamed), new_id, old_id, src, time_axis));
+
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_TIME_AXIS ;
+
+ // add the old id and length
+ msgBuffer << std::setw(3) << old_id.length() ;
+ msgBuffer << old_id ;
+
+ // add the new id and length
+ msgBuffer << std::setw(3) << new_id.length() ;
+ msgBuffer << new_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+//------------------------
+// MarkerTimeAxis Messages
+
+/**
+ * Sends a message stating that the named marker time axis has been removed
+ *
+ * @param track_id the unique id of the removed image frame time axis
+ * @param src the identity of the object that initiated the change
+ */
+void
+ImageFrameSocketHandler::send_marker_time_axis_removed(std::string track_id, void* src)
+{
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::MARKER_TIME_AXIS ;
+
+ // add the id length, and the id
+ msgBuffer << std::setw(3) << track_id.length() ;
+ msgBuffer << track_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+/**
+ * Sends a message indicating that an MarkerTimeAxis has been renamed
+ *
+ * @param new_id the new name, or Id, of the track
+ * @param old_id the old name, or Id, of the track
+ * @param src the identity of the object that initiated the change
+ * @param time_axis the time axis that has changed
+ */
+void
+ImageFrameSocketHandler::send_marker_time_axis_renamed(std::string new_id, std::string old_id, void* src, MarkerTimeAxis* time_axis)
+{
+ // ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameSocketHandler::send_marker_time_axis_renamed), new_id, old_id, src, time_axis));
+
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // ctreate a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::RENAME_ITEM << ardourvis::MARKER_TIME_AXIS ;
+
+ // add the old id and length
+ msgBuffer << std::setw(3) << old_id.length() ;
+ msgBuffer << old_id ;
+
+ // add the new id and length
+ msgBuffer << std::setw(3) << new_id.length() ;
+ msgBuffer << new_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+//---------------------------------
+// ImageFrameTimeAxisGroup Messages
+
+/**
+ * Sends a message stating that the group has been removed
+ *
+ * @param group_id the unique id of the removed image frame time axis
+ * @param src the identity of the object that initiated the change
+ * @param group the group that has changed
+ */
+void
+ImageFrameSocketHandler::send_imageframe_time_axis_group_removed(std::string group_id, void* src, ImageFrameTimeAxisGroup* group)
+{
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_GROUP ;
+
+ // add the id length, and the id of the parent image time axis
+ std::string track_id = group->get_view().trackview().name() ;
+ msgBuffer << std::setw(3) << track_id.length() ;
+ msgBuffer << track_id ;
+
+ // add the group id and length
+ msgBuffer << std::setw(3) << group_id.length() ;
+ msgBuffer << group_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+/**
+ * Send a message indicating that an ImageFrameTimeAxisGroup has been renamed
+ *
+ * @param new_id the new name, or Id, of the group
+ * @param old_id the old name, or Id, of the group
+ * @param src the identity of the object that initiated the change
+ * @param group the group that has changed
+ */
+void
+ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed(std::string new_id, std::string old_id, void* src, ImageFrameTimeAxisGroup* group)
+{
+ // ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed), new_id, old_id, src, group));
+
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // ctreate a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_GROUP ;
+
+ // add the track this group is upon
+ std::string track_id = group->get_view().trackview().name() ;
+ msgBuffer << std::setw(3) << track_id.length() << track_id ;
+
+ // add the old id and length
+ msgBuffer << std::setw(3) << old_id.length() ;
+ msgBuffer << old_id ;
+
+ // add the new id and length
+ msgBuffer << std::setw(3) << new_id.length() ;
+ msgBuffer << new_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+
+//---------------------------------
+// ImageFrameView Messages
+
+/**
+ * Send an Image Frame View Item position changed message
+ *
+ * @param pos the new position value
+ * @param src the identity of the object that initiated the change
+ * @param item the time axis item whos position has changed
+ */
+void
+ImageFrameSocketHandler::send_imageframe_view_position_change(jack_nframes_t pos, void* src, ImageFrameView* item)
+{
+ // ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameSocketHandler::send_imageframe_view_position_change), pos, src, item));
+
+ if(this == src || src == 0)
+ {
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::IMAGEFRAME_ITEM << ardourvis::POSITION_CHANGE ;
+
+ // add the item description
+ this->compose_imageframe_item_desc(item, msgBuffer) ;
+
+ msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << pos ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+/**
+ * Send a Image Frame View item duration changed message
+ *
+ * @param dur the the new duration value
+ * @param src the identity of the object that initiated the change
+ * @param item the item which has had a duration change
+ */
+void
+ImageFrameSocketHandler::send_imageframe_view_duration_change(jack_nframes_t dur, void* src, ImageFrameView* item)
+{
+ // ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameSocketHandler::send_imageframe_view_duration_change), dur, src, item));
+
+ if(this == src || src == 0)
+ {
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::IMAGEFRAME_ITEM << ardourvis::DURATION_CHANGE ;
+
+ this->compose_imageframe_item_desc(item, msgBuffer) ;
+
+ msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << dur ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+/**
+ * Send a message indicating that an ImageFrameView has been renamed
+ *
+ * @param item the ImageFrameView which has been renamed
+ * @param src the identity of the object that initiated the change
+ * @param item the renamed item
+ */
+void
+ImageFrameSocketHandler::send_imageframe_view_renamed(std::string new_id, std::string old_id, void* src, ImageFrameView* item)
+{
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // ctreate a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_ITEM ;
+
+ this->compose_imageframe_item_desc(item, msgBuffer) ;
+
+ // add the old id and length
+ msgBuffer << std::setw(3) << old_id.length() ;
+ msgBuffer << old_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+/**
+ * Send a message indicating that an ImageFrameView item has been removed message
+ *
+ * @param item_id the id of the item that was removed
+ * @param item the removed item
+ */
+void
+ImageFrameSocketHandler::send_imageframe_view_removed(std::string item_id, void* src, ImageFrameView* item)
+{
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_ITEM ;
+
+ // add the id length, and the id
+ ImageFrameTimeAxisGroup* parentGroup = item->get_time_axis_group() ;
+ std::string group_id = parentGroup->get_group_name() ;
+ std::string track_id = parentGroup->get_view().trackview().name() ;
+ msgBuffer << std::setw(3) << track_id.length() << track_id ;
+ msgBuffer << std::setw(3) << group_id.length() << group_id ;
+ msgBuffer << std::setw(3) << item_id.length() << item_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+
+
+
+//---------------------------------
+// MarkerView Messages
+
+/**
+ * Send a Marker View Item position changed message
+ *
+ * @param pos the new position value
+ * @param src the identity of the object that initiated the change
+ * @param item the time axis item whos position has changed
+ */
+void
+ImageFrameSocketHandler::send_marker_view_position_change(jack_nframes_t pos, void* src, MarkerView* item)
+{
+ if(this == src || src == 0)
+ {
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::MARKER_ITEM << ardourvis::POSITION_CHANGE ;
+
+ // add the item description
+ this->compose_marker_item_desc(item, msgBuffer) ;
+
+ msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << pos ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+/**
+ * Send a Marker View item duration changed message
+ *
+ * @param dur the new duration value
+ * @param src the identity of the object that initiated the change
+ * @param item the time axis item whos position has changed
+ */
+void
+ImageFrameSocketHandler::send_marker_view_duration_change(jack_nframes_t dur, void* src, MarkerView* item)
+{
+ if(this == src || src == 0)
+ {
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::MARKER_ITEM << ardourvis::DURATION_CHANGE ;
+
+ this->compose_marker_item_desc(item, msgBuffer) ;
+
+ msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << dur ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+
+/**
+ * Send a message indicating that a MarkerView has been renamed
+ *
+ * @param new_id the new_id of the object
+ * @param old_id the old_id of the object
+ * @param src the identity of the object that initiated the change
+ * @param item the MarkerView which has been renamed
+ */
+void
+ImageFrameSocketHandler::send_marker_view_renamed(std::string new_id, std::string old_id, void* src, MarkerView* item)
+{
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // ctreate a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::RENAME_ITEM << ardourvis::MARKER_ITEM ;
+
+ this->compose_marker_item_desc(item, msgBuffer) ;
+
+ // add the old id and length
+ msgBuffer << std::setw(3) << old_id.length() ;
+ msgBuffer << old_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+/**
+ * Send a message indicating that a MarkerView item has been removed message
+ *
+ * @param item_id the id of the item that was removed
+ * @param src the identity of the object that initiated the change
+ * @param item the MarkerView which has been removed
+ */
+void
+ImageFrameSocketHandler::send_marker_view_removed(std::string item_id, void* src, MarkerView* item)
+{
+ if(this == src || src == 0)
+ {
+ // ie the change originated from us, then dont send any message back
+ return ;
+ }
+
+ // create a message buffer
+ std::ostringstream msgBuffer ;
+ msgBuffer << std::setfill('0') ;
+
+ // add the msg type
+ msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::MARKER_ITEM ;
+
+ // add the id length, and the id
+ std::string track_id = item->get_time_axis_view().name() ;
+ msgBuffer << std::setw(3) << track_id.length() << track_id ;
+ msgBuffer << std::setw(3) << item_id.length() << item_id ;
+
+ send_message(msgBuffer.str()) ;
+
+ // XXX should do something with the return
+ std::string retmsg ;
+ read_message(retmsg) ;
+}
+
+
+
+
+
+
+
+
+
+
+
+//---------------------------------------------------------------------------------------//
+//---------------------------------------------------------------------------------------//
+//---------------------------------------------------------------------------------------//
+// Message breakdown ie avoid a big if...then...else
+
+
+/**
+ * Handle insert item requests
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_insert_message(const char* msg)
+{
+ // handle the insert item message
+ // determine the object type to insert based upon characters 2-3
+
+ std::string oType = get_message_part(2,2,msg) ;
+
+ if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
+ {
+ this->handle_insert_imageframe_time_axis(msg) ;
+ }
+ else if (oType == ardourvis::MARKER_TIME_AXIS)
+ {
+ this->handle_insert_marker_time_axis(msg) ;
+ }
+ else if (oType == ardourvis::IMAGEFRAME_GROUP)
+ {
+ this->handle_insert_imageframe_group(msg) ;
+ }
+ else if (oType == ardourvis::IMAGEFRAME_ITEM)
+ {
+ this->handle_insert_imageframe_view(msg) ;
+ }
+ else if (oType == ardourvis::MARKER_ITEM)
+ {
+ this->handle_insert_marker_view(msg) ;
+ }
+ else
+ {
+ std::string errMsg = "Unknown Object type during insert: " ;
+ errMsg.append(oType) ;
+ send_return_failure(errMsg) ;
+ }
+}
+
+/**
+ * Handle remove item requests
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_remove_message(const char* msg)
+{
+ // handle the removal of an item message
+ // determine the object type to remove based upon characters 2-3
+
+ std::string oType = get_message_part(2,2,msg) ;
+
+ if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
+ {
+ this->handle_remove_imageframe_time_axis(msg) ;
+ }
+ else if (oType == ardourvis::MARKER_TIME_AXIS)
+ {
+ this->handle_remove_marker_time_axis(msg) ;
+ }
+ else if (oType == ardourvis::IMAGEFRAME_ITEM)
+ {
+ this->handle_remove_imageframe_view(msg) ;
+ }
+ else if (oType == ardourvis::MARKER_ITEM)
+ {
+ this->handle_remove_marker_view(msg) ;
+ }
+ else
+ {
+ std::string errMsg = "Unknown Object type during Remove: " ;
+ errMsg.append(oType) ;
+ send_return_failure(errMsg) ;
+ }
+}
+
+/**
+ * Handle rename item requests
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_rename_message(const char* msg)
+{
+ // handle the renaming of an item message
+ // determine the object type to rename based upon characters 2-3
+
+ std::string oType = get_message_part(2,2,msg) ;
+
+ if(oType == ardourvis::IMAGEFRAME_TIME_AXIS)
+ {
+ this->handle_rename_imageframe_time_axis(msg) ;
+ }
+ else if (oType == ardourvis::MARKER_TIME_AXIS)
+ {
+ this->handle_rename_marker_time_axis(msg) ;
+ }
+ else if (oType == ardourvis::IMAGEFRAME_ITEM)
+ {
+ this->handle_rename_imageframe_view(msg) ;
+ }
+ else if (oType == ardourvis::MARKER_ITEM)
+ {
+ this->handle_rename_marker_view(msg) ;
+ }
+ else
+ {
+ std::string errMsg = "Unknown Object type during Rename: " ;
+ errMsg.append(oType) ;
+ send_return_failure(errMsg) ;
+ }
+}
+
+/**
+ * Handle a request for session information
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_request_data(const char* msg)
+{
+ // determine the request type
+ std::string reqType = get_message_part(2,2,msg) ;
+
+ if(reqType == ardourvis::SESSION_NAME)
+ {
+ handle_session_name_request(msg) ;
+ }
+}
+
+/**
+ * Handle the update of a particular item
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_item_update_message(const char* msg)
+{
+ // determin the object that requires updating, characters 2-3
+ std::string oType = get_message_part(2,2,msg) ;
+
+ // What needs updating? chars 4-5
+ std::string attr = get_message_part(4,2,msg) ;
+
+ if(oType == ardourvis::IMAGEFRAME_ITEM)
+ {
+ if(attr == ardourvis::POSITION_CHANGE)
+ {
+ handle_imageframe_view_position_update(msg) ;
+ }
+ else if(attr == ardourvis::DURATION_CHANGE)
+ {
+ handle_imageframe_view_duration_update(msg) ;
+ }
+ else if(attr == ardourvis::POSITION_LOCK_CHANGE)
+ {
+ handle_imageframe_position_lock_update(msg) ;
+ }
+ else if(attr == ardourvis::MAX_DURATION_CHANGE)
+ {
+ handle_imageframe_view_max_duration_update(msg) ;
+ }
+ else if(attr == ardourvis::MAX_DURATION_ENABLE_CHANGE)
+ {
+ handle_imageframe_view_max_duration_enable_update(msg) ;
+ }
+ else if(attr == ardourvis::MIN_DURATION_CHANGE)
+ {
+ handle_imageframe_view_min_duration_update(msg) ;
+ }
+ else if(attr == ardourvis::MIN_DURATION_ENABLE_CHANGE)
+ {
+ handle_imageframe_view_min_duration_enable_update(msg) ;
+ }
+ else
+ {
+ std::string errMsg = "Unknown Attribute during Item Update: " ;
+ errMsg.append(oType) ;
+ send_return_failure(errMsg) ;
+ }
+ }
+ else if(oType == ardourvis::MARKER_ITEM)
+ {
+ if(attr == ardourvis::POSITION_CHANGE)
+ {
+ handle_marker_view_position_update(msg) ;
+ }
+ else if(attr == ardourvis::DURATION_CHANGE)
+ {
+ handle_marker_view_duration_update(msg) ;
+ }
+ else
+ {
+ std::string errMsg = "Unknown Attribute during Item Update: " ;
+ errMsg.append(oType) ;
+ send_return_failure(errMsg) ;
+ }
+ }
+ else
+ {
+ std::string errMsg = "Unknown Object type during Item Update: " ;
+ errMsg.append(oType) ;
+ send_return_failure(errMsg) ;
+ }
+}
+
+/**
+ * Handle the selection of an Item
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_item_selected(const char* msg)
+{
+ // determine the object that requires updating, characters 2-3
+ std::string oType = get_message_part(2,2,msg) ;
+
+ if(oType == std::string(ardourvis::IMAGEFRAME_ITEM))
+ {
+ int position = 4 ; // message type chars
+
+ std::string track_id ;
+ std::string scene_id ;
+ std::string item_id ;
+ int track_id_size ;
+ int scene_id_size ;
+ int item_id_size ;
+
+ this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
+
+ // get the named time axis
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
+
+ if(!ifta)
+ {
+ send_return_failure(std::string("No parent Image Track found : ").append(track_id)) ;
+ }
+ else
+ {
+ // get the parent scene
+ ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
+ if(!iftag)
+ {
+ send_return_failure(std::string("No parent Scene found : ").append(scene_id)) ;
+ }
+ else
+ {
+ ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
+ if(!ifv)
+ {
+ send_return_failure(std::string("No Image Frame Item found : ").append(item_id)) ;
+ }
+ else
+ {
+ ifv->set_selected(true, this) ;
+ ifta->get_view()->set_selected_imageframe_view(iftag, ifv) ;
+
+ thePublicEditor.scroll_timeaxis_to_imageframe_item(ifv) ;
+ send_return_success() ;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Handle s session action message
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_session_action(const char* msg)
+{
+ std::string actionType = get_message_part(2,2,msg) ;
+
+ if(actionType == ardourvis::OPEN_SESSION)
+ {
+ this->handle_open_session(msg) ;
+ }
+}
+
+
+
+
+
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// handlers for specific insert procedures
+
+/**
+ * Handle the insertion of a new ImaegFrameTimeAxis
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_insert_imageframe_time_axis(const char* msg)
+{
+ int position = 4 ; // message type chars
+
+ // get the ImageFrameTrack name size
+ int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
+ position += ardourvis::TEXT_SIZE_CHARS ;
+
+ // get the image frame track name
+ std::string track_name = get_message_part(position, track_name_size, msg) ;
+ position += track_name_size ;
+
+ // check we dont already have an time axis with that name
+ TimeAxisView* tav = thePublicEditor.get_named_time_axis(track_name) ;
+ if(tav)
+ {
+ std::string errmsg("Track already exists: ") ;
+ errmsg.append(track_name) ;
+ send_return_failure(errmsg) ;
+ }
+ else
+ {
+ thePublicEditor.add_imageframe_time_axis(track_name, this) ;
+ TimeAxisView* new_tav = thePublicEditor.get_named_time_axis(track_name) ;
+
+ if(new_tav)
+ {
+ ImageFrameTimeAxis* ifta = (ImageFrameTimeAxis*)new_tav ;
+ ifta->VisualTimeAxisRemoved.connect(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_removed)) ;
+ ifta->NameChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_renamed), ifta)) ;
+
+ send_return_success() ;
+ }
+ else
+ {
+ std::string msg("Addition Failed: ") ;
+ msg.append(track_name) ;
+ send_return_failure(msg) ;
+ }
+ }
+}
+
+
+/**
+ * Handle the insertion of a new MarkerTimeAxis
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_insert_marker_time_axis(const char* msg)
+{
+ int position = 4 ; // message type chars
+
+ // get the ImageFrameTrack name size
+ int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
+ position += ardourvis::TEXT_SIZE_CHARS ;
+
+ // get the image frame track name
+ std::string track_name = get_message_part(position, track_name_size, msg) ;
+ position += track_name_size ;
+
+ // get the size of the name of the associated track
+ int assoc_track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
+ position += ardourvis::TEXT_SIZE_CHARS ;
+
+ // get the name of the track we associate the marker track with
+ std::string assoc_track_name = get_message_part(position, assoc_track_name_size, msg) ;
+ position += assoc_track_name_size ;
+
+ // check that we dont already have a time axis with that name
+ TimeAxisView* checkTav = thePublicEditor.get_named_time_axis(track_name) ;
+ if(checkTav)
+ {
+ std::string errmsg("Track already exists: ") ;
+ errmsg.append(track_name) ;
+ send_return_failure(errmsg) ;
+ }
+ else
+ {
+ // check the associated time axis exists
+ TimeAxisView* assoc_tav = thePublicEditor.get_named_time_axis(assoc_track_name) ;
+ if(assoc_tav)
+ {
+ thePublicEditor.add_imageframe_marker_time_axis(track_name, assoc_tav, this) ;
+ TimeAxisView* new_tav = thePublicEditor.get_named_time_axis(track_name) ;
+
+ bool added = false ;
+
+ if(new_tav)
+ {
+ MarkerTimeAxis* mta = dynamic_cast<MarkerTimeAxis*>(new_tav) ;
+ if(mta)
+ {
+ added = true ;
+ mta->VisualTimeAxisRemoved.connect(SigC::slot(*this, &ImageFrameSocketHandler::send_marker_time_axis_removed)) ;
+ mta->NameChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_marker_time_axis_renamed), mta)) ;
+ }
+ }
+
+ if(added)
+ {
+ std::string msg("Addition Failed: ") ;
+ msg.append(track_name) ;
+ send_return_failure(msg) ;
+ }
+ }
+ else
+ {
+ std::string errmsg("No associated Track Found: ") ;
+ errmsg.append(track_name) ;
+ send_return_failure(errmsg) ;
+ }
+ }
+}
+
+/**
+ * Handle the insertion of a time axis group (a scene)
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_insert_imageframe_group(const char* msg)
+{
+ int position = 4 ; // message type chars
+
+ // get the ImageFrameTrack name size
+ int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
+ position += ardourvis::TEXT_SIZE_CHARS ;
+
+ // get the image frame track name
+ std::string track_name = get_message_part(position, track_name_size, msg) ;
+ position += track_name_size ;
+
+ // get the scene id size
+ int scene_id_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ;
+ position += ardourvis::TEXT_SIZE_CHARS ;
+
+ // get the scene id
+ std::string scene_id = get_message_part(position, scene_id_size, msg) ;
+ position += scene_id_size ;
+
+
+ // get the named ImageFrameTrack
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_name)) ;
+
+ // check we got a valid ImageFrameTimeAxis
+ if(!ifta)
+ {
+ send_return_failure(std::string("No Image Frame Time Axis Found: ").append(track_name)) ;
+ return ;
+ }
+
+ ImageFrameTimeAxisGroup* iftag = ifta->get_view()->add_imageframe_group(scene_id, this) ;
+ if(!iftag)
+ {
+ send_return_failure(std::string("Image Frame Group insert failed")) ;
+ }
+ else
+ {
+ iftag->NameChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed), iftag)) ;
+ iftag->GroupRemoved.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_removed), iftag)) ;
+ send_return_success() ;
+ }
+}
+
+
+/**
+ * Handle the insertion of a new ImageFrameItem
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_insert_imageframe_view(const char* msg)
+{
+ int position = 4 ; // message type chars
+
+ // get the ImageFrameTrack name size
+ int track_name_size = atoi(get_message_part(position,3,msg).c_str()) ;
+ position += 3 ;
+
+ // get the ImageFrameTrack Name
+ std::string imageframe_track_name = get_message_part(position,track_name_size,msg) ;
+ position += track_name_size ;
+
+ // get the scene name size
+ int scene_size = atoi(get_message_part(position,3,msg).c_str()) ;
+ position += 3 ;
+
+ // get the scene Name
+ std::string scene_name = get_message_part(position,scene_size,msg) ;
+ position += scene_size ;
+
+ // get the image frame_id size
+ int image_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
+ position += 3 ;
+
+ // get the image frame_id
+ std::string image_id = get_message_part(position,image_id_size,msg) ;
+ position += image_id_size ;
+
+ // get the start frame value
+ jack_nframes_t start = strtoul((get_message_part(position,10,msg).c_str()),0,10) ;
+ position += 10 ;
+
+ // get the duration value
+ jack_nframes_t duration = strtoul((get_message_part(position,10,msg).c_str()),0,10) ;
+ position += 10 ;
+
+ //get the named time axis view we about to add an image to
+ TimeAxisView* tav = thePublicEditor.get_named_time_axis(imageframe_track_name) ;
+ ImageFrameTimeAxis* ifta = 0 ;
+
+ if(tav)
+ {
+ ifta = dynamic_cast<ImageFrameTimeAxis*>(tav) ;
+ }
+
+ if(!ifta)
+ {
+ std::string errmsg("No Parent Image Track Found: ") ;
+ errmsg.append(imageframe_track_name) ;
+ send_return_failure(errmsg) ;
+
+ // dont really like all these returns mid-way
+ // but this is goinf to get awfully if..then nested if not
+ return ;
+ }
+
+ // check the parent group exists
+ ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_name) ;
+ if(!iftag)
+ {
+ std::string errmsg("No Image Frame Group Found: ") ;
+ errmsg.append(scene_name) ;
+ send_return_failure(errmsg) ;
+ return ;
+ }
+
+ // ok, so we have the parent group and track, now we need dome image data
+
+
+ //
+ // request the image data from the image compositor
+ //
+
+ // ctreate a message buffer
+ std::ostringstream reqBuffer ;
+ reqBuffer << std::setfill('0') ;
+
+ // add the msg type
+ reqBuffer << REQUEST_DATA << IMAGE_RGB_DATA ;
+
+ // add the image track and size
+ reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << track_name_size ;
+ reqBuffer << imageframe_track_name ;
+
+ // add the scene id and size
+ reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << scene_size ;
+ reqBuffer << scene_name ;
+
+ // add the image id and size
+ reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << image_id_size ;
+ reqBuffer << image_id ;
+
+ // add the preferred image height
+ reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << ifta->get_image_display_height() ;
+
+ // send the request message
+ send_message(reqBuffer.str()) ;
+
+
+ // read the reply, the inital image data message
+ // this gives us the image dimensions and the expected size of the image data
+ // msg type(4) + image width(3) + height(3) + num channels(3) + size of the image data (32)
+ std::string init_image_data_msg ;
+ read_message(init_image_data_msg) ;
+ int init_msg_pos = 4 ;
+
+ int imgWidth = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
+ init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ;
+ int imgHeight = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
+ init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ;
+ int imgChannels = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ;
+ init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ;
+ int imgSize = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_DATA_MESSAGE_SIZE_CHARS).c_str()) ;
+
+ // send a success msg
+ // we need to do this to keep things moving
+ send_return_success() ;
+
+ // create our image rgb buffer, this holds the image data we receive
+ unsigned char* rgb_img_buf = new unsigned char[imgSize] ;
+
+ int retcode = ::recv(theArdourToCompositorSocket, rgb_img_buf, imgSize, MSG_WAITALL) ;
+
+ if(retcode != imgSize)
+ {
+ delete [] rgb_img_buf ;
+ send_return_failure("Could not create new Image Frame View : image data sizes did not match") ;
+ }
+ else
+ {
+ ImageFrameView* ifv = iftag->add_imageframe_item(image_id, start, duration, rgb_img_buf, (uint32_t)imgWidth, (uint32_t)imgHeight, (uint32_t)imgChannels, this) ;
+ if(ifv)
+ {
+ ifv->PositionChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_view_position_change), ifv)) ;
+ ifv->DurationChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_view_duration_change), ifv)) ;
+ ifv->ItemRemoved.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_view_removed), ifv)) ;
+
+ send_return_success() ;
+ }
+ else
+ {
+ //addition failed. assume duplicate item_id
+ send_return_failure("Could not create new Image Frame View") ;
+ }
+ }
+}
+
+
+
+/**
+ * Handle the insertion of a new MarkerItem
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_insert_marker_view(const char* msg)
+{}
+
+
+//---------------------------------------------------------------------------------------//
+// handlers for specific removal procedures
+
+
+/**
+ * Handle the removal of an ImageTimeAxis
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_remove_imageframe_time_axis(const char* msg)
+{}
+
+/**
+ * Handle the removal of an MarkerTimeAxis
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_remove_marker_time_axis(const char* msg)
+{}
+
+/**
+ * Handle the removal of an ImageFrameTimeAxisGroup
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_remove_imageframe_time_axis_group(const char* msg)
+{}
+
+/**
+ * Handle the removal of an ImageFrameItem
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_remove_imageframe_view(const char* msg)
+{}
+
+/**
+ * Handle the removal of an MarkerItem
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_remove_marker_view(const char* msg)
+{}
+
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// handlers for the specific rename procedures
+
+/**
+ * Handle the renaming of an ImageTimeAxis
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_rename_imageframe_time_axis(const char* msg)
+{
+ // msg [MVIT][oldSize][oldId][newSize][newId]
+
+ int position = 4 ; // message type chars
+
+ // get the old Id size
+ int old_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
+ position += 3 ;
+
+ // get the old id
+ std::string old_id = get_message_part(position,old_id_size,msg) ;
+ position += old_id_size ;
+
+ //get the new Id size
+ int new_id_size = atoi(get_message_part(position,3,msg).c_str()) ;
+ position += 3 ;
+
+ // get the new Id
+ std::string new_id = get_message_part(position,new_id_size,msg) ;
+ position += new_id_size ;
+
+ // get the Named time axis
+ TimeAxisView* tav = thePublicEditor.get_named_time_axis(old_id) ;
+ if(dynamic_cast<ImageFrameTimeAxis*>(tav))
+ {
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(tav) ;
+ ifta->set_time_axis_name(new_id, this) ;
+ send_return_success() ;
+ }
+ else
+ {
+ std::string msg = "No Image Track Found: " ;
+ msg.append(old_id) ;
+ send_return_failure(msg) ;
+ }
+}
+
+/**
+ * Handle the renaming of an MarkerTimeAxis
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_rename_marker_time_axis(const char* msg)
+{}
+
+/**
+ * Handle the renaming of an ImageFrameItem
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_rename_imageframe_time_axis_group(const char* msg)
+{}
+
+/**
+ * Handle the renaming of an ImageFrameItem
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_rename_imageframe_view(const char* msg)
+{}
+
+/**
+ * Handle the renaming of an Marker
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_rename_marker_view(const char* msg)
+{}
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// handlers for data request
+
+/**
+ * Handle a request for the sessnio naem fo the current session
+ * We return a failure state if no session is open
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_session_name_request(const char* msg)
+{
+ ARDOUR::Session* currentSession = thePublicEditor.current_session() ;
+
+ if(currentSession == 0)
+ {
+ // no current session, return failure
+ std::string msg("No Current Session") ;
+ send_return_failure(msg) ;
+ }
+ else
+ {
+ std::string sessionName = currentSession->name() ;
+ std::string sessionPath = currentSession->path() ;
+
+ if(sessionPath[sessionPath.length() -1] != '/')
+ {
+ sessionPath.append("/") ;
+ }
+
+ sessionPath.append(sessionName) ;
+
+ std::ostringstream msgBuf ;
+ msgBuf << ardourvis::RETURN_DATA << ardourvis::SESSION_NAME ;
+ msgBuf << std::setfill('0') ;
+ msgBuf << std::setw(ardourvis::TEXT_SIZE_CHARS) << sessionPath.length() ;
+ msgBuf << sessionPath ;
+ send_message(msgBuf.str()) ;
+ }
+}
+
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// handlers for specific item update changes
+
+/**
+ * Handle ImageFrameView positional changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_imageframe_view_position_update(const char* msg)
+{
+ int position = 6 ; // message type chars
+
+ std::string track_id ;
+ std::string scene_id ;
+ std::string item_id ;
+ int track_id_size ;
+ int scene_id_size ;
+ int item_id_size ;
+
+ this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
+
+ jack_nframes_t start_frame = strtoul(get_message_part(position, ardourvis::TIME_VALUE_CHARS, msg).c_str(), 0, 10) ;
+ position += ardourvis::TIME_VALUE_CHARS ;
+
+ // get the named time axis
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
+
+ if(!ifta)
+ {
+ send_return_failure(std::string("No parent Image Track found: ").append(track_id)) ;
+ return ;
+ }
+
+ // get the parent scene
+ ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
+ if(!iftag)
+ {
+ send_return_failure(std::string("No parent Scene found: ").append(scene_id)) ;
+ return ;
+ }
+
+ ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
+
+ if(!ifv)
+ {
+ send_return_failure(std::string("No Image Frame Item found: ").append(item_id)) ;
+ return ;
+ }
+
+
+ ifv->set_position(start_frame, this) ;
+ send_return_success() ;
+}
+
+/**
+ * Handle ImageFrameView Duration changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_imageframe_view_duration_update(const char* msg)
+{
+ int position = 6 ; // message type chars
+
+ std::string track_id ;
+ std::string scene_id ;
+ std::string item_id ;
+ int track_id_size ;
+ int scene_id_size ;
+ int item_id_size ;
+
+ this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ;
+
+ jack_nframes_t duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
+ position += ardourvis::TIME_VALUE_CHARS ;
+
+ // get the named time axis
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
+
+ if(!ifta)
+ {
+ send_return_failure(std::string("No parent Image Track found : ").append(track_id)) ;
+ return ;
+ }
+
+ // get the parent scene
+ ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ;
+ if(!iftag)
+ {
+ send_return_failure(std::string("No parent Scene found : ").append(scene_id)) ;
+ return ;
+ }
+
+ ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
+
+ if(!ifv)
+ {
+ send_return_failure(std::string("No Image Frame Item found : ").append(item_id)) ;
+ return ;
+ }
+
+ ifv->set_duration(duration, this) ;
+ send_return_success() ;
+}
+
+/**
+ * Handle ImageFrameView Position Lock Constraint changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_imageframe_position_lock_update(const char* msg)
+{
+ int position = 6 ; // message type chars
+
+ std::string track_id ;
+ std::string group_id ;
+ std::string item_id ;
+ int track_id_size ;
+ int group_id_size ;
+ int item_id_size ;
+
+ this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
+
+ std::string pos_lock = get_message_part(position,1,msg) ;
+ bool pos_lock_active = false ;
+
+ if(pos_lock == "0")
+ {
+ pos_lock_active = false ;
+ }
+ else if(pos_lock == "1")
+ {
+ pos_lock_active = true ;
+ }
+ else
+ {
+ send_return_failure(std::string("Unknown Value used during Position Loack: ").append(pos_lock)) ;
+ return ;
+ }
+
+ position += 1 ;
+
+ int errcode ;
+ std::string errmsg ;
+ ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
+ if(ifv)
+ {
+ ifv->set_position_locked(pos_lock_active, this) ;
+ send_return_success() ;
+ }
+ else
+ {
+ send_return_failure(errmsg) ;
+ }
+}
+
+/**
+ * Handle ImageFrameView Maximum Duration changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_imageframe_view_max_duration_update(const char* msg)
+{
+ int position = 6 ; // message type chars
+
+ std::string track_id ;
+ std::string group_id ;
+ std::string item_id ;
+ int track_id_size ;
+ int group_id_size ;
+ int item_id_size ;
+
+ this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
+
+ jack_nframes_t max_duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
+ position += ardourvis::TIME_VALUE_CHARS ;
+
+ int errcode ;
+ std::string errmsg ;
+ ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
+ if(ifv)
+ {
+ ifv->set_max_duration(max_duration, this) ;
+ send_return_success() ;
+ }
+ else
+ {
+ send_return_failure(errmsg) ;
+ }
+}
+
+/**
+ * Handle image frame max duration enable constraint changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_imageframe_view_max_duration_enable_update(const char* msg)
+{
+ int position = 6 ; // message type chars
+
+ std::string track_id ;
+ std::string group_id ;
+ std::string item_id ;
+ int track_id_size ;
+ int group_id_size ;
+ int item_id_size ;
+
+ this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
+
+ std::string active = get_message_part(position,1,msg) ;
+ bool max_duration_active = false ;
+
+ if(active == "0")
+ {
+ max_duration_active = false ;
+ }
+ else if(active == "1")
+ {
+ max_duration_active = true ;
+ }
+ else
+ {
+ send_return_failure(std::string("Unknown Value used during enable max duration: ").append(active)) ;
+ return ;
+ }
+
+ position += 1 ;
+
+ int errcode ;
+ std::string errmsg ;
+ ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
+ if(ifv)
+ {
+ ifv->set_max_duration_active(max_duration_active, this) ;
+ send_return_success() ;
+ }
+ else
+ {
+ send_return_failure(errmsg) ;
+ }
+}
+
+/**
+ * Handle ImageFrameView Minimum Duration changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_imageframe_view_min_duration_update(const char* msg)
+{
+ int position = 6 ; // message type chars
+
+ std::string track_id ;
+ std::string group_id ;
+ std::string item_id ;
+ int track_id_size ;
+ int group_id_size ;
+ int item_id_size ;
+
+ this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
+
+ jack_nframes_t min_duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ;
+ position += ardourvis::TIME_VALUE_CHARS ;
+
+ int errcode ;
+ std::string errmsg ;
+ ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
+ if(ifv)
+ {
+ ifv->set_min_duration(min_duration, this) ;
+ send_return_success() ;
+ }
+ else
+ {
+ send_return_failure(errmsg) ;
+ }
+}
+
+/**
+ * Handle image frame min duration enable constraint changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_imageframe_view_min_duration_enable_update(const char* msg)
+{
+ int position = 6 ; // message type chars
+
+ std::string track_id ;
+ std::string group_id ;
+ std::string item_id ;
+ int track_id_size ;
+ int group_id_size ;
+ int item_id_size ;
+
+ this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ;
+
+ std::string active = get_message_part(position,1,msg) ;
+ bool min_duration_active = false ;
+
+ if(active == "0")
+ {
+ min_duration_active = false ;
+ }
+ else if(active == "1")
+ {
+ min_duration_active = true ;
+ }
+ else
+ {
+ send_return_failure(std::string("Unknown Value used during enable max duration: ").append(active)) ;
+ return ;
+ }
+
+ position += 1 ;
+
+ int errcode ;
+ std::string errmsg ;
+ ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ;
+ if(ifv)
+ {
+ ifv->set_min_duration_active(min_duration_active, this) ;
+ send_return_success() ;
+ }
+ else
+ {
+ send_return_failure(errmsg) ;
+ }
+}
+
+/**
+ * Handle MarkerView position changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_marker_view_position_update(const char* msg)
+{}
+
+/**
+ * Handle MarkerView duration changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_marker_view_duration_update(const char* msg)
+{}
+
+/**
+ * Handle MarkerView Position Lock Constraint changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_marker_view_position_lock_update(const char* msg)
+{
+}
+
+/**
+ * Handle MarkerView maximum duration changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_marker_view_max_duration_update(const char* msg)
+{}
+
+/**
+ * Handle MarkerView minimum duration changes
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_marker_view_min_duration_update(const char* msg)
+{}
+
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// handlers for Session Actions
+
+/**
+ * Handle the opening of a named audio session
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_open_session(const char* msg)
+{
+ // msg [SAOS][sessionSize][sessionPath]
+
+ int position = 4 ; // message type chars
+
+ // get the session name size
+ int session_name_size = atoi(get_message_part(position,3,msg).c_str()) ;
+ position += 3 ;
+
+ // get the session name
+ std::string session_name = get_message_part(position,session_name_size,msg) ;
+ position += session_name_size ;
+
+
+ // open the session
+ std::string path, name ;
+ bool isnew;
+
+ if (ARDOUR::Session::find_session(session_name, path, name, isnew) == 0) {
+ if (ARDOUR_UI::instance()->load_session (path, name) == 0) {
+ send_return_success() ;
+ } else {
+ std::string retMsg = "Failed to load Session" ;
+ send_return_failure(retMsg) ;
+ }
+ } else {
+ std::string retMsg = "Failed to find Session" ;
+ send_return_failure(retMsg) ;
+ }
+}
+
+
+/**
+ * Handle the closing of a named audio session
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_closed_session(const char* msg)
+{}
+
+//---------------------------------------------------------------------------------------//
+// handlers for the shutdown of the Image Compositor
+
+/**
+ * Handle the shutdown message from the image compositor
+ *
+ * @param msg the received message
+ */
+void
+ImageFrameSocketHandler::handle_shutdown(const char* msg)
+{
+ CompositorSocketShutdown() ; /* EMIT_SIGNAL */
+}
+
+
+
+
+
+
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// convenince methods to break up messages
+
+/**
+ * Returns part of the received message as a std::string
+ *
+ * @param start the start character
+ * @param num_chars the number of characters to read
+ * @param the message to break apart
+ * @return the sub string of the message
+ */
+std::string
+ImageFrameSocketHandler::get_message_part(int start, int32_t num_chars, const char* msg)
+{
+ char buf[num_chars + 1] ;
+ strncpy(buf,msg+start,num_chars) ;
+ buf[num_chars] = '\0' ;
+ std::string s(buf) ;
+
+ return(s) ;
+}
+
+
+
+/**
+ * break up am image item description message
+ * we break the mesage up into the parent Image Track id and size,
+ * the parent group id and size, and the image id and size
+ *
+ * @param track_id
+ * @param track_id_size
+ * @param scene_id
+ * @param scene_id_size
+ * @param item_id
+ * @param item_id_size
+ */
+void
+ImageFrameSocketHandler::decompose_imageframe_item_desc(const char* msg, int& position, std::string& track_id,
+ int& track_id_size, std::string& scene_id, int& scene_id_size, std::string& item_id, int& item_id_size)
+{
+ // get the track Id size
+ track_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
+ position += ardourvis::TEXT_SIZE_CHARS ;
+
+ // get the track id
+ track_id = get_message_part(position,track_id_size,msg) ;
+ position += track_id_size ;
+
+ // get the track Id size
+ scene_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
+ position += ardourvis::TEXT_SIZE_CHARS ;
+
+ // get the scene id
+ scene_id = get_message_part(position,scene_id_size,msg) ;
+ position += scene_id_size ;
+
+ // get the item id size
+ item_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ;
+ position += ardourvis::TEXT_SIZE_CHARS ;
+
+ // get the item id
+ item_id = get_message_part(position,item_id_size,msg) ;
+ position += item_id_size ;
+}
+
+/**
+ * Compose a description of the specified image frame view
+ * The description consists of the parent track name size and name,
+ * the parent group name size and name, and the item name size and name
+ *
+ * @param ifv the item to compose a description of
+ * @param buffer the buffer to write the description
+ */
+void
+ImageFrameSocketHandler::compose_imageframe_item_desc(ImageFrameView* ifv, std::ostringstream& buffer)
+{
+ buffer << std::setw(3) << ifv->get_time_axis_group()->get_view().trackview().name().length() ;
+ buffer << ifv->get_time_axis_group()->get_view().trackview().name() ;
+
+ // add the parent scene
+ buffer << std::setw(3) << ifv->get_time_axis_group()->get_group_name().length() ;
+ buffer << ifv->get_time_axis_group()->get_group_name() ;
+
+ // add the ImageFrameItem id length and Id
+ buffer << setw(3) << ifv->get_item_name().length() ;
+ buffer << ifv->get_item_name() ;
+}
+
+/**
+ * Compose a description of the specified marker view
+ * The description consists of the parent track name size and name,
+ * and the item name size and name
+ *
+ * @param mv the item to compose a description of
+ * @param buffer the buffer to write the description
+ */
+void
+ImageFrameSocketHandler::compose_marker_item_desc(MarkerView* mv, std::ostringstream& buffer)
+{
+ MarkerTimeAxis* mta = dynamic_cast<MarkerTimeAxis*>(&mv->get_time_axis_view()) ;
+
+ if(!mta)
+ {
+ return ;
+ }
+
+ buffer << std::setw(3) << mta->name().length() ;
+ buffer << mta->name() ;
+
+ buffer << std::setw(3) << mv->get_item_name().length() ;
+ buffer << mv->get_item_name() ;
+}
+
+
+/**
+ * Returns the ImageFrameView from the specified description
+ * The errcode parameter is used to indicate the item which caused
+ * an error on failure of this method
+ * 0 = success
+ * 1 = the track item was not found
+ * 2 = the group item was not found
+ * 3 = the imageframe item was not found
+ *
+ * @paran track_id the track on which the item is placed
+ * @param group_id the group in which the item is a member
+ * @param item_id the id of the item
+ * @param int32_t reference used for error codes on failure
+ * @param errmsg populated with a description of the error on failure
+ * @return the described item on success, 0 otherwise
+ */
+ImageFrameView*
+ImageFrameSocketHandler::get_imageframe_view_from_desc(const std::string& track_id, const std::string& group_id, const std::string& item_id, int& errcode, std::string& errmsg)
+{
+ ImageFrameView* item = 0 ;
+
+ // get the named time axis
+ ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(thePublicEditor.get_named_time_axis(track_id)) ;
+
+ if(!ifta)
+ {
+ errcode = 1 ;
+ errmsg = std::string("Image Frame Time Axis Not Found: ").append(track_id) ;
+ }
+ else
+ {
+ // get the parent scene
+ ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(group_id) ;
+ if(!iftag)
+ {
+ errcode = 2 ;
+ errmsg = std::string("Image Frame Group Not Found: ").append(group_id) ;
+ }
+ else
+ {
+ ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ;
+ if(!ifv)
+ {
+ errcode = 3 ;
+ errmsg = std::string("Image Frame Item Not Found: ").append(item_id) ;
+ }
+ else
+ {
+ // yay!!
+ item = ifv ;
+ errcode = 0 ;
+ }
+ }
+ }
+
+ return(item) ;
+}
+
+//---------------------------------------------------------------------------------------//
+// Convenince Message Send Methods
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+/**
+ * Sends a message throught the socket
+ *
+ * @param msg the message to send
+ * @return the return value of the socket call
+ */
+int
+ImageFrameSocketHandler::send_message(const std::string& msg)
+{
+ //std::cout << "Sending Message [" << msg << "]\n" ;
+ int retcode = ::send(theArdourToCompositorSocket, msg.c_str(), msg.length(), MSG_NOSIGNAL) ;
+
+ return(retcode) ;
+}
+
+/**
+ * Reads a message from the Socket
+ *
+ * @param msg a string to populate with the received message
+ * @return the return value from the socket call
+ */
+int
+ImageFrameSocketHandler::read_message(std::string& msg)
+{
+ char buf[ardourvis::MAX_MSG_SIZE + 1] ;
+ memset(buf, 0, (ardourvis::MAX_MSG_SIZE + 1)) ;
+
+ msg = "" ;
+ int retcode = ::recv(theArdourToCompositorSocket, buf, ardourvis::MAX_MSG_SIZE, 0) ;
+
+ msg = buf ;
+ //std::cout << "Received Message [" << msg << "]\n" ;
+
+ return(retcode) ;
+}
+
+
+/**
+ * Convenience method to compose and send a success messasge back to the Image Compositor
+ *
+ */
+void
+ImageFrameSocketHandler::send_return_success()
+{
+ send_message(ardourvis::RETURN_TRUE) ;
+}
+
+/**
+ * Convenience method to compose and send a failure messasge back to the Image Compositor
+ *
+ * @param msg the failure message
+ */
+void
+ImageFrameSocketHandler::send_return_failure(const std::string& msg)
+{
+ std::ostringstream buf ;
+ buf << std::setfill('0') ;
+ buf << ardourvis::RETURN_FALSE ;
+ buf << std::setw(3) << msg.length(); ;
+ buf << msg ;
+
+ send_message(buf.str()) ;
+}
diff --git a/gtk2_ardour/imageframe_socket_handler.h b/gtk2_ardour/imageframe_socket_handler.h
new file mode 100644
index 0000000000..93a82b63bb
--- /dev/null
+++ b/gtk2_ardour/imageframe_socket_handler.h
@@ -0,0 +1,705 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_imageframe_socket_handler_h__
+#define __ardour_gtk_imageframe_socket_handler_h__
+
+#include <string>
+#include <gtk--.h>
+#include <list>
+#include "editor.h"
+#include "ardour_image_compositor_socket.h"
+
+class TimeAxisViewItem ;
+class ImageFrameView ;
+class MarkerView ;
+class ImageFrameTimeAxisGroup ;
+
+/**
+ * ImageFrameSocketHandler defines the handler between Ardour and an Image Compositor
+ * As this is purely visual, we do all processing within the main gtk loop via
+ * message passing through a socket.
+ *
+ */
+class ImageFrameSocketHandler : public SigC::Object
+{
+ public:
+ /**
+ * Constructs a new ImageFrameSocketHandler to handle communication between Ardour and the Image Compositor
+ *
+ * @param ed the PublicEditor
+ */
+ ImageFrameSocketHandler(PublicEditor& ed) ;
+
+ /**
+ * Descructor
+ * this will shutdown the socket if open
+ */
+ virtual ~ImageFrameSocketHandler() ;
+
+ /**
+ * Returns the instance of the ImageFrameSocketHandler
+ * the instance should first be created with createInstance
+ *
+ * @return the instance of the ImageFrameSocketHandler
+ */
+ static ImageFrameSocketHandler* get_instance() ;
+
+ /**
+ * call back to handle doing the processing work
+ * This method is added to the gdk main loop and called when there is data
+ * upon the socket.
+ *
+ */
+ static void image_socket_callback(void *arg, int32_t fd, GdkInputCondition cond) ;
+
+ /**
+ * Attempt to connect to the image compositor on the specified host and port
+ *
+ * @param hostIp the ip address of the image compositor host
+ * @param port the oprt number to attemp the connection on
+ * @return true if the connection was a succees
+ * false otherwise
+ */
+ bool connect(std::string hostIp, int32_t port) ;
+
+ /**
+ * Closes the connection to th Image Compositor
+ *
+ */
+ void close_connection() ;
+ /**
+ * Returns true if this ImagFrameSocketHandler is currently connected to rthe image compositor
+ *
+ * @return true if connected to the image compositor
+ */
+ bool is_connected() ;
+
+ /**
+ * Sets the tag used to describe this input within gtk
+ * this is returned when gdk_input_add is called and is required to remove the input
+ *
+ * @param tag the gdk input tag of this input
+ */
+ void set_gdk_input_tag(int tag) ;
+
+ /**
+ * Returns the gdk input tag of this input
+ *
+ * @return the gdk input tag of this input
+ * @see setGdkInputTag
+ */
+ int get_gdk_input_tag() ;
+
+
+ /**
+ * Returns the socket file descriptor
+ *
+ * @return the Sockt file descriptor
+ */
+ int get_socket_descriptor() ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Handle Sending messages to the Image Compositor
+
+ //----------------------------
+ // ImageFrameTimeAxis Messages
+
+ /**
+ * Sends a message stating that the named image frame time axis has been removed
+ *
+ * @param track_id the unique id of the removed image frame time axis
+ * @param src the identity of the object that initiated the change
+ */
+ void send_imageframe_time_axis_removed(std::string track_id, void* src) ;
+
+ /**
+ * Sends a message indicating that an ImageFrameTimeAxis has been renamed
+ *
+ * @param new_id the new name, or Id, of the track
+ * @param old_id the old name, or Id, of the track
+ * @param src the identity of the object that initiated the change
+ * @param time_axis the time axis that has changed
+ */
+ void send_imageframe_time_axis_renamed(std::string new_id, std::string old_id, void* src, ImageFrameTimeAxis* time_axis) ;
+
+ //------------------------
+ // MarkerTimeAxis Messages
+
+ /**
+ * Sends a message stating that the named marker time axis has been removed
+ *
+ * @param track_id the unique id of the removed image frame time axis
+ * @param src the identity of the object that initiated the change
+ */
+ void send_marker_time_axis_removed(std::string track_id, void* src) ;
+
+ /**
+ * Sends a message indicating that an MarkerTimeAxis has been renamed
+ *
+ * @param new_id the new name, or Id, of the track
+ * @param old_id the old name, or Id, of the track
+ * @param src the identity of the object that initiated the change
+ * @param time_axis the time axis that has changed
+ */
+ void send_marker_time_axis_renamed(std::string new_id, std::string old_id, void* src, MarkerTimeAxis* time_axis) ;
+
+
+ //---------------------------------
+ // ImageFrameTimeAxisGroup Messages
+
+ /**
+ * Sends a message stating that the group has been removed
+ *
+ * @param group_id the unique id of the removed image frame time axis
+ * @param src the identity of the object that initiated the change
+ * @param group the group that has changed
+ */
+ void send_imageframe_time_axis_group_removed(std::string group_id, void* src, ImageFrameTimeAxisGroup* group) ;
+
+ /**
+ * Send a message indicating that an ImageFrameTimeAxisGroup has been renamed
+ *
+ * @param new_id the new name, or Id, of the group
+ * @param old_id the old name, or Id, of the group
+ * @param src the identity of the object that initiated the change
+ * @param group the group that has changed
+ */
+ void send_imageframe_time_axis_group_renamed(std::string new_id, std::string old_id, void* src, ImageFrameTimeAxisGroup* group) ;
+
+
+ //---------------------------------
+ // ImageFrameView Messages
+
+ /**
+ * Send an Image Frame View Item position changed message
+ *
+ * @param pos the new position value
+ * @param src the identity of the object that initiated the change
+ * @param item the time axis item whos position has changed
+ */
+ void send_imageframe_view_position_change(jack_nframes_t pos, void* src, ImageFrameView* item) ;
+
+ /**
+ * Send a Image Frame View item duration changed message
+ *
+ * @param dur the the new duration value
+ * @param src the identity of the object that initiated the change
+ * @param item the item which has had a duration change
+ */
+ void send_imageframe_view_duration_change(jack_nframes_t dur, void* src, ImageFrameView* item) ;
+
+ /**
+ * Send a message indicating that an ImageFrameView has been renamed
+ *
+ * @param item the ImageFrameView which has been renamed
+ * @param src the identity of the object that initiated the change
+ * @param item the renamed item
+ */
+ void send_imageframe_view_renamed(std::string new_id, std::string old_id, void* src, ImageFrameView* item) ;
+
+ /**
+ * Send a message indicating that an ImageFrameView item has been removed message
+ *
+ * @param item_id the id of the item that was removed
+ * @param src the identity of the object that initiated the change
+ * @param item the removed item
+ */
+ void send_imageframe_view_removed(std::string item_id, void* src, ImageFrameView* item) ;
+
+ //---------------------------------
+ // MarkerView Messages
+
+ /**
+ * Send a Marker View Item position changed message
+ *
+ * @param pos the new position value
+ * @param src the identity of the object that initiated the change
+ * @param item the time axis item whos position has changed
+ */
+ void send_marker_view_position_change(jack_nframes_t pos, void* src, MarkerView* item) ;
+
+ /**
+ * Send a Marker View item duration changed message
+ *
+ * @param dur the new duration value
+ * @param src the identity of the object that initiated the change
+ * @param item the time axis item whos position has changed
+ */
+ void send_marker_view_duration_change(jack_nframes_t dur, void* src, MarkerView* item) ;
+
+ /**
+ * Send a message indicating that a MarkerView has been renamed
+ *
+ * @param new_id the new_id of the object
+ * @param old_id the old_id of the object
+ * @param src the identity of the object that initiated the change
+ * @param item the MarkerView which has been renamed
+ */
+ void send_marker_view_renamed(std::string new_id, std::string old_id, void* src, MarkerView* item) ;
+
+ /**
+ * Send a message indicating that a MarkerView item has been removed message
+ *
+ * @param item_id the id of the item that was removed
+ * @param src the identity of the object that initiated the change
+ * @param item the MarkerView which has been removed
+ */
+ void send_marker_view_removed(std::string item_id, void* src, MarkerView* item) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Emitted Signals
+
+ /** Emitted if the socket connection is shutdown at the other end */
+ SigC::Signal0<void> CompositorSocketShutdown ;
+
+ /** Emitted as a generic error is captured from the socket connection to the animatic compositor */
+ SigC::Signal0<void> CompositorSocketError ;
+
+
+ protected:
+
+
+ private:
+ /* I dont like friends :-( */
+ friend class Editor;
+
+ /**
+ * Create an new instance of the ImageFrameSocketHandler, if one does not already exist
+ *
+ * @param ed the Ardour PublicEditor
+ */
+ static ImageFrameSocketHandler* create_instance(PublicEditor& ed) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Message breakdown ie avoid a big if...then...else
+
+ /**
+ * Handle insert item requests
+ *
+ * @param msg the received message
+ */
+ void handle_insert_message(const char* msg) ;
+
+ /**
+ * Handle remove item requests
+ *
+ * @param msg the received message
+ */
+ void handle_remove_message(const char* msg) ;
+
+ /**
+ * Handle rename item requests
+ *
+ * @param msg the received message
+ */
+ void handle_rename_message(const char* msg) ;
+
+ /**
+ * Handle a request for session information
+ *
+ * @param msg the received message
+ */
+ void handle_request_data(const char* msg) ;
+
+ /**
+ * Handle the update of a particular item
+ *
+ * @param msg the received message
+ */
+ void handle_item_update_message(const char* msg) ;
+
+ /**
+ * Handle the selection of an Item
+ *
+ * @param msg the received message
+ */
+ void handle_item_selected(const char* msg) ;
+
+ /**
+ * Handle s session action message
+ *
+ * @param msg the received message
+ */
+ void handle_session_action(const char* msg) ;
+
+ //---------------------------------------------------------------------------------------//
+ // handlers for specific insert procedures
+
+ /**
+ * Handle the insertion of a new ImaegFrameTimeAxis
+ *
+ * @param msg the received message
+ */
+ void handle_insert_imageframe_time_axis(const char* msg) ;
+
+ /**
+ * Handle the insertion of a new MarkerTimeAxis
+ *
+ * @param msg the received message
+ */
+ void handle_insert_marker_time_axis(const char* msg) ;
+
+ /**
+ * Handle the insertion of a time axis group (a scene)
+ *
+ * @param msg the received message
+ */
+ void handle_insert_imageframe_group(const char* msg) ;
+
+ /**
+ * Handle the insertion of a new ImageFrameItem
+ *
+ * @param msg the received message
+ */
+ void handle_insert_imageframe_view(const char* msg) ;
+
+ /**
+ * Handle the insertion of a new MarkerItem
+ *
+ * @param msg the received message
+ */
+ void handle_insert_marker_view(const char* msg) ;
+
+ //---------------------------------------------------------------------------------------//
+ // handlers for specific removal procedures
+
+ /**
+ * Handle the removal of an ImageTimeAxis
+ *
+ * @param msg the received message
+ */
+ void handle_remove_imageframe_time_axis(const char* msg) ;
+
+ /**
+ * Handle the removal of an MarkerTimeAxis
+ *
+ * @param msg the received message
+ */
+ void handle_remove_marker_time_axis(const char* msg) ;
+
+ /**
+ * Handle the removal of an ImageFrameTimeAxisGroup
+ *
+ * @param msg the received message
+ */
+ void handle_remove_imageframe_time_axis_group(const char* msg) ;
+
+ /**
+ * Handle the removal of an ImageFrameItem
+ *
+ * @param msg the received message
+ */
+ void handle_remove_imageframe_view(const char* msg) ;
+
+ /**
+ * Handle the removal of an MarkerItem
+ *
+ * @param msg the received message
+ */
+ void handle_remove_marker_view(const char* msg) ;
+
+ //---------------------------------------------------------------------------------------//
+ // handlers for the specific rename procedures
+
+ /**
+ * Handle the renaming of an ImageTimeAxis
+ *
+ * @param msg the received message
+ */
+ void handle_rename_imageframe_time_axis(const char* msg) ;
+
+ /**
+ * Handle the renaming of an MarkerTimeAxis
+ *
+ * @param msg the received message
+ */
+ void handle_rename_marker_time_axis(const char* msg) ;
+
+ /**
+ * Handle the renaming of an ImageFrameItem
+ *
+ * @param msg the received message
+ */
+ void handle_rename_imageframe_time_axis_group(const char* msg) ;
+
+ /**
+ * Handle the renaming of an ImageFrameItem
+ *
+ * @param msg the received message
+ */
+ void handle_rename_imageframe_view(const char* msg) ;
+
+ /**
+ * Handle the renaming of an Marker
+ *
+ * @param msg the received message
+ */
+ void handle_rename_marker_view(const char* msg) ;
+
+ //---------------------------------------------------------------------------------------//
+ // handlers for data request
+
+ /**
+ * Handle a request for the sessnio naem fo the current session
+ * We return a failure state if no session is open
+ *
+ * @param msg the received message
+ */
+ void handle_session_name_request(const char* msg) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // handlers for specific item update changes
+
+ /**
+ * Handle ImageFrameView positional changes
+ *
+ * @param msg the received message
+ */
+ void handle_imageframe_view_position_update(const char* msg) ;
+
+ /**
+ * Handle ImageFrameView Duration changes
+ *
+ * @param msg the received message
+ */
+ void handle_imageframe_view_duration_update(const char* msg) ;
+
+ /**
+ * Handle ImageFrameView Position Lock Constraint changes
+ *
+ * @param msg the received message
+ */
+ void handle_imageframe_position_lock_update(const char* msg) ;
+
+ /**
+ * Handle ImageFrameView Maximum Duration changes
+ *
+ * @param msg the received message
+ */
+ void handle_imageframe_view_max_duration_update(const char* msg) ;
+
+ /**
+ * Handle image frame max duration enable constraint changes
+ *
+ * @param msg the received message
+ */
+ void handle_imageframe_view_max_duration_enable_update(const char* msg) ;
+
+ /**
+ * Handle ImageFrameView Minimum Duration changes
+ *
+ * @param msg the received message
+ */
+ void handle_imageframe_view_min_duration_update(const char* msg) ;
+
+ /**
+ * Handle image frame min duration enable constraint changes
+ *
+ * @param msg the received message
+ */
+ void handle_imageframe_view_min_duration_enable_update(const char* msg) ;
+
+
+ /**
+ * Handle MarkerView position changes
+ *
+ * @param msg the received message
+ */
+ void handle_marker_view_position_update(const char* msg) ;
+
+ /**
+ * Handle MarkerView duration changes
+ *
+ * @param msg the received message
+ */
+ void handle_marker_view_duration_update(const char* msg) ;
+
+ /**
+ * Handle MarkerView Position Lock Constraint changes
+ *
+ * @param msg the received message
+ */
+ void handle_marker_view_position_lock_update(const char* msg) ;
+
+ /**
+ * Handle MarkerView maximum duration changes
+ *
+ * @param msg the received message
+ */
+ void handle_marker_view_max_duration_update(const char* msg) ;
+
+ /**
+ * Handle MarkerView minimum duration changes
+ *
+ * @param msg the received message
+ */
+ void handle_marker_view_min_duration_update(const char* msg) ;
+
+
+
+ //---------------------------------------------------------------------------------------//
+ // handlers for Session Actions
+
+ /**
+ * Handle the opening of a named audio session
+ *
+ * @param msg the received message
+ */
+ void handle_open_session(const char* msg) ;
+
+ /**
+ * Handle the closing of a named audio session
+ *
+ * @param msg the received message
+ */
+ void handle_closed_session(const char* msg) ;
+
+ //---------------------------------------------------------------------------------------//
+ // handlers for the shutdown of the Image Compositor
+
+ /**
+ * Handle the shutdown message from the image compositor
+ *
+ * @param msg the received message
+ */
+ void handle_shutdown(const char* msg) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // convenince methods to break up messages
+
+ /**
+ * Returns part of the received message as a std::string
+ *
+ * @param start the start character
+ * @param num_chars the number of characters to read
+ * @param the message to break apart
+ * @return the sub string of the message
+ */
+ std::string get_message_part(int start, int32_t num_chars, const char* msg) ;
+
+
+ /**
+ * break up am image item description message
+ * we break the mesage up into the parent Image Track id and size,
+ * the parent group id and size, and the image id and size
+ *
+ * @param track_id
+ * @param track_id_size
+ * @param scene_id
+ * @param scene_id_size
+ * @param item_id
+ * @param item_id_size
+ */
+ void decompose_imageframe_item_desc(const char* msg, int& position, std::string& track_id, int& track_id_size, std::string& scene_id, int& scene_id_size, std::string& item_id, int& item_id_size) ;
+
+ /**
+ * Compose a description of the specified image frame view
+ * The description consists of the parent track name size and name,
+ * the parent group name size and name, and the item name size and name
+ *
+ * @param ifv the item to compose a description of
+ * @param buffer the buffer to write the description
+ */
+ void compose_imageframe_item_desc(ImageFrameView* ifv, std::ostringstream& buffer) ;
+
+ /**
+ * Compose a description of the specified marker view
+ * The description consists of the parent track name size and name,
+ * and the item name size and name
+ *
+ * @param mv the item to compose a description of
+ * @param buffer the buffer to write the description
+ */
+ void compose_marker_item_desc(MarkerView* mv, std::ostringstream& buffer) ;
+
+
+ /**
+ * Returns the ImageFrameView from the specified description
+ * The errcode parameter is used to indicate the item which caused
+ * an error on failure of this method
+ * 0 = suces
+ * 1 = the track item was not found
+ * 2 = the group item was not found
+ * 3 = the imageframe item was not found
+ *
+ * @paran track_id the track on which the item is placed
+ * @param group_id the group in which the item is a member
+ * @param item_id the id of the item
+ * @param int32_t reference used for error codes on failure
+ * @param errmsg populated with a description of the error on failure
+ * @return the described item on success, 0 otherwise
+ */
+ ImageFrameView* get_imageframe_view_from_desc(const std::string& track_id, const std::string& group_ud, const std::string& item_id, int& errcode, std::string& errmsg) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Convenince Message Send Methods
+
+ /**
+ * Sends a message throught the socket
+ *
+ * @param msg the message to send
+ * @return the return value of the socket call
+ */
+ int send_message(const std::string& msg) ;
+
+ /**
+ * Reads a message from the Socket
+ *
+ * @param msg a string to populate with the received message
+ * @return the return value from the socket call
+ */
+ int read_message(std::string& msg) ;
+
+ /**
+ * Convenience method to compose and send a success messasge back to the Image Compositor
+ *
+ */
+ void send_return_success() ;
+
+ /**
+ * Convenience method to compose and send a failure messasge back to the Image Compositor
+ *
+ * @param msg the failure message
+ */
+ void send_return_failure(const std::string& msg) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Memebr Data
+
+ /** Our instance of the socket handler, singleton */
+ static ImageFrameSocketHandler* _instance ;
+
+ /** The Ardour PublicEditor */
+ PublicEditor& thePublicEditor ;
+
+ /** the socket file descriptor */
+ int theArdourToCompositorSocket ;
+
+ /** This stores the 'tag' returned from gdk_input_add, which is required for removing the input */
+ int theGdkInputTag ;
+
+} ; /* class ImageFrameSocketHandler */
+
+#endif /* __ardour_gtk_imageframe_socket_handler_h__ */
diff --git a/gtk2_ardour/imageframe_time_axis.cc b/gtk2_ardour/imageframe_time_axis.cc
new file mode 100644
index 0000000000..51325ca38f
--- /dev/null
+++ b/gtk2_ardour/imageframe_time_axis.cc
@@ -0,0 +1,440 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+#include <algorithm>
+
+#include <pbd/error.h>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include <ardour/session.h>
+#include <ardour/utils.h>
+
+#include "public_editor.h"
+#include "imageframe_time_axis.h"
+#include "canvas-simplerect.h"
+#include "enums.h"
+#include "imageframe_time_axis_view.h"
+#include "imageframe_time_axis_group.h"
+#include "marker_time_axis_view.h"
+#include "imageframe_view.h"
+#include "marker_time_axis.h"
+#include "marker_view.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR ;
+using namespace SigC ;
+using namespace Gtk ;
+
+/**
+ * Constructs a new ImageFrameTimeAxis.
+ *
+ * @param track_id the track name/id
+ * @param ed the PublicEditor
+ * @param sess the current session
+ * @param canvas the parent canvas item
+ */
+ImageFrameTimeAxis::ImageFrameTimeAxis(std::string track_id, PublicEditor& ed, ARDOUR::Session& sess, Widget *canvas)
+ : AxisView(sess),
+ VisualTimeAxis(track_id, ed, sess, canvas)
+{
+ _color = unique_random_color() ;
+
+ selection_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display), gtk_canvas_group_get_type (), NULL) ;
+ gtk_canvas_item_hide(selection_group) ;
+
+ // intialize our data items
+ _marked_for_display = true;
+ y_position = -1 ;
+ name_prompter = 0 ;
+
+ /* create our new image frame view */
+ view = new ImageFrameTimeAxisView(*this) ;
+
+ /* create the Image Frame Edit Menu */
+ create_imageframe_menu() ;
+
+ // set the initial time axis text label
+ label_view() ;
+
+ // set the initial height of this time axis
+ set_height(Normal) ;
+}
+
+/**
+ * Destructor
+ * Responsible for destroying any child image items that may have been added to thie time axis
+ */
+ImageFrameTimeAxis::~ImageFrameTimeAxis ()
+{
+ GoingAway() ; /* EMIT_SIGNAL */
+
+ // Destroy all the marker views we may have associaited with this TimeAxis
+ for(MarkerTimeAxisList::iterator iter = marker_time_axis_list.begin(); iter != marker_time_axis_list.end(); ++iter)
+ {
+ MarkerTimeAxis* mta = *iter ;
+ MarkerTimeAxisList::iterator next = iter ;
+ next++ ;
+
+ marker_time_axis_list.erase(iter) ;
+
+ delete mta ;
+ mta = 0 ;
+
+ iter = next ;
+ }
+
+ if(image_action_menu)
+ {
+ delete image_action_menu ;
+ image_action_menu = 0 ;
+ }
+
+ for(list<SelectionRect*>::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i)
+ {
+ gtk_object_destroy (GTK_OBJECT((*i)->rect));
+ gtk_object_destroy (GTK_OBJECT((*i)->start_trim));
+ gtk_object_destroy (GTK_OBJECT((*i)->end_trim));
+ }
+
+ for(list<SelectionRect*>::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i)
+ {
+ gtk_object_destroy (GTK_OBJECT((*i)->rect));
+ gtk_object_destroy (GTK_OBJECT((*i)->start_trim));
+ gtk_object_destroy (GTK_OBJECT((*i)->end_trim));
+ }
+
+ if (selection_group)
+ {
+ gtk_object_destroy (GTK_OBJECT (selection_group));
+ selection_group = 0 ;
+ }
+
+ // Destroy our Axis View helper
+ if(view)
+ {
+ delete view ;
+ view = 0 ;
+ }
+}
+
+//---------------------------------------------------------------------------------------//
+// ui methods & data
+
+/**
+ * Sets the height of this TrackView to one of ths TrackHeghts
+ *
+ * @param h the TrackHeight value to set
+ */
+void
+ImageFrameTimeAxis::set_height (TrackHeight h)
+{
+ VisualTimeAxis::set_height(h) ;
+
+ // tell out view helper of the change too
+ if(view != 0)
+ {
+ view->set_height((double) height) ;
+ }
+
+ // tell those interested that we have had our height changed
+ gui_changed("track_height",(void*)0); /* EMIT_SIGNAL */
+}
+
+/**
+ * Sets the number of samples per unit that are used.
+ * This is used to determine the siezes of items upon this time axis
+ *
+ * @param spu the number of samples per unit
+ */
+void
+ImageFrameTimeAxis::set_samples_per_unit(double spu)
+{
+ TimeAxisView::set_samples_per_unit (editor.get_current_zoom());
+
+ if(view) {
+ view->set_samples_per_unit(spu) ;
+ }
+}
+
+
+/**
+ * Returns the available height for images to be drawn onto
+ *
+ * @return the available height for an image item to be drawn onto
+ */
+int
+ImageFrameTimeAxis::get_image_display_height()
+{
+ return(height - (gint)TimeAxisViewItem::NAME_HIGHLIGHT_SIZE) ;
+}
+
+
+/**
+ * Show the popup edit menu
+ *
+ * @param button the mouse button pressed
+ * @param time when to show the popup
+ * @param clicked_imageframe the ImageFrameItem that the event ocured upon, or 0 if none
+ * @param with_item true if an item has been selected upon the time axis, used to set context menu
+ */
+void
+ImageFrameTimeAxis::popup_imageframe_edit_menu(int button, int32_t time, ImageFrameView* clicked_imageframe, bool with_item)
+{
+ if (!imageframe_menu)
+ {
+ create_imageframe_menu() ;
+ }
+
+ if(with_item)
+ {
+ imageframe_item_menu->set_sensitive(true) ;
+ }
+ else
+ {
+ imageframe_item_menu->set_sensitive(false) ;
+ }
+
+ imageframe_menu->popup(button,time) ;
+}
+
+/**
+ * convenience method to select a new track color and apply it to the view and view items
+ *
+ */
+void
+ImageFrameTimeAxis::select_track_color()
+{
+ if (choose_time_axis_color())
+ {
+ if (view)
+ {
+ view->apply_color (_color) ;
+ }
+ }
+}
+
+/**
+ * Handles the building of the popup menu
+ */
+void
+ImageFrameTimeAxis::build_display_menu()
+{
+ using namespace Menu_Helpers;
+
+ /* get the size menu ready */
+
+ build_size_menu();
+
+ /* prepare it */
+
+ TimeAxisView::build_display_menu () ;
+
+ /* now fill it with our stuff */
+
+ MenuList& items = display_menu->items();
+
+ items.push_back (MenuElem (_("Rename"), slot(*this, &ImageFrameTimeAxis::start_time_axis_rename)));
+
+ image_action_menu = new Menu() ;
+ image_action_menu->set_name ("ArdourContextMenu");
+ MenuList image_items = image_action_menu->items() ;
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Height"), *size_menu));
+ items.push_back (MenuElem (_("Color"), slot(*this, &ImageFrameTimeAxis::select_track_color)));
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Remove"), bind(slot(*this, &VisualTimeAxis::remove_this_time_axis), (void*)this))) ;
+}
+
+/**
+ * handles the building of the ImageFrameView sub menu
+ */
+void
+ImageFrameTimeAxis::create_imageframe_menu()
+{
+ using namespace Menu_Helpers;
+
+ imageframe_menu = manage(new Menu) ;
+ imageframe_menu->set_name ("ArdourContextMenu");
+ MenuList& items = imageframe_menu->items();
+
+ imageframe_item_menu = manage(new Menu) ;
+ imageframe_item_menu->set_name ("ArdourContextMenu");
+ MenuList& imageframe_sub_items = imageframe_item_menu->items() ;
+
+ /* duration menu */
+ Menu* duration_menu = manage(new Menu) ;
+ duration_menu->set_name ("ArdourContextMenu");
+ MenuList& duration_items = duration_menu->items() ;
+
+ if(view)
+ {
+ duration_items.push_back(MenuElem (_("0.5 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 0.5))) ;
+ duration_items.push_back(MenuElem (_("1 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 1.0))) ;
+ duration_items.push_back(MenuElem (_("1.5 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 1.5))) ;
+ duration_items.push_back(MenuElem (_("2 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 2.0))) ;
+ duration_items.push_back(MenuElem (_("2.5 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 2.5))) ;
+ duration_items.push_back(MenuElem (_("3 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 3.0))) ;
+ //duration_items.push_back(SeparatorElem()) ;
+ //duration_items.push_back(MenuElem (_("custom"), slot (*this, &ImageFrameTimeAxis::set_imageframe_duration_custom))) ;
+ }
+
+ imageframe_sub_items.push_back(MenuElem(_("Duration (sec)"), *duration_menu)) ;
+
+ imageframe_sub_items.push_back(SeparatorElem()) ;
+ if(view)
+ {
+ imageframe_sub_items.push_back(MenuElem (_("Remove Frame"), bind(slot (view, &ImageFrameTimeAxisView::remove_selected_imageframe_item), (void*)this))) ;
+ }
+
+ items.push_back(MenuElem(_("Image Frame"), *imageframe_item_menu)) ;
+ items.push_back(MenuElem (_("Rename Track"), slot (*this,&ImageFrameTimeAxis::start_time_axis_rename))) ;
+
+ imageframe_menu->show_all() ;
+}
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// Marker Time Axis Methods
+
+/**
+ * Add a MarkerTimeAxis to the ilst of MarkerTimeAxis' associated with this ImageFrameTimeAxis
+ *
+ * @param marker_track the MarkerTimeAxis to add
+ * @param src the identity of the object that initiated the change
+ * @return true if the addition was a success,
+ * false otherwise
+ */
+bool
+ImageFrameTimeAxis::add_marker_time_axis(MarkerTimeAxis* marker_track, void* src)
+{
+ bool ret = false ;
+
+ if(get_named_marker_time_axis(marker_track->name()) != 0)
+ {
+ ret = false ;
+ }
+ else
+ {
+ marker_time_axis_list.push_back(marker_track) ;
+ marker_track->GoingAway.connect(bind(slot(*this, &ImageFrameTimeAxis::remove_time_axis_view), marker_track, (void*)this));
+
+ MarkerTimeAxisAdded(marker_track, src) ; /* EMIT_SIGNAL */
+ ret = true ;
+ }
+
+ return(ret) ;
+}
+
+/**
+ * Returns the named MarkerTimeAxis associated with this ImageFrameTimeAxis
+ *
+ * @param track_id the track_id of the MarkerTimeAxis to search for
+ * @return the named markerTimeAxis, or 0 if the named MarkerTimeAxis is not associated with this ImageFrameTimeAxis
+ */
+MarkerTimeAxis*
+ImageFrameTimeAxis::get_named_marker_time_axis(std::string track_id)
+{
+ MarkerTimeAxis* mta = 0 ;
+
+ for (MarkerTimeAxisList::iterator i = marker_time_axis_list.begin(); i != marker_time_axis_list.end(); ++i)
+ {
+ if (((MarkerTimeAxis*)*i)->name() == track_id)
+ {
+ mta = ((MarkerTimeAxis*)*i) ;
+ break ;
+ }
+ }
+ return(mta) ;
+}
+
+/**
+ * Removes the named markerTimeAxis from those associated with this ImageFrameTimeAxis
+ *
+ * @param track_id the track id of the MarkerTimeAxis to remove
+ * @param src the identity of the object that initiated the change
+ * @return the removed MarkerTimeAxis
+ */
+MarkerTimeAxis*
+ImageFrameTimeAxis::remove_named_marker_time_axis(std::string track_id, void* src)
+{
+ MarkerTimeAxis* mta = 0 ;
+
+ for(MarkerTimeAxisList::iterator i = marker_time_axis_list.begin(); i != marker_time_axis_list.end(); ++i)
+ {
+ if (((MarkerTimeAxis*)*i)->name() == track_id)
+ {
+ mta = ((MarkerTimeAxis*)*i) ;
+
+ // the iterator is invalid after this call, so we can no longer use it as is.
+ marker_time_axis_list.erase(i) ;
+
+ MarkerTimeAxisRemoved(mta->name(), src) ; /* EMIT_SIGNAL */
+ break ;
+ }
+ }
+
+ return(mta) ;
+}
+
+/**
+ * Removes the specified MarkerTimeAxis from the list of MarkerTimaAxis associated with this ImageFrameTimeAxis
+ * Note that the MarkerTimeAxis is not deleted, only removed from the list os associated tracks
+ *
+ * @param mta the TimeAxis to remove
+ * @param src the identity of the object that initiated the change
+ */
+void
+ImageFrameTimeAxis::remove_time_axis_view(MarkerTimeAxis* mta, void* src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameTimeAxis::remove_time_axis_view), mta, src));
+
+ MarkerTimeAxisList::iterator i;
+ if((i = find (marker_time_axis_list.begin(), marker_time_axis_list.end(), mta)) != marker_time_axis_list.end())
+ {
+ // note that we dont delete the object itself, we just remove it from our list
+ marker_time_axis_list.erase(i) ;
+
+ MarkerTimeAxisRemoved(mta->name(), src) ; /* EMIT_SIGNAL */
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Parent/Child helper object accessors
+
+/**
+ * Returns the view helper of this TimeAxis
+ *
+ * @return the view helper of this TimeAxis
+ */
+ImageFrameTimeAxisView*
+ImageFrameTimeAxis::get_view()
+{
+ return(view) ;
+}
diff --git a/gtk2_ardour/imageframe_time_axis.h b/gtk2_ardour/imageframe_time_axis.h
new file mode 100644
index 0000000000..dfbb0bd72f
--- /dev/null
+++ b/gtk2_ardour/imageframe_time_axis.h
@@ -0,0 +1,200 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_imageframe_time_axis_h__
+#define __ardour_imageframe_time_axis_h__
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+
+#include "ardour_dialog.h"
+#include "enums.h"
+#include "time_axis_view.h"
+#include <list>
+#include "visual_time_axis.h"
+
+namespace ARDOUR
+{
+ class Session ;
+}
+
+class PublicEditor ;
+class ImageFrameView ;
+class ImageFrameTimeAxisView ;
+class MarkersTimeAxisView ;
+class MarkerTimeAxis;
+
+/**
+ * ImageFrameTimeAxis defines a visual time axis view for holding and arranging image items.
+ *
+ */
+class ImageFrameTimeAxis : public VisualTimeAxis
+{
+ public:
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * Constructs a new ImageFrameTimeAxis.
+ *
+ * @param track_id the track name/id
+ * @param ed the PublicEditor
+ * @param sess the current session
+ * @param canvas the parent canvas item
+ */
+ ImageFrameTimeAxis(std::string track_id, PublicEditor& ed, ARDOUR::Session& sess, Gtk::Widget *canvas) ;
+
+ /**
+ * Destructor
+ * Responsible for destroying any child image items that may have been added to thie time axis
+ */
+ virtual ~ImageFrameTimeAxis() ;
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods & data
+
+ /**
+ * Sets the height of this TrackView to one of ths TrackHeghts
+ *
+ * @param h the TrackHeight value to set
+ */
+ virtual void set_height(TimeAxisView::TrackHeight) ;
+
+ /**
+ * Sets the number of samples per unit that are used.
+ * This is used to determine the siezes of items upon this time axis
+ *
+ * @param spu the number of samples per unit
+ */
+ virtual void set_samples_per_unit(double spu) ;
+
+ /**
+ * Returns the available height for images to be drawn onto
+ *
+ * @return the available height for an image item to be drawn onto
+ */
+ int get_image_display_height() ;
+
+
+ /**
+ * Show the popup edit menu
+ *
+ * @param button the mouse button pressed
+ * @param time when to show the popup
+ * @param clicked_imageframe the ImageFrameItem that the event ocured upon, or 0 if none
+ * @param with_item true if an item has been selected upon the time axis, used to set context menu
+ */
+ void popup_imageframe_edit_menu(int button, int32_t time, ImageFrameView* clicked_imageframe, bool with_item) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Marker Time Axis Methods
+
+ /**
+ * Add a MarkerTimeAxis to the ilst of MarkerTimeAxis' associated with this ImageFrameTimeAxis
+ *
+ * @param marker_track the MarkerTimeAxis to add
+ * @param src the identity of the object that initiated the change
+ * @return true if the addition was a success,
+ * false otherwise
+ */
+ bool add_marker_time_axis(MarkerTimeAxis* marker_track, void* src) ;
+
+ /**
+ * Returns the named MarkerTimeAxis associated with this ImageFrameTimeAxis
+ *
+ * @param track_id the track_id of the MarkerTimeAxis to search for
+ * @return the named markerTimeAxis, or 0 if the named MarkerTimeAxis is not associated with this ImageFrameTimeAxis
+ */
+ MarkerTimeAxis* get_named_marker_time_axis(std::string track_id) ;
+
+ /**
+ * Removes the named markerTimeAxis from those associated with this ImageFrameTimeAxis
+ *
+ * @param track_id the track id of the MarkerTimeAxis to remove
+ * @param src the identity of the object that initiated the change
+ * @return the removed MarkerTimeAxis
+ */
+ MarkerTimeAxis* remove_named_marker_time_axis(std::string track_id, void* src) ;
+
+ /**
+ * Removes tav from the list of MarkerTimaAxis associated with this ImageFrameTimeAxis
+ *
+ * @param tav the TimeAxis to remove
+ * @param src the identity of the object that initiated the change
+ */
+ void remove_time_axis_view(MarkerTimeAxis* tav, void* src) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Parent/Child helper object accessors
+
+ /**
+ * Returns the view helper of this TimeAxis
+ *
+ * @return the view helper of this TimeAxis
+ */
+ ImageFrameTimeAxisView* get_view() ;
+
+
+ //---------------------------------------------------------------------------------//
+ // Emitted Signals
+
+ /** Emitted when a Marker Time Axis is Added, or associated with, this time axis */
+ SigC::Signal2<void,MarkerTimeAxis*,void*> MarkerTimeAxisAdded ;
+
+ /** Emitted when a Marker Time Axis is removed, from this time axis */
+ SigC::Signal2<void,std::string,void*> MarkerTimeAxisRemoved ;
+
+ protected:
+
+ private:
+ /**
+ * convenience method to select a new track color and apply it to the view and view items
+ *
+ */
+ void select_track_color() ;
+
+ /**
+ * Handles the building of the popup menu
+ */
+ virtual void build_display_menu() ;
+
+ /**
+ * handles the building of the ImageFrameView sub menu
+ */
+ void create_imageframe_menu() ;
+
+ /* We may have multiple marker views, but each marker view should only be associated with one timeaxisview */
+ typedef std::list<MarkerTimeAxis*> MarkerTimeAxisList ;
+ MarkerTimeAxisList marker_time_axis_list;
+
+ /* the TimeAxis view helper */
+ ImageFrameTimeAxisView *view ;
+
+ // popup menu widgets
+ Gtk::Menu *image_action_menu ;
+ Gtk::Menu *imageframe_menu ;
+ Gtk::Menu *imageframe_item_menu ;
+
+}; /* class ImageFrameTimeAxis */
+
+#endif /* __ardour_imageframe_time_axis_h__ */
+
diff --git a/gtk2_ardour/imageframe_time_axis_group.cc b/gtk2_ardour/imageframe_time_axis_group.cc
new file mode 100644
index 0000000000..228ce8bb2c
--- /dev/null
+++ b/gtk2_ardour/imageframe_time_axis_group.cc
@@ -0,0 +1,461 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+
+#include <gtk--.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include "imageframe_time_axis_group.h"
+#include "imageframe_time_axis_view.h"
+#include "imageframe_view.h"
+#include "imageframe_time_axis.h"
+#include "canvas-simplerect.h"
+#include "region_selection.h"
+#include "public_editor.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR ;
+
+//---------------------------------------------------------------------------------------//
+// Constructor / Desctructor
+
+/**
+ * Constructs a new ImageFrameTimeAxisGroup.
+ *
+ * @param iftav the parent ImageFrameTimeAxis of this view helper
+ * @param group_id the unique name/id of this group
+ */
+ImageFrameTimeAxisGroup::ImageFrameTimeAxisGroup(ImageFrameTimeAxisView& iftav, std::string group_id)
+ : _view_helper(iftav), _group_id(group_id)
+{
+ selected_imageframe_item = 0 ;
+ is_selected = false ;
+}
+
+/**
+ * Destructor
+ * Responsible for destroying any Items that may have been added to this group
+ *
+ */
+ImageFrameTimeAxisGroup::~ImageFrameTimeAxisGroup()
+{
+ // Destroy all the ImageFramViews that we have
+ for(ImageFrameViewList::iterator iter = imageframe_views.begin(); iter != imageframe_views.end(); ++iter)
+ {
+ ImageFrameView* ifv = *iter ;
+
+ ImageFrameViewList::iterator next = iter ;
+ next++ ;
+
+ imageframe_views.erase(iter) ;
+
+ delete ifv ;
+ ifv = 0 ;
+
+ iter = next ;
+ }
+
+ GoingAway() ; /* EMIT_SIGNAL */
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Name/Id Accessors/Mutators
+
+/**
+ * Set the name/Id of this group.
+ *
+ * @param new_name the new name of this group
+ * @param src the identity of the object that initiated the change
+ */
+void
+ImageFrameTimeAxisGroup::set_group_name(std::string new_name, void* src)
+{
+ if(_group_id != new_name)
+ {
+ std::string temp_name = _group_id ;
+ _group_id = new_name ;
+ NameChanged(_group_id, temp_name, src) ; /* EMIT_SIGNAL */
+ }
+}
+
+/**
+ * Returns the id of this group
+ * The group id must be unique upon a time axis
+ *
+ * @return the id of this group
+ */
+std::string
+ImageFrameTimeAxisGroup::get_group_name() const
+{
+ return(_group_id) ;
+}
+
+
+//---------------------------------------------------------------------------------------//
+// ui methods & data
+
+/**
+ * Sets the height of the time axis view and the item upon it
+ *
+ * @param height the new height
+ */
+int
+ImageFrameTimeAxisGroup::set_item_heights(gdouble h)
+{
+ /* limit the values to something sane-ish */
+ if (h < 10.0 || h > 1000.0)
+ {
+ return(-1) ;
+ }
+
+ // set the heights of all the imaeg frame views within the group
+ for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); ++citer)
+ {
+ (*citer)->set_height(h) ;
+ }
+
+ return(0) ;
+}
+
+/**
+ * Sets the current samples per unit.
+ * this method tells each item upon the time axis of the change
+ *
+ * @param spu the new samples per canvas unit value
+ */
+int
+ImageFrameTimeAxisGroup::set_item_samples_per_units(gdouble spp)
+{
+ if(spp < 1.0)
+ {
+ return(-1) ;
+ }
+
+ for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); ++citer)
+ {
+ (*citer)->set_samples_per_unit(spp) ;
+ }
+
+ return(0) ;
+}
+
+/**
+ * Sets the color of the items contained uopn this view helper
+ *
+ * @param color the new base color
+ */
+void
+ImageFrameTimeAxisGroup::apply_item_color(GdkColor& color)
+{
+ region_color = color ;
+ for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); citer++)
+ {
+ (*citer)->set_color (region_color) ;
+ }
+}
+
+
+
+//---------------------------------------------------------------------------------------//
+// child ImageFrameView methods
+
+/**
+ * Adds an ImageFrameView to the list of items upon this time axis view helper
+ * the new ImageFrameView is returned
+ *
+ * @param item_id the unique id of the new item
+ * @param image_id the id/name of the image data we are usin
+ * @param start the position the new item should be placed upon the time line
+ * @param duration the duration the new item should be placed upon the timeline
+ * @param rgb_data the rgb data of the image
+ * @param width the original image width of the rgb_data (not the size to display)
+ * @param height the irigianl height of the rgb_data
+ * @param num_channels the number of channles within the rgb_data
+ * @param src the identity of the object that initiated the change
+ */
+ImageFrameView*
+ImageFrameTimeAxisGroup::add_imageframe_item(std::string frame_id, jack_nframes_t start, jack_nframes_t duration, unsigned char* rgb_data, uint32_t width, uint32_t height, uint32_t num_channels, void* src)
+{
+ ImageFrameView* ifv = 0 ;
+
+ //check that there is not already an imageframe with that id
+ if(get_named_imageframe_item(frame_id) == 0)
+ {
+ ifv = new ImageFrameView(frame_id,
+ GTK_CANVAS_GROUP(_view_helper.canvas_item()),
+ &(_view_helper.trackview()),
+ this,
+ _view_helper.trackview().editor.get_current_zoom(),
+ region_color,
+ start,
+ duration,
+ rgb_data,
+ width,
+ height,
+ num_channels) ;
+
+ imageframe_views.push_front(ifv) ;
+
+ ifv->GoingAway.connect(bind(slot (*this,&ImageFrameTimeAxisGroup::remove_imageframe_item), (void*)this)) ;
+
+ ImageFrameAdded(ifv, src) ; /* EMIT_SIGNAL */
+ }
+
+ return(ifv) ;
+}
+
+
+/**
+ * Returns the named ImageFrameView or 0 if the named view does not exist on this view helper
+ *
+ * @param item_id the unique id of the item to search for
+ * @return the named ImageFrameView, or 0 if it is not held upon this view
+ */
+ImageFrameView*
+ImageFrameTimeAxisGroup::get_named_imageframe_item(std::string frame_id)
+{
+ ImageFrameView* ifv = 0 ;
+
+ for (ImageFrameViewList::const_iterator i = imageframe_views.begin(); i != imageframe_views.end(); ++i)
+ {
+ if (((ImageFrameView*)*i)->get_item_name() == frame_id)
+ {
+ ifv = ((ImageFrameView*)*i) ;
+ break ;
+ }
+ }
+ return(ifv) ;
+}
+
+/**
+ * Removes the currently selected ImageFrameView
+ *
+ * @param src the identity of the object that initiated the change
+ * @todo need to remoev this, the selected item within group is no longer
+ * used in favour of a time axis selected item
+ * @see add_imageframe_view
+ */
+void
+ImageFrameTimeAxisGroup::remove_selected_imageframe_item(void* src)
+{
+ std::string frame_id ;
+
+ if(selected_imageframe_item)
+ {
+ ImageFrameViewList::iterator i ;
+
+ if((i = find(imageframe_views.begin(), imageframe_views.end(), selected_imageframe_item)) != imageframe_views.end())
+ {
+ imageframe_views.erase(i) ;
+ frame_id = selected_imageframe_item->get_item_name() ;
+
+ // note that we delete the item here
+ delete(selected_imageframe_item) ;
+ selected_imageframe_item = 0 ;
+
+ std::string track_id = _view_helper.trackview().name() ;
+ ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */
+ }
+ }
+ else
+ {
+ //cerr << "No Selected ImageFrame" << endl ;
+ }
+}
+
+
+/**
+ * Removes and returns the named ImageFrameView from the list of ImageFrameViews held by this view helper
+ *
+ * @param item_id the ImageFrameView unique id to remove
+ * @param src the identity of the object that initiated the change
+ * @see add_imageframe_view
+ */
+ImageFrameView*
+ImageFrameTimeAxisGroup::remove_named_imageframe_item(std::string frame_id, void* src)
+{
+ ImageFrameView* removed = 0 ;
+
+ for(ImageFrameViewList::iterator iter = imageframe_views.begin(); iter != imageframe_views.end(); ++iter)
+ {
+ ImageFrameView* tempItem = *iter ;
+ if(tempItem->get_item_name() == frame_id)
+ {
+ removed = tempItem ;
+ imageframe_views.erase(iter) ;
+
+ if (removed == selected_imageframe_item)
+ {
+ selected_imageframe_item = 0 ;
+ }
+
+ std::string track_id = _view_helper.trackview().name() ;
+ ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */
+
+ // break from the for loop
+ break ;
+ }
+ iter++ ;
+ }
+
+ return(removed) ;
+}
+
+/**
+ * Removes ifv from the list of ImageFrameViews upon this TimeAxis.
+ * if ifv is not upon this TimeAxis, this method takes no action
+ *
+ * @param ifv the ImageFrameView to remove
+ */
+void
+ImageFrameTimeAxisGroup::remove_imageframe_item(ImageFrameView* ifv, void* src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameTimeAxisGroup::remove_imageframe_item), ifv, src));
+
+ ImageFrameViewList::iterator i;
+ if((i = find (imageframe_views.begin(), imageframe_views.end(), ifv)) != imageframe_views.end())
+ {
+ imageframe_views.erase(i) ;
+
+ std::string frame_id = ifv->get_item_name() ;
+ std::string track_id = _view_helper.trackview().name() ;
+ ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */
+ }
+}
+
+//---------------------------------------------------------------------------------------//
+// Selected group methods
+
+/**
+ * Sets the currently selected item upon this time axis
+ *
+ * @param ifv the item to set selected
+ */
+//void
+//ImageFrameTimeAxisGroup::set_selected_imageframe_item(ImageFrameView* ifv)
+//{
+// if(selected_imageframe_item)
+// {
+// selected_imageframe_item->set_selected(false, this) ;
+// }
+//
+// selected_imageframe_item = ifv ;
+//
+// if(!ifv->get_selected())
+// {
+// selected_imageframe_item->set_selected(true, this) ;
+// }
+//}
+
+
+/**
+ * Sets the currently selected item upon this time axis to the named item
+ *
+ * @param item_id the name/id of the item to set selected
+ */
+//void
+//ImageFrameTimeAxisGroup::set_selected_imageframe_item(std::string frame_id)
+//{
+// selected_imageframe_item = get_named_imageframe_item(frame_id) ;
+//}
+
+
+/**
+ * Returns the currently selected item upon this time axis
+ *
+ * @return the currently selected item pon this time axis
+ */
+// ImageFrameView*
+// ImageFrameTimeAxisGroup::get_selected_imageframe_item()
+// {
+ // return(selected_imageframe_item) ;
+// }
+
+
+
+/**
+ * Returns whether this grou pis currently selected
+ *
+ * @returns true if this group is currently selected
+ */
+bool
+ImageFrameTimeAxisGroup::get_selected() const
+{
+ return(is_selected) ;
+}
+
+
+/**
+ * Sets he selected state of this group
+ *
+ * @param yn set true if this group is selected, false otherwise
+ */
+void
+ImageFrameTimeAxisGroup::set_selected(bool yn)
+{
+ is_selected = yn ;
+}
+
+
+
+//---------------------------------------------------------------------------------------//
+// Handle time axis removal
+
+/**
+ * Handles the Removal of this VisualTimeAxis
+ * This _needs_ to be called to alert others of the removal properly, ie where the source
+ * of the removal came from.
+ *
+ * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method
+ * just now to capture the source of the removal
+ *
+ * @param src the identity of the object that initiated the change
+ */
+void
+ImageFrameTimeAxisGroup::remove_this_group(void* src)
+{
+ /*
+ defer to idle loop, otherwise we'll delete this object
+ while we're still inside this function ...
+ */
+ Gtk::Main::idle.connect(bind(slot(&ImageFrameTimeAxisGroup::idle_remove_this_group), this, src));
+}
+
+/**
+ * Callback used to remove this group during the gtk idle loop
+ * This is used to avoid deleting the obejct while inside the remove_this_group
+ * method
+ *
+ * @param group the ImageFrameTimeAxisGroup to remove
+ * @param src the identity of the object that initiated the change
+ */
+gint
+ImageFrameTimeAxisGroup::idle_remove_this_group(ImageFrameTimeAxisGroup* group, void* src)
+{
+ delete group ;
+ group = 0 ;
+ group->GroupRemoved(group->get_group_name(), src) ; /* EMIT_SIGNAL */
+ return(false) ;
+}
+
diff --git a/gtk2_ardour/imageframe_time_axis_group.h b/gtk2_ardour/imageframe_time_axis_group.h
new file mode 100644
index 0000000000..18731acbb8
--- /dev/null
+++ b/gtk2_ardour/imageframe_time_axis_group.h
@@ -0,0 +1,299 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_imageframe_time_axis_group_h__
+#define __ardour_imageframe_time_axis_group_h__
+
+#include <list>
+#include <cmath>
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <jack/jack.h>
+#include "imageframe_time_axis_view.h"
+
+class PublicEditor ;
+class ImageFrameView ;
+
+/**
+ * ImageFrameTimeAxisGroup defines a group/scene of ImageFrame view that can appear upon a time axis
+ * At the moment this is a bit bare, we really want to add some kind of time constraints upon
+ * items atht are added to the group, ie bounded by the start and end of the scene, which itself
+ * needs fleshed out.
+ * A viewable object may also be useful...
+ *
+ */
+class ImageFrameTimeAxisGroup : public SigC::Object
+{
+ public:
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * Constructs a new ImageFrameTimeAxisGroup.
+ *
+ * @param iftav the parent ImageFrameTimeAxis of this view helper
+ * @param group_id the unique name/id of this group
+ */
+ ImageFrameTimeAxisGroup(ImageFrameTimeAxisView& iftav, std::string group_id) ;
+
+ /**
+ * Destructor
+ * Responsible for destroying any Items that may have been added to this group
+ *
+ */
+ virtual ~ImageFrameTimeAxisGroup() ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Name/Id Accessors/Mutators
+
+ /**
+ * Set the name/Id of this group.
+ *
+ * @param new_name the new name of this group
+ * @param src the identity of the object that initiated the change
+ */
+ void set_group_name(std::string new_name, void* src) ;
+
+ /**
+ * Returns the id of this group
+ * The group id must be unique upon a time axis
+ *
+ * @return the id of this group
+ */
+ std::string get_group_name() const ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Parent/Child helper object accessors
+
+ /**
+ * Returns the TimeAxisView thatt his object is acting as a helper for
+ *
+ * @return the TimeAxisView that this object is acting as a view helper for
+ */
+ ImageFrameTimeAxisView& get_view() const { return _view_helper ; }
+
+
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods & data
+
+ /**
+ * Sets the height of the time axis view and the item upon it
+ *
+ * @param height the new height
+ */
+ int set_item_heights(gdouble) ;
+
+ /**
+ * Sets the current samples per unit.
+ * this method tells each item upon the time axis of the change
+ *
+ * @param spu the new samples per canvas unit value
+ */
+ int set_item_samples_per_units(gdouble spu) ;
+
+ /**
+ * Sets the color of the items contained uopn this view helper
+ *
+ * @param color the new base color
+ */
+ void apply_item_color(GdkColor&) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // child ImageFrameView methods
+
+ /**
+ * Adds an ImageFrameView to the list of items upon this time axis view helper
+ * the new ImageFrameView is returned
+ *
+ * @param item_id the unique id of the new item
+ * @param image_id the id/name of the image data we are usin
+ * @param start the position the new item should be placed upon the time line
+ * @param duration the duration the new item should be placed upon the timeline
+ * @param rgb_data the rgb data of the image
+ * @param width the original image width of the rgb_data (not the size to display)
+ * @param height the irigianl height of the rgb_data
+ * @param num_channels the number of channles within the rgb_data
+ * @param src the identity of the object that initiated the change
+ */
+ ImageFrameView* add_imageframe_item(std::string item_id, jack_nframes_t start, jack_nframes_t duration, unsigned char* rgb_data, uint32_t width, uint32_t height, uint32_t num_channels, void* src) ;
+
+ /**
+ * Returns the named ImageFrameView or 0 if the named view does not exist on this view helper
+ *
+ * @param item_id the unique id of the item to search for
+ * @return the named ImageFrameView, or 0 if it is not held upon this view
+ */
+ ImageFrameView* get_named_imageframe_item(std::string item_id) ;
+
+ /**
+ * Removes the currently selected ImageFrameView
+ *
+ * @param src the identity of the object that initiated the change
+ * @see add_imageframe_view
+ */
+ void remove_selected_imageframe_item(void* src) ;
+
+ /**
+ * Removes and returns the named ImageFrameView from the list of ImageFrameViews held by this view helper
+ *
+ * @param item_id the ImageFrameView unique id to remove
+ * @param src the identity of the object that initiated the change
+ * @see add_imageframe_view
+ */
+ ImageFrameView* remove_named_imageframe_item(std::string item_id, void* src) ;
+
+ /**
+ * Removes ifv from the list of ImageFrameViews upon this TimeAxis.
+ * if ifv is not upon this TimeAxis, this method takes no action
+ *
+ * @param ifv the ImageFrameView to remove
+ */
+ void remove_imageframe_item(ImageFrameView*, void* src) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Selected group methods
+
+
+ // removed in favour of a track level selectewd item
+ // this is simply easier to manage a singularly selected item, rather than
+ // a selected item within each group
+
+ /**
+ * Sets the currently selected item upon this time axis
+ *
+ * @param ifv the item to set selected
+ */
+ //void set_selected_imageframe_item(ImageFrameView* ifv) ;
+
+ /**
+ * Sets the currently selected item upon this time axis to the named item
+ *
+ * @param item_id the name/id of the item to set selected
+ */
+ //void set_selected_imageframe_item(std::string item_id) ;
+
+ /**
+ * Returns the currently selected item upon this time axis
+ *
+ * @return the currently selected item pon this time axis
+ */
+ //ImageFrameView* get_selected_imageframe_item() ;
+
+ /**
+ * Returns whether this grou pis currently selected
+ *
+ * @returns true if this group is currently selected
+ */
+ bool get_selected() const ;
+
+ /**
+ * Sets he selected state of this group
+ *
+ * @param yn set true if this group is selected, false otherwise
+ */
+ void set_selected(bool yn) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Handle group removal
+
+ /**
+ * Handles the Removal of this VisualTimeAxis
+ * This _needs_ to be called to alert others of the removal properly, ie where the source
+ * of the removal came from.
+ *
+ * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method
+ * just now to capture the source of the removal
+ *
+ * @param src the identity of the object that initiated the change
+ */
+ virtual void remove_this_group(void* src) ;
+
+ //---------------------------------------------------------------------------------//
+ // Emitted Signals
+
+ SigC::Signal0<void> GoingAway ;
+
+ /**
+ * Emitted when this Group has been removed
+ * This is different to the GoingAway signal in that this signal
+ * is emitted during the deletion of this Time Axis, and not during
+ * the destructor, this allows us to capture the source of the deletion
+ * event
+ */
+ SigC::Signal2<void,std::string,void*> GroupRemoved ;
+
+ /** Emitted when we have changed the name of this TimeAxis */
+ SigC::Signal3<void,std::string,std::string,void*> NameChanged ;
+
+ /** Emitted when an ImageFrameView is added to this group */
+ SigC::Signal2<void, ImageFrameView*, void*> ImageFrameAdded ;
+
+ /** Emitted when an ImageFrameView is removed from this group */
+ SigC::Signal4<void, std::string&, std::string&, std::string&, void*> ImageFrameRemoved ;
+
+ protected:
+
+
+ private:
+ /**
+ * convenience method to re-get the samples per unit and tell items upon this view
+ *
+ */
+ void reset_samples_per_unit() ;
+
+ /**
+ * Callback used to remove this group during the gtk idle loop
+ * This is used to avoid deleting the obejct while inside the remove_this_group
+ * method
+ *
+ * @param group the ImageFrameTimeAxisGroup to remove
+ * @param src the identity of the object that initiated the change
+ */
+ static gint idle_remove_this_group(ImageFrameTimeAxisGroup* group, void* src) ;
+
+ /** The list of ImageFrameViews held by this view helper */
+ typedef std::list<ImageFrameView *> ImageFrameViewList ;
+ ImageFrameViewList imageframe_views ;
+
+ /** the currently selected time axis item upon this time axis */
+ ImageFrameView* selected_imageframe_item ;
+
+ /** the view helper that this object is acting as a container upon on */
+ ImageFrameTimeAxisView& _view_helper ;
+
+ /** the is of this group */
+ std::string _group_id ;
+
+ /* XXX why are these different? */
+ GdkColor region_color ;
+ uint32_t stream_base_color ;
+
+ /** indicates if this group is currently selected */
+ bool is_selected ;
+
+} ; /* class ImageFrameTimeAxisGroup */
+
+#endif /* __ardour_imageframe_time_axis_group_h__ */
diff --git a/gtk2_ardour/imageframe_time_axis_view.cc b/gtk2_ardour/imageframe_time_axis_view.cc
new file mode 100644
index 0000000000..20ccb7d61f
--- /dev/null
+++ b/gtk2_ardour/imageframe_time_axis_view.cc
@@ -0,0 +1,460 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+
+#include <gtk--.h>
+
+#include <gtkmmext/gtk_ui.h>
+
+#include "imageframe_time_axis_view.h"
+#include "imageframe_time_axis_group.h"
+#include "imageframe_view.h"
+#include "imageframe_time_axis.h"
+#include "canvas-simplerect.h"
+#include "region_selection.h"
+#include "public_editor.h"
+#include "rgb_macros.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR ;
+using namespace Editing;
+
+//---------------------------------------------------------------------------------------//
+// Constructor / Desctructor
+
+/**
+ * Constructs a new ImageFrameTimeAxisView.
+ *
+ * @param ifta the parent ImageFrameTimeAxis of this view helper
+ */
+ImageFrameTimeAxisView::ImageFrameTimeAxisView (ImageFrameTimeAxis& tv)
+ : _trackview (tv)
+{
+ region_color = _trackview.color() ;
+ stream_base_color = color_map[cImageTrackBase] ;
+
+ canvas_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(_trackview.canvas_display), gtk_canvas_group_get_type (), 0) ;
+
+ canvas_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 1000000.0,
+ "y2", (double) tv.height,
+ "outline_color_rgba", color_map[cImageTrackOutline],
+ "fill_color_rgba", stream_base_color,
+ 0) ;
+
+ gtk_signal_connect(GTK_OBJECT(canvas_rect), "event", (GtkSignalFunc) PublicEditor::canvas_imageframe_view_event, &_trackview) ;
+
+ _samples_per_unit = _trackview.editor.get_current_zoom() ;
+
+ _trackview.editor.ZoomChanged.connect (slot (*this, &ImageFrameTimeAxisView::reset_samples_per_unit)) ;
+
+ selected_imageframe_group = 0 ;
+ selected_imageframe_view = 0 ;
+}
+
+/**
+ * Destructor
+ * Responsible for destroying all items tat may have been added to this time axis
+ */
+ImageFrameTimeAxisView::~ImageFrameTimeAxisView()
+{
+ // Destroy all the ImageFrameGroups that we have
+
+ for(ImageFrameGroupList::iterator iter = imageframe_groups.begin(); iter != imageframe_groups.end(); ++iter)
+ {
+ ImageFrameTimeAxisGroup* iftag = (*iter) ;
+
+ ImageFrameGroupList::iterator next = iter ;
+ next++ ;
+
+ // remove the front element
+ imageframe_groups.erase(iter) ;
+
+ delete iftag ;
+ iftag = 0 ;
+
+ iter = next ;
+ }
+
+ // Destroy all our canvas components
+ if(canvas_rect)
+ {
+ gtk_object_destroy(GTK_OBJECT(canvas_rect)) ;
+ canvas_rect = 0 ;
+ }
+
+ if(canvas_group)
+ {
+ gtk_object_destroy(GTK_OBJECT(canvas_group));
+ canvas_group = 0 ;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// ui methods & data
+
+/**
+ * Sets the height of the time axis view and the item upon it
+ *
+ * @param height the new height
+ */
+int
+ImageFrameTimeAxisView::set_height (gdouble h)
+{
+ /* limit the values to something sane-ish */
+ if (h < 10.0 || h > 1000.0)
+ {
+ return(-1) ;
+ }
+
+ if(canvas_rect != 0)
+ {
+ gtk_object_set(GTK_OBJECT(canvas_rect), "y2", h, NULL) ;
+ }
+
+ for(ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); ++citer)
+ {
+ (*citer)->set_item_heights(h) ;
+ }
+
+ return(0) ;
+}
+
+/**
+ * Sets the position of this view helper on the canvas
+ *
+ * @param x the x position upon the canvas
+ * @param y the y position npon the canvas
+ */
+int
+ImageFrameTimeAxisView::set_position (gdouble x, gdouble y)
+
+{
+ gtk_canvas_item_set (canvas_group, "x", x, "y", y, NULL);
+ return 0;
+}
+
+/**
+ * Sets the current samples per unit.
+ * this method tells each item upon the time axis of the change
+ *
+ * @param spu the new samples per canvas unit value
+ */
+int
+ImageFrameTimeAxisView::set_samples_per_unit (gdouble spp)
+{
+ if (spp < 1.0) {
+ return(-1) ;
+ }
+
+ _samples_per_unit = spp;
+
+ for(ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); ++citer)
+ {
+ (*citer)->set_item_samples_per_units(spp) ;
+ }
+
+ return(0) ;
+}
+
+/**
+ * Sets the color of the items contained uopn this view helper
+ *
+ * @param color the new base color
+ */
+void
+ImageFrameTimeAxisView::apply_color(GdkColor& color)
+{
+ region_color = color ;
+ for(ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); citer++)
+ {
+ (*citer)->apply_item_color(region_color) ;
+ }
+}
+
+
+/**
+ * convenience method to re-get the samples per unit and tell items upon this view
+ *
+ */
+void
+ImageFrameTimeAxisView::reset_samples_per_unit ()
+{
+ set_samples_per_unit (_trackview.editor.get_current_zoom());
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Child ImageFrameTimeAxisGroup Accessors/Mutators
+
+/**
+ * Adds an ImageFrameTimeAxisGroup to the list of items upon this time axis view helper
+ * the new ImageFrameTimeAxisGroup is returned
+ *
+ * @param group_id the unique id of the new group
+ * @param src the identity of the object that initiated the change
+ */
+ImageFrameTimeAxisGroup*
+ImageFrameTimeAxisView::add_imageframe_group(std::string group_id, void* src)
+{
+ ImageFrameTimeAxisGroup* iftag = 0 ;
+
+ //check that there is not already a group with that id
+ if(get_named_imageframe_group(group_id) != 0)
+ {
+ // iftag = 0 ;
+ }
+ else
+ {
+ iftag = new ImageFrameTimeAxisGroup(*this, group_id) ;
+
+ imageframe_groups.push_front(iftag) ;
+
+ iftag->GoingAway.connect(bind(slot (*this,&ImageFrameTimeAxisView::remove_imageframe_group), iftag, (void*)this)) ;
+
+ ImageFrameGroupAdded(iftag, src) ; /* EMIT_SIGNAL */
+ }
+
+ return(iftag) ;
+}
+
+/**
+ * Returns the named ImageFrameTimeAxisGroup or 0 if the named group does not exist on this view helper
+ *
+ * @param group_id the unique id of the group to search for
+ * @return the named ImageFrameTimeAxisGroup, or 0 if it is not held upon this view
+ */
+ImageFrameTimeAxisGroup*
+ImageFrameTimeAxisView::get_named_imageframe_group(std::string group_id)
+{
+ ImageFrameTimeAxisGroup* iftag = 0 ;
+
+ for(ImageFrameGroupList::iterator i = imageframe_groups.begin(); i != imageframe_groups.end(); ++i)
+ {
+ if (((ImageFrameTimeAxisGroup*)*i)->get_group_name() == group_id)
+ {
+ iftag = ((ImageFrameTimeAxisGroup*)*i) ;
+ break ;
+ }
+ }
+
+ return(iftag) ;
+}
+
+
+/**
+ * Removes and returns the named ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroup held by this view helper
+ *
+ * @param group_id the ImageFrameTimeAxisGroup unique id to remove
+ * @param src the identity of the object that initiated the change
+ * @see add_imageframe_group
+ */
+ImageFrameTimeAxisGroup*
+ImageFrameTimeAxisView::remove_named_imageframe_group(std::string group_id, void* src)
+{
+ ImageFrameTimeAxisGroup* removed = 0 ;
+
+ for(ImageFrameGroupList::iterator iter = imageframe_groups.begin(); iter != imageframe_groups.end(); ++iter)
+ {
+ if(((ImageFrameTimeAxisGroup*)*iter)->get_group_name() == group_id)
+ {
+ removed = (*iter) ;
+ imageframe_groups.erase(iter) ;
+
+ if(removed == selected_imageframe_group)
+ {
+ selected_imageframe_group = 0 ;
+ }
+
+ ImageFrameGroupRemoved(removed->get_group_name(), src) ; /* EMIT_SIGNAL */
+
+ // break from the for loop
+ break ;
+ }
+ iter++ ;
+ }
+
+ return(removed) ;
+}
+
+
+/**
+ * Removes the specified ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroups upon this TimeAxis.
+ *
+ * @param iftag the ImageFrameView to remove
+ */
+void
+ImageFrameTimeAxisView::remove_imageframe_group(ImageFrameTimeAxisGroup* iftag, void* src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameTimeAxisView::remove_imageframe_group), iftag, src));
+
+ ImageFrameGroupList::iterator i;
+ if((i = find (imageframe_groups.begin(), imageframe_groups.end(), iftag)) != imageframe_groups.end())
+ {
+ imageframe_groups.erase(i) ;
+
+ ImageFrameGroupRemoved(iftag->get_group_name(), src) ; /* EMIT_SIGNAL */
+ }
+}
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// Selected group methods
+
+/**
+ * Sets the currently selected group upon this time axis
+ *
+ * @param ifv the item to set selected
+ */
+void
+ImageFrameTimeAxisView::set_selected_imageframe_group(ImageFrameTimeAxisGroup* iftag)
+{
+ if(selected_imageframe_group)
+ {
+ selected_imageframe_group->set_selected(false) ;
+ }
+
+ selected_imageframe_group = iftag ;
+ selected_imageframe_group->set_selected(true) ;
+}
+
+/**
+ * Clears the currently selected image frame group unpo this time axis
+ *
+*/
+void
+ImageFrameTimeAxisView::clear_selected_imageframe_group()
+{
+ if(selected_imageframe_group)
+ {
+ selected_imageframe_group->set_selected(false) ;
+ }
+ selected_imageframe_group = 0 ;
+}
+
+/**
+ * Returns the currently selected group upon this time axis
+ *
+ * @return the currently selected group upon this time axis
+ */
+ImageFrameTimeAxisGroup*
+ImageFrameTimeAxisView::get_selected_imageframe_group() const
+{
+ return(selected_imageframe_group) ;
+}
+
+//---------------------------------------------------------------------------------------//
+// Selected item methods
+
+/**
+ * Sets the currently selected imag frame view item
+ *
+ * @param iftag the group the selected item is part
+ * @param ifv the selected item
+ */
+void
+ImageFrameTimeAxisView::set_selected_imageframe_view(ImageFrameTimeAxisGroup* iftag, ImageFrameView* ifv)
+{
+ set_selected_imageframe_group(iftag) ;
+
+ if(selected_imageframe_view)
+ {
+ selected_imageframe_view->set_selected(false, this) ;
+ }
+
+ selected_imageframe_view = ifv ;
+ selected_imageframe_view->set_selected(true, this) ;
+}
+
+/**
+ * Clears the currently selected image frame view item
+ *
+ */
+void
+ImageFrameTimeAxisView::clear_selected_imageframe_item(bool clear_group)
+{
+ if(clear_group)
+ {
+ clear_selected_imageframe_group() ;
+ }
+
+ if(selected_imageframe_view)
+ {
+ selected_imageframe_view->set_selected(false, this) ;
+ }
+ selected_imageframe_view = 0 ;
+}
+
+/**
+ * Returns the currently selected image frame view item upon this time axis
+ *
+ * @return the currently selected image frame view item
+ */
+ImageFrameView*
+ImageFrameTimeAxisView::get_selected_imageframe_view() const
+{
+ return(selected_imageframe_view) ;
+}
+
+
+
+
+void
+ImageFrameTimeAxisView::set_imageframe_duration_sec(double sec)
+{
+ if(selected_imageframe_group && selected_imageframe_view)
+ {
+ selected_imageframe_view->set_duration((jack_nframes_t) (sec * _trackview.editor.current_session()->frame_rate()), this) ;
+ }
+}
+
+
+
+/**
+ * Removes the currently selected ImageFrame view item
+ *
+ * @param src the identity of the object that initiated the change
+ * @see add_imageframe_group
+ */
+void
+ImageFrameTimeAxisView::remove_selected_imageframe_item(void* src)
+{
+ if(selected_imageframe_group && selected_imageframe_view)
+ {
+ ImageFrameView* temp_item = selected_imageframe_view ;
+ selected_imageframe_group->remove_imageframe_item(temp_item, src) ;
+
+ // XXX although we have removed the item from the group, we need the group id still set within the
+ // item as the remove method requires this data when telling others about the deletion
+ // to fully specify the item we need the track, group and item id
+ selected_imageframe_view->remove_this_item(src) ;
+ clear_selected_imageframe_item(false) ;
+ }
+}
+
diff --git a/gtk2_ardour/imageframe_time_axis_view.h b/gtk2_ardour/imageframe_time_axis_view.h
new file mode 100644
index 0000000000..41c111fdc2
--- /dev/null
+++ b/gtk2_ardour/imageframe_time_axis_view.h
@@ -0,0 +1,271 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_imageframe_time_axis_view_h__
+#define __ardour_imageframe_time_axis_view_h__
+
+#include <list>
+#include <cmath>
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <jack/jack.h>
+
+class PublicEditor ;
+class ImageFrameTimeAxis ;
+class ImageFrameView ;
+class ImageFrameTimeAxisGroup ;
+
+/**
+ * ImageFrameTimeAxisView defines the time axis view helper
+ * This object is responsible for the time axis canvas view, and
+ * maintains the list of items that have been added to it
+ *
+ */
+class ImageFrameTimeAxisView : public SigC::Object
+{
+ public:
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * Constructs a new ImageFrameTimeAxisView.
+ *
+ * @param ifta the parent ImageFrameTimeAxis of this view helper
+ */
+ ImageFrameTimeAxisView(ImageFrameTimeAxis& ifta) ;
+
+ /**
+ * Destructor
+ * Responsible for destroying all items tat may have been added to this time axis
+ */
+ ~ImageFrameTimeAxisView () ;
+
+ //---------------------------------------------------------------------------------------//
+ // Parent/Child helper object accessors
+
+ /**
+ * Returns the TimeAxisView thatt his object is acting as a helper for
+ *
+ * @return the TimeAxisView that this object is acting as a view helper for
+ */
+ ImageFrameTimeAxis& trackview() { return _trackview; }
+
+ /**
+ *
+ */
+ GtkCanvasItem* canvas_item() { return canvas_group; }
+
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods & data
+
+ /**
+ * Sets the height of the time axis view and the item upon it
+ *
+ * @param height the new height
+ */
+ int set_height(gdouble) ;
+
+ /**
+ * Sets the position of this view helper on the canvas
+ *
+ * @param x the x position upon the canvas
+ * @param y the y position upon the canvas
+ */
+ int set_position(gdouble x, gdouble y) ;
+
+ /**
+ * Sets the current samples per unit.
+ * this method tells each item upon the time axis of the change
+ *
+ * @param spu the new samples per canvas unit value
+ */
+ int set_samples_per_unit(gdouble spu) ;
+
+ /**
+ * Returns the current samples per unit of this time axis view helper
+ *
+ * @return the current samples per unit of this time axis view helper
+ */
+ gdouble get_samples_per_unit() { return _samples_per_unit; }
+
+ /**
+ * Sets the color of the items contained uopn this view helper
+ *
+ * @param color the new base color
+ */
+ void apply_color (GdkColor&) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Child ImageFrameTimeAxisGroup Accessors/Mutators
+
+ /**
+ * Adds an ImageFrameTimeAxisGroup to the list of items upon this time axis view helper
+ * the new ImageFrameTimeAxisGroup is returned
+ *
+ * @param group_id the unique id of the new group
+ * @param src the identity of the object that initiated the change
+ */
+ ImageFrameTimeAxisGroup* add_imageframe_group(std::string group_id, void* src) ;
+
+ /**
+ * Returns the named ImageFrameTimeAxisGroup or 0 if the named group does not exist on this view helper
+ *
+ * @param group_id the unique id of the group to search for
+ * @return the named ImageFrameTimeAxisGroup, or 0 if it is not held upon this view
+ */
+ ImageFrameTimeAxisGroup* get_named_imageframe_group(std::string group_id) ;
+
+ /**
+ * Removes and returns the named ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroup held by this view helper
+ *
+ * @param group_id the ImageFrameTimeAxisGroup unique id to remove
+ * @param src the identity of the object that initiated the change
+ * @see add_imageframe_group
+ */
+ ImageFrameTimeAxisGroup* remove_named_imageframe_group(std::string group_id, void* src) ;
+
+ /**
+ * Removes the specified ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroups upon this TimeAxis.
+ *
+ * @param iftag the ImageFrameView to remove
+ */
+ void remove_imageframe_group(ImageFrameTimeAxisGroup* iftag, void* src) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Selected group methods
+
+ /**
+ * Sets the currently selected group upon this time axis
+ *
+ * @param ifv the item to set selected
+ */
+ void set_selected_imageframe_group(ImageFrameTimeAxisGroup* iftag) ;
+
+ /**
+ * Clears the currently selected image frame group unpo this time axis
+ *
+ */
+ void clear_selected_imageframe_group() ;
+
+ /**
+ * Returns the currently selected group upon this time axis
+ *
+ * @return the currently selected group upon this time axis
+ */
+ ImageFrameTimeAxisGroup* get_selected_imageframe_group() const ;
+
+
+ /**
+ * Sets the duration of the selected ImageFrameView to the specified number of seconds
+ *
+ * @param sec the duration to set the ImageFrameView to, in seconds
+ */
+ void set_imageframe_duration_sec(double sec) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Selected item methods
+
+ /**
+ * Sets the currently selected image frame view item
+ *
+ * @param iftag the group the selected item is part
+ * @param ifv the selected item
+ */
+ void set_selected_imageframe_view(ImageFrameTimeAxisGroup* iftag, ImageFrameView* ifv) ;
+
+ /**
+ * Clears the currently selected image frame view item
+ *
+ * @param clear_group set true if the selected parent group of the item should be cleared also
+ */
+ void clear_selected_imageframe_item(bool clear_group) ;
+
+ /**
+ * Returns the currently selected image frame view item upon this time axis
+ *
+ * @return the currently selected image frame view item
+ */
+ ImageFrameView* get_selected_imageframe_view() const ;
+
+
+
+ /**
+ * Removes the currently selected ImageFrameTimeAxisGroup
+ *
+ * @param src the identity of the object that initiated the change
+ * @see add_imageframe_group
+ */
+ void remove_selected_imageframe_item(void* src) ;
+
+
+ //---------------------------------------------------------------------------------//
+ // Emitted Signals
+
+ /** Emitted when and ImageFrameGroup is added to this time axis */
+ SigC::Signal2<void,ImageFrameTimeAxisGroup*,void*> ImageFrameGroupAdded ;
+
+ /** Emitted when an ImageFrameGroup is removed from this time axis */
+ SigC::Signal2<void,std::string,void*> ImageFrameGroupRemoved ;
+
+ protected:
+
+
+ private:
+ /**
+ * convenience method to re-get the samples per unit and tell items upon this view
+ *
+ */
+ void reset_samples_per_unit() ;
+
+ /**
+ * The list of ImageFrameViews held by this view helper */
+ typedef std::list<ImageFrameTimeAxisGroup *> ImageFrameGroupList ;
+ ImageFrameGroupList imageframe_groups ;
+
+ /** the currently selected time axis item upon this time axis */
+ ImageFrameTimeAxisGroup* selected_imageframe_group ;
+
+ /**
+ * thecurrently selected image frame view
+ * we keep this here so that we only have one per view, not one per group
+ */
+ ImageFrameView* selected_imageframe_view ;
+
+
+
+ /* the TimeAxisView that this object is acting as the view helper for */
+ ImageFrameTimeAxis& _trackview ;
+
+ GtkCanvasItem *canvas_group ;
+ GtkCanvasItem *canvas_rect; /* frame around the whole thing */
+
+ /** the current samples per unit */
+ double _samples_per_unit ;
+
+ /* XXX why are these different? */
+ GdkColor region_color ;
+ uint32_t stream_base_color ;
+
+} ; /* class ImageFrameTimeAxisView */
+
+#endif /* __ardour_imageframe_time_axis_view_h__ */
diff --git a/gtk2_ardour/imageframe_view.cc b/gtk2_ardour/imageframe_view.cc
new file mode 100644
index 0000000000..27fe741204
--- /dev/null
+++ b/gtk2_ardour/imageframe_view.cc
@@ -0,0 +1,395 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+#include <cmath>
+
+#include <gtk--.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include "imageframe_time_axis.h"
+#include "imageframe_time_axis_group.h"
+#include "marker_time_axis.h"
+#include "marker_time_axis_view.h"
+#include "canvas-simplerect.h"
+#include "public_editor.h"
+#include "utils.h"
+#include "imageframe_view.h"
+#include "canvas-imageframe.h"
+#include "gui_thread.h"
+
+using namespace SigC ;
+using namespace ARDOUR ;
+
+SigC::Signal1<void,ImageFrameView*> ImageFrameView::GoingAway;
+
+/**
+ * Constructs a new ImageFrameView upon the canvas
+ *
+ * @param item_id unique id of this item
+ * @param parent the parent canvas item
+ * @param tv the time axis view that this item is to be placed upon
+ * @param group the ImageFrameGroup that this item is a member of
+ * @param spu the current samples per canvas unit
+ * @param start the start frame ogf this item
+ * @param duration the duration of this item
+ * @param rgb_data the rgb data of the image
+ * @param width the width of the original rgb_data image data
+ * @param height the width of the origianl rgb_data image data
+ * @param num_channels the number of color channels within rgb_data
+ */
+ImageFrameView::ImageFrameView(std::string item_id,
+ GtkCanvasGroup *parent,
+ ImageFrameTimeAxis* tv,
+ ImageFrameTimeAxisGroup* item_group,
+ double spu,
+ GdkColor& basic_color,
+ jack_nframes_t start,
+ jack_nframes_t duration,
+ unsigned char* rgb_data,
+ uint32_t width,
+ uint32_t height,
+ uint32_t num_channels)
+ : TimeAxisViewItem(item_id, parent, *tv, spu, basic_color, start, duration,
+ TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
+ TimeAxisViewItem::ShowNameHighlight|
+ TimeAxisViewItem::ShowFrame|
+ TimeAxisViewItem::ShowHandles))
+
+{
+ the_parent_group = item_group ;
+ set_name_text(item_id) ;
+
+ image_data_width = width ;
+ image_data_height = height ;
+ image_data_num_channels = num_channels ;
+
+ //This should be art_free'd once the ArtPixBuf is destroyed - this should happen when we destroy the imageframe canvas item
+ unsigned char* the_rgb_data = (unsigned char*) art_alloc(width*height*num_channels) ;
+ memcpy(the_rgb_data, rgb_data, (width*height*num_channels)) ;
+
+ ArtPixBuf* pbuf ;
+ pbuf = art_pixbuf_new_rgba(the_rgb_data, width, height, (num_channels * width));
+ imageframe = 0 ;
+
+ //calculate our image width based on the track height
+ double im_ratio = (double)width/(double)height ;
+ int im_width = (int)((double)(trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE) * im_ratio) ;
+
+ imageframe = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
+ gtk_canvas_imageframe_get_type(),
+ "pixbuf", pbuf,
+ "x", (gdouble) 1.0,
+ "y", (gdouble) 1.0,
+ "anchor", GTK_ANCHOR_NW,
+ "width", (gdouble) im_width,
+ "height", (gdouble) (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE),
+ NULL) ;
+
+
+ gtk_signal_connect (GTK_OBJECT(frame_handle_start), "event",
+ (GtkSignalFunc) PublicEditor::canvas_imageframe_start_handle_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(frame_handle_end), "event",
+ (GtkSignalFunc) PublicEditor::canvas_imageframe_end_handle_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(group), "event",
+ (GtkSignalFunc) PublicEditor::canvas_imageframe_item_view_event, this);
+
+ /* handle any specific details required by the initial start end duration values */
+
+ gtk_canvas_item_raise_to_top(frame_handle_start) ;
+ gtk_canvas_item_raise_to_top(frame_handle_end) ;
+
+ set_position(start, this) ;
+ set_duration(duration, this) ;
+}
+
+/**
+ * Destructor
+ * Reposible for removing and destroying all marker items associated with this item
+ */
+ImageFrameView::~ImageFrameView()
+{
+ GoingAway (this);
+
+ // destroy any marker items we have associated with this item
+
+ for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
+ {
+ MarkerView* mv = (*iter) ;
+
+ MarkerViewList::iterator next = iter ;
+ next++ ;
+
+ // remove the item from our marker list
+ // the current iterator becomes invalid after this point, so we cannot call next upon it
+ // luckily enough, we already have next
+ marker_view_list.erase(iter) ;
+
+ // remove the item from the marker time axis
+ MarkerTimeAxisView* mtav = dynamic_cast<MarkerTimeAxis*>(&mv->get_time_axis_view())->get_view() ;
+ if(mtav)
+ {
+ mtav->remove_marker_view(mv, this) ;
+ }
+
+ mv->set_marked_item(0) ;
+ delete mv ;
+ mv = 0 ;
+
+ // set our iterator to next, as we have invalided the current iterator with the call to erase
+ iter = next ;
+ }
+
+ // if we are the currently selected item withi the parent track, we need to se-select
+ if(the_parent_group)
+ {
+ if(the_parent_group->get_view().get_selected_imageframe_view() == this)
+ {
+ the_parent_group->get_view().clear_selected_imageframe_item(false) ;
+ }
+ }
+
+ if(imageframe)
+ {
+ gtk_object_destroy(GTK_OBJECT(imageframe)) ;
+ imageframe = 0 ;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Position and duration Accessors/Mutators
+
+/**
+ * Set the position of this item to the specified value
+ *
+ * @param pos the new position
+ * @param src the identity of the object that initiated the change
+ * @return true if the position change was a success, false otherwise
+ */
+bool
+ImageFrameView::set_position(jack_nframes_t pos, void* src)
+{
+ jack_nframes_t old_pos = frame_position ;
+
+ // do the standard stuff
+ bool ret = TimeAxisViewItem::set_position(pos, src) ;
+
+ // everything went ok with the standard stuff?
+ if(ret)
+ {
+ /* move each of our associated markers with this ImageFrameView */
+ for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
+ {
+ // calculate the offset of the marker
+ MarkerView* mv = (MarkerView*)*i ;
+ jack_nframes_t marker_old_pos = mv->get_position() ;
+
+ mv->set_position(pos + (marker_old_pos - old_pos), src) ;
+ }
+ }
+
+ return(ret) ;
+}
+
+/**
+ * Sets the duration of this item
+ *
+ * @param dur the new duration of this item
+ * @param src the identity of the object that initiated the change
+ * @return true if the duration change was succesful, false otherwise
+ */
+bool
+ImageFrameView::set_duration(jack_nframes_t dur, void* src)
+{
+ /* do the standard stuff */
+ bool ret = TimeAxisViewItem::set_duration(dur, src) ;
+
+ // eveything went ok with the standard stuff?
+ if(ret)
+ {
+ /* handle setting the sizes of our canvas itesm based on the new duration */
+ gtk_canvas_item_set(imageframe, "drawwidth", (gdouble) trackview.editor.frame_to_pixel(get_duration()), NULL) ;
+ }
+
+ return(ret) ;
+}
+
+//---------------------------------------------------------------------------------------//
+// Parent Component Methods
+
+/**
+ * Sets the parent ImageFrameTimeAxisGroup of thie item
+ * each Item must be part of exactly one group (or 'scene') upon the timeline
+ *
+ * @param group the new parent group
+ */
+void
+ImageFrameView::set_time_axis_group(ImageFrameTimeAxisGroup* group)
+{
+ the_parent_group = group ;
+}
+
+/**
+ * Returns the parent group of this item
+ *
+ * @return the parent group of this item
+ */
+ImageFrameTimeAxisGroup*
+ImageFrameView::get_time_axis_group()
+{
+ return(the_parent_group) ;
+}
+
+
+//---------------------------------------------------------------------------------------//
+// ui methods
+
+/**
+ * Set the height of this item
+ *
+ * @param h the new height
+ */
+void
+ImageFrameView::set_height (gdouble h)
+{
+ // set the image size
+ // @todo might have to re-get the image data, for a large height...hmmm.
+ double im_ratio = (double)image_data_width/(double)image_data_height ;
+ int im_width = (int)((double)(h - TimeAxisViewItem::NAME_Y_OFFSET) * im_ratio) ;
+ gtk_canvas_item_set(imageframe, "width", (gdouble)im_width, NULL) ;
+ gtk_canvas_item_set(imageframe, "height",(gdouble) (h - TimeAxisViewItem::NAME_Y_OFFSET), NULL) ;
+
+
+ gtk_canvas_item_raise_to_top(frame) ;
+ gtk_canvas_item_raise_to_top(imageframe) ;
+ gtk_canvas_item_raise_to_top(name_highlight) ;
+ gtk_canvas_item_raise_to_top(name_text) ;
+ gtk_canvas_item_raise_to_top(frame_handle_start) ;
+ gtk_canvas_item_raise_to_top(frame_handle_end) ;
+
+ gtk_canvas_item_set (name_text, "y", h - TimeAxisViewItem::NAME_Y_OFFSET, NULL);
+ gtk_canvas_item_set (frame, "y2", h, NULL);
+
+ gtk_canvas_item_set (name_highlight, "y1", (gdouble) h - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE, "y2", (gdouble) h - 1.0, NULL);
+}
+
+
+//---------------------------------------------------------------------------------------//
+// MarkerView methods
+
+/**
+ * Adds a markerView to the list of marker views associated with this item
+ *
+ * @param item the marker item to add
+ * @param src the identity of the object that initiated the change
+ */
+void
+ImageFrameView::add_marker_view_item(MarkerView* item, void* src)
+{
+ marker_view_list.push_back(item) ;
+
+ item->GoingAway.connect(bind(slot(*this, &ImageFrameView::remove_marker_view_item), (void*)this));
+
+ MarkerViewAdded(item, src) ; /* EMIT_SIGNAL */
+}
+
+/**
+ * Removes the named marker view from the list of marker view associated with this item
+ * The Marker view is not destroyed on removal, so the caller must handle the item themself
+ *
+ * @param markId the id/name of the item to remove
+ * @param src the identity of the object that initiated the change
+ * @return the removed marker item
+ */
+MarkerView*
+ImageFrameView::remove_named_marker_view_item(std::string markerId, void* src)
+{
+ MarkerView* mv = 0 ;
+ MarkerViewList::iterator i = marker_view_list.begin() ;
+
+ while(i != marker_view_list.end())
+ {
+ if (((MarkerView*)*i)->get_item_name() == markerId)
+ {
+ mv = (*i) ;
+
+ marker_view_list.erase(i) ;
+
+ MarkerViewRemoved(mv,src) ; /* EMIT_SIGNAL */
+
+ // iterator is now invalid, but since we should only ever have
+ // one item with the specified name, things are ok, and we can
+ // break from the while loop
+ break ;
+ }
+ i++ ;
+ }
+
+ return(mv) ;
+}
+
+/**
+ * Removes item from the list of marker views assocaited with this item
+ * This method will do nothing if item if not assiciated with this item
+ *
+ * @param item the item to remove
+ * @param src the identity of the object that initiated the change
+ */
+void
+ImageFrameView::remove_marker_view_item(MarkerView* mv, void* src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameView::remove_marker_view_item), mv, src));
+
+ MarkerViewList::iterator i ;
+
+ if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) {
+ marker_view_list.erase(i) ;
+ MarkerViewRemoved (mv, src) ; /* EMIT_SIGNAL */
+ }
+}
+
+/**
+ * Determines if the named marker is one of those associated with this item
+ *
+ * @param markId the id/name of the item to search for
+ */
+bool
+ImageFrameView::has_marker_view_item(std::string mname)
+{
+ bool result = false ;
+
+ for (MarkerViewList::iterator ci = marker_view_list.begin(); ci != marker_view_list.end(); ++ci)
+ {
+ if (((MarkerView*)*ci)->get_item_name() == mname)
+ {
+ result = true ;
+
+ // found the item, so we can break the for loop
+ break ;
+ }
+ }
+
+ return(result) ;
+}
diff --git a/gtk2_ardour/imageframe_view.h b/gtk2_ardour/imageframe_view.h
new file mode 100644
index 0000000000..6a6aa3d33a
--- /dev/null
+++ b/gtk2_ardour/imageframe_view.h
@@ -0,0 +1,212 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_imageframe_view_h__
+#define __gtk_ardour_imageframe_view_h__
+
+#include <string>
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <sigc++/signal_system.h>
+#include <list>
+
+#include "enums.h"
+#include "time_axis_view_item.h"
+#include "marker_view.h"
+
+class ImageFrameTimeAxis;
+class ImageFrameTimeAxisGroup ;
+
+/**
+ * An ImageFrameItem to display an image upon the ardour time line
+ *
+ */
+class ImageFrameView : public TimeAxisViewItem
+{
+ public:
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * Constructs a new ImageFrameView upon the canvas
+ *
+ * @param item_id unique id of this item
+ * @param parent the parent canvas item
+ * @param tv the time axis view that this item is to be placed upon
+ * @param group the ImageFrameGroup that this item is a member of
+ * @param spu the current samples per canvas unit
+ * @param start the start frame ogf this item
+ * @param duration the duration of this item
+ * @param rgb_data the rgb data of the image
+ * @param width the width of the original rgb_data image data
+ * @param height the width of the origianl rgb_data image data
+ * @param num_channels the number of color channels within rgb_data
+ */
+ ImageFrameView(std::string item_id,
+ GtkCanvasGroup *parent,
+ ImageFrameTimeAxis *tv,
+ ImageFrameTimeAxisGroup* group,
+ double spu,
+ GdkColor& base_color,
+ jack_nframes_t start,
+ jack_nframes_t duration,
+ unsigned char* rgb_data,
+ uint32_t width,
+ uint32_t height,
+ uint32_t num_channels) ;
+
+ /**
+ * Destructor
+ * Reposible for removing and destroying all marker items associated with this item
+ */
+ ~ImageFrameView() ;
+
+ static SigC::Signal1<void,ImageFrameView*> GoingAway;
+
+ //---------------------------------------------------------------------------------------//
+ // Position and duration Accessors/Mutators
+
+ /**
+ * Set the position of this item to the specified value
+ *
+ * @param pos the new position
+ * @param src the identity of the object that initiated the change
+ * @return true if the position change was a success, false otherwise
+ */
+ virtual bool set_position(jack_nframes_t pos, void* src) ;
+
+ /**
+ * Sets the duration of this item
+ *
+ * @param dur the new duration of this item
+ * @param src the identity of the object that initiated the change
+ * @return true if the duration change was succesful, false otherwise
+ */
+ virtual bool set_duration(jack_nframes_t dur, void* src) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Parent Component Methods
+
+ /**
+ * Sets the parent ImageFrameTimeAxisGroup of thie item
+ * each Item must be part of exactly one group (or 'scene') upon the timeline
+ *
+ * @param group the new parent group
+ */
+ void set_time_axis_group(ImageFrameTimeAxisGroup* group) ;
+
+ /**
+ * Returns the parent group of this item
+ *
+ * @return the parent group of this item
+ */
+ ImageFrameTimeAxisGroup* get_time_axis_group() ;
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods
+
+ /**
+ * Set the height of this item
+ *
+ * @param h the new height
+ */
+ virtual void set_height(gdouble h) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // MarkerView methods
+
+ /**
+ * Adds a markerView to the list of marker views associated with this item
+ *
+ * @param item the marker item to add
+ * @param src the identity of the object that initiated the change
+ */
+ void add_marker_view_item(MarkerView* item, void* src) ;
+
+ /**
+ * Removes the named marker view from the list of marker view associated with this item
+ * The Marker view is not destroyed on removal, so the caller must handle the item themself
+ *
+ * @param markId the id/name of the item to remove
+ * @param src the identity of the object that initiated the change
+ * @return the removed marker item
+ */
+ MarkerView* remove_named_marker_view_item(std::string markId, void* src) ;
+
+ /**
+ * Removes item from the list of marker views assocaited with this item
+ * This method will do nothing if item if not assiciated with this item
+ * The Marker view is not destroyed on removal, so the caller must handle the item themself
+ *
+ * @param item the item to remove
+ * @param src the identity of the object that initiated the change
+ */
+ void remove_marker_view_item(MarkerView* item, void* src) ;
+
+ /**
+ * Determines if the named marker is one of those associated with this item
+ *
+ * @param markId the id/name of the item to search for
+ */
+ bool has_marker_view_item(std::string markId) ;
+
+
+ //---------------------------------------------------------------------------------//
+ // Emitted Signals
+
+ /** Emitted when a marker Item is added to this Item */
+ SigC::Signal2<void,MarkerView*,void*> MarkerViewAdded ;
+
+ /** Emitted when a Marker Item is added to this Item */
+ SigC::Signal2<void,MarkerView*,void*> MarkerViewRemoved ;
+
+ private:
+ /** the list of MarkerViews associated with this item */
+ typedef std::list<MarkerView*> MarkerViewList ;
+ MarkerViewList marker_view_list ;
+
+
+ /** The parent group that this item is a member of */
+ ImageFrameTimeAxisGroup* the_parent_group ;
+
+ // ------- Image data -----------
+
+ /** the image data that we display */
+ //unsigned char* the_rgb_data ;
+
+ /** The width of the image contained within the_rgb_data */
+ uint32_t image_data_width ;
+
+ /** The height of the image contained within the_rgb_data */
+ uint32_t image_data_height ;
+
+ /** the number of channels contained in the_rgb_data */
+ uint32_t image_data_num_channels ;
+
+
+ // ------- Our canvas element -----------
+
+ /** the CanvasImageFrame to display the image */
+ GtkCanvasItem* imageframe ;
+
+} ; /* class ImageFrameView */
+
+#endif /* __gtk_ardour_imageframe_view_h__ */
diff --git a/gtk2_ardour/io_menu.h b/gtk2_ardour/io_menu.h
new file mode 100644
index 0000000000..b1fb785128
--- /dev/null
+++ b/gtk2_ardour/io_menu.h
@@ -0,0 +1,25 @@
+/*
+ Copyright (C) 1999-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_io_menu_h__
+#define __gtk_ardour_io_menu_h__
+
+
+#endif /* __gtk_ardour_io_menu_h__ */
diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc
new file mode 100644
index 0000000000..0d013c72f4
--- /dev/null
+++ b/gtk2_ardour/io_selector.cc
@@ -0,0 +1,857 @@
+/*
+ Copyright (C) 2002-2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <map>
+#include <vector>
+
+#include <pbd/lockmonitor.h>
+
+#include <ardour/io.h>
+#include <ardour/route.h>
+#include <ardour/audioengine.h>
+#include <ardour/port.h>
+#include <ardour/insert.h>
+#include <ardour/session.h>
+#include <ardour/diskstream.h>
+
+#include <gtkmmext/doi.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include "utils.h"
+#include "ardour_message.h"
+#include "io_selector.h"
+#include "extra_bind.h"
+#include "keyboard.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtk;
+using namespace SigC;
+using namespace ARDOUR;
+
+IOSelectorWindow::IOSelectorWindow (Session& sess, IO& ior, bool input, bool can_cancel)
+ : ArdourDialog ("i/o selector"),
+ _selector (sess, ior, input),
+ ok_button (can_cancel ? _("OK"): _("Close")),
+ cancel_button (_("Cancel")),
+ rescan_button (_("Rescan"))
+
+{
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+ set_name ("IOSelectorWindow");
+
+ string title;
+ if (input) {
+ title = compose(_("%1 input"), ior.name());
+ } else {
+ title = compose(_("%1 output"), ior.name());
+ }
+
+ ok_button.set_name ("IOSelectorButton");
+ cancel_button.set_name ("IOSelectorButton");
+ rescan_button.set_name ("IOSelectorButton");
+
+ button_box.set_spacing (5);
+ button_box.set_border_width (5);
+ button_box.set_homogeneous (true);
+ button_box.pack_start (rescan_button);
+
+ if (can_cancel) {
+ button_box.pack_start (cancel_button);
+ }
+ else {
+ cancel_button.hide();
+ }
+
+ button_box.pack_start (ok_button);
+
+ vbox.pack_start (_selector);
+ vbox.pack_start (button_box, false, false);
+
+ ok_button.clicked.connect (slot (*this, &IOSelectorWindow::accept));
+ cancel_button.clicked.connect (slot (*this, &IOSelectorWindow::cancel));
+ rescan_button.clicked.connect (slot (*this, &IOSelectorWindow::rescan));
+
+ set_title (title);
+ set_position (GTK_WIN_POS_MOUSE);
+ add (vbox);
+
+ delete_event.connect (bind (slot (just_hide_it), reinterpret_cast<Window *> (this)));
+}
+
+IOSelectorWindow::~IOSelectorWindow()
+{
+}
+
+void
+IOSelectorWindow::rescan ()
+{
+ _selector.redisplay ();
+}
+
+void
+IOSelectorWindow::cancel ()
+{
+ _selector.Finished(IOSelector::Cancelled);
+ hide ();
+}
+
+void
+IOSelectorWindow::accept ()
+{
+ _selector.Finished(IOSelector::Accepted);
+ hide ();
+}
+
+
+gint
+IOSelectorWindow::map_event_impl (GdkEventAny *ev)
+{
+ _selector.redisplay ();
+ return Window::map_event_impl (ev);
+}
+
+/*************************
+ The IO Selector "widget"
+ *************************/
+
+IOSelector::IOSelector (Session& sess, IO& ior, bool input)
+ : session (sess),
+ io (ior),
+ for_input (input),
+ port_frame (for_input? _("Inputs") : _("Outputs")),
+ add_port_button (for_input? _("Add Input") : _("Add Output")),
+ remove_port_button (for_input? _("Remove Input") : _("Remove Output")),
+ clear_connections_button (_("Disconnect All"))
+{
+ selected_port = 0;
+
+ notebook.set_name ("IOSelectorNotebook");
+ notebook.set_usize (-1, 125);
+
+ clear_connections_button.set_name ("IOSelectorButton");
+ add_port_button.set_name ("IOSelectorButton");
+ remove_port_button.set_name ("IOSelectorButton");
+
+ selector_frame.set_name ("IOSelectorFrame");
+ port_frame.set_name ("IOSelectorFrame");
+
+ selector_frame.set_label (_("Available connections"));
+
+ selector_button_box.set_spacing (5);
+ selector_button_box.set_border_width (5);
+
+ selector_box.set_spacing (5);
+ selector_box.set_border_width (5);
+ selector_box.pack_start (notebook);
+ selector_box.pack_start (selector_button_box, false, false);
+
+ selector_frame.add (selector_box);
+
+ port_box.set_spacing (5);
+ port_box.set_border_width (5);
+
+ port_display_scroller.set_name ("IOSelectorNotebook");
+ port_display_scroller.set_border_width (0);
+ port_display_scroller.set_usize (-1, 170);
+ port_display_scroller.add_with_viewport (port_box);
+ port_display_scroller.set_policy (GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+
+ port_button_box.set_spacing (5);
+ port_button_box.set_border_width (5);
+
+ port_button_box.pack_start (add_port_button, false, false);
+
+ if (for_input) {
+ if (io.input_maximum() < 0 || io.input_maximum() > (int) io.n_inputs()) {
+ add_port_button.set_sensitive (true);
+ } else {
+ add_port_button.set_sensitive (false);
+ }
+
+ } else {
+ if (io.output_maximum() < 0 || io.output_maximum() > (int) io.n_outputs()) {
+ add_port_button.set_sensitive (true);
+ } else {
+ add_port_button.set_sensitive (false);
+ }
+
+ }
+
+ port_button_box.pack_start (remove_port_button, false, false);
+
+ if (for_input) {
+ if (io.input_minimum() < 0 || io.input_minimum() < (int) io.n_inputs()) {
+ remove_port_button.set_sensitive (true);
+ } else {
+ remove_port_button.set_sensitive (false);
+ }
+
+ } else {
+ if (io.output_minimum() < 0 || io.output_minimum() < (int) io.n_outputs()) {
+ remove_port_button.set_sensitive (true);
+ } else {
+ remove_port_button.set_sensitive (false);
+ }
+ }
+
+ port_button_box.pack_start (clear_connections_button, false, false);
+
+ port_and_button_box.set_border_width (5);
+ port_and_button_box.pack_start (port_button_box, false, false);
+ port_and_button_box.pack_start (port_display_scroller);
+
+ port_frame.add (port_and_button_box);
+
+ port_and_selector_box.set_spacing (5);
+ port_and_selector_box.pack_start (port_frame);
+ port_and_selector_box.pack_start (selector_frame);
+
+ set_spacing (5);
+ set_border_width (5);
+ pack_start (port_and_selector_box);
+
+ rescan();
+ display_ports ();
+
+ clear_connections_button.clicked.connect (slot (*this, &IOSelector::clear_connections));
+
+ add_port_button.clicked.connect (slot (*this, &IOSelector::add_port));
+ remove_port_button.clicked.connect (slot (*this, &IOSelector::remove_port));
+
+ if (for_input) {
+ io.input_changed.connect (slot (*this, &IOSelector::ports_changed));
+ } else {
+ io.output_changed.connect (slot (*this, &IOSelector::ports_changed));
+ }
+
+ io.name_changed.connect (slot (*this, &IOSelector::name_changed));
+}
+
+IOSelector::~IOSelector ()
+{
+}
+
+void
+IOSelector::name_changed (void* src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &IOSelector::name_changed), src));
+
+ display_ports ();
+}
+
+void
+IOSelector::clear_connections ()
+{
+ if (for_input) {
+ io.disconnect_inputs (this);
+ } else {
+ io.disconnect_outputs (this);
+ }
+}
+
+void
+IOSelector::rescan ()
+{
+ using namespace Notebook_Helpers;
+ using namespace CList_Helpers;
+
+ typedef map<string,vector<pair<string,string> > > PortMap;
+ PortMap portmap;
+ const char **ports;
+ PageList& pages = notebook.pages();
+ gint current_page;
+ vector<string> rowdata;
+
+ current_page = notebook.get_current_page_num ();
+ pages.clear ();
+
+ /* get relevant current JACK ports */
+
+ ports = session.engine().get_ports ("", JACK_DEFAULT_AUDIO_TYPE, for_input?JackPortIsOutput:JackPortIsInput);
+
+ if (ports == 0) {
+ return;
+ }
+
+ /* find all the client names and group their ports into a list-by-client */
+
+ for (int n = 0; ports[n]; ++n) {
+
+ pair<string,vector<pair<string,string> > > newpair;
+ pair<string,string> strpair;
+ pair<PortMap::iterator,bool> result;
+
+ string str = ports[n];
+ string::size_type pos;
+ string portname;
+
+ pos = str.find (':');
+
+ newpair.first = str.substr (0, pos);
+ portname = str.substr (pos+1);
+
+ /* this may or may not succeed at actually inserting.
+ we don't care, however: we just want an iterator
+ that gives us either the inserted element or
+ the existing one with the same name.
+ */
+
+ result = portmap.insert (newpair);
+
+ strpair.first = portname;
+ strpair.second = str;
+
+ result.first->second.push_back (strpair);
+ }
+
+ PortMap::iterator i;
+
+ for (i = portmap.begin(); i != portmap.end(); ++i) {
+
+ Box *client_box = manage (new VBox);
+ Gtk::CList *client_port_display = manage (new Gtk::CList (1));
+ ScrolledWindow *scroller = manage (new ScrolledWindow);
+
+ scroller->add_with_viewport (*client_port_display);
+ scroller->set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ client_box->pack_start (*scroller);
+
+ client_port_display->set_selection_mode (GTK_SELECTION_BROWSE);
+ client_port_display->set_name ("IOSelectorList");
+
+ for (vector<pair<string,string> >::iterator s = i->second.begin(); s != i->second.end(); ++s) {
+
+ rowdata.clear ();
+ rowdata.push_back (s->first);
+ client_port_display->rows().push_back (rowdata);
+ client_port_display->rows().back().set_data (g_strdup (s->second.c_str()), free);
+ }
+
+ client_port_display->columns_autosize ();
+ client_port_display->select_row.connect (bind (slot (*this, &IOSelector::port_selection_handler), client_port_display));
+
+ Label *tab_label = manage (new Label);
+
+ tab_label->set_name ("IOSelectorNotebookTab");
+ tab_label->set_text ((*i).first);
+
+ pages.push_back (TabElem (*client_box, *tab_label));
+ }
+
+ notebook.set_page (current_page);
+ notebook.show.connect (bind (slot (notebook, &Notebook::set_page), current_page));
+ selector_box.show_all ();
+}
+
+void
+IOSelector::display_ports ()
+{
+ CList *clist = 0;
+ CList *firstclist = 0;
+ CList *selected_port_list = 0;
+
+ {
+ LockMonitor lm (port_display_lock, __LINE__, __FILE__);
+ Port *port;
+ uint32_t limit;
+
+ if (for_input) {
+ limit = io.n_inputs();
+ } else {
+ limit = io.n_outputs();
+ }
+
+ for (slist<CList *>::iterator i = port_displays.begin(); i != port_displays.end(); ) {
+
+ slist<CList *>::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ port_box.remove (**i);
+ delete *i;
+ port_displays.erase (i);
+
+ i = tmp;
+ }
+
+ for (uint32_t n = 0; n < limit; ++n) {
+ const gchar *title[1];
+ string really_short_name;
+
+ if (for_input) {
+ port = io.input (n);
+ } else {
+ port = io.output (n);
+ }
+
+ /* we know there is '/' because we put it there */
+
+ really_short_name = port->short_name();
+ really_short_name = really_short_name.substr (really_short_name.find ('/') + 1);
+
+ title[0] = really_short_name.c_str();
+ clist = new CList (1, title);
+ if (!firstclist) {
+ firstclist = clist;
+ }
+
+ port_displays.insert (port_displays.end(), clist);
+ port_box.pack_start (*clist);
+
+ clist->set_data (_("port"), port);
+
+ /* XXX THIS IS A DIGUSTING AND DIRTY HACK, FORCED UPON US BECAUSE
+ GtkCList DOESN'T PROVIDE ANY WAY TO CONNECT TO BUTTON_PRESS_EVENTS
+ FOR THE COLUMN TITLE BUTTON.
+ */
+
+ clist->column(0).get_widget(); // force the column title button to be created
+ GtkButton *b = GTK_BUTTON(clist->gtkobj()->column[0].button); // no API to access this
+ Gtk::Button *B = wrap (b); // make C++ signal handling easier.
+
+ clist->column_titles_show ();
+ clist->column_titles_active ();
+
+ if (for_input) {
+
+ if (io.input_maximum() == 1) {
+ selected_port = port;
+ selected_port_list = clist;
+ } else {
+ if (port == selected_port) {
+ selected_port_list = clist;
+ }
+ }
+
+ B->button_release_event.connect
+ (bind (slot (*this, &IOSelector::port_column_button_release), clist));
+
+ } else {
+
+ if (io.output_maximum() == 1) {
+ selected_port = port;
+ selected_port_list = clist;
+ } else {
+ if (port == selected_port) {
+ selected_port_list = clist;
+ }
+ }
+
+ B->button_release_event.connect
+ (bind (slot (*this, &IOSelector::port_column_button_release), clist));
+ }
+
+ clist->set_name ("IOSelectorPortList");
+ clist->set_selection_mode (GTK_SELECTION_SINGLE);
+ clist->set_shadow_type (GTK_SHADOW_IN);
+ clist->set_usize (-1, 75);
+
+ /* now fill the clist with the current connections */
+
+ const char **connections = port->get_connections ();
+
+ if (connections) {
+
+ for (uint32_t c = 0; connections[c]; ++c) {
+
+ const gchar *txt[1];
+
+ txt[0] = connections[c];
+
+ clist->rows().push_back (txt);
+ }
+
+ free (connections);
+ }
+
+ clist->columns_autosize ();
+ clist->button_release_event.connect (bind (slot (*this, &IOSelector::connection_click), clist));
+ }
+
+ port_box.show_all ();
+
+ if (selected_port_list) {
+ selected_port_list->click_column(0);
+ selected_port_list->set_name ("IOSelectorPortListSelected");
+ for (slist<CList *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) {
+ if (*i != selected_port_list) {
+ (*i)->set_name ("IOSelectorPortList");
+ (*i)->queue_draw ();
+ }
+ }
+ } else {
+ selected_port = 0;
+ selector_box.hide_all ();
+ }
+ }
+
+ if (selected_port_list) {
+ select_clist (selected_port_list);
+ } else if (firstclist) {
+ // select first
+ select_clist (firstclist);
+ }
+}
+
+void
+IOSelector::port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *clist)
+{
+ using namespace CList_Helpers;
+ int status;
+
+ if (selected_port == 0) {
+ return;
+ }
+
+ string other_port_name = (char *) clist->rows()[row].get_data();
+
+ if (for_input) {
+ if ((status = io.connect_input (selected_port, other_port_name, this)) == 0) {
+ Port *p = session.engine().get_port_by_name (other_port_name);
+ p->enable_metering();
+ }
+ } else {
+ status = io.connect_output (selected_port, other_port_name, this);
+ }
+
+ if (status == 0) {
+ select_next_clist ();
+ }
+}
+
+void
+IOSelector::ports_changed (IOChange change, void *src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &IOSelector::ports_changed), change, src));
+
+ display_ports ();
+}
+
+void
+IOSelector::add_port ()
+{
+ /* add a new port, then hide the button if we're up to the maximum allowed */
+
+ if (for_input) {
+
+
+ try {
+
+ io.add_input_port ("", this);
+ }
+
+ catch (AudioEngine::PortRegistrationFailure& err) {
+ ArdourMessage msg (0, X_("noport dialog"),
+ _("There are no more JACK ports available."));
+ }
+
+ if (io.input_maximum() >= 0 && io.input_maximum() <= (int) io.n_inputs()) {
+ add_port_button.set_sensitive (false);
+ }
+
+ if (io.input_minimum() < (int) io.n_inputs()) {
+ remove_port_button.set_sensitive (true);
+ }
+
+ } else {
+
+ try {
+ io.add_output_port ("", this);
+ }
+
+ catch (AudioEngine::PortRegistrationFailure& err) {
+ ArdourMessage msg (0, X_("noport dialog"),
+ _("There are no more JACK ports available."));
+ }
+
+ if (io.output_maximum() >= 0 && io.output_maximum() <= (int) io.n_outputs()) {
+ add_port_button.set_sensitive (false);
+ }
+ }
+}
+
+void
+IOSelector::remove_port ()
+{
+ // always remove last port
+ uint32_t nports;
+
+ if (for_input) {
+ if ((nports = io.n_inputs()) > 0) {
+ io.remove_input_port (io.input(nports-1), this);
+ }
+ if (io.input_minimum() == (int) io.n_inputs()) {
+ remove_port_button.set_sensitive (false);
+ }
+ } else {
+ if ((nports = io.n_outputs()) > 0) {
+ io.remove_output_port (io.output(nports-1), this);
+ }
+ }
+}
+
+gint
+IOSelector::remove_port_when_idle (Port *port)
+{
+ if (for_input) {
+ io.remove_input_port (port, this);
+ } else {
+ io.remove_output_port (port, this);
+ }
+
+ return FALSE;
+}
+
+gint
+IOSelector::port_column_button_release (GdkEventButton *event, CList *clist)
+{
+ if (Keyboard::is_delete_event (event)) {
+ Port* port;
+ {
+ LockMonitor lm (port_display_lock, __LINE__, __FILE__);
+
+ port = reinterpret_cast<Port *> (clist->get_data (_("port")));
+
+ if (port == selected_port) {
+ selected_port = 0;
+ clist->set_name ("IOSelectorPortList");
+ clist->queue_draw();
+ }
+ }
+
+ /* remove the port when idle - if we do it here, we will destroy the widget
+ for whom we are handling an event. not good.
+ */
+
+ Gtk::Main::idle.connect (bind (slot (*this, &IOSelector::remove_port_when_idle), port));
+
+ } else {
+ select_clist(clist);
+ }
+
+ return TRUE;
+}
+
+void
+IOSelector::select_next_clist ()
+{
+ slist<CList*>::iterator next;
+
+ for (slist<CList *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) {
+
+ if ((*i)->get_name() == "IOSelectorPortListSelected") {
+
+ ++i;
+
+ if (i == port_displays.end()) {
+ select_clist (port_displays.front());
+ } else {
+ select_clist (*i);
+ }
+
+ break;
+ }
+ }
+}
+
+void
+IOSelector::select_clist(Gtk::CList* clist)
+{
+ /* Gack. CList's don't respond visually to a change
+ in their state, so rename them to force a style
+ switch.
+ */
+ LockMonitor lm (port_display_lock, __LINE__, __FILE__);
+ Port* port = reinterpret_cast<Port *> (clist->get_data (_("port")));
+
+ if (port != selected_port) {
+ selected_port = port;
+
+ clist->set_name ("IOSelectorPortListSelected");
+
+ for (slist<CList *>::iterator i = port_displays.begin(); i != port_displays.end(); ++i) {
+ if (*i != clist) {
+ (*i)->set_name ("IOSelectorPortList");
+ (*i)->queue_draw ();
+ }
+ }
+ selector_box.show_all ();
+ }
+}
+
+gint
+IOSelector::connection_click (GdkEventButton *ev, CList *clist)
+{
+ gint row, col;
+
+ /* only handle button1 events here */
+
+ if (ev->button != 1) {
+ return FALSE;
+ }
+
+ if (clist->get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) {
+ return FALSE;
+ }
+
+ if (row < 0 || col < 0) {
+ return FALSE;
+ }
+
+ Port *port = reinterpret_cast<Port *> (clist->get_data (_("port")));
+ string connected_port_name = clist->cell(row,col).get_text ();
+
+ if (for_input) {
+ Port *p = session.engine().get_port_by_name (connected_port_name);
+ p->disable_metering();
+ io.disconnect_input (port, connected_port_name, this);
+ } else {
+ io.disconnect_output (port, connected_port_name, this);
+ }
+
+ return TRUE;
+}
+
+void
+IOSelector::redisplay ()
+{
+ display_ports ();
+
+ if (for_input) {
+ if (io.input_maximum() != 0) {
+ rescan ();
+ }
+ } else {
+ if (io.output_maximum() != 0) {
+ rescan();
+ }
+ }
+}
+
+PortInsertUI::PortInsertUI (Session& sess, PortInsert& pi)
+ : input_selector (sess, pi, true),
+ output_selector (sess, pi, false)
+{
+ hbox.pack_start (output_selector, true, true);
+ hbox.pack_start (input_selector, true, true);
+
+
+ pack_start (hbox);
+}
+
+void
+PortInsertUI::redisplay()
+{
+
+ input_selector.redisplay();
+ output_selector.redisplay();
+}
+
+void
+PortInsertUI::finished(IOSelector::Result r)
+{
+ input_selector.Finished (r);
+ output_selector.Finished (r);
+}
+
+
+PortInsertWindow::PortInsertWindow (Session& sess, PortInsert& pi, bool can_cancel)
+ : ArdourDialog ("port insert dialog"),
+ _portinsertui(sess, pi),
+ ok_button (can_cancel ? _("OK"): _("Close")),
+ cancel_button (_("Cancel")),
+ rescan_button (_("Rescan"))
+{
+
+ set_name ("IOSelectorWindow");
+ string title = _("ardour: ");
+ title += pi.name();
+ set_title (title);
+
+ ok_button.set_name ("IOSelectorButton");
+ cancel_button.set_name ("IOSelectorButton");
+ rescan_button.set_name ("IOSelectorButton");
+
+ button_box.set_spacing (5);
+ button_box.set_border_width (5);
+ button_box.set_homogeneous (true);
+ button_box.pack_start (rescan_button);
+ if (can_cancel) {
+ button_box.pack_start (cancel_button);
+ }
+ else {
+ cancel_button.hide();
+ }
+ button_box.pack_start (ok_button);
+
+ vbox.pack_start (_portinsertui);
+ vbox.pack_start (button_box, false, false);
+
+ add (vbox);
+
+ ok_button.clicked.connect (slot (*this, &PortInsertWindow::accept));
+ cancel_button.clicked.connect (slot (*this, &PortInsertWindow::cancel));
+ rescan_button.clicked.connect (slot (*this, &PortInsertWindow::rescan));
+
+ delete_event.connect (bind (slot (just_hide_it), reinterpret_cast<Window *> (this)));
+ pi.GoingAway.connect (slot (*this, &PortInsertWindow::plugin_going_away));
+}
+
+void
+PortInsertWindow::plugin_going_away (ARDOUR::Redirect* ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &PortInsertWindow::plugin_going_away), ignored));
+
+ delete_when_idle (this);
+}
+
+gint
+PortInsertWindow::map_event_impl (GdkEventAny *ev)
+{
+ _portinsertui.redisplay ();
+ return Window::map_event_impl (ev);
+}
+
+
+void
+PortInsertWindow::rescan ()
+{
+ _portinsertui.redisplay();
+}
+
+void
+PortInsertWindow::cancel ()
+{
+ _portinsertui.finished(IOSelector::Cancelled);
+ hide ();
+}
+
+void
+PortInsertWindow::accept ()
+{
+ _portinsertui.finished(IOSelector::Accepted);
+ hide ();
+}
diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h
new file mode 100644
index 0000000000..5187f64689
--- /dev/null
+++ b/gtk2_ardour/io_selector.h
@@ -0,0 +1,182 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_ui_io_selector_h__
+#define __ardour_ui_io_selector_h__
+
+#if __GNUC__ >= 3
+#include <ext/slist>
+using __gnu_cxx::slist;
+#else
+#include <slist.h>
+#endif
+
+#include <string>
+#include <gtk--.h>
+
+#include <ardour_dialog.h>
+
+namespace ARDOUR {
+ class IO;
+ class Session;
+ class PortInsert;
+ class Port;
+ class Redirect;
+}
+
+class IOSelector : public Gtk::VBox {
+ public:
+ IOSelector (ARDOUR::Session&, ARDOUR::IO&, bool for_input);
+ ~IOSelector ();
+
+ void redisplay ();
+
+ enum Result {
+ Cancelled,
+ Accepted
+ };
+
+ SigC::Signal1<void,Result> Finished;
+
+ protected:
+ ARDOUR::Session& session;
+
+ private:
+ ARDOUR::IO& io;
+ bool for_input;
+ ARDOUR::Port *selected_port;
+
+ Gtk::VBox main_box;
+ Gtk::HBox port_and_selector_box;
+
+ /* client/port selection */
+
+ Gtk::Notebook notebook;
+ Gtk::Frame selector_frame;
+ Gtk::VBox selector_box;
+ Gtk::HBox selector_button_box;
+
+ /* ports */
+
+ Gtk::VBox port_box;
+ Gtk::HBox port_button_box;
+ Gtk::VBox port_and_button_box;
+ Gtk::Frame port_frame;
+ Gtk::Button add_port_button;
+ Gtk::Button remove_port_button;
+ Gtk::Button clear_connections_button;
+ Gtk::ScrolledWindow port_display_scroller;
+
+ PBD::Lock port_display_lock;
+ slist<Gtk::CList *> port_displays;
+ void display_ports ();
+
+ void rescan ();
+ void clear_connections ();
+
+ void port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *);
+
+ void ports_changed (ARDOUR::IOChange, void *);
+ void name_changed (void*);
+
+ void add_port ();
+ void remove_port ();
+ gint remove_port_when_idle (ARDOUR::Port *);
+
+ gint port_column_button_release (GdkEventButton*, Gtk::CList*);
+ gint connection_click (GdkEventButton *, Gtk::CList *clist);
+
+ void select_clist(Gtk::CList*);
+ void select_next_clist ();
+};
+
+class IOSelectorWindow : public ArdourDialog
+{
+ public:
+ IOSelectorWindow (ARDOUR::Session&, ARDOUR::IO&, bool for_input, bool can_cancel=false);
+ ~IOSelectorWindow ();
+
+ IOSelector& selector() { return _selector; }
+
+ protected:
+ gint map_event_impl (GdkEventAny *);
+
+ private:
+ IOSelector _selector;
+
+ Gtk::VBox vbox;
+
+ /* overall operation buttons */
+
+ Gtk::Button ok_button;
+ Gtk::Button cancel_button;
+ Gtk::Button rescan_button;
+ Gtk::HBox button_box;
+
+ void rescan ();
+ void cancel ();
+ void accept ();
+};
+
+
+class PortInsertUI : public Gtk::VBox
+{
+ public:
+ PortInsertUI (ARDOUR::Session&, ARDOUR::PortInsert&);
+
+ void redisplay ();
+ void finished (IOSelector::Result);
+
+ private:
+
+ Gtk::HBox hbox;
+ IOSelector input_selector;
+ IOSelector output_selector;
+
+};
+
+class PortInsertWindow : public ArdourDialog
+{
+ public:
+ PortInsertWindow (ARDOUR::Session&, ARDOUR::PortInsert&, bool can_cancel=false);
+
+ protected:
+ gint map_event_impl (GdkEventAny *);
+
+ private:
+
+ PortInsertUI _portinsertui;
+ Gtk::VBox vbox;
+
+ Gtk::Button ok_button;
+ Gtk::Button cancel_button;
+ Gtk::Button rescan_button;
+ Gtk::Frame button_frame;
+ Gtk::HBox button_box;
+
+ void rescan ();
+ void cancel ();
+ void accept ();
+
+ void plugin_going_away (ARDOUR::Redirect*);
+};
+
+
+#endif /* __ardour_ui_io_selector_h__ */
diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc
new file mode 100644
index 0000000000..e0d2314b2f
--- /dev/null
+++ b/gtk2_ardour/keyboard.cc
@@ -0,0 +1,1006 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include "ardour_ui.h"
+
+#include <algorithm>
+#include <fstream>
+
+#include <ctype.h>
+
+#include <X11/keysymdef.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <pbd/error.h>
+
+#include "keyboard.h"
+#include "keyboard_target.h"
+#include "ardour_dialog.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+#define KBD_DEBUG 1
+bool debug_keyboard = false;
+
+guint Keyboard::edit_but = 3;
+guint Keyboard::edit_mod = GDK_CONTROL_MASK;
+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 = GDK_MOD2_MASK;
+
+Keyboard* Keyboard::_the_keyboard = 0;
+
+/* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
+
+GdkModifierType Keyboard::RelevantModifierKeyMask =
+ GdkModifierType (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD3_MASK);
+
+
+Keyboard::Keyboard ()
+{
+ if (_the_keyboard == 0) {
+ _the_keyboard = this;
+ }
+
+ target = 0;
+ default_target = 0;
+ _queue_events = false;
+ _flush_queue = false;
+ playback_ignore_count = 0;
+ focus_allowed = false;
+ collecting_prefix = false;
+ current_dialog = 0;
+
+ get_modifier_masks ();
+
+ snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
+
+ /* some global key actions */
+
+ KeyboardTarget::add_action ("close-dialog", slot (*this, &Keyboard::close_current_dialog));
+
+ XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
+ set_state (*node);
+}
+
+Keyboard::~Keyboard ()
+{
+ gtk_key_snooper_remove (snooper_id);
+ delete [] modifier_masks;
+}
+
+XMLNode&
+Keyboard::get_state (void)
+{
+ XMLNode* node = new XMLNode ("Keyboard");
+ char buf[32];
+
+ snprintf (buf, sizeof (buf), "%d", edit_but);
+ node->add_property ("edit-button", buf);
+ snprintf (buf, sizeof (buf), "%d", edit_mod);
+ node->add_property ("edit-modifier", buf);
+ snprintf (buf, sizeof (buf), "%d", delete_but);
+ node->add_property ("delete-button", buf);
+ snprintf (buf, sizeof (buf), "%d", delete_mod);
+ node->add_property ("delete-modifier", buf);
+ snprintf (buf, sizeof (buf), "%d", snap_mod);
+ node->add_property ("snap-modifier", buf);
+
+ return *node;
+}
+
+int
+Keyboard::set_state (const XMLNode& node)
+{
+ const XMLProperty* prop;
+
+ if ((prop = node.property ("edit-button")) != 0) {
+ sscanf (prop->value().c_str(), "%d", &edit_but);
+ }
+
+ if ((prop = node.property ("edit-modifier")) != 0) {
+ sscanf (prop->value().c_str(), "%d", &edit_mod);
+ }
+
+ if ((prop = node.property ("delete-button")) != 0) {
+ sscanf (prop->value().c_str(), "%d", &delete_but);
+ }
+
+ if ((prop = node.property ("delete-modifier")) != 0) {
+ sscanf (prop->value().c_str(), "%d", &delete_mod);
+ }
+
+ if ((prop = node.property ("snap-modifier")) != 0) {
+ sscanf (prop->value().c_str(), "%d", &snap_mod);
+ }
+
+ return 0;
+}
+
+gint
+Keyboard::_snooper (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ return ((Keyboard *) data)->snooper (widget, event);
+}
+
+gint
+Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
+{
+ bool handled = false;
+ uint32_t keyval;
+
+#if KBD_DEBUG
+ if (debug_keyboard) {
+ cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type
+ << " focus allowed? " << focus_allowed << " current dialog = " << current_dialog
+ << endl;
+ }
+#endif
+
+ /* Only allow key events to propagate to the
+ usual GTK model when specifically allowed.
+ Returning FALSE here does that.
+ */
+
+ if (focus_allowed) {
+ return FALSE;
+ }
+
+ if (event->keyval == GDK_Shift_R) {
+ keyval = GDK_Shift_L;
+
+ } else if (event->keyval == GDK_Control_R) {
+ keyval = GDK_Control_L;
+
+ } else {
+ keyval = event->keyval;
+ }
+
+
+ if (event->type == GDK_KEY_PRESS) {
+ bool was_prefix = false;
+
+ if (collecting_prefix) {
+ switch (keyval) {
+ case GDK_0:
+ current_prefix += '0';
+ was_prefix = true;
+ break;
+ case GDK_1:
+ current_prefix += '1';
+ was_prefix = true;
+ break;
+ case GDK_2:
+ current_prefix += '2';
+ was_prefix = true;
+ break;
+ case GDK_3:
+ current_prefix += '3';
+ was_prefix = true;
+ break;
+ case GDK_4:
+ current_prefix += '4';
+ was_prefix = true;
+ break;
+ case GDK_5:
+ current_prefix += '5';
+ was_prefix = true;
+ break;
+ case GDK_6:
+ current_prefix += '6';
+ was_prefix = true;
+ break;
+ case GDK_7:
+ current_prefix += '7';
+ was_prefix = true;
+ break;
+ case GDK_8:
+ current_prefix += '8';
+ was_prefix = true;
+ break;
+ case GDK_9:
+ current_prefix += '9';
+ was_prefix = true;
+ break;
+ case GDK_period:
+ current_prefix += '.';
+ was_prefix = true;
+ break;
+ default:
+ was_prefix = false;
+ collecting_prefix = false;
+ break;
+ }
+ }
+
+ if (find (state.begin(), state.end(), keyval) == state.end()) {
+ state.push_back (keyval);
+ sort (state.begin(), state.end());
+ }
+
+#if KBD_DEBUG
+ if (debug_keyboard) {
+ cerr << "STATE: ";
+ for (State::iterator i = state.begin(); i != state.end(); ++i) {
+ cerr << (*i) << ' ';
+ }
+ cerr << endl;
+ }
+#endif
+
+ if (!was_prefix) {
+
+ bool old_collecting_prefix = collecting_prefix;
+
+ if (target) {
+#if KBD_DEBUG
+ if (debug_keyboard) {
+ cerr << "PRESS: delivering to target " << target << endl;
+ }
+#endif
+ target->key_press_event (event, state, handled);
+ }
+
+ if (!handled && default_target) {
+#if KBD_DEBUG
+ if (debug_keyboard) {
+ cerr << "PRESS: not handled, delivering to default target " << default_target << endl;
+ }
+#endif
+ default_target->key_press_event (event, state, handled);
+ }
+
+#if KBD_DEBUG
+ if (debug_keyboard) {
+ cerr << "PRESS: handled ? " << handled << endl;
+ }
+#endif
+
+ if (handled) {
+
+ /* don't reset collecting prefix is start_prefix()
+ was called by the handler.
+ */
+
+ if (collecting_prefix == old_collecting_prefix) {
+ collecting_prefix = false;
+ current_prefix = "";
+ }
+ }
+ }
+
+ } else if (event->type == GDK_KEY_RELEASE) {
+
+ State::iterator i;
+
+ if ((i = find (state.begin(), state.end(), keyval)) != state.end()) {
+ state.erase (i);
+ sort (state.begin(), state.end());
+ }
+
+ if (target) {
+#if KBD_DEBUG
+ if (debug_keyboard) {
+ cerr << "RELEASE: delivering to target " << target << endl;
+ }
+#endif
+ target->key_release_event (event, state);
+ }
+
+ if (default_target) {
+#if KBD_DEBUG
+ if (debug_keyboard) {
+ cerr << "RELEASE: delivering to default target " << default_target << endl;
+ }
+#endif
+ default_target->key_release_event (event, state);
+ }
+ }
+
+ return TRUE;
+}
+
+bool
+Keyboard::key_is_down (uint32_t keyval)
+{
+ return find (state.begin(), state.end(), keyval) != state.end();
+}
+
+void
+Keyboard::set_target (KeyboardTarget *kt)
+{
+ /* XXX possible thread issues here */
+ target = kt;
+}
+
+void
+Keyboard::maybe_unset_target (KeyboardTarget* kt)
+{
+ if (target == kt) {
+ target = 0;
+ }
+}
+
+void
+Keyboard::set_default_target (KeyboardTarget *kt)
+{
+ /* XXX possible thread issues here */
+
+ default_target = kt;
+}
+
+void
+Keyboard::allow_focus (bool yn)
+{
+ focus_allowed = yn;
+}
+
+Keyboard::State
+Keyboard::translate_key_name (const string& name)
+
+{
+ string::size_type i;
+ string::size_type len;
+ bool at_end;
+ string::size_type hyphen;
+ string keyname;
+ string whatevers_left;
+ State result;
+ guint keycode;
+
+ i = 0;
+ len = name.length();
+ at_end = (len == 0);
+
+ while (!at_end) {
+
+ whatevers_left = name.substr (i);
+
+ if ((hyphen = whatevers_left.find_first_of ('-')) == string::npos) {
+
+ /* no hyphen, so use the whole thing */
+
+ keyname = whatevers_left;
+ at_end = true;
+
+ } else {
+
+ /* There is a hyphen. */
+
+ if (hyphen == 0 && whatevers_left.length() == 1) {
+ /* its the first and only character */
+
+ keyname = "-";
+ at_end = true;
+
+ } else {
+
+ /* use the text before the hypen */
+
+ keyname = whatevers_left.substr (0, hyphen);
+
+ if (hyphen == len - 1) {
+ at_end = true;
+ } else {
+ i += hyphen + 1;
+ at_end = (i >= len);
+ }
+ }
+ }
+
+ if (keyname.length() == 1 && isupper (keyname[0])) {
+ result.push_back (GDK_Shift_L);
+ }
+
+ if ((keycode = gdk_keyval_from_name(get_real_keyname (keyname).c_str())) == GDK_VoidSymbol) {
+ error << compose(_("KeyboardTarget: keyname \"%1\" is unknown."), keyname) << endmsg;
+ result.clear();
+ return result;
+ }
+
+ result.push_back (keycode);
+ }
+
+ sort (result.begin(), result.end());
+
+ return result;
+}
+
+string
+Keyboard::get_real_keyname (const string& name)
+{
+
+ if (name == "Control" || name == "Ctrl") {
+ return "Control_L";
+ }
+ if (name == "Meta" || name == "MetaL") {
+ return "Meta_L";
+ }
+ if (name == "MetaR") {
+ return "Meta_R";
+ }
+ if (name == "Alt" || name == "AltL") {
+ return "Alt_L";
+ }
+ if (name == "AltR") {
+ return "Alt_R";
+ }
+ if (name == "Shift") {
+ return "Shift_L";
+ }
+ if (name == "Shift_R") {
+ return "Shift_L";
+ }
+ if (name == " ") {
+ return "space";
+ }
+ if (name == "!") {
+ return "exclam";
+ }
+ if (name == "\"") {
+ return "quotedbl";
+ }
+ if (name == "#") {
+ return "numbersign";
+ }
+ if (name == "$") {
+ return "dollar";
+ }
+ if (name == "%") {
+ return "percent";
+ }
+ if (name == "&") {
+ return "ampersand";
+ }
+ if (name == "'") {
+ return "apostrophe";
+ }
+ if (name == "'") {
+ return "quoteright";
+ }
+ if (name == "(") {
+ return "parenleft";
+ }
+ if (name == ")") {
+ return "parenright";
+ }
+ if (name == "*") {
+ return "asterisk";
+ }
+ if (name == "+") {
+ return "plus";
+ }
+ if (name == ",") {
+ return "comma";
+ }
+ if (name == "-") {
+ return "minus";
+ }
+ if (name == ".") {
+ return "period";
+ }
+ if (name == "/") {
+ return "slash";
+ }
+ if (name == ":") {
+ return "colon";
+ }
+ if (name == ";") {
+ return "semicolon";
+ }
+ if (name == "<") {
+ return "less";
+ }
+ if (name == "=") {
+ return "equal";
+ }
+ if (name == ">") {
+ return "greater";
+ }
+ if (name == "?") {
+ return "question";
+ }
+ if (name == "@") {
+ return "at";
+ }
+ if (name == "[") {
+ return "bracketleft";
+ }
+ if (name == "\\") {
+ return "backslash";
+ }
+ if (name == "]") {
+ return "bracketright";
+ }
+ if (name == "^") {
+ return "asciicircum";
+ }
+ if (name == "_") {
+ return "underscore";
+ }
+ if (name == "`") {
+ return "grave";
+ }
+ if (name == "`") {
+ return "quoteleft";
+ }
+ if (name == "{") {
+ return "braceleft";
+ }
+ if (name == "|") {
+ return "bar";
+ }
+ if (name == "}") {
+ return "braceright";
+ }
+ if (name == "~") {
+ return "asciitilde";
+ }
+
+ return name;
+}
+
+int
+Keyboard::get_prefix (float& val, bool& was_floating)
+{
+ if (current_prefix.length()) {
+ if (current_prefix.find ('.') != string::npos) {
+ was_floating = true;
+ } else {
+ was_floating = false;
+ }
+ if (sscanf (current_prefix.c_str(), "%f", &val) == 1) {
+ return 0;
+ }
+ current_prefix = "";
+ }
+ return -1;
+}
+
+void
+Keyboard::start_prefix ()
+{
+ collecting_prefix = true;
+ current_prefix = "";
+}
+
+void
+Keyboard::clear_modifier_state ()
+{
+ modifier_mask = 0;
+}
+
+void
+Keyboard::check_modifier_state ()
+{
+ char keys[32];
+ int i, j;
+
+ clear_modifier_state ();
+ XQueryKeymap (GDK_DISPLAY(), keys);
+
+ for (i = 0; i < 32; ++i) {
+ for (j = 0; j < 8; ++j) {
+
+ if (keys[i] & (1<<j)) {
+ modifier_mask |= modifier_masks[(i*8)+j];
+ }
+ }
+ }
+}
+
+void
+Keyboard::check_meta_numlock (char keycode, guint mod, string modname)
+{
+ guint alternate_meta_mod;
+ string alternate_meta_modname;
+
+ if (mod == Meta) {
+
+ guint keysym = XKeycodeToKeysym (GDK_DISPLAY(), keycode, 0);
+
+ if (keysym == GDK_Num_Lock) {
+
+ switch (mod) {
+ case GDK_MOD2_MASK:
+ alternate_meta_mod = GDK_MOD3_MASK;
+ alternate_meta_modname = "Mod3";
+ break;
+ case GDK_MOD3_MASK:
+ alternate_meta_mod = GDK_MOD2_MASK;
+ alternate_meta_modname = "Mod2";
+ break;
+ case GDK_MOD4_MASK:
+ alternate_meta_mod = GDK_MOD2_MASK;
+ alternate_meta_modname = "Mod2";
+ break;
+ case GDK_MOD5_MASK:
+ alternate_meta_mod = GDK_MOD2_MASK;
+ alternate_meta_modname = "Mod2";
+ break;
+ default:
+ error << compose (_("Your system is completely broken - NumLock uses \"%1\""
+ "as its modifier. This is madness - see the man page "
+ "for xmodmap to find out how to fix this."),
+ modname)
+ << endmsg;
+ return;
+ }
+
+ warning << compose (_("Your system generates \"%1\" when the NumLock key "
+ "is pressed. This can cause problems when editing "
+ "so Ardour will use %2 to mean Meta rather than %1"),
+ modname, alternate_meta_modname)
+ << endmsg;
+
+ set_meta_modifier (alternate_meta_mod);
+ }
+ }
+}
+
+void
+Keyboard::get_modifier_masks ()
+{
+ XModifierKeymap *modifiers;
+ KeyCode *keycode;
+ int i;
+ int bound;
+
+ XDisplayKeycodes (GDK_DISPLAY(), &min_keycode, &max_keycode);
+
+ /* This function builds a lookup table to provide rapid answers to
+ the question: what, if any, modmask, is associated with a given
+ keycode ?
+ */
+
+ modifiers = XGetModifierMapping (GDK_DISPLAY());
+
+ modifier_masks = new int32_t [max_keycode+1];
+
+ keycode = modifiers->modifiermap;
+
+ for (i = 0; i < modifiers->max_keypermod; ++i) { /* shift */
+ if (*keycode) {
+ modifier_masks[*keycode] = GDK_SHIFT_MASK;
+ // cerr << "Shift = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
+ }
+ keycode++;
+ }
+
+ for (i = 0; i < modifiers->max_keypermod; ++i) keycode++; /* skip lock */
+
+ for (i = 0; i < modifiers->max_keypermod; ++i) { /* control */
+ if (*keycode) {
+ modifier_masks[*keycode] = GDK_CONTROL_MASK;
+ // cerr << "Control = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
+ }
+ keycode++;
+ }
+
+ bound = 0;
+ for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 1 */
+ if (*keycode) {
+ modifier_masks[*keycode] = GDK_MOD1_MASK;
+ // cerr << "Mod1 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
+ bound++;
+ }
+ keycode++;
+ }
+#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
+ if (bound > 1) {
+ warning << compose (_("You have %1 keys bound to \"mod1\""), bound) << endmsg;
+ }
+#endif
+ bound = 0;
+ for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod2 */
+ if (*keycode) {
+ modifier_masks[*keycode] = GDK_MOD2_MASK;
+ check_meta_numlock (*keycode, GDK_MOD2_MASK, "Mod2");
+ //cerr << "Mod2 = " << std::hex << (int) *keycode << std::dec << " = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
+ bound++;
+ }
+ keycode++;
+ }
+#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
+ if (bound > 1) {
+ warning << compose (_("You have %1 keys bound to \"mod2\""), bound) << endmsg;
+ }
+#endif
+ bound = 0;
+ for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod3 */
+ if (*keycode) {
+ modifier_masks[*keycode] = GDK_MOD3_MASK;
+ check_meta_numlock (*keycode, GDK_MOD3_MASK, "Mod3");
+ // cerr << "Mod3 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
+ bound++;
+ }
+ keycode++;
+ }
+#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
+ if (bound > 1) {
+ warning << compose (_("You have %1 keys bound to \"mod3\""), bound) << endmsg;
+ }
+#endif
+ bound = 0;
+ for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 4 */
+ if (*keycode) {
+ modifier_masks[*keycode] = GDK_MOD4_MASK;
+ check_meta_numlock (*keycode, GDK_MOD4_MASK, "Mod4");
+ // cerr << "Mod4 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
+ bound++;
+ }
+ keycode++;
+ }
+#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
+ if (bound > 1) {
+ warning << compose (_("You have %1 keys bound to \"mod4\""), bound) << endmsg;
+ }
+#endif
+ bound = 0;
+ for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 5 */
+ if (*keycode) {
+ modifier_masks[*keycode] = GDK_MOD5_MASK;
+ check_meta_numlock (*keycode, GDK_MOD5_MASK, "Mod5");
+ // cerr << "Mod5 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
+ bound++;
+ }
+ keycode++;
+ }
+#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
+ if (bound > 1) {
+ warning << compose (_("You have %1 keys bound to \"mod5\""), bound) << endmsg;
+ }
+#endif
+
+ XFreeModifiermap (modifiers);
+}
+
+gint
+Keyboard::enter_window (GdkEventCrossing *ev, KeyboardTarget *kt)
+{
+ switch (ev->detail) {
+ case GDK_NOTIFY_INFERIOR:
+ if (debug_keyboard) {
+ cerr << "INFERIOR crossing to " << kt->name() << endl;
+ }
+ break;
+
+ case GDK_NOTIFY_VIRTUAL:
+ if (debug_keyboard) {
+ cerr << "VIRTUAL crossing to " << kt->name() << endl;
+ }
+ /* fallthru */
+
+ default:
+ if (debug_keyboard) {
+ cerr << "REAL crossing to " << kt->name() << endl;
+ cerr << "set current target to " << kt->name() << endl;
+ }
+
+ set_target (kt);
+ check_modifier_state ();
+ }
+
+ return FALSE;
+}
+
+gint
+Keyboard::leave_window (GdkEventCrossing *ev)
+{
+ switch (ev->detail) {
+ case GDK_NOTIFY_INFERIOR:
+ if (debug_keyboard) {
+ cerr << "INFERIOR crossing ... out\n";
+ }
+ break;
+
+ case GDK_NOTIFY_VIRTUAL:
+ if (debug_keyboard) {
+ cerr << "VIRTUAL crossing ... out\n";
+ }
+ /* fallthru */
+
+ default:
+ if (debug_keyboard) {
+ cerr << "REAL CROSSING ... out\n";
+ cerr << "clearing current target\n";
+ }
+
+ set_target (0);
+ state.clear ();
+ clear_modifier_state ();
+ }
+ return FALSE;
+
+}
+
+void
+Keyboard::register_target (KeyboardTarget *kt)
+{
+ /* do not register the default - its not meant to be
+ an actual window, just a fallback if the current
+ target for keyboard events doesn't handle an event.
+ */
+
+ if (kt->name() == X_("default")) {
+ return;
+ }
+
+ kt->window().enter_notify_event.connect (bind (slot (*this, &Keyboard::enter_window), kt));
+ kt->window().leave_notify_event.connect (slot (*this, &Keyboard::leave_window));
+
+ kt->GoingAway.connect (bind (slot (*this, &Keyboard::maybe_unset_target), kt));
+ kt->Hiding.connect (bind (slot (*this, &Keyboard::maybe_unset_target), kt));
+}
+
+void
+Keyboard::set_current_dialog (ArdourDialog* dialog)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Keyboard::set_current_dialog), dialog));
+
+ current_dialog = dialog;
+
+ if (current_dialog) {
+
+ if (find (known_dialogs.begin(), known_dialogs.end(), dialog) == known_dialogs.end()) {
+
+ current_dialog->GoingAway.connect
+ (bind (slot (*this, &Keyboard::set_current_dialog),
+ reinterpret_cast<ArdourDialog *>(0)));
+ current_dialog->Hiding.connect
+ (bind (slot (*this, &Keyboard::set_current_dialog),
+ reinterpret_cast<ArdourDialog *>(0)));
+
+ current_dialog->unmap_event.connect (slot (*this, &Keyboard::current_dialog_vanished));
+
+ known_dialogs.push_back (dialog);
+ }
+ }
+}
+
+gint
+Keyboard::current_dialog_vanished (GdkEventAny *ev)
+{
+ current_dialog = 0;
+ state.clear ();
+ focus_allowed = false;
+ clear_modifier_state ();
+ current_prefix = "";
+
+ return FALSE;
+}
+
+void
+Keyboard::close_current_dialog ()
+{
+ if (current_dialog) {
+ current_dialog->hide ();
+ }
+}
+
+void
+Keyboard::set_edit_button (guint but)
+{
+ edit_but = but;
+}
+
+void
+Keyboard::set_edit_modifier (guint mod)
+{
+ RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~edit_mod);
+ edit_mod = mod;
+ RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | edit_mod);
+}
+
+void
+Keyboard::set_delete_button (guint but)
+{
+ delete_but = but;
+}
+
+void
+Keyboard::set_delete_modifier (guint mod)
+{
+ RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~delete_mod);
+ delete_mod = mod;
+ RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | delete_mod);
+}
+
+void
+Keyboard::set_meta_modifier (guint mod)
+{
+ /* 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;
+}
+
+void
+Keyboard::set_snap_modifier (guint mod)
+{
+ RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_mod);
+ snap_mod = mod;
+ RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_mod);
+}
+
+bool
+Keyboard::is_edit_event (GdkEventButton *ev)
+{
+ return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
+ (ev->button == Keyboard::edit_button()) &&
+ ((ev->state & RelevantModifierKeyMask) == Keyboard::edit_modifier());
+}
+
+bool
+Keyboard::is_delete_event (GdkEventButton *ev)
+{
+ return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
+ (ev->button == Keyboard::delete_button()) &&
+ ((ev->state & RelevantModifierKeyMask) == Keyboard::delete_modifier());
+}
+
+bool
+Keyboard::is_context_menu_event (GdkEventButton *ev)
+{
+ return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
+ (ev->button == 3) &&
+ ((ev->state & RelevantModifierKeyMask) == 0);
+}
+
+bool
+Keyboard::no_modifiers_active (guint state)
+{
+ return (state & RelevantModifierKeyMask) == 0;
+}
+
+bool
+Keyboard::modifier_state_contains (guint state, ModifierMask mask)
+{
+ return (state & mask) == (guint) mask;
+}
+
+bool
+Keyboard::modifier_state_equals (guint state, ModifierMask mask)
+{
+ return (state & RelevantModifierKeyMask) == (guint) mask;
+}
+
+gint
+Keyboard::focus_in_handler (GdkEventFocus* ev)
+{
+ allow_focus (true);
+ return FALSE;
+}
+
+gint
+Keyboard::focus_out_handler (GdkEventFocus* ev)
+{
+ allow_focus (false);
+ return FALSE;
+}
diff --git a/gtk2_ardour/keyboard.h b/gtk2_ardour/keyboard.h
new file mode 100644
index 0000000000..d7d527e63e
--- /dev/null
+++ b/gtk2_ardour/keyboard.h
@@ -0,0 +1,153 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_keyboard_h__
+#define __ardour_keyboard_h__
+
+#include <vector>
+#include <string>
+
+#include <sigc++/signal_system.h>
+#include <gtk/gtk.h>
+
+#include <ardour/types.h>
+#include <ardour/stateful.h>
+
+using std::vector;
+using std::string;
+
+class KeyboardTarget;
+class ArdourDialog;
+
+class Keyboard : public SigC::Object, Stateful
+{
+ public:
+ Keyboard ();
+ ~Keyboard ();
+
+ XMLNode& get_state (void);
+ int set_state (const XMLNode&);
+
+ typedef vector<uint32_t> State;
+
+ void set_target (KeyboardTarget *);
+ void set_default_target (KeyboardTarget *);
+ void allow_focus (bool);
+
+ gint focus_in_handler (GdkEventFocus*);
+ gint focus_out_handler (GdkEventFocus*);
+
+ int get_prefix(float&, bool& was_floating);
+ void start_prefix ();
+
+ static State translate_key_name (const string&);
+ static string get_real_keyname (const string& name);
+
+ void register_target (KeyboardTarget *);
+
+ void set_current_dialog (ArdourDialog*);
+ void close_current_dialog ();
+
+ typedef uint32_t ModifierMask;
+
+ static uint32_t Control;
+ static uint32_t Shift;
+ static uint32_t Alt;
+ static uint32_t Meta;
+
+ bool key_is_down (uint32_t keyval);
+
+ static GdkModifierType RelevantModifierKeyMask;
+
+ static bool no_modifier_keys_pressed(GdkEventButton* ev) {
+ return (ev->state & RelevantModifierKeyMask) == 0;
+ }
+
+ static bool modifier_state_contains (guint state, ModifierMask);
+ static bool modifier_state_equals (guint state, ModifierMask);
+
+ 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); }
+
+ static guint edit_button() { return edit_but; }
+ static void set_edit_button (guint);
+ static guint edit_modifier() { return edit_mod; }
+ static void set_edit_modifier(guint);
+
+ static guint delete_button() { return delete_but; }
+ static void set_delete_button(guint);
+ static guint delete_modifier() { return delete_mod; }
+ static void set_delete_modifier(guint);
+
+ static bool is_edit_event (GdkEventButton*);
+ static bool is_delete_event (GdkEventButton*);
+ static bool is_context_menu_event (GdkEventButton*);
+
+ static Keyboard& the_keyboard() { return *_the_keyboard; }
+
+ private:
+ static Keyboard* _the_keyboard;
+
+ bool _queue_events;
+ bool _flush_queue;
+ guint32 playback_ignore_count;
+
+ guint snooper_id;
+ State state;
+ KeyboardTarget* target;
+ KeyboardTarget* default_target;
+ bool focus_allowed;
+ bool collecting_prefix;
+ string current_prefix;
+ int* modifier_masks;
+ int modifier_mask;
+ int min_keycode;
+ int max_keycode;
+ ArdourDialog* current_dialog;
+ std::vector<ArdourDialog*> known_dialogs;
+
+ static guint edit_but;
+ static guint edit_mod;
+ static guint delete_but;
+ static guint delete_mod;
+ static guint snap_mod;
+
+ static gint _snooper (GtkWidget*, GdkEventKey*, gpointer);
+ gint snooper (GtkWidget*, GdkEventKey*);
+
+ void maybe_unset_target (KeyboardTarget *);
+ void queue_event (GdkEventKey*);
+ void playback_queue ();
+ void clear_queue ();
+ void get_modifier_masks ();
+ void check_modifier_state ();
+ void clear_modifier_state ();
+ gint enter_window (GdkEventCrossing*, KeyboardTarget*);
+ gint leave_window (GdkEventCrossing*);
+ gint current_dialog_vanished (GdkEventAny*);
+
+ void check_meta_numlock (char keycode, guint mod, string modname);
+};
+
+#endif /* __ardour_keyboard_h__ */
diff --git a/gtk2_ardour/keyboard_target.cc b/gtk2_ardour/keyboard_target.cc
new file mode 100644
index 0000000000..9f92d2f460
--- /dev/null
+++ b/gtk2_ardour/keyboard_target.cc
@@ -0,0 +1,258 @@
+/*
+ Copyright (C) 2001-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gdk/gdkkeysyms.h>
+#include <pbd/error.h>
+
+#include "keyboard.h"
+#include "keyboard_target.h"
+
+#include "i18n.h"
+
+using std::pair;
+
+KeyboardTarget::ActionMap KeyboardTarget::actions;
+
+KeyboardTarget::KeyboardTarget (Gtk::Window& win, string name)
+ : _window (win)
+{
+ _name = name;
+ Keyboard::the_keyboard().register_target (this);
+}
+
+KeyboardTarget::~KeyboardTarget ()
+{
+ GoingAway ();
+}
+
+void
+KeyboardTarget::key_release_event (GdkEventKey *event, Keyboard::State& state)
+{
+ // relax
+}
+
+void
+KeyboardTarget::key_press_event (GdkEventKey *event, Keyboard::State& state, bool& handled)
+{
+ KeyMap::iterator result;
+
+ if ((result = keymap.find (state)) != keymap.end()) {
+ (*result).second ();
+ handled = true;
+ }
+}
+
+int
+KeyboardTarget::add_binding (string keystring, string action)
+{
+ KeyMap::iterator existing;
+ Keyboard::State state;
+ KeyAction key_action = 0;
+
+ state = Keyboard::translate_key_name (keystring);
+
+ if (keystring.length() == 0) {
+ error << _("KeyboardTarget: empty string passed to add_binding.")
+ << endmsg;
+ return -1;
+ }
+
+ if (state.size() == 0) {
+ error << compose(_("KeyboardTarget: no translation found for \"%1\""), keystring) << endmsg;
+ return -1;
+ }
+
+ if (find_action (action, key_action)) {
+ error << compose(_("KeyboardTarget: unknown action \"%1\""), action) << endmsg;
+ return -1;
+ }
+
+ /* remove any existing binding */
+
+ if ((existing = keymap.find (state)) != keymap.end()) {
+ keymap.erase (existing);
+ }
+
+ keymap.insert (pair<Keyboard::State,KeyAction> (state, key_action));
+ bindings.insert (pair<string,string> (keystring, action));
+ return 0;
+}
+
+string
+KeyboardTarget::get_binding (string name)
+{
+ BindingMap::iterator i;
+
+ for (i = bindings.begin(); i != bindings.end(); ++i) {
+
+ if (i->second == name) {
+
+ /* convert keystring to GTK format */
+
+ string str = i->first;
+ string gtkstr;
+ string::size_type p;
+
+ while (1) {
+
+ if ((p = str.find ('-')) == string::npos || (p == str.length() - 1)) {
+ break;
+ }
+
+ gtkstr += '<';
+ gtkstr += str.substr (0, p);
+ gtkstr += '>';
+
+ str = str.substr (p+1);
+
+ }
+
+ gtkstr += str;
+
+ if (gtkstr.length() == 0) {
+ return i->first;
+ }
+
+ return gtkstr;
+ }
+ }
+ return string ();
+}
+
+void
+KeyboardTarget::show_all_actions ()
+{
+ ActionMap::iterator i;
+
+ for (i = actions.begin(); i != actions.end(); ++i) {
+ cout << i->first << endl;
+ }
+}
+
+int
+KeyboardTarget::add_action (string name, KeyAction action)
+{
+ pair<string,KeyAction> newpair;
+ pair<ActionMap::iterator,bool> result;
+ newpair.first = name;
+ newpair.second = action;
+
+ result = actions.insert (newpair);
+ return result.second ? 0 : -1;
+}
+
+int
+KeyboardTarget::find_action (string name, KeyAction& action)
+{
+ map<string,KeyAction>::iterator i;
+
+ if ((i = actions.find (name)) != actions.end()) {
+ action = i->second;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int
+KeyboardTarget::remove_action (string name)
+{
+ map<string,KeyAction>::iterator i;
+
+ if ((i = actions.find (name)) != actions.end()) {
+ actions.erase (i);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+XMLNode&
+KeyboardTarget::get_binding_state () const
+{
+ XMLNode *node = new XMLNode ("context");
+ BindingMap::const_iterator i;
+
+ node->add_property ("name", _name);
+
+ for (i = bindings.begin(); i != bindings.end(); ++i) {
+ XMLNode *child;
+
+ child = new XMLNode ("binding");
+ child->add_property ("keys", i->first);
+ child->add_property ("action", i->second);
+ node->add_child_nocopy (*child);
+ }
+
+ return *node;
+}
+
+int
+KeyboardTarget::set_binding_state (const XMLNode& node)
+{
+ XMLNodeList nlist = node.children();
+ XMLNodeConstIterator niter;
+ XMLNode *child_node;
+
+ bindings.clear ();
+ keymap.clear ();
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ child_node = *niter;
+
+ if (child_node->name() == "context") {
+ XMLProperty *prop;
+
+ if ((prop = child_node->property ("name")) != 0) {
+ if (prop->value() == _name) {
+ return load_bindings (*child_node);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+KeyboardTarget::load_bindings (const XMLNode& node)
+{
+ XMLNodeList nlist = node.children();
+ XMLNodeConstIterator niter;
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ XMLProperty *keys;
+ XMLProperty *action;
+
+ keys = (*niter)->property ("keys");
+ action = (*niter)->property ("action");
+
+ if (!keys || !action) {
+ error << _("misformed binding node - ignored") << endmsg;
+ continue;
+ }
+
+ add_binding (keys->value(), action->value());
+
+ }
+
+ return 0;
+}
+
diff --git a/gtk2_ardour/keyboard_target.h b/gtk2_ardour/keyboard_target.h
new file mode 100644
index 0000000000..cb76579314
--- /dev/null
+++ b/gtk2_ardour/keyboard_target.h
@@ -0,0 +1,82 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_keyboard_target_h__
+#define __ardour_keyboard_target_h__
+
+#include <map>
+#include <string>
+#include <sigc++/signal_system.h>
+#include <gdk/gdk.h>
+#include <gtk--/window.h>
+#include <pbd/xml++.h>
+
+#include "keyboard.h"
+
+using std::map;
+using std::string;
+
+class KeyboardTarget
+{
+ public:
+ KeyboardTarget(Gtk::Window& w, string name);
+ virtual ~KeyboardTarget();
+
+ SigC::Signal0<void> Hiding;
+ SigC::Signal0<void> GoingAway;
+
+ typedef SigC::Slot0<void> KeyAction;
+
+ string name() const { return _name; }
+
+ void key_press_event (GdkEventKey *, Keyboard::State&, bool& handled);
+ void key_release_event (GdkEventKey *, Keyboard::State&);
+
+ int add_binding (string keys, string name);
+ string get_binding (string name); /* returns keys bound to name */
+
+ XMLNode& get_binding_state () const;
+ int set_binding_state (const XMLNode&);
+
+ static int32_t add_action (string, KeyAction);
+ static int32_t find_action (string, KeyAction&);
+ static int32_t remove_action (string);
+ static void show_all_actions();
+
+ Gtk::Window& window() const { return _window; }
+
+ protected:
+ typedef map<Keyboard::State,KeyAction> KeyMap;
+ typedef map<string,string> BindingMap;
+
+ KeyMap keymap;
+ BindingMap bindings;
+
+ private:
+ typedef map<string,KeyAction> ActionMap;
+ static ActionMap actions;
+ string _name;
+ Gtk::Window& _window;
+
+ int load_bindings (const XMLNode&);
+};
+
+#endif /* __ardour_keyboard_target_h__ */
+
diff --git a/gtk2_ardour/library_ui.cc b/gtk2_ardour/library_ui.cc
new file mode 100644
index 0000000000..7e17079e49
--- /dev/null
+++ b/gtk2_ardour/library_ui.cc
@@ -0,0 +1,1541 @@
+/*
+ Copyright (C) 2000-2003 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 <vector>
+#include <string>
+#include <cstdlib>
+#include <cctype>
+#include <cerrno>
+
+#include <sys/stat.h>
+#include <sndfile.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <pbd/basename.h>
+#include <pbd/forkexec.h>
+#include <pbd/ftw.h>
+#include <gtk--.h>
+#include <gtk--/fileselection.h>
+#include <gtkmmext/gtk_ui.h>
+#include <ardour/audio_library.h>
+#include <ardour/audioregion.h>
+#include <ardour/region.h>
+#include <ardour/session.h>
+#include <ardour/sndfile_helpers.h>
+#include <ardour/sndfilesource.h>
+#include <ardour/utils.h>
+
+#include <gtkmmext/doi.h>
+
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "library_ui.h"
+#include "prompter.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace SigC;
+
+SoundFileSelector::SoundFileSelector ()
+ : ArdourDialog ("sound file selector"),
+ vbox(false, 4),
+ sfdb_label(_("Soundfile Library")),
+ fs_label(_("Filesystem")),
+ import_box(false, 4),
+ import_btn (X_("foo")), // force a label
+ split_channels (_("Split Channels"), 0.0),
+ info_box (0)
+{
+ set_title(_("ardour: soundfile selector"));
+ set_name("SoundFileSelector");
+ set_default_size (500, 400);
+ set_keyboard_input (true);
+
+ add (main_box);
+ main_box.set_border_width (6);
+
+ main_box.pack_start(vbox, true, true);
+ vbox.pack_start(notebook, true, true);
+ vbox.pack_start(import_box, false, false);
+
+ notebook.set_name("SoundFileSelectorNotebook");
+ notebook.append_page(sf_browser, fs_label);
+ notebook.append_page(sfdb_tree, sfdb_label);
+
+ import_box.set_homogeneous (true);
+ import_box.pack_start(import_btn);
+ import_box.pack_start (split_channels);
+
+ split_channels.set_active(false);
+ split_channels.set_sensitive (false);
+
+ delete_event.connect (slot (*this, &ArdourDialog::wm_close_event));
+
+ import_btn.clicked.connect (slot (*this, &SoundFileSelector::import_btn_clicked));
+
+ sfdb_tree.group_selected.connect (slot(*this, &SoundFileSelector::sfdb_group_selected));
+ sfdb_tree.member_selected.connect (bind (slot(*this, &SoundFileSelector::member_selected), true));
+ sf_browser.member_selected.connect (bind (slot(*this, &SoundFileSelector::member_selected), false));
+ sf_browser.member_deselected.connect (bind (slot(*this, &SoundFileSelector::member_deselected), false));
+ sfdb_tree.deselected.connect (slot(*this, &SoundFileSelector::sfdb_deselected));
+ sf_browser.group_selected.connect (slot(*this, &SoundFileSelector::browser_group_selected));
+ notebook.switch_page.connect (slot(*this, &SoundFileSelector::page_switched));
+}
+
+SoundFileSelector::~SoundFileSelector()
+{
+}
+
+void
+SoundFileSelector::import_btn_clicked ()
+{
+ vector<string> paths;
+
+ PublicEditor& edit = ARDOUR_UI::instance()->the_editor();
+ ARDOUR::Session* sess = edit.current_session();
+ if (sess) {
+ sess->cancel_audition();
+ }
+
+ if (sfdb) {
+ for (list<string>::iterator i = sfdb_tree.selection.begin(); i != sfdb_tree.selection.end(); ++i) {
+ paths.push_back (Library->get_member_filename (*i));
+ }
+ } else {
+ for (list<RowTaggedString>::iterator i = sf_browser.selection.begin(); i != sf_browser.selection.end(); ++i) {
+ paths.push_back ((*i).str);
+ }
+ }
+
+ Action (paths, split_channels.get_active()); /* EMIT_SIGNAL */
+
+ if (sfdb) {
+ sfdb_tree.clear_selection ();
+ } else {
+ sf_browser.clear_selection ();
+ }
+
+ if (hide_after_action) {
+ hide ();
+ Action.clear();
+ }
+ hide_after_action = false;
+
+}
+
+void
+SoundFileSelector::run (string action, bool multi, bool hide_after)
+{
+ static_cast<Label*>(import_btn.get_child())->set_text (action);
+ import_btn.set_sensitive(false);
+
+ if (multi) {
+ split_channels.show ();
+ } else {
+ split_channels.hide ();
+ }
+
+ multiable = multi;
+ hide_after_action = hide_after;
+
+ set_position (GTK_WIN_POS_MOUSE);
+ ArdourDialog::run ();
+}
+
+void
+SoundFileSelector::hide_import_stuff()
+{
+ import_box.hide_all();
+}
+
+void
+SoundFileSelector::page_switched(Gtk::Notebook_Helpers::Page* page, guint page_num)
+{
+ if (page_num == 1) {
+ sfdb = true;
+ if (!sfdb_tree.selection.empty()) {
+ member_selected (sfdb_tree.selection.back(), true);
+ }
+ } else {
+ sfdb = false;
+ if (!sf_browser.selection.empty()) {
+ member_selected (sf_browser.selection.back().str, false);
+ }
+ }
+}
+
+void
+SoundFileSelector::sfdb_deselected()
+{
+ import_btn.set_sensitive(false);
+}
+
+void
+SoundFileSelector::browser_group_selected()
+{
+ sfdb_group_selected();
+}
+
+void
+SoundFileSelector::sfdb_group_selected()
+{
+ import_btn.set_sensitive(false);
+ split_channels.set_sensitive(false);
+
+ if (info_box) {
+ delete info_box;
+ info_box = 0;
+ }
+}
+
+void
+SoundFileSelector::member_selected(string member, bool sfdb)
+{
+ if (info_box) {
+ delete info_box;
+ info_box = 0;
+ }
+
+ if (member.empty()) {
+ return;
+ }
+
+ try {
+ info_box = new SoundFileBox(member, sfdb);
+ } catch (failed_constructor& err) {
+ /* nothing to do */
+ return;
+ }
+
+ main_box.pack_start (*info_box, false, false);
+
+ import_btn.set_sensitive (true);
+
+ if (multiable) {
+ split_channels.set_sensitive(true);
+ }
+}
+
+void
+SoundFileSelector::member_deselected (bool sfdb)
+{
+ bool keep_action_available;
+ string last;
+
+ if (info_box) {
+ delete info_box;
+ info_box = 0;
+ }
+
+ if (sfdb) {
+ if ((keep_action_available = !sfdb_tree.selection.empty())) {
+ last = sfdb_tree.selection.back();
+ }
+
+ } else {
+ if ((keep_action_available = !sf_browser.selection.empty())) {
+ last = sf_browser.selection.back().str;
+ }
+ }
+
+ if (keep_action_available) {
+
+ if (info_box) {
+ delete info_box;
+ info_box = 0;
+ }
+
+ try {
+ info_box = new SoundFileBox(last, sfdb);
+ } catch (failed_constructor& err) {
+ /* nothing to do */
+ return;
+ }
+
+ import_btn.set_sensitive (true);
+
+ if (multiable) {
+ split_channels.set_sensitive(true);
+ }
+
+ main_box.pack_start(*info_box, false, false);
+ }
+}
+
+void
+SoundFileSelector::get_result (vector<string>& paths, bool& split)
+{
+ if (sfdb) {
+ for (list<string>::iterator i = sfdb_tree.selection.begin(); i != sfdb_tree.selection.end(); ++i) {
+ paths.push_back (Library->get_member_filename (*i));
+ }
+ } else {
+ for (list<RowTaggedString>::iterator i = sf_browser.selection.begin(); i != sf_browser.selection.end(); ++i) {
+ paths.push_back ((*i).str);
+ }
+ }
+
+ split = split_channels.get_active();
+}
+
+SoundFileBrowser::SoundFileBrowser()
+ :
+ Gtk::VBox(false, 3)
+{
+ fs_selector.hide_fileop_buttons();
+ fs_selector.set_filename("/");
+
+ // This is ugly ugly ugly. But gtk1 (and gtk2) don't give us any
+ // choice.
+ GtkFileSelection* fs_gtk = fs_selector.gtkobj();
+ file_list= Gtk::wrap((GtkCList*)(fs_gtk->file_list));
+
+ Gtk::VBox* vbox = manage(new Gtk::VBox);
+ Gtk::HBox* tmphbox = manage(new Gtk::HBox);
+ Gtk::OptionMenu* option_menu = Gtk::wrap((GtkOptionMenu*)(fs_gtk->history_pulldown));
+ option_menu->reparent(*tmphbox);
+ vbox->pack_start(*tmphbox, false, false);
+
+ /* XXX This interface isn't supported in gtkmm. Redo it with a BoxList&
+ vbox->set_child_packing(*option_menu, false, false); */
+
+ Gtk::HBox* hbox = manage(new Gtk::HBox);
+ Gtk::ScrolledWindow* dir_scroll = manage(new Gtk::ScrolledWindow);
+ Gtk::ScrolledWindow* file_scroll = manage(new Gtk::ScrolledWindow);
+ dir_scroll->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ file_scroll->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ Gtk::CList* dir_list = Gtk::wrap((GtkCList*)(fs_gtk->dir_list));
+
+ dir_list->reparent(*dir_scroll);
+ file_list->reparent(*file_scroll);
+ file_list->set_selection_mode (GTK_SELECTION_MULTIPLE);
+ hbox->pack_start(*dir_scroll);
+ hbox->pack_start(*file_scroll);
+ vbox->pack_start(*hbox, true, true);
+
+ Gtk::VBox* tmpvbox = manage(new Gtk::VBox);
+
+ Gtk::Label* selection_text = Gtk::wrap((GtkLabel*)(fs_gtk->selection_text));
+ selection_text->reparent(*tmpvbox);
+ Gtk::Entry* selection_entry= Gtk::wrap((GtkEntry*)(fs_gtk->selection_entry));
+ selection_entry->reparent(*tmpvbox);
+ vbox->pack_start(*tmpvbox, false, false);
+
+ pack_start(*vbox, true, true);
+
+ dir_list->select_row.connect(slot (*this, &SoundFileBrowser::dir_list_selected));
+ file_list->select_row.connect(slot (*this, &SoundFileBrowser::file_list_selected));
+ file_list->unselect_row.connect(slot (*this, &SoundFileBrowser::file_list_deselected));
+
+ dir_list->set_name("SoundFileBrowserList");
+ file_list->set_name("SoundFileBrowserList");
+}
+
+SoundFileBrowser::~SoundFileBrowser()
+{
+}
+
+void
+SoundFileBrowser::clear_selection ()
+{
+ file_list->selection().clear ();
+ selection.clear ();
+}
+
+void
+SoundFileBrowser::dir_list_selected(gint row, gint col, GdkEvent* ev)
+{
+ current_member = "";
+ current_group = "";
+
+ group_selected(); /* EMIT_SIGNAL */
+}
+
+void
+SoundFileBrowser::file_list_selected(gint row, gint col, GdkEvent* ev)
+{
+ current_group = "";
+ current_member = fs_selector.get_filename();
+
+ selection.push_back (RowTaggedString (row, current_member));
+
+ member_selected(safety_check_file(current_member)); /* EMIT_SIGNAL */
+}
+
+void
+SoundFileBrowser::file_list_deselected(gint row, gint col, GdkEvent* ev)
+{
+ current_group = "";
+ current_member = file_list->cell (row, 0).get_text();
+
+ for (list<RowTaggedString>::iterator i = selection.begin(); i != selection.end(); ++i) {
+ if ((*i).row == row) {
+ selection.erase (i);
+ break;
+ }
+ }
+
+ member_deselected(); /* EMIT_SIGNAL */
+}
+
+string
+SoundFileBrowser::safety_check_file(string file)
+{
+ if (file.rfind(".wav") == string::npos &&
+ file.rfind(".aiff")== string::npos &&
+ file.rfind(".aif") == string::npos &&
+ file.rfind(".snd") == string::npos &&
+ file.rfind(".au") == string::npos &&
+ file.rfind(".raw") == string::npos &&
+ file.rfind(".sf") == string::npos &&
+ file.rfind(".cdr") == string::npos &&
+ file.rfind(".smp") == string::npos &&
+ file.rfind(".maud")== string::npos &&
+ file.rfind(".vwe") == string::npos &&
+ file.rfind(".paf") == string::npos &&
+ file.rfind(".voc") == string::npos) {
+ return "";
+ } else {
+ return file;
+ }
+}
+
+static int32_t process_node (const char *file, const struct stat *sb, int32_t flag);
+static string length2string (const int, const int);
+
+LibraryTree::LibraryTree ()
+ : Gtk::VBox(false, 3),
+ btn_box_top(true, 4),
+ btn_box_bottom (true, 4),
+ add_btn(_("Add to Library...")),
+ remove_btn(_("Remove...")),
+ find_btn(_("Find...")),
+ folder_btn(_("Add Folder")),
+ files_select(_("Add audio file or directory"))
+{
+ set_border_width (3);
+
+ pack_start(hbox, true, true);
+ pack_start(btn_box_top, false, false);
+ pack_start(btn_box_bottom, false, false);
+
+ hbox.pack_start(scroll);
+ scroll.set_usize (200, 150);
+ scroll.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ scroll.add_with_viewport(tree);
+ tree.set_selection_mode(GTK_SELECTION_MULTIPLE);
+
+ btn_box_top.pack_start(add_btn);
+ btn_box_top.pack_start(folder_btn);
+ btn_box_top.pack_start(remove_btn);
+
+ btn_box_bottom.pack_start(find_btn);
+
+ remove_btn.set_sensitive (false);
+
+ add_btn.clicked.connect (slot (*this, &LibraryTree::add_btn_clicked));
+ folder_btn.clicked.connect (slot(*this, &LibraryTree::folder_btn_clicked));
+ remove_btn.clicked.connect (slot(*this, &LibraryTree::remove_btn_clicked));
+ find_btn.clicked.connect (slot (*this, &LibraryTree::find_btn_clicked));
+
+ files_select.hide_fileop_buttons();
+ files_select.set_filename("/");
+ files_select.get_ok_button()->clicked.connect (slot ( *this,
+ &LibraryTree::file_ok_clicked));
+ files_select.get_cancel_button()->clicked.connect (slot ( *this,
+ &LibraryTree::file_cancel_clicked));
+
+
+ Library->added_group.connect (slot (*this, &LibraryTree::added_group));
+ Library->removed_group.connect (slot (*this, &LibraryTree::removed_group));
+ Library->added_member.connect (slot (*this, &LibraryTree::added_member));
+ Library->removed_member.connect (slot (*this, &LibraryTree::removed_member));
+
+ current_group = "";
+ current_member = "";
+
+ populate ();
+}
+
+LibraryTree::~LibraryTree ()
+{
+}
+
+void
+LibraryTree::clear_selection ()
+{
+ using namespace Gtk::Tree_Helpers;
+ for (SelectionList::iterator i = tree.selection().begin(); i != tree.selection().end(); ++i) {
+ (*i)->deselect ();
+ }
+ selection.clear ();
+}
+
+void
+LibraryTree::added_group (string group, string parent)
+{
+ using namespace Gtk;
+ ENSURE_GUI_THREAD(bind (slot (*this, &LibraryTree::added_group), group, parent));
+
+ Tree* parent_tree;
+ if (parent.length()) {
+ parent_tree = uri_mapping[parent]->get_subtree();
+ } else {
+ parent_tree = &tree;
+ }
+
+ TreeItem *item = manage(new TreeItem(Library->get_label(group)));
+ Tree_Helpers::ItemList items = parent_tree->tree();
+ Tree_Helpers::ItemList::iterator i = items.begin();
+
+ list<string> groups;
+ Library->get_groups(groups, parent);
+ list<string>::iterator j = groups.begin();
+
+ while (i != items.end() && j != groups.end()){
+ if ((cmp_nocase(Library->get_label(group),Library->get_label(*j)) <= 0) ||
+ !((*i)->get_subtree())){
+
+ break;
+ }
+ ++i;
+ ++j;
+ }
+
+ parent_tree->tree().insert (i, *item);
+ Tree *subtree = manage(new Tree());
+ item->set_subtree (*subtree);
+ item->expand();
+
+ item->select.connect (bind(slot(*this,&LibraryTree::cb_group_select), item, group));
+
+ uri_mapping.insert(map<string, TreeItem*>::value_type(group, item));
+ uri_parent.insert(map<string,string>::value_type(group, parent));
+
+ subtree->show();
+ item->show();
+
+ while (gtk_events_pending()){
+ gtk_main_iteration();
+ }
+}
+
+void
+LibraryTree::removed_group (string group)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LibraryTree::removed_group), group));
+
+ Gtk::TreeItem* group_item = uri_mapping[group];
+
+ Gtk::Tree* parent_tree;
+ if (uri_parent[group].length()) {
+ parent_tree = uri_mapping[uri_parent[group]]->get_subtree();
+ } else {
+ parent_tree = &tree;
+ }
+
+ parent_tree->tree().remove(*group_item);
+ uri_mapping.erase(uri_mapping.find(group));
+ uri_parent.erase(uri_parent.find(group));
+
+ while (gtk_events_pending()){
+ gtk_main_iteration();
+ }
+}
+
+void
+LibraryTree::added_member (string member, string parent)
+{
+ using namespace Gtk;
+
+ ENSURE_GUI_THREAD(bind (slot (*this, &LibraryTree::added_member), member, parent));
+
+ Tree* parent_tree;
+ if (parent.length()) {
+ parent_tree = uri_mapping[parent]->get_subtree();
+ } else {
+ parent_tree = &tree;
+ }
+
+ TreeItem *item = manage(new TreeItem(Library->get_label(member)));
+ Tree_Helpers::ItemList items = parent_tree->tree();
+ Tree_Helpers::ItemList::iterator i = items.begin();
+
+ list<string> members;
+ Library->get_members(members, parent);
+ list<string>::iterator j = members.begin();
+
+ while (i != items.end() && j != members.end()){
+ if (cmp_nocase(Library->get_label(member), Library->get_label(*j)) <= 0){
+ break;
+ }
+ ++i;
+ ++j;
+ }
+
+ parent_tree->tree().insert (i, *item);
+
+ item->select.connect
+ (bind(slot(*this,&LibraryTree::cb_member_select), item, member));
+ item->deselect.connect
+ (bind(slot(*this,&LibraryTree::cb_member_deselect), item, member));
+
+ uri_mapping.insert(map<string, TreeItem*>::value_type(member, item));
+ uri_parent.insert(map<string,string>::value_type(member, parent));
+
+ item->show();
+
+ while (gtk_events_pending()){
+ gtk_main_iteration();
+ }
+}
+
+void
+LibraryTree::removed_member (string member)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LibraryTree::removed_member), member));
+
+ Gtk::TreeItem* member_item = uri_mapping[member];
+
+ Gtk::Tree* parent_tree;
+ if (uri_parent[member].length()) {
+ parent_tree = uri_mapping[uri_parent[member]]->get_subtree();
+ } else {
+ parent_tree = &tree;
+ }
+
+ parent_tree->tree().remove(*member_item);
+ uri_mapping.erase(uri_mapping.find(member));
+ uri_parent.erase(uri_parent.find(member));
+
+ while (gtk_events_pending()){
+ gtk_main_iteration();
+ }
+}
+
+void
+LibraryTree::populate ()
+{
+ subpopulate (&tree, current_group);
+}
+
+void
+LibraryTree::subpopulate (Gtk::Tree* tree, string group)
+{
+ using namespace Gtk;
+
+ list<string> groups;
+ Library->get_groups(groups, group);
+
+ list<string>::iterator i;
+
+ for (i = groups.begin(); i != groups.end(); ++i) {
+ TreeItem *item =
+ manage(new TreeItem(Library->get_label(*i)));
+ tree->append (*item);
+ Tree *subtree = manage(new Tree());
+ item->set_subtree (*subtree);
+
+ uri_mapping.insert(map<string, Gtk::TreeItem*>::value_type(*i, item));
+ uri_parent.insert(map<string,string>::value_type(*i, group));
+
+ item->select.connect
+ (bind(slot(*this,&LibraryTree::cb_group_select), item, *i));
+
+ subpopulate (subtree, *i);
+ subtree->show();
+ item->expand();
+ item->show();
+ }
+
+ list<string> members;
+ Library->get_members(members, group);
+ for (i = members.begin(); i != members.end(); ++i) {
+ TreeItem *item = manage(new TreeItem(Library->get_label(*i)));
+ tree->append (*item);
+ item->show();
+
+ uri_mapping.insert(map<string, Gtk::TreeItem*>::value_type(*i, item));
+ uri_parent.insert(map<string,string>::value_type(*i, group));
+
+ item->select.connect
+ (bind(slot(*this,&LibraryTree::cb_member_select), item, *i));
+ item->deselect.connect
+ (bind(slot(*this,&LibraryTree::cb_member_deselect), item, *i));
+
+ }
+}
+
+void
+LibraryTree::add_btn_clicked ()
+{
+ files_select.show_all();
+}
+
+// Gah, too many globals
+static string parent_uri;
+static vector<string>* old_parent;
+static vector<string>* old_parent_uri;
+
+static void clone_ftw(void*);
+static int32_t ftw_return;
+static Gtk::ProgressBar* bar;
+
+void
+LibraryTree::file_ok_clicked ()
+{
+ files_select.hide_all();
+
+ string* file = new string(files_select.get_filename());
+ parent_uri = current_group;
+
+ Gtk::Window* progress_win = new Gtk::Window();
+ progress_win->set_title(_("Importing"));
+ progress_win->set_policy(false, false, true);
+ Gtk::VBox* main_box = manage(new Gtk::VBox());
+ progress_win->add(*main_box);
+ bar = manage(new Gtk::ProgressBar());
+ bar->set_activity_mode(true);
+ bar->set_activity_step(15);
+ bar->set_activity_blocks(10);
+ main_box->pack_start(*bar);
+ Gtk::Button* cancel_btn = manage(new Gtk::Button(_("Cancel")));
+ main_box->pack_start(*cancel_btn);
+ cancel_btn->clicked.connect (slot (*this, &LibraryTree::cancel_import_clicked));
+ progress_win->show_all();
+
+ clone_ftw((void*)file);
+
+ delete progress_win;
+}
+
+void
+LibraryTree::cancel_import_clicked()
+{
+ ftw_return = 1;
+}
+
+void
+clone_ftw(void* ptr)
+{
+ string* file = (string*) ptr;
+
+ old_parent = new vector<string>;
+ old_parent_uri = new vector<string>;
+ ftw_return = 0;
+
+ if (ftw (file->c_str(), process_node, 100) < 0){
+ warning << compose(_("%1 not added to database"), *file) << endmsg;
+ }
+
+ delete old_parent;
+ delete old_parent_uri;
+
+ delete file;
+}
+
+void
+LibraryTree::file_cancel_clicked ()
+{
+ files_select.hide_all();
+}
+
+void
+LibraryTree::folder_btn_clicked ()
+{
+ ArdourPrompter prompter (true);
+ prompter.set_prompt(_("Folder name:"));
+
+ prompter.done.connect(Gtk::Main::quit.slot());
+ prompter.show_all();
+
+ Gtk::Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+
+ prompter.get_result(name);
+
+ if (name.length()) {
+ Library->add_group(name, current_group);
+ }
+ }
+}
+
+void
+LibraryTree::cb_group_select (Gtk::TreeItem* item, string uri)
+{
+ current_group = uri;
+ current_member = "";
+ remove_btn.set_sensitive(true);
+
+ group_selected(); /* EMIT_SIGNAL */
+}
+
+void
+LibraryTree::cb_member_select (Gtk::TreeItem* item, string uri)
+{
+ current_member = uri;
+ current_group = "";
+ selection.push_back (uri);
+ member_selected(uri); /* EMIT_SIGNAL */
+ remove_btn.set_sensitive(true);
+}
+
+void
+LibraryTree::cb_member_deselect (Gtk::TreeItem* item, string uri)
+{
+ current_member = "";
+ current_group = "";
+ selection.remove (uri);
+
+ member_deselected(); /* EMIT_SIGNAL */
+}
+
+void
+LibraryTree::find_btn_clicked ()
+{
+ SearchSounds* search = new SearchSounds ();
+
+ search->file_chosen.connect(slot (*this, &LibraryTree::file_found));
+ search->show_all();
+}
+
+void
+LibraryTree::file_found (string uri, bool multi)
+{
+ file_chosen (Library->get_member_filename(uri), multi); /* EMIT_SIGNAL */
+}
+
+void
+LibraryTree::remove_btn_clicked ()
+{
+ if (current_member != ""){
+ Library->remove_member(current_member);
+ } else if (current_group != ""){
+ Library->remove_group(current_group);
+ } else {
+ error << _("Should not be reached") << endmsg;
+ }
+
+ current_member = "";
+ current_group = "";
+
+ remove_btn.set_sensitive(false);
+
+ deselected(); /* EMIT_SIGNAL */
+}
+
+string
+length2string (const int32_t frames, const int32_t sample_rate)
+{
+ int secs = (int) (frames / (float) sample_rate);
+ int hrs = secs / 3600;
+ secs -= (hrs * 3600);
+ int mins = secs / 60;
+ secs -= (mins * 60);
+
+ int total_secs = (hrs * 3600) + (mins * 60) + secs;
+ int frames_remaining = frames - (total_secs * sample_rate);
+ float fractional_secs = (float) frames_remaining / sample_rate;
+
+ char duration_str[32];
+ sprintf (duration_str, "%02d:%02d:%05.2f", hrs, mins, (float) secs + fractional_secs);
+
+ return duration_str;
+}
+
+int
+process_node (const char *file, const struct stat *sb, int32_t flag)
+{
+ bar->set_value(0.0);
+ while (gtk_events_pending()){
+ gtk_main_iteration();
+ }
+ bar->set_value(1.0);
+
+ string s_file(file);
+
+ if (s_file.find("/.") != string::npos){
+ return ftw_return;
+ }
+
+ if (flag == FTW_D) {
+ string::size_type size = s_file.find_last_of('/');
+ string label = s_file.substr(++size);
+
+ while (!old_parent->empty()
+ && (s_file.find(old_parent->back()) == string::npos)) {
+
+ parent_uri = old_parent_uri->back();
+ old_parent_uri->pop_back();
+ old_parent->pop_back();
+ }
+
+ string uri = Library->add_group(label, parent_uri);
+
+ old_parent->push_back(s_file);
+ old_parent_uri->push_back(parent_uri);
+ parent_uri = uri;
+
+ return ftw_return;
+ } else if (flag != FTW_F) {
+ return ftw_return;
+ }
+
+ // We can't realistically check every file - or can we ?
+ char* suffix;
+ if ((suffix = strrchr (file, '.')) == 0) {
+ return ftw_return;
+ }
+
+ if (*(suffix+1) == '\0') {
+ return ftw_return;
+ }
+
+ if (strcasecmp (suffix+1, "wav") != 0 &&
+ strcasecmp (suffix+1, "aiff") != 0 &&
+ strcasecmp (suffix+1, "aif") != 0 &&
+ strcasecmp (suffix+1, "snd") != 0 &&
+ strcasecmp (suffix+1, "au") != 0 &&
+ strcasecmp (suffix+1, "raw") != 0 &&
+ strcasecmp (suffix+1, "sf") != 0 &&
+ strcasecmp (suffix+1, "cdr") != 0 &&
+ strcasecmp (suffix+1, "smp") != 0 &&
+ strcasecmp (suffix+1, "maud") != 0 &&
+ strcasecmp (suffix+1, "vwe") != 0 &&
+ strcasecmp (suffix+1, "paf") != 0 &&
+ strcasecmp (suffix+1, "voc") != 0) {
+
+ return ftw_return;
+ }
+
+ /* OK, it stands a good chance of being a sound file that we
+ might be able to handle.
+ */
+
+ SNDFILE *sf;
+ SF_INFO info;
+ if ((sf = sf_open ((char *) file, SFM_READ, &info)) < 0) {
+ error << compose(_("file \"%1\" could not be opened"), file) << endmsg;
+ return ftw_return;
+ }
+ sf_close (sf);
+
+ string uri = Library->add_member(file, parent_uri);
+
+ Library->set_field(uri, "channels", compose("%1", info.channels));
+ Library->set_field(uri, "samplerate", compose("%1", info.samplerate));
+ Library->set_field(uri, "resolution", compose("%1", sndfile_data_width(info.format)));
+ Library->set_field(uri, "format", compose("%1", info.format));
+
+ return ftw_return;
+}
+
+static const gchar* selector_titles[] = {
+ N_("Field"),
+ N_("Value"),
+ 0
+};
+
+SoundFileBox::SoundFileBox (string uri, bool meta)
+ :
+ uri(uri),
+ metadata(meta),
+ sf_info(new SF_INFO),
+ current_pid(0),
+ fields(_fields_refiller, this, internationalize (selector_titles),
+ false, true),
+ main_box (false, 3),
+ top_box (true, 4),
+ bottom_box (true, 4),
+ play_btn(_("Play")),
+ stop_btn(_("Stop")),
+ add_field_btn(_("Add Field...")),
+ remove_field_btn(_("Remove Field"))
+{
+ set_name ("SoundFileBox");
+
+ border_frame.set_label (_("Soundfile Info"));
+ border_frame.add (main_box);
+
+ pack_start (border_frame);
+ set_border_width (4);
+
+ Gtk::HBox* path_box = manage (new HBox);
+
+ path_box->set_spacing (4);
+ path_box->pack_start (path, false, false);
+ path_box->pack_start (path_entry, true, true);
+
+ main_box.set_border_width (4);
+
+ main_box.pack_start(label, false, false);
+ main_box.pack_start(*path_box, false, false);
+ main_box.pack_start(length, false, false);
+ main_box.pack_start(format, false, false);
+ main_box.pack_start(channels, false, false);
+ main_box.pack_start(samplerate, false, false);
+ if (metadata){
+ main_box.pack_start(fields, true, true);
+ main_box.pack_start(top_box, false, false);
+ }
+ main_box.pack_start(bottom_box, false, false);
+
+ fields.set_usize(200, 150);
+
+ top_box.set_homogeneous(true);
+ top_box.pack_start(add_field_btn);
+ top_box.pack_start(remove_field_btn);
+
+ remove_field_btn.set_sensitive(false);
+
+ bottom_box.set_homogeneous(true);
+ bottom_box.pack_start(play_btn);
+ bottom_box.pack_start(stop_btn);
+
+ play_btn.clicked.connect (slot (*this, &SoundFileBox::play_btn_clicked));
+ stop_btn.clicked.connect (slot (*this, &SoundFileBox::stop_btn_clicked));
+
+ PublicEditor& edit = ARDOUR_UI::instance()->the_editor();
+ ARDOUR::Session* sess = edit.current_session();
+ if (!sess) {
+ play_btn.set_sensitive(false);
+ } else {
+ sess->AuditionActive.connect(slot (*this, &SoundFileBox::audition_status_changed));
+ }
+
+ add_field_btn.clicked.connect
+ (slot (*this, &SoundFileBox::add_field_clicked));
+ remove_field_btn.clicked.connect
+ (slot (*this, &SoundFileBox::remove_field_clicked));
+
+ fields.selection_made.connect (slot (*this, &SoundFileBox::field_selected));
+ fields.choice_made.connect (slot (*this, &SoundFileBox::field_chosen));
+
+ Library->fields_changed.connect (slot (*this, &SoundFileBox::setup_fields));
+
+ if (setup_labels (uri)) {
+ throw failed_constructor();
+ }
+
+ show_all();
+ stop_btn.hide();
+}
+
+SoundFileBox::~SoundFileBox ()
+{
+}
+
+void
+SoundFileBox::_fields_refiller (Gtk::CList &list, void* arg)
+{
+ ((SoundFileBox *) arg)->fields_refiller (list);
+}
+
+void
+SoundFileBox::fields_refiller (Gtk::CList &clist)
+{
+ if (metadata) {
+ list<string> flist;
+ Library->get_fields(flist);
+ list<string>::iterator i;
+
+ const gchar *rowdata[3];
+ guint row = 0;
+ for (i=flist.begin(); i != flist.end(); ++i, ++row){
+ if (*i != "channels" && *i != "samplerate" &&
+ *i != "resolution" && *i != "format") {
+
+ rowdata[0] = (*i).c_str();
+ rowdata[1] = Library->get_field(uri, *i).c_str();
+ clist.insert_row (row, rowdata);
+ ++row;
+ }
+ }
+
+ clist.column(0).set_auto_resize(true);
+ clist.set_sort_column (0);
+ clist.sort ();
+ }
+}
+
+int
+SoundFileBox::setup_labels (string uri)
+{
+ SNDFILE *sf;
+
+ string file;
+ if (metadata){
+ file = Library->get_member_filename(uri);
+ } else {
+ file = uri;
+ }
+
+ if ((sf = sf_open ((char *) file.c_str(), SFM_READ, sf_info)) < 0) {
+ error << compose(_("file \"%1\" could not be opened"), file) << endmsg;
+ return -1;
+ }
+
+ if (sf_info->frames == 0 &&
+ sf_info->channels == 0 &&
+ sf_info->samplerate == 0 &&
+ sf_info->format == 0 &&
+ sf_info->sections == 0) {
+ /* .. ok, its not a sound file */
+ error << compose(_("file \"%1\" appears not to be an audio file"), file) << endmsg;
+ return -1;
+ }
+
+ if (metadata) {
+ label.set_alignment (0.0f, 0.0f);
+ label.set_text ("Label: " + Library->get_label(uri));
+ }
+
+ path.set_text ("Path: ");
+
+ path_entry.set_text (file);
+ path_entry.set_position (-1);
+
+ path_entry.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event));
+ path_entry.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event));
+
+ length.set_alignment (0.0f, 0.0f);
+ length.set_text (compose("Length: %1", length2string(sf_info->frames, sf_info->samplerate)));
+
+ format.set_alignment (0.0f, 0.0f);
+ format.set_text (compose("Format: %1, %2",
+ sndfile_major_format(sf_info->format),
+ sndfile_minor_format(sf_info->format)));
+
+ channels.set_alignment (0.0f, 0.0f);
+ channels.set_text (compose("Channels: %1", sf_info->channels));
+
+ samplerate.set_alignment (0.0f, 0.0f);
+ samplerate.set_text (compose("Samplerate: %1", sf_info->samplerate));
+
+ return 0;
+}
+
+void
+SoundFileBox::play_btn_clicked ()
+{
+ PublicEditor& edit = ARDOUR_UI::instance()->the_editor();
+ ARDOUR::Session* sess = edit.current_session();
+ if (!sess) {
+ return;
+ }
+
+ sess->cancel_audition();
+ string file;
+
+ if (metadata) {
+ file = Library->get_member_filename(uri);
+ } else {
+ file = uri;
+ }
+
+ if (access(file.c_str(), R_OK)) {
+ warning << compose(_("Could not read file: %1 (%2)."), file, strerror(errno)) << endmsg;
+ return;
+ }
+
+ static map<string, ARDOUR::AudioRegion*> region_cache;
+
+ if (region_cache.find (file) == region_cache.end()) {
+
+ AudioRegion::SourceList srclist;
+ SndFileSource* sfs;
+
+ for (int n=0; n < sf_info->channels; ++n) {
+
+ try {
+ sfs = new SndFileSource(file+":"+compose("%1", n), false);
+ srclist.push_back(sfs);
+
+ } catch (failed_constructor& err) {
+ error << _("Could not access soundfile: ") << file << endmsg;
+ return;
+ }
+ }
+
+ if (srclist.empty()) {
+ return;
+ }
+
+ string result;
+ sess->region_name (result, PBD::basename(srclist[0]->name()), false);
+ AudioRegion* a_region = new AudioRegion(srclist, 0, srclist[0]->length(), result, 0, Region::DefaultFlags, false);
+ region_cache[file] = a_region;
+ }
+
+ play_btn.hide();
+ stop_btn.show();
+
+ sess->audition_region(*region_cache[file]);
+}
+
+void
+SoundFileBox::stop_btn_clicked ()
+{
+ PublicEditor& edit = ARDOUR_UI::instance()->the_editor();
+ ARDOUR::Session* sess = edit.current_session();
+ if (sess) {
+ sess->cancel_audition();
+ play_btn.show();
+ stop_btn.hide();
+ }
+}
+
+void
+SoundFileBox::audition_status_changed (bool active)
+{
+ if (!active) {
+ Gtkmmext::UI::instance()->call_slot( slot(*this, &SoundFileBox::stop_btn_clicked));
+ }
+}
+
+void
+SoundFileBox::add_field_clicked ()
+{
+ ArdourPrompter prompter (true);
+ prompter.set_prompt(_("Field name:"));
+
+ prompter.show_all();
+ prompter.done.connect(Gtk::Main::quit.slot());
+
+ Gtk::Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+
+ prompter.get_result(name);
+
+ if (name.length()) {
+ Library->add_field(name);
+ }
+ }
+}
+
+void
+SoundFileBox::remove_field_clicked ()
+{
+ Library->remove_field(selected_field);
+ selected_field = "";
+ remove_field_btn.set_sensitive(false);
+}
+
+void
+SoundFileBox::setup_fields ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &SoundFileBox::setup_fields));
+
+ fields.rescan();
+}
+
+void
+SoundFileBox::field_chosen (Gtkmmext::Selector *selector, Gtkmmext::SelectionResult *res)
+{
+ if (res) {
+ remove_field_btn.set_sensitive(true);
+ selected_field = selector->clist().row(res->row)[0].get_text();
+ }
+}
+
+void
+SoundFileBox::field_selected (Gtkmmext::Selector *selector, Gtkmmext::SelectionResult *res)
+{
+ if (!res){
+ return;
+ }
+
+ string field_name(selector->clist().row(res->row)[0].get_text());
+
+ ArdourPrompter prompter (true);
+ prompter.set_prompt(_("Field value:"));
+ prompter.set_initial_text (selector->clist().row(res->row)[1].get_text());
+
+ prompter.show_all();
+ prompter.done.connect(Gtk::Main::quit.slot());
+
+ Gtk::Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string data;
+
+ prompter.get_result(data);
+ Library->set_field(uri, field_name, data);
+ }
+
+ fields.rescan();
+}
+
+SearchSounds::SearchSounds ()
+ : ArdourDialog ("search sounds dialog"),
+ find_btn (_("Find")),
+ and_rbtn (_("AND")),
+ or_rbtn (_("OR")),
+ fields(_fields_refiller, this, internationalize(selector_titles))
+{
+ set_title (_("ardour: locate soundfiles"));
+ set_name ("AudioSearchSound");
+
+ add(main_box);
+
+ or_rbtn.set_group(and_rbtn.group());
+ or_rbtn.set_active(true);
+ rbtn_box.set_homogeneous(true);
+ rbtn_box.pack_start(and_rbtn);
+ rbtn_box.pack_start(or_rbtn);
+
+ bottom_box.set_homogeneous(true);
+ bottom_box.pack_start(find_btn);
+
+ fields.set_usize(200, 150);
+
+ main_box.pack_start(fields);
+ main_box.pack_start(rbtn_box, false, false);
+ main_box.pack_start(bottom_box, false, false);
+
+ delete_event.connect (slot (*this, &ArdourDialog::wm_doi_event));
+
+ find_btn.clicked.connect (slot (*this, &SearchSounds::find_btn_clicked));
+ fields.selection_made.connect (slot
+ (*this, &SearchSounds::field_selected));
+
+ show_all();
+}
+
+SearchSounds::~SearchSounds ()
+{
+}
+
+void
+SearchSounds::_fields_refiller (Gtk::CList &list, void* arg)
+{
+ ((SearchSounds *) arg)->fields_refiller (list);
+}
+
+void
+SearchSounds::fields_refiller (Gtk::CList &clist)
+{
+ list<string> flist;
+ Library->get_fields(flist);
+ list<string>::iterator i;
+
+ const gchar *rowdata[3];
+ guint row;
+ for (row=0,i=flist.begin(); i != flist.end(); ++i, ++row){
+ rowdata[0] = (*i).c_str();
+ rowdata[1] = "";
+ clist.insert_row (row, rowdata);
+ }
+
+ clist.column(0).set_auto_resize(true);
+ clist.set_sort_column (0);
+ clist.sort ();
+}
+
+void
+SearchSounds::field_selected (Gtkmmext::Selector *selector, Gtkmmext::SelectionResult *res)
+{
+ if (!res){
+ return;
+ }
+
+ ArdourPrompter prompter (true);
+ prompter.set_prompt(_("Field value:"));
+
+ prompter.show_all();
+ prompter.done.connect(Gtk::Main::quit.slot());
+
+ Gtk::Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string data;
+
+ prompter.get_result(data);
+ selector->clist().cell(res->row, 1).set_text(data);
+ }
+}
+
+void
+SearchSounds::find_btn_clicked ()
+{
+ using namespace Gtk::CList_Helpers;
+ typedef map<string,string> StringMap;
+
+ StringMap search_info;
+
+ RowList rows = fields.clist().rows();
+ RowList::const_iterator i;
+
+ for (i = rows.begin(); i != rows.end(); ++i) {
+ Cell cfield((*i)[0]);
+ Cell cdata((*i)[1]);
+ if (cdata.get_text().length()){
+ search_info.insert(
+ StringMap::value_type(cfield.get_text(), cdata.get_text()));
+ }
+ }
+
+ SearchResults* results;
+ if (and_rbtn.get_active()){
+ results = new SearchResults(search_info, true);
+ } else {
+ results = new SearchResults(search_info, false);
+ }
+
+ results->file_chosen.connect (slot (*this, &SearchSounds::file_found));
+ results->show_all();
+}
+
+void
+SearchSounds::file_found (string uri, bool multi)
+{
+ PublicEditor& edit = ARDOUR_UI::instance()->the_editor();
+ ARDOUR::Session* sess = edit.current_session();
+ if (sess) {
+ sess->cancel_audition();
+ }
+
+ file_chosen (uri, multi); /* EMIT_SIGNAL */
+}
+
+static const gchar* result_titles[] = {
+ N_("Results"),
+ N_("Uris"),
+ 0
+};
+
+SearchResults::SearchResults (map<string,string> field_values, bool and_search)
+ : ArdourDialog ("search results dialog"),
+ search_info(field_values),
+ search_and (and_search),
+ selection (""),
+ main_box (false, 3),
+ import_box (true, 4),
+ import_btn (_("Import")),
+ multichan_check (_("Create multi-channel region")),
+ results (_results_refiller, this, internationalize (result_titles), false, true)
+{
+ set_title (_("Ardour: Search Results"));
+ set_name ("ArdourSearchResults");
+
+ add(main_box);
+ set_border_width (3);
+
+ main_box.pack_start(hbox);
+ hbox.pack_start(results);
+
+ main_box.pack_start(import_box, false, false);
+
+ results.set_usize (200, 150);
+
+ import_box.set_homogeneous(true);
+ import_box.pack_start(import_btn);
+ import_box.pack_start(multichan_check);
+
+ import_btn.set_sensitive(false);
+ multichan_check.set_active(true);
+ multichan_check.set_sensitive(false);
+
+ delete_event.connect (slot (*this, &ArdourDialog::wm_doi_event));
+
+ import_btn.clicked.connect (slot (*this, &SearchResults::import_clicked));
+
+ results.choice_made.connect (slot (*this, &SearchResults::result_chosen));
+
+ show_all();
+}
+
+SearchResults::~SearchResults ()
+{
+}
+
+void
+SearchResults::_results_refiller (Gtk::CList &list, void* arg)
+{
+ ((SearchResults *) arg)->results_refiller (list);
+}
+
+void
+SearchResults::results_refiller (Gtk::CList &clist)
+{
+ list<string> results;
+ if (search_and) {
+ Library->search_members_and (results, search_info);
+ } else {
+ Library->search_members_or (results, search_info);
+ }
+
+ list<string>::iterator i;
+ const gchar *rowdata[3];
+ guint row;
+ for (row=0, i=results.begin(); i != results.end(); ++i, ++row){
+ rowdata[0] = (Library->get_label(*i)).c_str();
+ // hide the uri in a hidden column
+ rowdata[1] = (*i).c_str();
+ clist.insert_row (row, rowdata);
+ }
+
+ clist.column(1).set_visiblity(false);
+ clist.column(0).set_auto_resize(true);
+ clist.set_sort_column (0);
+ clist.sort ();
+}
+
+void
+SearchResults::import_clicked ()
+{
+ PublicEditor& edit = ARDOUR_UI::instance()->the_editor();
+ ARDOUR::Session* sess = edit.current_session();
+
+ if (sess) {
+ sess->cancel_audition();
+ }
+
+ file_chosen(selection, multichan_check.get_active()); /* EMIT_SIGNAL */
+}
+
+void
+SearchResults::result_chosen (Gtkmmext::Selector *selector, Gtkmmext::SelectionResult *res)
+{
+ if (res) {
+ selection = selector->clist().row(res->row)[1].get_text();
+
+ if (info_box){
+ delete info_box;
+ info_box = 0;
+ }
+
+ try {
+ info_box = new SoundFileBox(selection, true);
+ } catch (failed_constructor& err) {
+ /* nothing to do */
+ return;
+ }
+
+ hbox.pack_start(*info_box);
+ }
+}
diff --git a/gtk2_ardour/library_ui.h b/gtk2_ardour/library_ui.h
new file mode 100644
index 0000000000..ae40aac2d7
--- /dev/null
+++ b/gtk2_ardour/library_ui.h
@@ -0,0 +1,307 @@
+/*
+ Copyright (C) 1999-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_library_ui_h__
+#define __ardour_library_ui_h__
+
+#include <map>
+#include <string>
+#include <list>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <sigc++/signal_system.h>
+#include <gtk--.h>
+#include <gtkmmext/selector.h>
+
+#include <ardour/region.h>
+
+#include "ardour_dialog.h"
+
+using std::string;
+using std::map;
+
+struct RowTaggedString {
+ RowTaggedString (int r, string s)
+ : row (r), str (s) {}
+
+ int32_t row;
+ string str;
+};
+
+class SoundFileBox : public Gtk::VBox
+{
+ public:
+ /**
+ @variable uri is the path name of string.
+ @variable metadata whether to show the user-added fields from sfdb.
+ */
+ SoundFileBox (string uri, bool metadata);
+ ~SoundFileBox ();
+
+ SigC::Signal2<void, string, bool> file_chosen;
+
+ private:
+ string uri;
+ bool metadata;
+ SF_INFO* sf_info;
+
+ char* playcmd;
+ pid_t current_pid;
+
+ Gtk::Label label;
+ Gtk::Label path;
+ Gtk::Entry path_entry;
+ Gtk::Label length;
+ Gtk::Label format;
+ Gtk::Label channels;
+ Gtk::Label samplerate;
+
+ Gtkmmext::Selector fields;
+ string selected_field;
+
+ Gtk::Frame border_frame;
+
+ Gtk::VBox main_box;
+ Gtk::HBox top_box;
+ Gtk::HBox bottom_box;
+
+ Gtk::Button play_btn;
+ Gtk::Button stop_btn;
+ Gtk::Button add_field_btn;
+ Gtk::Button remove_field_btn;
+
+ static void _fields_refiller (Gtk::CList &list, void* arg);
+ void fields_refiller (Gtk::CList &clist);
+ int setup_labels (string uri);
+ void setup_fields ();
+
+ void play_btn_clicked ();
+ void stop_btn_clicked ();
+ void add_field_clicked ();
+ void remove_field_clicked ();
+
+ void field_selected (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *re);
+ void field_chosen (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *re);
+ void audition_status_changed (bool state);
+};
+
+class SearchSounds : public ArdourDialog
+{
+ public:
+ SearchSounds ();
+ ~SearchSounds ();
+
+ SigC::Signal2<void, string, bool> file_chosen;
+
+ private:
+ Gtk::Button find_btn;
+
+ Gtk::RadioButton and_rbtn;
+ Gtk::RadioButton or_rbtn;
+
+ Gtkmmext::Selector fields;
+ string selected_field;
+
+ Gtk::VBox main_box;
+ Gtk::HBox rbtn_box;
+ Gtk::HBox bottom_box;
+
+ static void _fields_refiller (Gtk::CList &list, void* arg);
+ void fields_refiller (Gtk::CList &clist);
+ void setup_fields ();
+
+ void field_selected (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *re);
+
+ void find_btn_clicked ();
+
+ void file_found (string uri, bool multi);
+};
+
+class SearchResults : public ArdourDialog
+{
+ public:
+ SearchResults (map<string,string> field_values, bool and_search);
+ ~SearchResults ();
+
+ SigC::Signal2<void, string, bool> file_chosen;
+
+ private:
+ map<string,string> search_info;
+ bool search_and;
+ string selection;
+
+ Gtk::VBox main_box;
+ Gtk::HBox hbox;
+ Gtk::HBox import_box;
+
+ Gtk::Button import_btn;
+ Gtk::CheckButton multichan_check;
+
+ SoundFileBox* info_box;
+
+ Gtkmmext::Selector results;
+ static void _results_refiller (Gtk::CList &list, void* arg);
+ void results_refiller (Gtk::CList &clist);
+
+ void import_clicked ();
+
+ void result_chosen (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *re);
+};
+
+class LibraryTree : public Gtk::VBox
+{
+ public:
+ LibraryTree ();
+ ~LibraryTree ();
+
+ SigC::Signal2<void, string, bool> file_chosen;
+ SigC::Signal0<void> group_selected;
+ SigC::Signal1<void, string> member_selected;
+ SigC::Signal0<void> member_deselected;
+ SigC::Signal0<void> deselected;
+
+ list<string> selection;
+ void clear_selection ();
+
+ private:
+ map<string, Gtk::TreeItem*> uri_mapping;
+ map<string, string> uri_parent; // this ugly, but necessary
+
+ string current_member;
+ string current_group;
+
+ Gtk::HBox hbox;
+ Gtk::VBox framed_box;
+ Gtk::HBox btn_box_top;
+ Gtk::HBox btn_box_bottom;
+
+ Gtk::ScrolledWindow scroll;
+ Gtk::Tree tree;
+
+ Gtk::Button add_btn;
+ Gtk::Button remove_btn;
+ Gtk::Button find_btn;
+ Gtk::Button folder_btn;
+
+ Gtk::FileSelection files_select;
+
+ void file_ok_clicked ();
+ void file_cancel_clicked ();
+
+ void add_btn_clicked ();
+ void folder_btn_clicked ();
+ void remove_btn_clicked ();
+ void find_btn_clicked ();
+
+ void file_found (string uri, bool multi);
+
+ void cb_group_select (Gtk::TreeItem* item, string uri);
+ void cb_member_select (Gtk::TreeItem* item, string uri);
+ void cb_member_deselect (Gtk::TreeItem* item, string uri);
+
+ void populate ();
+ void subpopulate (Gtk::Tree*, string group);
+
+ void added_group (string, string);
+ void removed_group (string);
+ void added_member (string, string);
+ void removed_member (string);
+
+ void cancel_import_clicked ();
+};
+
+class SoundFileBrowser : public Gtk::VBox {
+ public:
+ SoundFileBrowser ();
+ ~SoundFileBrowser ();
+
+ SigC::Signal0<void> group_selected;
+ SigC::Signal1<void, string> member_selected;
+ SigC::Signal0<void> member_deselected;
+ SigC::Signal0<void> deselected;
+
+ list<RowTaggedString> selection;
+ void clear_selection ();
+
+ private:
+ string current_member;
+ string current_group;
+ Gtk::FileSelection fs_selector;
+ Gtk::CList* file_list;
+
+ void dir_list_selected(gint row, gint col, GdkEvent* ev);
+ void file_list_selected(gint row, gint col, GdkEvent* ev);
+ void file_list_deselected(gint row, gint col, GdkEvent* ev);
+
+ string safety_check_file(string file);
+};
+
+class SoundFileSelector : public ArdourDialog {
+ public:
+ /**
+ @variable action the name given to the action button
+ @variable import is action button sensitive
+ @variable multi does splitting the region by channel make sense here
+ @variable persist should this LibraryTree be hidden or deleted when closed
+ */
+ SoundFileSelector ();
+ ~SoundFileSelector ();
+
+ void run (string action, bool split_makes_sense, bool hide_after_action = false);
+ void get_result (vector<string>& paths, bool& split);
+ void hide_import_stuff();
+
+ SigC::Signal2<void,vector<string>,bool> Action;
+
+ private:
+ bool multiable;
+ bool hide_after_action;
+ bool sfdb;
+
+ void import_btn_clicked ();
+ void sfdb_group_selected();
+ void browser_group_selected();
+ void member_selected(string member, bool sfdb);
+ void member_deselected(bool sfdb);
+ void sfdb_deselected();
+ void page_switched(Gtk::Notebook_Helpers::Page* page, guint page_num);
+
+ Gtk::HBox main_box;
+ Gtk::VBox vbox;
+ Gtk::Notebook notebook;
+ Gtk::Label sfdb_label;
+ Gtk::Label fs_label;
+
+ SoundFileBrowser sf_browser;
+ LibraryTree sfdb_tree;
+
+ Gtk::HBox import_box;
+ Gtk::Button import_btn;
+ Gtk::CheckButton split_channels;
+ Gtk::CheckButton resample_check;
+
+ SoundFileBox* info_box;
+};
+
+#endif // __ardour_library_ui_h__
diff --git a/gtk2_ardour/location_ui.cc b/gtk2_ardour/location_ui.cc
new file mode 100644
index 0000000000..3cac264e50
--- /dev/null
+++ b/gtk2_ardour/location_ui.cc
@@ -0,0 +1,886 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <cstdlib>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/stop_signal.h>
+
+#include <ardour/utils.h>
+#include <ardour/configuration.h>
+#include <ardour/session.h>
+
+#include "ardour_ui.h"
+#include "prompter.h"
+#include "location_ui.h"
+#include "keyboard.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+
+LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num)
+ : location(0), session(0),
+ item_table (1, 7, false),
+ start_set_button (_("Set")),
+ start_go_button (_("Go")),
+ start_clock (X_("LocationEditRowClock"), true),
+ end_set_button (_("Set")),
+ end_go_button (_("Go")),
+ end_clock (X_("LocationEditRowClock"), true),
+ length_clock (X_("LocationEditRowClock"), true, true),
+ cd_check_button (_("CD")),
+ hide_check_button (_("Hidden")),
+ remove_button (_("Remove")),
+ scms_check_button (_("SCMS")),
+ preemph_check_button (_("Pre-Emphasis"))
+
+{
+
+ i_am_the_modifier = 0;
+
+ number_label.set_name ("LocationEditNumberLabel");
+ name_label.set_name ("LocationEditNameLabel");
+ name_entry.set_name ("LocationEditNameEntry");
+ start_set_button.set_name ("LocationEditSetButton");
+ start_go_button.set_name ("LocationEditGoButton");
+ end_set_button.set_name ("LocationEditSetButton");
+ end_go_button.set_name ("LocationEditGoButton");
+ cd_check_button.set_name ("LocationEditCdButton");
+ hide_check_button.set_name ("LocationEditHideButton");
+ remove_button.set_name ("LocationEditRemoveButton");
+ isrc_label.set_name ("LocationEditNumberLabel");
+ isrc_entry.set_name ("LocationEditNameEntry");
+ scms_check_button.set_name ("LocationEditCdButton");
+ preemph_check_button.set_name ("LocationEditCdButton");
+ performer_label.set_name ("LocationEditNumberLabel");
+ performer_entry.set_name ("LocationEditNameEntry");
+ composer_label.set_name ("LocationEditNumberLabel");
+ composer_entry.set_name ("LocationEditNameEntry");
+
+
+ isrc_label.set_text ("ISRC: ");
+ isrc_label.set_usize (30, -1);
+ performer_label.set_text ("Performer: ");
+ performer_label.set_usize (60, -1);
+ composer_label.set_text ("Composer: ");
+ composer_label.set_usize (60, -1);
+
+ isrc_entry.set_usize (112, -1);
+ isrc_entry.set_max_length(12);
+ isrc_entry.set_editable (true);
+
+ performer_entry.set_usize (100, -1);
+ performer_entry.set_editable (true);
+
+ composer_entry.set_usize (100, -1);
+ composer_entry.set_editable (true);
+
+ cd_track_details_hbox.pack_start (isrc_label, false, false);
+ cd_track_details_hbox.pack_start (isrc_entry, false, false);
+ cd_track_details_hbox.pack_start (scms_check_button, false, false);
+ cd_track_details_hbox.pack_start (preemph_check_button, false, false);
+ cd_track_details_hbox.pack_start (performer_label, false, false);
+ cd_track_details_hbox.pack_start (performer_entry, true, true);
+ cd_track_details_hbox.pack_start (composer_label, false, false);
+ cd_track_details_hbox.pack_start (composer_entry, true, true);
+
+ isrc_entry.changed.connect (slot (*this, &LocationEditRow::isrc_entry_changed));
+ isrc_entry.focus_in_event.connect (slot (*this, &LocationEditRow::entry_focus_event));
+ isrc_entry.focus_out_event.connect (slot (*this, &LocationEditRow::entry_focus_event));
+
+ performer_entry.changed.connect (slot (*this, &LocationEditRow::performer_entry_changed));
+ performer_entry.focus_in_event.connect (slot (*this, &LocationEditRow::entry_focus_event));
+ performer_entry.focus_out_event.connect (slot (*this, &LocationEditRow::entry_focus_event));
+
+ composer_entry.changed.connect (slot (*this, &LocationEditRow::composer_entry_changed));
+ composer_entry.focus_in_event.connect (slot (*this, &LocationEditRow::entry_focus_event));
+ composer_entry.focus_out_event.connect (slot (*this, &LocationEditRow::entry_focus_event));
+
+ scms_check_button.toggled.connect(slot (*this, &LocationEditRow::scms_toggled));
+ preemph_check_button.toggled.connect(slot (*this, &LocationEditRow::preemph_toggled));
+
+
+ set_session (sess);
+
+
+ item_table.attach (number_label, 0, 1, 0, 1, 0, 0, 3, 0);
+
+ start_hbox.pack_start (start_go_button, false, false);
+ start_hbox.pack_start (start_clock, false, false);
+ start_hbox.pack_start (start_set_button, false, false);
+
+ item_table.attach (start_hbox, 2, 3, 0, 1, 0, 0, 4, 0);
+
+
+ start_set_button.clicked.connect( bind ( slot (*this, &LocationEditRow::set_button_pressed), LocStart));
+ start_go_button.clicked.connect( bind ( slot (*this, &LocationEditRow::go_button_pressed), LocStart));
+ start_clock.ValueChanged.connect (bind ( slot (*this, &LocationEditRow::clock_changed), LocStart));
+
+
+ end_hbox.pack_start (end_go_button, false, false);
+ end_hbox.pack_start (end_clock, false, false);
+ end_hbox.pack_start (end_set_button, false, false);
+
+ //item_table.attach (end_hbox, 2, 3, 0, 1, 0, 0, 4, 0);
+
+ end_set_button.clicked.connect( bind ( slot (*this, &LocationEditRow::set_button_pressed), LocEnd));
+ end_go_button.clicked.connect( bind ( slot (*this, &LocationEditRow::go_button_pressed), LocEnd));
+ end_clock.ValueChanged.connect (bind ( slot (*this, &LocationEditRow::clock_changed), LocEnd));
+
+// item_table.attach (length_clock, 3, 4, 0, 1, 0, 0, 4, 0);
+ length_clock.ValueChanged.connect (bind ( slot (*this, &LocationEditRow::clock_changed), LocLength));
+
+// item_table.attach (cd_check_button, 4, 5, 0, 1, 0, GTK_FILL, 4, 0);
+// item_table.attach (hide_check_button, 5, 6, 0, 1, 0, GTK_FILL, 4, 0);
+// item_table.attach (remove_button, 7, 8, 0, 1, 0, GTK_FILL, 4, 0);
+
+ cd_check_button.toggled.connect(slot (*this, &LocationEditRow::cd_toggled));
+ hide_check_button.toggled.connect(slot (*this, &LocationEditRow::hide_toggled));
+
+ remove_button.clicked.connect(slot (*this, &LocationEditRow::remove_button_pressed));
+
+ pack_start(item_table, true, true);
+
+ set_location (loc);
+ set_number (num);
+}
+
+LocationEditRow::~LocationEditRow()
+{
+ if (location) {
+ start_changed_connection.disconnect();
+ end_changed_connection.disconnect();
+ name_changed_connection.disconnect();
+ changed_connection.disconnect();
+ flags_changed_connection.disconnect();
+ }
+}
+
+void
+LocationEditRow::set_session (Session *sess)
+{
+ session = sess;
+
+ if (!session) return;
+
+ start_clock.set_session (session);
+ end_clock.set_session (session);
+ length_clock.set_session (session);
+
+}
+
+void
+LocationEditRow::set_number (int num)
+{
+ number = num;
+
+ if (number >= 0 ) {
+ number_label.set_text (compose ("%1", number));
+ }
+}
+
+void
+LocationEditRow::set_location (Location *loc)
+{
+ if (location) {
+ start_changed_connection.disconnect();
+ end_changed_connection.disconnect();
+ name_changed_connection.disconnect();
+ changed_connection.disconnect();
+ flags_changed_connection.disconnect();
+ }
+
+ location = loc;
+
+ if (!location) return;
+
+ if (!hide_check_button.get_parent()) {
+ item_table.attach (hide_check_button, 6, 7, 0, 1, 0, GTK_FILL, 4, 0);
+ }
+ hide_check_button.set_active (location->is_hidden());
+
+ if (location->is_auto_loop() || location->is_auto_punch()) {
+ // use label instead of entry
+
+ name_label.set_text (location->name());
+ name_label.set_usize (80, -1);
+
+ if (!name_label.get_parent()) {
+ item_table.attach (name_label, 1, 2, 0, 1, 0, GTK_FILL, 4, 0);
+ }
+
+ name_label.show();
+
+ } else {
+
+ name_entry.set_text (location->name());
+ name_entry.set_usize (100, -1);
+ name_entry.set_editable (true);
+ name_entry.changed.connect (slot (*this, &LocationEditRow::name_entry_changed));
+ name_entry.focus_in_event.connect (slot (*this, &LocationEditRow::entry_focus_event));
+ name_entry.focus_out_event.connect (slot (*this, &LocationEditRow::entry_focus_event));
+
+ if (!name_entry.get_parent()) {
+ item_table.attach (name_entry, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 4, 0);
+ }
+ name_entry.show();
+
+ if (!cd_check_button.get_parent()) {
+ item_table.attach (cd_check_button, 5, 6, 0, 1, 0, GTK_FILL, 4, 0);
+ }
+ if (!remove_button.get_parent()) {
+ item_table.attach (remove_button, 7, 8, 0, 1, 0, GTK_FILL, 4, 0);
+ }
+
+ /* XXX i can't find a way to hide the button without messing up
+ the row spacing, so make it insensitive (paul).
+ */
+
+ if (location->is_end()) {
+ remove_button.set_sensitive (false);
+ }
+
+ cd_check_button.set_active (location->is_cd_marker());
+ cd_check_button.show();
+ hide_check_button.show();
+ }
+
+ start_clock.set (location->start(), true);
+
+
+ if (!location->is_mark()) {
+ if (!end_hbox.get_parent()) {
+ item_table.attach (end_hbox, 3, 4, 0, 1, 0, 0, 4, 0);
+ }
+ if (!length_clock.get_parent()) {
+ item_table.attach (length_clock, 4, 5, 0, 1, 0, 0, 4, 0);
+ }
+
+ end_clock.set (location->end(), true);
+ length_clock.set (location->length(), true);
+
+ end_set_button.show();
+ end_go_button.show();
+ end_clock.show();
+ length_clock.show();
+ }
+ else {
+ end_set_button.hide();
+ end_go_button.hide();
+ end_clock.hide();
+ length_clock.hide();
+ }
+
+ start_changed_connection = location->start_changed.connect (slot (*this, &LocationEditRow::start_changed));
+ end_changed_connection = location->end_changed.connect (slot (*this, &LocationEditRow::end_changed));
+ name_changed_connection = location->name_changed.connect (slot (*this, &LocationEditRow::name_changed));
+ changed_connection = location->changed.connect (slot (*this, &LocationEditRow::location_changed));
+ flags_changed_connection = location->FlagsChanged.connect (slot (*this, &LocationEditRow::flags_changed));
+
+}
+
+gint
+LocationEditRow::entry_focus_event (GdkEventFocus* ev)
+{
+ if (ev->in) {
+ ARDOUR_UI::instance()->allow_focus (true);
+ } else {
+ ARDOUR_UI::instance()->allow_focus (false);
+ }
+ return TRUE;
+}
+
+
+void
+LocationEditRow::name_entry_changed ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &LocationEditRow::name_entry_changed));
+ if (i_am_the_modifier || !location) return;
+
+ location->set_name (name_entry.get_text());
+}
+
+
+void
+LocationEditRow::isrc_entry_changed ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &LocationEditRow::isrc_entry_changed));
+
+ if (i_am_the_modifier || !location) return;
+
+ if (isrc_entry.get_text() != "" ) {
+
+ location->cd_info["isrc"] = isrc_entry.get_text();
+
+ } else {
+ location->cd_info.erase("isrc");
+ }
+}
+
+void
+LocationEditRow::performer_entry_changed ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &LocationEditRow::performer_entry_changed));
+
+ if (i_am_the_modifier || !location) return;
+
+ if (performer_entry.get_text() != "") {
+ location->cd_info["performer"] = performer_entry.get_text();
+ } else {
+ location->cd_info.erase("performer");
+ }
+}
+
+void
+LocationEditRow::composer_entry_changed ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &LocationEditRow::composer_entry_changed));
+
+ if (i_am_the_modifier || !location) return;
+
+ if (composer_entry.get_text() != "") {
+ location->cd_info["composer"] = composer_entry.get_text();
+ } else {
+ location->cd_info.erase("composer");
+ }
+}
+
+
+void
+LocationEditRow::set_button_pressed (LocationPart part)
+{
+ if (!location) return;
+
+ switch (part) {
+ case LocStart:
+ location->set_start (session->transport_frame ());
+ break;
+ case LocEnd:
+ location->set_end (session->transport_frame ());
+ break;
+ default:
+ break;
+ }
+}
+
+void
+LocationEditRow::go_button_pressed (LocationPart part)
+{
+ if (!location) return;
+
+ switch (part) {
+ case LocStart:
+ ARDOUR_UI::instance()->do_transport_locate (location->start());
+ break;
+ case LocEnd:
+ ARDOUR_UI::instance()->do_transport_locate (location->end());
+ break;
+ default:
+ break;
+ }
+}
+
+void
+LocationEditRow::clock_changed (LocationPart part)
+{
+ if (i_am_the_modifier || !location) return;
+
+ switch (part) {
+ case LocStart:
+ location->set_start (start_clock.current_time());
+ break;
+ case LocEnd:
+ location->set_end (end_clock.current_time());
+ break;
+ case LocLength:
+ location->set_end (location->start() + length_clock.current_duration());
+ default:
+ break;
+ }
+
+}
+
+void
+LocationEditRow::cd_toggled ()
+{
+
+ if (i_am_the_modifier || !location) return;
+ location->set_cd (cd_check_button.get_active(), this);
+
+ if (location->is_cd_marker() && !(location->is_mark())) {
+
+ if (location->cd_info.find("isrc") != location->cd_info.end()) {
+ isrc_entry.set_text(location->cd_info["isrc"]);
+ }
+ if (location->cd_info.find("performer") != location->cd_info.end()) {
+ performer_entry.set_text(location->cd_info["performer"]);
+ }
+ if (location->cd_info.find("composer") != location->cd_info.end()) {
+ composer_entry.set_text(location->cd_info["composer"]);
+ }
+ if (location->cd_info.find("scms") != location->cd_info.end()) {
+ scms_check_button.set_active(true);
+ }
+ if (location->cd_info.find("preemph") != location->cd_info.end()) {
+ preemph_check_button.set_active(true);
+ }
+
+ if(!cd_track_details_hbox.get_parent()) {
+ item_table.attach (cd_track_details_hbox, 1, 8, 1, 2, GTK_FILL | GTK_EXPAND, 0, 4, 0);
+ }
+ // item_table.resize(2, 7);
+ cd_track_details_hbox.show_all();
+
+ } else if (cd_track_details_hbox.get_parent()){
+
+ item_table.remove (cd_track_details_hbox);
+ // item_table.resize(1, 7);
+ redraw_ranges(); /* EMIT_SIGNAL */
+ }
+
+}
+
+
+void
+LocationEditRow::hide_toggled ()
+{
+ if (i_am_the_modifier || !location) return;
+
+ location->set_hidden (hide_check_button.get_active(), this);
+}
+
+void
+LocationEditRow::remove_button_pressed ()
+{
+ if (!location) return;
+
+ remove_requested(location); /* EMIT_SIGNAL */
+}
+
+
+
+void
+LocationEditRow::scms_toggled ()
+{
+ if (i_am_the_modifier || !location) return;
+
+ if (scms_check_button.get_active()) {
+ location->cd_info["scms"] = "on";
+ } else {
+ location->cd_info.erase("scms");
+ }
+
+}
+
+void
+LocationEditRow::preemph_toggled ()
+{
+ if (i_am_the_modifier || !location) return;
+
+ if (preemph_check_button.get_active()) {
+ location->cd_info["preemph"] = "on";
+ } else {
+ location->cd_info.erase("preemph");
+ }
+}
+
+void
+LocationEditRow::end_changed (ARDOUR::Location *loc)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::end_changed), loc));
+
+ if (!location) return;
+
+ // update end and length
+ i_am_the_modifier++;
+
+ end_clock.set (location->end());
+ length_clock.set (location->length());
+
+ i_am_the_modifier--;
+}
+
+void
+LocationEditRow::start_changed (ARDOUR::Location *loc)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::start_changed), loc));
+
+ if (!location) return;
+
+ // update end and length
+ i_am_the_modifier++;
+
+ start_clock.set (location->start());
+
+ i_am_the_modifier--;
+}
+
+void
+LocationEditRow::name_changed (ARDOUR::Location *loc)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::name_changed), loc));
+
+ if (!location) return;
+
+ // update end and length
+ i_am_the_modifier++;
+
+ name_entry.set_text(location->name());
+ name_label.set_text(location->name());
+
+ i_am_the_modifier--;
+
+}
+
+void
+LocationEditRow::location_changed (ARDOUR::Location *loc)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::location_changed), loc));
+
+ if (!location) return;
+
+ i_am_the_modifier++;
+
+ start_clock.set (location->start());
+ end_clock.set (location->end());
+ length_clock.set (location->length());
+
+ i_am_the_modifier--;
+
+}
+
+void
+LocationEditRow::flags_changed (ARDOUR::Location *loc, void *src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::flags_changed), loc, src));
+
+ if (!location) return;
+
+ i_am_the_modifier++;
+
+ cd_check_button.set_active (location->is_cd_marker());
+ hide_check_button.set_active (location->is_hidden());
+
+ i_am_the_modifier--;
+}
+
+LocationUI::LocationUI ()
+ : ArdourDialog ("location dialog"),
+ add_location_button (_("Add New Location")),
+ add_range_button (_("Add New Range"))
+{
+ i_am_the_modifier = 0;
+
+ set_title(_("ardour: locations"));
+ set_wmclass(_("ardour_locations"), "Ardour");
+
+ set_name ("LocationWindow");
+ delete_event.connect (bind (slot (just_hide_it), static_cast<Window*>(this)));
+
+ add (location_hpacker);
+
+
+ location_vpacker.set_border_width (10);
+ location_vpacker.set_spacing (5);
+
+
+ location_vpacker.pack_start (loop_edit_row, false, false);
+ location_vpacker.pack_start (punch_edit_row, false, false);
+
+ location_rows.set_name("LocationLocRows");
+ location_rows_scroller.add_with_viewport (location_rows);
+ location_rows_scroller.set_name ("LocationLocRowsScroller");
+ location_rows_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ location_rows_scroller.set_usize (-1, 130);
+
+ loc_frame_box.set_spacing (5);
+ loc_frame_box.set_border_width (5);
+ loc_frame_box.set_name("LocationFrameBox");
+
+ loc_frame_box.pack_start (location_rows_scroller, true, true);
+
+ add_location_button.set_name ("LocationAddLocationButton");
+ loc_frame_box.pack_start (add_location_button, false, false);
+
+ loc_frame.set_name ("LocationLocEditorFrame");
+ loc_frame.set_label (_("Location (CD Index) Markers"));
+ loc_frame.add (loc_frame_box);
+ loc_range_panes.pack1(loc_frame, true, false);
+
+
+ range_rows.set_name("LocationRangeRows");
+ range_rows_scroller.add_with_viewport (range_rows);
+ range_rows_scroller.set_name ("LocationRangeRowsScroller");
+ range_rows_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ range_rows_scroller.set_usize (-1, 130);
+
+ range_frame_box.set_spacing (5);
+ range_frame_box.set_name("LocationFrameBox");
+ range_frame_box.set_border_width (5);
+ range_frame_box.pack_start (range_rows_scroller, true, true);
+
+ add_range_button.set_name ("LocationAddRangeButton");
+ range_frame_box.pack_start (add_range_button, false, false);
+
+ range_frame.set_name ("LocationRangeEditorFrame");
+ range_frame.set_label (_("Range (CD Track) Markers"));
+ range_frame.add (range_frame_box);
+ loc_range_panes.pack2(range_frame, true, false);
+ location_vpacker.pack_start (loc_range_panes, true, true);
+
+ location_hpacker.pack_start (location_vpacker, true, true);
+
+ add_location_button.clicked.connect (slot (*this, &LocationUI::add_new_location));
+ add_range_button.clicked.connect (slot (*this, &LocationUI::add_new_range));
+
+ //add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_BUTTON_RELEASE_MASK);
+
+
+}
+
+LocationUI::~LocationUI()
+{
+}
+
+
+
+gint LocationUI::do_location_remove (ARDOUR::Location *loc)
+{
+ /* this is handled internally by Locations, but there's
+ no point saving state etc. when we know the marker
+ cannot be removed.
+ */
+
+ if (loc->is_end()) {
+ return FALSE;
+ }
+
+ session->begin_reversible_command (_("remove marker"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->remove (loc);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+
+ return FALSE;
+}
+
+void LocationUI::location_remove_requested (ARDOUR::Location *loc)
+{
+ // must do this to prevent problems when destroying
+ // the effective sender of this event
+
+ Main::idle.connect (bind (slot (*this, &LocationUI::do_location_remove), loc));
+}
+
+
+void LocationUI::location_redraw_ranges ()
+{
+
+ range_rows.hide();
+ range_rows.show();
+
+}
+
+
+void
+LocationUI::location_added (Location* location)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LocationUI::location_added), location));
+
+ if (location->is_auto_punch()) {
+ punch_edit_row.set_location(location);
+ }
+ else if (location->is_auto_loop()) {
+ loop_edit_row.set_location(location);
+ }
+ else {
+ refresh_location_list ();
+ }
+}
+
+void
+LocationUI::location_removed (Location* location)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LocationUI::location_removed), location));
+
+ if (location->is_auto_punch()) {
+ punch_edit_row.set_location(0);
+ }
+ else if (location->is_auto_loop()) {
+ loop_edit_row.set_location(0);
+ }
+ else {
+ refresh_location_list ();
+ }
+}
+
+struct LocationSortByStart {
+ bool operator() (Location *a, Location *b) {
+ return a->start() < b->start();
+ }
+};
+
+void
+LocationUI::map_locations (Locations::LocationList& locations)
+{
+ Locations::LocationList::iterator i;
+ Location* location;
+ gint n;
+ int mark_n = 0;
+ Locations::LocationList temp = locations;
+ LocationSortByStart cmp;
+
+ temp.sort (cmp);
+ locations = temp;
+
+ Box_Helpers::BoxList & loc_children = location_rows.children();
+ Box_Helpers::BoxList & range_children = range_rows.children();
+ LocationEditRow * erow;
+
+ for (n = 0, i = locations.begin(); i != locations.end(); ++n, ++i) {
+
+ location = *i;
+
+ if (location->is_mark()) {
+ mark_n++;
+ erow = manage (new LocationEditRow(session, location, mark_n));
+ erow->remove_requested.connect (slot (*this, &LocationUI::location_remove_requested));
+ erow->redraw_ranges.connect (slot (*this, &LocationUI::location_redraw_ranges));
+ loc_children.push_back(Box_Helpers::Element(*erow, false, false, 1));
+ }
+ else if (location->is_auto_punch()) {
+ punch_edit_row.set_session (session);
+ punch_edit_row.set_location (location);
+ }
+ else if (location->is_auto_loop()) {
+ loop_edit_row.set_session (session);
+ loop_edit_row.set_location (location);
+ }
+ else {
+ erow = manage (new LocationEditRow(session, location));
+ erow->remove_requested.connect (slot (*this, &LocationUI::location_remove_requested));
+ range_children.push_back(Box_Helpers::Element(*erow, false, false, 1));
+ }
+ }
+
+ range_rows.show_all();
+ location_rows.show_all();
+}
+
+void
+LocationUI::add_new_location()
+{
+ if (session) {
+ jack_nframes_t where = session->audible_frame();
+ Location *location = new Location (where, where, "mark", Location::IsMark);
+ session->begin_reversible_command (_("add marker"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->add (location, true);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+ }
+
+}
+
+void
+LocationUI::add_new_range()
+{
+ if (session) {
+ jack_nframes_t where = session->audible_frame();
+ Location *location = new Location (where, where, "unnamed");
+ session->begin_reversible_command (_("add range marker"));
+ session->add_undo (session->locations()->get_memento());
+ session->locations()->add (location, true);
+ session->add_redo_no_execute (session->locations()->get_memento());
+ session->commit_reversible_command ();
+ }
+}
+
+
+void
+LocationUI::refresh_location_list_s (Change ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &LocationUI::refresh_location_list_s), ignored));
+
+ refresh_location_list ();
+}
+
+void
+LocationUI::refresh_location_list ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &LocationUI::refresh_location_list));
+ using namespace Box_Helpers;
+
+ BoxList & loc_children = location_rows.children();
+ BoxList & range_children = range_rows.children();
+
+ loc_children.clear();
+ range_children.clear();
+
+ if (session) {
+ session->locations()->apply (*this, &LocationUI::map_locations);
+ }
+
+}
+
+void
+LocationUI::set_session(ARDOUR::Session* sess)
+{
+ ArdourDialog::set_session (sess);
+
+ if (session) {
+ session->locations()->changed.connect (slot (*this, &LocationUI::refresh_location_list));
+ session->locations()->StateChanged.connect (slot (*this, &LocationUI::refresh_location_list_s));
+ session->locations()->added.connect (slot (*this, &LocationUI::location_added));
+ session->locations()->removed.connect (slot (*this, &LocationUI::location_removed));
+ session->going_away.connect (slot (*this, &LocationUI::session_gone));
+ }
+ refresh_location_list ();
+}
+
+void
+LocationUI::session_gone()
+{
+ ENSURE_GUI_THREAD(slot (*this, &LocationUI::session_gone));
+
+ hide_all();
+
+ using namespace Box_Helpers;
+ BoxList & loc_children = location_rows.children();
+ BoxList & range_children = range_rows.children();
+
+ loc_children.clear();
+ range_children.clear();
+
+ loop_edit_row.set_session (0);
+ loop_edit_row.set_location (0);
+
+ punch_edit_row.set_session (0);
+ punch_edit_row.set_location (0);
+
+ ArdourDialog::session_gone();
+}
+
diff --git a/gtk2_ardour/location_ui.h b/gtk2_ardour/location_ui.h
new file mode 100644
index 0000000000..92ea933928
--- /dev/null
+++ b/gtk2_ardour/location_ui.h
@@ -0,0 +1,198 @@
+/*
+ Copyright (C) 1999-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_location_ui_h__
+#define __ardour_location_ui_h__
+
+#include <gtk--.h>
+#include <ardour/location.h>
+#include <ardour/session.h>
+
+#include "ardour_dialog.h"
+#include "keyboard_target.h"
+
+namespace ARDOUR {
+ class LocationStack;
+ class Session;
+ class Location;
+}
+
+class LocationEditRow : public Gtk::HBox
+{
+ public:
+ LocationEditRow (ARDOUR::Session *sess=0, ARDOUR::Location *loc=0, int32_t num=-1);
+ virtual ~LocationEditRow();
+
+ void set_location (ARDOUR::Location*);
+ ARDOUR::Location * get_location() { return location; }
+
+ void set_session (ARDOUR::Session *);
+
+ void set_number (int);
+
+ SigC::Signal1<void,ARDOUR::Location*> remove_requested;
+ SigC::Signal0<void> redraw_ranges;
+
+ protected:
+
+ enum LocationPart {
+ LocStart,
+ LocEnd,
+ LocLength
+ };
+
+ ARDOUR::Location *location;
+ ARDOUR::Session *session;
+
+
+
+ Gtk::Table item_table;
+
+ Gtk::Entry name_entry;
+ Gtk::Label name_label;
+ Gtk::Label number_label;
+
+ Gtk::HBox start_hbox;
+ Gtk::Button start_set_button;
+ Gtk::Button start_go_button;
+ AudioClock start_clock;
+
+ Gtk::HBox end_hbox;
+ Gtk::Button end_set_button;
+ Gtk::Button end_go_button;
+ AudioClock end_clock;
+
+ AudioClock length_clock;
+ Gtk::CheckButton cd_check_button;
+ Gtk::CheckButton hide_check_button;
+
+ Gtk::Button remove_button;
+
+ Gtk::HBox cd_track_details_hbox;
+ Gtk::Entry isrc_entry;
+ Gtk::Label isrc_label;
+
+
+ Gtk::Label performer_label;
+ Gtk::Entry performer_entry;
+ Gtk::Label composer_label;
+ Gtk::Entry composer_entry;
+ Gtk::CheckButton scms_check_button;
+ Gtk::CheckButton preemph_check_button;
+
+
+ guint32 i_am_the_modifier;
+ int number;
+
+ void name_entry_changed ();
+ void isrc_entry_changed ();
+ void performer_entry_changed ();
+ void composer_entry_changed ();
+
+ void set_button_pressed (LocationPart part);
+ void go_button_pressed (LocationPart part);
+
+ void clock_changed (LocationPart part);
+
+ void cd_toggled ();
+ void hide_toggled ();
+ void remove_button_pressed ();
+
+ void scms_toggled ();
+ void preemph_toggled ();
+
+ gint entry_focus_event (GdkEventFocus* ev);
+
+ void end_changed (ARDOUR::Location *);
+ void start_changed (ARDOUR::Location *);
+ void name_changed (ARDOUR::Location *);
+ void location_changed (ARDOUR::Location *);
+ void flags_changed (ARDOUR::Location *, void *src);
+
+ SigC::Connection start_changed_connection;
+ SigC::Connection end_changed_connection;
+ SigC::Connection name_changed_connection;
+ SigC::Connection changed_connection;
+ SigC::Connection flags_changed_connection;
+
+};
+
+
+class LocationUI : public ArdourDialog
+{
+ public:
+ LocationUI ();
+ ~LocationUI ();
+
+ void set_session (ARDOUR::Session *);
+
+ private:
+
+
+ ARDOUR::LocationStack *locations;
+
+ void session_gone();
+
+
+ Gtk::VBox location_vpacker;
+ Gtk::HBox location_hpacker;
+
+ LocationEditRow loop_edit_row;
+ LocationEditRow punch_edit_row;
+
+ Gtk::VPaned loc_range_panes;
+
+ Gtk::Frame loc_frame;
+ Gtk::VBox loc_frame_box;
+ Gtk::Button add_location_button;
+ Gtk::ScrolledWindow location_rows_scroller;
+ Gtk::VBox location_rows;
+
+ Gtk::Frame range_frame;
+ Gtk::VBox range_frame_box;
+ Gtk::Button add_range_button;
+ Gtk::ScrolledWindow range_rows_scroller;
+ Gtk::VBox range_rows;
+
+
+ /* When any location changes it start
+ or end points, it sends a signal that is caught
+ by one of these functions
+ */
+
+ void location_remove_requested (ARDOUR::Location *);
+
+ void location_redraw_ranges ();
+
+ gint do_location_remove (ARDOUR::Location *);
+
+ guint32 i_am_the_modifier;
+
+ void add_new_location();
+ void add_new_range();
+
+ void refresh_location_list ();
+ void refresh_location_list_s (ARDOUR::Change);
+ void location_removed (ARDOUR::Location *);
+ void location_added (ARDOUR::Location *);
+ void map_locations (ARDOUR::Locations::LocationList&);
+};
+
+#endif // __ardour_location_ui_h__
diff --git a/gtk2_ardour/logmeter.h b/gtk2_ardour/logmeter.h
new file mode 100644
index 0000000000..f7ed1dd2be
--- /dev/null
+++ b/gtk2_ardour/logmeter.h
@@ -0,0 +1,49 @@
+#ifndef __ardour_gtk_log_meter_h__
+#define __ardour_gtk_log_meter_h__
+
+#if 0
+inline float
+_log_meter (float power, double lower_db, double upper_db, double non_linearity)
+{
+ return (power < lower_db ? 0.0 : pow((power-lower_db)/(upper_db-lower_db), non_linearity));
+}
+
+inline float
+log_meter (float power)
+{
+ return _log_meter (power, -192.0, 0.0, 8.0);
+}
+#endif
+
+inline float
+log_meter (float db)
+{
+ gfloat def = 0.0f; /* Meter deflection %age */
+
+ if (db < -70.0f) {
+ def = 0.0f;
+ } else if (db < -60.0f) {
+ def = (db + 70.0f) * 0.25f;
+ } else if (db < -50.0f) {
+ def = (db + 60.0f) * 0.5f + 2.5f;
+ } else if (db < -40.0f) {
+ def = (db + 50.0f) * 0.75f + 7.5f;
+ } else if (db < -30.0f) {
+ def = (db + 40.0f) * 1.5f + 15.0f;
+ } else if (db < -20.0f) {
+ def = (db + 30.0f) * 2.0f + 30.0f;
+ } else if (db < 6.0f) {
+ def = (db + 20.0f) * 2.5f + 50.0f;
+ } else {
+ def = 115.0f;
+ }
+
+ /* 115 is the deflection %age that would be
+ when db=6.0. this is an arbitrary
+ endpoint for our scaling.
+ */
+
+ return def/115.0f;
+}
+
+#endif /* __ardour_gtk_log_meter_h__ */
diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
new file mode 100644
index 0000000000..88ea54c44c
--- /dev/null
+++ b/gtk2_ardour/main.cc
@@ -0,0 +1,498 @@
+/*
+ Copyright (C) 2001-2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <cerrno>
+#include <cstdlib>
+#include <signal.h>
+#include <unistd.h>
+
+#include <sigc++/bind.h>
+
+#include <pbd/error.h>
+#include <pbd/textreceiver.h>
+#include <pbd/platform.h>
+#include <pbd/platform_factory.h>
+#include <pbd/failed_constructor.h>
+#include <pbd/pthread_utils.h>
+
+#include <jack/jack.h>
+
+#include <ardour/version.h>
+#include <ardour/ardour.h>
+#include <ardour/audioengine.h>
+
+#include <gtk--/main.h>
+#include <gtkmmext/popup.h>
+#include <gtkmmext/utils.h>
+
+#include "version.h"
+#include "ardour_ui.h"
+#include "opts.h"
+
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace GTK_ARDOUR;
+using namespace ARDOUR;
+using namespace SigC;
+
+Transmitter error (Transmitter::Error);
+Transmitter info (Transmitter::Info);
+Transmitter fatal (Transmitter::Fatal);
+Transmitter warning (Transmitter::Warning);
+TextReceiver text_receiver ("ardour");
+
+extern int curvetest (string);
+
+static ARDOUR_UI *ui = 0;
+
+static void
+shutdown (int status)
+{
+ char* msg;
+
+ if (status) {
+
+ msg = _("ardour is killing itself for a clean exit\n");
+ write (1, msg, strlen (msg));
+ /* drastic, but perhaps necessary */
+ kill (-getpgrp(), SIGKILL);
+ /*NOTREACHED*/
+
+ } else {
+
+ if (ui) {
+ msg = _("stopping user interface\n");
+ write (1, msg, strlen (msg));
+ ui->kill();
+ }
+
+ pthread_cancel_all ();
+ }
+
+ exit (status);
+}
+
+
+static void
+handler (int sig)
+{
+ char buf[64];
+ int n;
+
+ /* XXX its doubtful that snprintf() is async-safe */
+ n = snprintf (buf, sizeof(buf), _("%d(%d): received signal %d\n"), getpid(), (int) pthread_self(), sig);
+ write (1, buf, n);
+
+ shutdown (1);
+}
+
+static void
+handler2 (int sig, siginfo_t* ctxt, void* ignored)
+{
+ handler (sig);
+}
+
+static void *
+signal_thread (void *arg)
+{
+ int sig;
+ sigset_t blocked;
+
+ PBD::ThreadCreated (pthread_self(), X_("Signal"));
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+
+ /* find out what's blocked right now */
+
+ //sigprocmask (SIG_SETMASK, 0, &blocked);
+ if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
+ cerr << "getting blocked signals failed\n";
+ }
+
+ /* wait for any of the currently blocked signals.
+
+ According to the man page found in linux 2.6 and 2.4, sigwait()
+ never returns an error. This is incorrect. Checking the man
+ pages for some other *nix systems makes it clear that
+ sigwait() can return several error codes, one of which
+ is EINTR. This happens if the thread receives a signal
+ which is not in the blocked set.
+
+ We do not expect that to happen, and if it did we should generally
+ exit as planned. However, under 2.6, the ptrace facility used
+ by gdb seems to also cause sigwait() to return with EINTR
+ but with a signal that sigwait cannot understand. As a result,
+ "sig" is set to zero, an impossible signal number.
+
+ Handling the EINTR code makes it possible to debug
+ ardour on a 2.6 kernel.
+
+ */
+
+ int swerr;
+
+ again:
+ if ((swerr = sigwait (&blocked, &sig))) {
+ if (swerr == EINTR) {
+ goto again;
+ } else {
+ cerr << "sigwait failed with " << swerr << endl;
+ }
+ }
+
+ cerr << "Signal " << sig << " received\n";
+
+ if (sig != SIGSEGV) {
+
+ /* unblock signals so we can see them during shutdown.
+ this will help prod developers not to lose sight
+ of bugs that cause segfaults etc. during shutdown.
+ */
+
+ sigprocmask (SIG_UNBLOCK, &blocked, 0);
+ }
+
+ shutdown (1);
+ /*NOTREACHED*/
+ return 0;
+}
+
+int
+catch_signals (void)
+{
+ struct sigaction action;
+ pthread_t signal_thread_id;
+ sigset_t signals;
+
+// if (setpgid (0,0)) {
+ if (setsid ()) {
+ warning << compose (_("cannot become new process group leader (%1)"),
+ strerror (errno))
+ << endmsg;
+ }
+
+ sigemptyset (&signals);
+ sigaddset(&signals, SIGHUP);
+ sigaddset(&signals, SIGINT);
+ sigaddset(&signals, SIGQUIT);
+ sigaddset(&signals, SIGPIPE);
+ sigaddset(&signals, SIGTERM);
+ sigaddset(&signals, SIGUSR1);
+ sigaddset(&signals, SIGUSR2);
+
+
+ /* install a handler because otherwise
+ pthreads behaviour is undefined when we enter
+ sigwait.
+ */
+
+ action.sa_handler = handler;
+ action.sa_mask = signals;
+ action.sa_flags = SA_RESTART|SA_RESETHAND;
+
+ for (int i = 1; i < 32; i++) {
+ if (sigismember (&signals, i)) {
+ if (sigaction (i, &action, 0)) {
+ cerr << compose (_("cannot setup signal handling for %1"), i) << endl;
+ return -1;
+ }
+ }
+ }
+
+ /* this sets the signal mask for this and all
+ subsequent threads that do not reset it.
+ */
+
+ if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
+ cerr << compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
+ return -1;
+ }
+
+ /* start a thread to wait for signals */
+
+ if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
+ cerr << "cannot create signal catching thread" << endl;
+ return -1;
+ }
+
+ pthread_detach (signal_thread_id);
+ return 0;
+}
+
+string
+which_ui_rcfile ()
+{
+ string rcfile;
+ char* envvar;
+
+ if ((envvar = getenv("ARDOUR_UI_RC")) == 0) {
+ rcfile = find_config_file ("ardour_ui.rc");
+
+ if (rcfile.length() == 0) {
+ warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR_UI_RC to point to a valid UI style file") << endmsg;
+ }
+ } else {
+ rcfile = envvar;
+ }
+
+ return rcfile;
+}
+
+gint
+show_ui_callback (void *arg)
+{
+ ARDOUR_UI * ui = (ARDOUR_UI *) arg;
+
+ ui->hide_splash();
+ ui->show ();
+
+ return FALSE;
+}
+
+gint
+jack_fooey (GdkEventAny* ignored)
+{
+ Main::quit ();
+ return FALSE;
+}
+
+void
+jack_foobar ()
+{
+ Main::quit ();
+}
+
+void
+gui_jack_error ()
+{
+ Window win (GTK_WINDOW_DIALOG);
+ VBox vpacker;
+ Button ok (_("OK"));
+ Label label (_("Ardour could not connect to JACK.\n\
+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."));
+
+ vpacker.set_spacing (12);
+ vpacker.pack_start (label);
+ vpacker.pack_start (ok, false, false);
+
+ win.set_title (_("ardour: unplugged"));
+ win.set_border_width (7);
+ win.add (vpacker);
+ win.show_all ();
+ win.delete_event.connect (SigC::slot (jack_fooey));
+ win.add_events (GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK);
+ win.set_position (GTK_WIN_POS_CENTER);
+ win.realize ();
+ win.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ ok.clicked.connect (SigC::slot (jack_foobar));
+
+ ok.grab_focus ();
+
+ Main::run ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ ARDOUR::AudioEngine *engine;
+ char *null_file_list[] = { 0 };
+
+ gtk_set_locale ();
+
+ (void) bindtextdomain (PACKAGE, LOCALEDIR);
+ (void) textdomain (PACKAGE);
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+
+ catch_signals ();
+
+ text_receiver.listen_to (error);
+ text_receiver.listen_to (info);
+ text_receiver.listen_to (fatal);
+ text_receiver.listen_to (warning);
+
+
+ if (parse_opts (argc, argv)) {
+ exit (1);
+ }
+
+ if (curvetest_file) {
+ return curvetest (curvetest_file);
+ }
+
+ /* desktop standard themes: just say no! */
+
+ if (getenv("GTK_RC_FILES")) {
+ unsetenv("GTK_RC_FILES");
+ }
+
+ if (getenv("GTK2_RC_FILES")) {
+ unsetenv("GTK_RC_FILES");
+ }
+
+ gtk_rc_set_default_files (null_file_list);
+
+ cout << _("Ardour/GTK ")
+ << VERSIONSTRING
+ << _("\n (built using ")
+ << gtk_ardour_major_version << '.'
+ << gtk_ardour_minor_version << '.'
+ << gtk_ardour_micro_version
+ << _(" with libardour ")
+ << libardour_major_version << '.'
+ << libardour_minor_version << '.'
+ << libardour_micro_version
+#ifdef __GNUC__
+ << _(" and GCC version ") << __VERSION__
+#endif
+ << ')'
+ << endl;
+
+ if (just_version) {
+ exit (0);
+ }
+
+ if (no_splash) {
+ cerr << _("Copyright (C) 1999-2005 Paul Davis") << endl
+ << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
+ << endl
+ << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
+ << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
+ << _("This is free software, and you are welcome to redistribute it ") << endl
+ << _("under certain conditions; see the source for copying conditions.")
+ << endl;
+ }
+
+ try {
+ ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
+ }
+
+ catch (failed_constructor& err) {
+ error << _("could not create ARDOUR GUI") << endmsg;
+ exit (1);
+ }
+
+
+ if (!no_splash) {
+ ui->show_splash ();
+ if (session_name.length()) {
+ gtk_timeout_add (4000, show_ui_callback, ui);
+ }
+ }
+
+ try {
+ engine = new ARDOUR::AudioEngine (jack_client_name);
+ ARDOUR::init (*engine, use_vst, try_hw_optimization, handler2);
+ ui->set_engine (*engine);
+ }
+
+ catch (AudioEngine::NoBackendAvailable& err) {
+ gui_jack_error ();
+ error << compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
+ return -1;
+ }
+
+ catch (failed_constructor& err) {
+ error << _("could not initialize Ardour.") << endmsg;
+ exit (1);
+ }
+
+ /* load session, if given */
+ string name, path;
+
+ if (session_name.length()){
+ bool isnew;
+
+ if (Session::find_session (session_name, path, name, isnew)) {
+ error << compose(_("could not load command line session \"%1\""), session_name) << endmsg;
+ } else {
+
+ if (new_session) {
+
+ /* command line required that the session be new */
+
+ if (isnew) {
+
+ /* popup the new session dialog
+ once everything else is OK.
+ */
+
+ Main::idle.connect (bind (slot (*ui, &ARDOUR_UI::cmdline_new_session), path));
+ ui->set_will_create_new_session_automatically (true);
+
+ } else {
+
+ /* it wasn't new, but we require a new session */
+
+ error << compose (_("\n\nA session named \"%1\" already exists.\n\
+To avoid this message, start ardour as \"ardour %1"), path)
+ << endmsg;
+ goto out;
+ }
+
+ } else {
+
+ /* command line didn't require a new session */
+
+ if (isnew) {
+ error << compose (_("\n\nNo session named \"%1\" exists.\n\
+To create it from the command line, start ardour as \"ardour --new %1"), path)
+ << endmsg;
+ goto out;
+ }
+
+ ui->load_session (path, name);
+ }
+ }
+
+ if (no_splash) {
+ ui->show();
+ }
+
+ } else {
+ ui->hide_splash ();
+ ui->show ();
+ if (!Config->get_no_new_session_dialog()) {
+ ui->new_session (true);
+ }
+ }
+
+ ui->run (text_receiver);
+
+ delete ui;
+ ui = 0;
+
+ out:
+ delete engine;
+ ARDOUR::cleanup ();
+ shutdown (0);
+}
+
diff --git a/gtk2_ardour/marker.cc b/gtk2_ardour/marker.cc
new file mode 100644
index 0000000000..0014476c29
--- /dev/null
+++ b/gtk2_ardour/marker.cc
@@ -0,0 +1,449 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/tempo.h>
+
+#include "marker.h"
+#include "public_editor.h"
+#include "canvas-simpleline.h"
+#include "utils.h"
+
+#include "i18n.h"
+
+Marker::Marker (PublicEditor& ed, GtkCanvasGroup *parent, guint32 rgba, const string& annotation,
+ Type type, gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer), jack_nframes_t frame)
+
+ : editor (ed), _type(type)
+{
+ double label_offset = 0;
+
+ /* Shapes we use:
+
+ Mark:
+
+ (0,0) -> (6,0)
+ ^ |
+ | V
+ (0,5) (6,5)
+ \ /
+ (3,10)
+
+
+ TempoMark:
+ MeterMark:
+
+ (3,0)
+ / \
+ (0,5) -> (6,5)
+ ^ |
+ | V
+ (0,10)<-(6,10)
+
+
+ Start:
+
+ 0,0 -> 5,0
+ | \
+ | 10,5
+ | /
+ 0,10 -> 5,10
+
+ End:
+
+ 5,0 -> 10,0
+ / |
+ 0,5 |
+ \ |
+ 5,10 <-10,10
+
+
+ TransportStart:
+
+ 0,0->3,0
+ | |
+ | |
+ | |
+ | 3,8 -> 7,8
+ | |
+ 0,11 ------ 7,11
+
+ TransportEnd:
+
+ 4,0->7,0
+ | |
+ | |
+ | |
+ 0,8 ---- 4,8 |
+ | |
+ 0,11 -------- 7,11
+
+
+ PunchIn:
+
+ 0,0 ------> 8,0
+ | /
+ | /
+ | 4,5
+ | |
+ | |
+ | |
+ 0,11->4,11
+
+ PunchOut
+
+ 0,0 -->-8,0
+ \ |
+ \ |
+ 4,5 |
+ | |
+ | |
+ | |
+ 4,11->8,11
+
+
+ */
+
+ switch (type) {
+ case Mark:
+ points = gtk_canvas_points_new (6);
+
+ points->coords[0] = 0.0;
+ points->coords[1] = 0.0;
+
+ points->coords[2] = 6.0;
+ points->coords[3] = 0.0;
+
+ points->coords[4] = 6.0;
+ points->coords[5] = 5.0;
+
+ points->coords[6] = 3.0;
+ points->coords[7] = 10.0;
+
+ points->coords[8] = 0.0;
+ points->coords[9] = 5.0;
+
+ points->coords[10] = 0.0;
+ points->coords[11] = 0.0;
+
+ shift = 3;
+ label_offset = 8.0;
+ break;
+
+ case Tempo:
+ case Meter:
+ points = gtk_canvas_points_new (6);
+
+ points->coords[0] = 3.0;
+ points->coords[1] = 0.0;
+
+ points->coords[2] = 6.0;
+ points->coords[3] = 5.0;
+
+ points->coords[4] = 6.0;
+ points->coords[5] = 10.0;
+
+ points->coords[6] = 0.0;
+ points->coords[7] = 10.0;
+
+ points->coords[8] = 0.0;
+ points->coords[9] = 5.0;
+
+ points->coords[10] = 3.0;
+ points->coords[11] = 0.0;
+
+ shift = 3;
+ label_offset = 8.0;
+ break;
+
+ case Start:
+ points = gtk_canvas_points_new (6);
+
+ points->coords[0] = 0.0;
+ points->coords[1] = 0.0;
+
+ points->coords[2] = 5.0;
+ points->coords[3] = 0.0;
+
+ points->coords[4] = 10.0;
+ points->coords[5] = 5.0;
+
+ points->coords[6] = 5.0;
+ points->coords[7] = 10.0;
+
+ points->coords[8] = 0.0;
+ points->coords[9] = 10.0;
+
+ points->coords[10] = 0.0;
+ points->coords[11] = 0.0;
+
+ shift = 10;
+ label_offset = 12.0;
+ break;
+
+ case End:
+ points = gtk_canvas_points_new (6);
+
+ points->coords[0] = 5.0;
+ points->coords[1] = 0.0;
+
+ points->coords[2] = 10.0;
+ points->coords[3] = 0.0;
+
+ points->coords[4] = 10.0;
+ points->coords[5] = 10.0;
+
+ points->coords[6] = 5.0;
+ points->coords[7] = 10.0;
+
+ points->coords[8] = 0.0;
+ points->coords[9] = 5.0;
+
+ points->coords[10] = 5.0;
+ points->coords[11] = 0.0;
+
+ shift = 0;
+ label_offset = 12.0;
+ break;
+
+ case LoopStart:
+ points = gtk_canvas_points_new (7);
+
+ points->coords[0] = 0.0;
+ points->coords[1] = 0.0;
+
+ points->coords[2] = 4.0;
+ points->coords[3] = 0.0;
+
+ points->coords[4] = 4.0;
+ points->coords[5] = 8.0;
+
+ points->coords[6] = 8.0;
+ points->coords[7] = 8.0;
+
+ points->coords[8] = 8.0;
+ points->coords[9] = 11.0;
+
+ points->coords[10] = 0.0;
+ points->coords[11] = 11.0;
+
+ points->coords[12] = 0.0;
+ points->coords[13] = 0.0;
+
+ shift = 0;
+ label_offset = 11.0;
+ break;
+
+ case LoopEnd:
+ points = gtk_canvas_points_new (7);
+
+ points->coords[0] = 8.0;
+ points->coords[1] = 0.0;
+
+ points->coords[2] = 8.0;
+ points->coords[3] = 11.0;
+
+ points->coords[4] = 0.0;
+ points->coords[5] = 11.0;
+
+ points->coords[6] = 0.0;
+ points->coords[7] = 8.0;
+
+ points->coords[8] = 4.0;
+ points->coords[9] = 8.0;
+
+ points->coords[10] = 4.0;
+ points->coords[11] = 0.0;
+
+ points->coords[12] = 8.0;
+ points->coords[13] = 0.0;
+
+ shift = 8;
+ label_offset = 11.0;
+ break;
+
+ case PunchIn:
+ points = gtk_canvas_points_new (6);
+
+ points->coords[0] = 0.0;
+ points->coords[1] = 0.0;
+
+ points->coords[2] = 8.0;
+ points->coords[3] = 0.0;
+
+ points->coords[4] = 4.0;
+ points->coords[5] = 4.0;
+
+ points->coords[6] = 4.0;
+ points->coords[7] = 11.0;
+
+ points->coords[8] = 0.0;
+ points->coords[9] = 11.0;
+
+ points->coords[10] = 0.0;
+ points->coords[11] = 0.0;
+
+ shift = 0;
+ label_offset = 10.0;
+ break;
+
+ case PunchOut:
+ points = gtk_canvas_points_new (6);
+
+ points->coords[0] = 0.0;
+ points->coords[1] = 0.0;
+
+ points->coords[2] = 8.0;
+ points->coords[3] = 0.0;
+
+ points->coords[4] = 8.0;
+ points->coords[5] = 11.0;
+
+ points->coords[6] = 4.0;
+ points->coords[7] = 11.0;
+
+ points->coords[8] = 4.0;
+ points->coords[9] = 4.0;
+
+ points->coords[10] = 0.0;
+ points->coords[11] = 0.0;
+
+ shift = 8;
+ label_offset = 11.0;
+ break;
+
+ }
+
+ frame_position = frame;
+ unit_position = editor.frame_to_unit (frame);
+
+ /* adjust to properly locate the tip */
+
+ unit_position -= shift;
+
+ group = gtk_canvas_item_new (parent,
+ gtk_canvas_group_get_type(),
+ "x", unit_position,
+ "y", 1.0,
+ NULL);
+
+ // cerr << "set mark al points, nc = " << points->num_points << endl;
+ mark = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_polygon_get_type(),
+ "points", points,
+ "fill_color_rgba", rgba,
+ "outline_color", "black",
+ NULL);
+
+ string fontname = get_font_for_style (N_("MarkerText"));
+
+ text = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_text_get_type (),
+ "text", annotation.c_str(),
+ "x", label_offset,
+ "y", 0.0,
+ "font", fontname.c_str(),
+ "anchor", GTK_ANCHOR_NW,
+ "fill_color", "black",
+ NULL);
+
+ gtk_object_set_data (GTK_OBJECT(group), "marker", this);
+ gtk_signal_connect (GTK_OBJECT(group), "event", (GtkSignalFunc) callback, &editor);
+
+ editor.ZoomChanged.connect (slot (*this, &Marker::reposition));
+}
+
+Marker::~Marker ()
+{
+ /* destroying the group destroys its contents */
+ gtk_object_destroy (GTK_OBJECT(group));
+ gtk_canvas_points_unref (points);
+}
+
+void
+Marker::set_name (const string& name)
+{
+ gtk_canvas_item_set (text, "text", name.c_str(), NULL);
+}
+
+void
+Marker::set_position (jack_nframes_t frame)
+{
+ double new_unit_position = editor.frame_to_unit (frame);
+ new_unit_position -= shift;
+ gtk_canvas_item_move (group, new_unit_position - unit_position, 0.0);
+ frame_position = frame;
+ unit_position = new_unit_position;
+}
+
+void
+Marker::reposition ()
+{
+ set_position (frame_position);
+}
+
+void
+Marker::show ()
+{
+ gtk_canvas_item_show (group);
+}
+
+void
+Marker::hide ()
+{
+ gtk_canvas_item_hide (group);
+}
+
+void
+Marker::set_color_rgba (uint32_t color)
+{
+ gtk_canvas_item_set (mark, "fill_color_rgba", color, NULL);
+}
+
+/***********************************************************************/
+
+TempoMarker::TempoMarker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text,
+ ARDOUR::TempoSection& temp,
+ gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer))
+ : Marker (editor, parent, rgba, text, Tempo, callback, 0),
+ _tempo (temp)
+{
+ set_position (_tempo.frame());
+ gtk_object_set_data (GTK_OBJECT(group), "tempo_marker", this);
+}
+
+TempoMarker::~TempoMarker ()
+{
+}
+
+/***********************************************************************/
+
+MeterMarker::MeterMarker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text,
+ ARDOUR::MeterSection& m,
+ gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer))
+ : Marker (editor, parent, rgba, text, Meter, callback, 0),
+ _meter (m)
+{
+ set_position (_meter.frame());
+ gtk_object_set_data (GTK_OBJECT(group), "meter_marker", this);
+}
+
+MeterMarker::~MeterMarker ()
+{
+}
diff --git a/gtk2_ardour/marker.h b/gtk2_ardour/marker.h
new file mode 100644
index 0000000000..01f1404a82
--- /dev/null
+++ b/gtk2_ardour/marker.h
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_marker_h__
+#define __gtk_ardour_marker_h__
+
+#include <string>
+#include <glib.h>
+#include <ardour/ardour.h>
+#include <gtk-canvas.h>
+#include <sigc++/signal_system.h>
+
+namespace ARDOUR {
+ class TempoSection;
+ class MeterSection;
+}
+
+class PublicEditor;
+
+class Marker : public SigC::Object
+{
+ public:
+ enum Type {
+ Mark,
+ Tempo,
+ Meter,
+ Start,
+ End,
+ LoopStart,
+ LoopEnd,
+ PunchIn,
+ PunchOut
+ };
+
+ Marker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text, Type,
+ gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer), jack_nframes_t frame = 0);
+ virtual ~Marker ();
+
+ void set_position (jack_nframes_t);
+ void set_name (const string&);
+ void set_color_rgba (uint32_t rgba);
+
+ void hide ();
+ void show ();
+
+ Type type () { return _type; }
+
+ protected:
+ PublicEditor& editor;
+
+ GtkCanvasItem *group;
+ GtkCanvasItem *mark;
+ GtkCanvasItem *text;
+ GtkCanvasPoints *points;
+
+ double unit_position;
+ jack_nframes_t frame_position;
+ unsigned char shift; /* should be double, but its always small and integral */
+ Type _type;
+
+ void reposition ();
+};
+
+class TempoMarker : public Marker
+{
+ public:
+ TempoMarker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text, ARDOUR::TempoSection&,
+ gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer));
+ ~TempoMarker ();
+
+ ARDOUR::TempoSection& tempo() const { return _tempo; }
+
+ private:
+ ARDOUR::TempoSection& _tempo;
+};
+
+class MeterMarker : public Marker
+{
+ public:
+ MeterMarker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text, ARDOUR::MeterSection&,
+ gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer));
+ ~MeterMarker ();
+
+ ARDOUR::MeterSection& meter() const { return _meter; }
+
+ private:
+ ARDOUR::MeterSection& _meter;
+};
+
+#endif /* __gtk_ardour_marker_h__ */
diff --git a/gtk2_ardour/marker_time_axis.cc b/gtk2_ardour/marker_time_axis.cc
new file mode 100644
index 0000000000..9efde933bb
--- /dev/null
+++ b/gtk2_ardour/marker_time_axis.cc
@@ -0,0 +1,333 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <string>
+
+#include <pbd/error.h>
+
+#include <gtkmmext/utils.h>
+
+#include <ardour/session.h>
+#include <ardour/utils.h>
+
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "imageframe_time_axis.h"
+#include "canvas-simplerect.h"
+#include "selection.h"
+#include "imageframe_time_axis_view.h"
+#include "marker_time_axis_view.h"
+#include "imageframe_view.h"
+#include "marker_time_axis.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+using namespace Gtk;
+
+//---------------------------------------------------------------------------------------//
+// Constructor / Desctructor
+
+/**
+ * Constructs a new MarkerTimeAxis
+ *
+ * @param ed the PublicEditor
+ * @param sess the current session
+ * @param canvas the parent canvas item
+ * @param name the name/id of this time axis
+ * @param tav the associated track view that this MarkerTimeAxis is marking up
+ */
+MarkerTimeAxis::MarkerTimeAxis (PublicEditor& ed, ARDOUR::Session& sess, Widget *canvas, std::string name, TimeAxisView* tav)
+ : AxisView(sess),
+ VisualTimeAxis(name, ed, sess, canvas)
+{
+ /* the TimeAxisView these markers are associated with */
+ marked_time_axis = tav ;
+
+ _color = unique_random_color() ;
+ time_axis_name = name ;
+
+ selection_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display), gtk_canvas_group_get_type (), 0) ;
+ gtk_canvas_item_hide(selection_group) ;
+
+ // intialize our data items
+ name_prompter = 0 ;
+ marker_menu = 0 ;
+
+ y_position = -1 ;
+
+ /* create our new marker time axis strip view */
+ view = new MarkerTimeAxisView(*this) ;
+
+ // set the initial time axis text label
+ label_view() ;
+
+ // set the initial height of this time axis
+ set_height(Small) ;
+}
+
+/**
+ * Destructor
+ * Responsible for destroying any marker items upon this time axis
+ */
+MarkerTimeAxis::~MarkerTimeAxis()
+{
+ GoingAway() ; /* EMIT_SIGNAL */
+
+ for (list<SelectionRect*>::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i)
+ {
+ gtk_object_destroy (GTK_OBJECT((*i)->rect));
+ gtk_object_destroy (GTK_OBJECT((*i)->start_trim));
+ gtk_object_destroy (GTK_OBJECT((*i)->end_trim));
+ }
+
+ for (list<SelectionRect*>::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i)
+ {
+ gtk_object_destroy (GTK_OBJECT((*i)->rect));
+ gtk_object_destroy (GTK_OBJECT((*i)->start_trim));
+ gtk_object_destroy (GTK_OBJECT((*i)->end_trim));
+ }
+
+ if(selection_group)
+ {
+ gtk_object_destroy(GTK_OBJECT (selection_group)) ;
+ selection_group = 0 ;
+ }
+
+ // destroy the view helper
+ // this handles removing and destroying individual marker items
+ if(view)
+ {
+ delete view ;
+ view = 0 ;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// ui methods & data
+
+/**
+ * Sets the height of this TrackView to one of the defined TrackHeights
+ *
+ * @param h the TrackHeight value to set
+ */
+void
+MarkerTimeAxis::set_height (TrackHeight h)
+{
+ VisualTimeAxis::set_height(h) ;
+
+ // tell out view helper of the change too
+ if (view != 0)
+ {
+ view->set_height((double) height) ;
+ }
+
+ // tell those interested that we have had our height changed
+ gui_changed("track_height",(void*)0) ; /* EMIT_SIGNAL */
+}
+
+/**
+ * Sets the number of samples per unit that are used.
+ * This is used to determine the sizes of items upon this time axis
+ *
+ * @param spu the number of samples per unit
+ */
+void
+MarkerTimeAxis::set_samples_per_unit(double spu)
+{
+ TimeAxisView::set_samples_per_unit (editor.get_current_zoom());
+
+ if (view) {
+ view->set_samples_per_unit(spu) ;
+ }
+}
+
+/**
+ * Show the popup edit menu
+ *
+ * @param button the mouse button pressed
+ * @param time when to show the popup
+ * @param clicked_mv the MarkerView that the event ocured upon, or 0 if none
+ * @param with_item true if an item has been selected upon the time axis, used to set context menu
+ */
+void
+MarkerTimeAxis::popup_marker_time_axis_edit_menu(int button, int32_t time, MarkerView* clicked_mv, bool with_item)
+{
+ if (!marker_menu)
+ {
+ build_marker_menu() ;
+ }
+
+ if (with_item)
+ {
+ marker_item_menu->set_sensitive(true) ;
+ }
+ else
+ {
+ marker_item_menu->set_sensitive(false) ;
+ }
+
+ marker_menu->popup(button,time) ;
+}
+
+
+/**
+ * convenience method to select a new track color and apply it to the view and view items
+ *
+ */
+void
+MarkerTimeAxis::select_track_color()
+{
+ if(VisualTimeAxis::choose_time_axis_color())
+ {
+ if(view)
+ {
+ view->apply_color(_color) ;
+ }
+ }
+}
+
+/**
+ * Handles the building of the popup menu
+ */
+void
+MarkerTimeAxis::build_display_menu()
+{
+ using namespace Menu_Helpers;
+
+ /* get the size menu ready */
+ build_size_menu() ;
+
+ /* prepare it */
+ TimeAxisView::build_display_menu();
+
+ /* now fill it with our stuff */
+ MenuList& items = display_menu->items();
+
+ items.push_back(MenuElem (_("Rename"), slot (*this, &VisualTimeAxis::start_time_axis_rename)));
+
+ items.push_back(SeparatorElem()) ;
+ items.push_back(MenuElem (_("Height"), *size_menu));
+ items.push_back(MenuElem (_("Color"), slot (*this, &MarkerTimeAxis::select_track_color)));
+ items.push_back(SeparatorElem()) ;
+
+ items.push_back(MenuElem (_("Remove"), bind(slot(*this, &MarkerTimeAxis::remove_this_time_axis), (void*)this)));
+}
+
+/**
+ * handles the building of the MarkerView sub menu
+ */
+void
+MarkerTimeAxis::build_marker_menu()
+{
+ using namespace Menu_Helpers;
+
+ marker_menu = manage(new Menu) ;
+ marker_menu->set_name ("ArdourContextMenu");
+ MenuList& items = marker_menu->items();
+
+ marker_item_menu = manage(new Menu) ;
+ marker_item_menu->set_name ("ArdourContextMenu");
+ MenuList& marker_sub_items = marker_item_menu->items() ;
+
+ /* duration menu */
+ Menu* duration_menu = manage(new Menu) ;
+ duration_menu->set_name ("ArdourContextMenu");
+ MenuList& duration_items = duration_menu->items() ;
+
+ if(view)
+ {
+ duration_items.push_back(MenuElem (_("1 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 1.0))) ;
+ duration_items.push_back(MenuElem (_("1.5 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 1.5))) ;
+ duration_items.push_back(MenuElem (_("2 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 2.0))) ;
+ duration_items.push_back(MenuElem (_("2.5 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 2.5))) ;
+ duration_items.push_back(MenuElem (_("3 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 3.0))) ;
+ }
+ //duration_items.push_back(SeparatorElem()) ;
+ //duration_items.push_back(MenuElem (_("custom"), slot (*this, &ImageFrameTimeAxis::set_marker_duration_custom))) ;
+
+ marker_sub_items.push_back(MenuElem(_("Duration (sec)"), *duration_menu)) ;
+
+ marker_sub_items.push_back(SeparatorElem()) ;
+ marker_sub_items.push_back(MenuElem (_("Remove Marker"), bind(slot(view, &MarkerTimeAxisView::remove_selected_marker_view),(void*)this))) ;
+
+ items.push_back(MenuElem(_("Marker"), *marker_item_menu)) ;
+ items.push_back(MenuElem (_("Rename Track"), slot (*this,&MarkerTimeAxis::start_time_axis_rename))) ;
+
+ marker_menu->show_all() ;
+}
+
+
+
+/**
+ * Returns the view helper of this TimeAxis
+ *
+ * @return the view helper of this TimeAxis
+ */
+MarkerTimeAxisView*
+MarkerTimeAxis::get_view()
+{
+ return(view) ;
+}
+
+/**
+ * Returns the TimeAxisView that this markerTimeAxis is marking up
+ *
+ * @return the TimeAXisView that this MarkerTimeAxis is marking
+ */
+TimeAxisView*
+MarkerTimeAxis::get_marked_time_axis()
+{
+ return(marked_time_axis) ;
+}
+
+
+
+
+/**
+ * Handle the closing of the renaming dialog during the rename of this item
+ */
+void
+MarkerTimeAxis::finish_route_rename()
+{
+ name_prompter->hide_all ();
+ ARDOUR_UI::instance()->allow_focus (false);
+
+ if (name_prompter->status == Gtkmmext::Prompter::cancelled) {
+ return;
+ }
+
+ string result;
+ name_prompter->get_result(result);
+ time_axis_name = result ;
+ editor.route_name_changed(this) ;
+ label_view() ;
+ delete name_prompter ;
+ name_prompter = 0 ;
+}
+
+
+
+
+
+
+
diff --git a/gtk2_ardour/marker_time_axis.h b/gtk2_ardour/marker_time_axis.h
new file mode 100644
index 0000000000..a46025cd19
--- /dev/null
+++ b/gtk2_ardour/marker_time_axis.h
@@ -0,0 +1,164 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_marker_time_axis_h__
+#define __ardour_marker_time_axis_h__
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+
+#include "ardour_dialog.h"
+#include "route_ui.h"
+#include "enums.h"
+#include "time_axis_view.h"
+#include <string>
+#include "visual_time_axis.h"
+
+namespace ARDOUR {
+ class Session;
+}
+
+class PublicEditor;
+class ImageFrameView ;
+class ImageFrameTimeAxisView ;
+class MarkerTimeAxisView ;
+class MarkerView ;
+
+/**
+ * MarkerTimeAxis defines a visual time axis for holding marker items associated with other time axis, and time axis items.
+ *
+ * The intention of this time axis is to allow markers with duration to be arranged on the time line
+ * to add additional timing information to items on an associated time axis, for instance the addition
+ * of effect duration and timings
+ */
+class MarkerTimeAxis : public VisualTimeAxis
+{
+ public:
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * Constructs a new MarkerTimeAxis
+ *
+ * @param ed the PublicEditor
+ * @param sess the current session
+ * @param canvas the parent canvas item
+ * @param name the name/id of this time axis
+ * @param tav the associated track view that this MarkerTimeAxis is marking up
+ */
+ MarkerTimeAxis(PublicEditor& ed, ARDOUR::Session& sess, Gtk::Widget* canvas, std::string name, TimeAxisView* tav) ;
+
+ /**
+ * Destructor
+ * Responsible for destroying any marker items upon this time axis
+ */
+ virtual ~MarkerTimeAxis() ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods & data
+
+ /**
+ * Sets the height of this TrackView to one of the defined TrackHeights
+ *
+ * @param h the TrackHeight value to set
+ */
+ virtual void set_height(TimeAxisView::TrackHeight h) ;
+
+ /**
+ * Sets the number of samples per unit that are used.
+ * This is used to determine the sizes of items upon this time axis
+ *
+ * @param spu the number of samples per unit
+ */
+ virtual void set_samples_per_unit(double spu) ;
+
+
+ /**
+ * Show the popup edit menu
+ *
+ * @param button the mouse button pressed
+ * @param time when to show the popup
+ * @param clicked_mv the MarkerView that the event ocured upon, or 0 if none
+ * @param with_item true if an item has been selected upon the time axis, used to set context menu
+ */
+ void popup_marker_time_axis_edit_menu(int button, int32_t time, MarkerView* clicked_mv, bool with_item) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Parent/Child helper object accessors
+
+ /**
+ * Returns the view helper of this TimeAxis
+ *
+ * @return the view helper of this TimeAxis
+ */
+ MarkerTimeAxisView* get_view() ;
+
+ /**
+ * Returns the TimeAxisView that this markerTimeAxis is marking up
+ *
+ * @return the TimeAXisView that this MarkerTimeAxis is marking
+ */
+ TimeAxisView* get_marked_time_axis() ;
+
+
+ protected:
+
+ /**
+ * Handle the closing of the renaming dialog during the rename of this item
+ */
+ virtual void finish_route_rename() ;
+
+ private:
+
+ /**
+ * convenience method to select a new track color and apply it to the view and view items
+ *
+ */
+ void select_track_color() ;
+
+ /**
+ * Handles the building of the popup menu
+ */
+ virtual void build_display_menu() ;
+
+ /**
+ * handles the building of the MarkerView sub menu
+ */
+ void build_marker_menu() ;
+
+ /** The associated TimeAxis that this MarkerTimeAxis is marking up */
+ TimeAxisView* marked_time_axis ;
+
+ /** Our time axis view helper */
+ MarkerTimeAxisView *view ;
+
+ /** the popup menu available by clicking upon this time axis */
+ Gtk::Menu *marker_menu ;
+
+ /** specialized sub menu available when clicking upon and item upon this time axis */
+ Gtk::Menu *marker_item_menu ;
+
+
+} ; /* class MarkerTimeAxis */
+
+#endif /* __ardour_imageframe_time_axis_h__ */
+
diff --git a/gtk2_ardour/marker_time_axis_view.cc b/gtk2_ardour/marker_time_axis_view.cc
new file mode 100644
index 0000000000..b07448e1a6
--- /dev/null
+++ b/gtk2_ardour/marker_time_axis_view.cc
@@ -0,0 +1,400 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+
+#include <gtk--.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include "marker_time_axis_view.h"
+#include "marker_time_axis.h"
+#include "marker_view.h"
+#include "imageframe_view.h"
+#include "imageframe_time_axis.h"
+#include "canvas-simplerect.h"
+#include "public_editor.h"
+#include "rgb_macros.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR ;
+using namespace Editing;
+
+//---------------------------------------------------------------------------------------//
+// Constructor / Desctructor
+
+/**
+ * Construct a new MarkerTimeAxisView helper time axis helper
+ *
+ * @param mta the TimeAxsiView that this objbect is the helper for
+ */
+MarkerTimeAxisView::MarkerTimeAxisView(MarkerTimeAxis& tv)
+ : _trackview (tv)
+{
+ region_color = _trackview.color();
+ stream_base_color = color_map[cMarkerTrackBase];
+
+ canvas_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(_trackview.canvas_display), gtk_canvas_group_get_type (), 0);
+
+ canvas_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 1000000.0,
+ "y2", (double)20,
+ "outline_color_rgba", color_map[cMarkerTrackOutline],
+ "fill_color_rgba", stream_base_color,
+ 0) ;
+
+ gtk_signal_connect(GTK_OBJECT(canvas_rect), "event", (GtkSignalFunc)PublicEditor::canvas_marker_time_axis_view_event, &_trackview) ;
+
+ _samples_per_unit = _trackview.editor.get_current_zoom() ;
+
+ _trackview.editor.ZoomChanged.connect (slot(*this, &MarkerTimeAxisView::reset_samples_per_unit));
+}
+
+/**
+ * Destructor
+ * Reposinsibly for destroying all marker items that may have been added to this time axis view
+ *
+ */
+MarkerTimeAxisView::~MarkerTimeAxisView()
+{
+ // destroy everything upon this view
+ for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
+ {
+ MarkerView* mv = (*iter) ;
+
+ MarkerViewList::iterator next = iter ;
+ next++ ;
+ marker_view_list.erase(iter) ;
+
+ delete mv ;
+ mv = 0 ;
+
+ iter = next ;
+ }
+
+ if(canvas_rect)
+ {
+ gtk_object_destroy(GTK_OBJECT(canvas_rect)) ;
+ canvas_rect = 0 ;
+ }
+
+ if(canvas_group)
+ {
+ gtk_object_destroy(GTK_OBJECT(canvas_group)) ;
+ canvas_group = 0 ;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// ui methods & data
+
+/**
+ * Sets the height of the time axis view and the item upon it
+ *
+ * @param height the new height
+ */
+int
+MarkerTimeAxisView::set_height(gdouble h)
+{
+ if (h < 10.0 || h > 1000.0)
+ {
+ return -1 ;
+ }
+
+ gtk_object_set (GTK_OBJECT(canvas_rect), "y2", h, NULL);
+
+ for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
+ {
+ (*i)->set_height(h) ;
+ }
+
+ return 0;
+}
+
+/**
+ * Sets the position of this view helper on the canvas
+ *
+ * @param x the x position upon the canvas
+ * @param y the y position upon the canvas
+ */
+int
+MarkerTimeAxisView::set_position(gdouble x, gdouble y)
+{
+ gtk_canvas_item_set (canvas_group, "x", x, "y", y, NULL);
+ return 0;
+}
+
+/**
+ * Sets the current samples per unit.
+ * this method tells each item upon the time axis of the change
+ *
+ * @param spu the new samples per canvas unit value
+ */
+int
+MarkerTimeAxisView::set_samples_per_unit(gdouble spp)
+{
+ if(spp < 1.0) {
+ return -1 ;
+ }
+
+ _samples_per_unit = spp ;
+
+ for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
+ {
+ (*i)->set_samples_per_unit(spp) ;
+ }
+ return(0) ;
+}
+
+/**
+ * Sets the color of the items contained upon this view helper
+ *
+ * @param color the new base color
+ */
+void
+MarkerTimeAxisView::apply_color(GdkColor& color)
+{
+ region_color = color;
+
+ for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); i++)
+ {
+ (*i)->set_color (region_color) ;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Child MarkerView Accessors/Mutators
+
+/**
+ * Adds a marker view to the list of items upon this time axis view helper
+ * the new MarkerView is returned
+ *
+ * @param ifv the ImageFrameView that the new item is marking up
+ * @param mark_text the text to be displayed uopn the new marker item
+ * @param mark_id the unique id of the new item
+ * @param start the position the new item should be placed upon the time line
+ * @param duration the duration the new item should be placed upon the timeline
+ * @param src the identity of the object that initiated the change
+ */
+MarkerView*
+MarkerTimeAxisView::add_marker_view(ImageFrameView* ifv, std::string mark_type, std::string mark_id, jack_nframes_t start, jack_nframes_t dur, void* src)
+{
+ if(ifv->has_marker_view_item(mark_id))
+ {
+ return(0) ;
+ }
+
+ MarkerView* mv = new MarkerView(GTK_CANVAS_GROUP(canvas_group),
+ &_trackview,
+ ifv,
+ _trackview.editor.get_current_zoom(),
+ region_color,
+ mark_type,
+ mark_id,
+ start,
+ dur) ;
+
+ ifv->add_marker_view_item(mv, src) ;
+ marker_view_list.push_front(mv) ;
+
+ mv->GoingAway.connect(bind (slot (*this,&MarkerTimeAxisView::remove_marker_view), (void*)this)) ;
+
+ MarkerViewAdded(mv,src) ; /* EMIT_SIGNAL */
+
+ return(mv) ;
+}
+
+/**
+ * Returns the named MarkerView or 0 if the named marker does not exist
+ *
+ * @param item_id the unique id of the item to search for
+ * @return the named MarkerView, or 0 if it is not held upon this view
+ */
+MarkerView*
+MarkerTimeAxisView::get_named_marker_view(std::string item_id)
+{
+ MarkerView* mv = 0 ;
+
+ for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i)
+ {
+ if(((MarkerView*)*i)->get_item_name() == item_id)
+ {
+ mv = ((MarkerView*)*i) ;
+ break ;
+ }
+ }
+ return(mv) ;
+}
+
+/**
+ * Removes the currently selected MarverView
+ * Note that this method actually destroys the MarkerView too.
+ * We assume that since we own the object, we are allowed to do this
+ *
+ * @param src the identity of the object that initiated the change
+ * @see add_marker_view
+ */
+void
+MarkerTimeAxisView::remove_selected_marker_view(void* src)
+{
+ std::string removed ;
+
+ if (selected_time_axis_item)
+ {
+ MarkerViewList::iterator i ;
+ if((i = find (marker_view_list.begin(), marker_view_list.end(), selected_time_axis_item)) != marker_view_list.end())
+ {
+ marker_view_list.erase(i) ;
+
+ MarkerViewRemoved(selected_time_axis_item->get_item_name(),src) ; /* EMIT_SIGNAL */
+
+ delete(selected_time_axis_item) ;
+ selected_time_axis_item = 0 ;
+ }
+ }
+ else
+ {
+ //No selected marker view
+ }
+}
+
+/**
+ * Removes and returns the named MarkerView from the list of MarkerView held by this view helper
+ *
+ * @param item_id the MarkerView unique id to remove
+ * @param src the identity of the object that initiated the change
+ * @see add_marker_view
+ */
+MarkerView*
+MarkerTimeAxisView::remove_named_marker_view(std::string item_id, void* src)
+{
+ MarkerView* mv = 0 ;
+
+ MarkerViewList::iterator i = marker_view_list.begin() ;
+
+ for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter)
+ {
+ if(((MarkerView*)*i)->get_item_name() == item_id)
+ {
+ mv = ((MarkerView*)*i) ;
+ marker_view_list.erase(i) ;
+
+ MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
+
+ // break from the for loop
+ break;
+ }
+ i++ ;
+ }
+
+ return(mv) ;
+}
+
+/**
+ * Removes mv from the list of MarkerView upon this TimeAxis
+ *
+ * @param mv the MarkerView to remove
+ * @param src the identity of the object that initiated the change
+ */
+void
+MarkerTimeAxisView::remove_marker_view(MarkerView* mv, void* src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &MarkerTimeAxisView::remove_marker_view), mv, src));
+
+ MarkerViewList::iterator i;
+
+ if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) {
+ marker_view_list.erase(i) ;
+
+ // Assume this remove happened locally, else use remove_named_marker_time_axis
+ // let listeners know that the named MarkerTimeAxis has been removed
+ MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */
+ }
+}
+
+
+/**
+ * Sets the duration of the selected MarkerView to the specified number of seconds
+ *
+ * @param sec the duration to set the MArkerView to, in seconds
+ */
+void
+MarkerTimeAxisView::set_marker_duration_sec(double sec)
+{
+ if(get_selected_time_axis_item() != 0)
+ {
+ get_selected_time_axis_item()->set_duration((jack_nframes_t) (sec * _trackview.editor.current_session()->frame_rate()), this) ;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Selected item methods
+
+/**
+ * Sets the currently selected item upon this time axis
+ *
+ * @param mv the item to set selected
+ */
+void
+MarkerTimeAxisView::set_selected_time_axis_item(MarkerView* mv)
+{
+ selected_time_axis_item = mv ;
+}
+
+/**
+ * Clears any selected item upon this time axis
+ *
+ */
+void
+MarkerTimeAxisView::clear_selected_time_axis_item()
+{
+ selected_time_axis_item = 0 ;
+}
+
+/**
+ * Returnsthe currently selected item upon this time axis
+ *
+ * @return the currently selected item pon this time axis
+ */
+MarkerView*
+MarkerTimeAxisView::get_selected_time_axis_item()
+{
+ return(selected_time_axis_item) ;
+}
+
+
+
+
+/**
+ * convenience method to re-get the samples per unit and tell items upon this view
+ *
+ */
+void
+MarkerTimeAxisView::reset_samples_per_unit ()
+{
+ set_samples_per_unit(_trackview.editor.get_current_zoom()) ;
+}
diff --git a/gtk2_ardour/marker_time_axis_view.h b/gtk2_ardour/marker_time_axis_view.h
new file mode 100644
index 0000000000..a8e86131cc
--- /dev/null
+++ b/gtk2_ardour/marker_time_axis_view.h
@@ -0,0 +1,239 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_marker_time_axis_view_h__
+#define __ardour_marker_time_axis_view_h__
+
+#include <list>
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+
+#include <ardour/location.h>
+
+class PublicEditor;
+class MarkerTimeAxis;
+class ImageFrameView ;
+class MarkerView ;
+class TimeAxisView ;
+class TimeAxisViewItem ;
+
+/**
+ * A view helper for handling MarkerView objects.
+ * This object is responsible for the time axis canvas view, and
+ * maintains the list of items that have been added to it
+ */
+class MarkerTimeAxisView : public SigC::Object
+{
+ public:
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * Construct a new MarkerTimeAxisView helper time axis helper
+ *
+ * @param mta the TimeAxsiView that this objbect is the helper for
+ */
+ MarkerTimeAxisView(MarkerTimeAxis& mta) ;
+
+ /**
+ * Destructor
+ * Reposinsibly for destroying all marker items that may have been added to this time axis view
+ *
+ */
+ ~MarkerTimeAxisView () ;
+
+ //---------------------------------------------------------------------------------------//
+ // Parent/Child helper object accessors
+
+ /**
+ * Returns the TimeAxisView thatt his object is acting as a helper for
+ *
+ * @return the TimeAxisView that this object is acting as a view helper for
+ */
+ MarkerTimeAxis& trackview() { return _trackview; }
+
+ /**
+ *
+ */
+ GtkCanvasItem *canvas_item() { return canvas_group; }
+
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods & data
+
+ /**
+ * Sets the height of the time axis view and the item upon it
+ *
+ * @param height the new height
+ */
+ int set_height(gdouble height) ;
+
+ /**
+ * Sets the position of this view helper on the canvas
+ *
+ * @param x the x position upon the canvas
+ * @param y the y position upon the canvas
+ */
+ int set_position(gdouble x, gdouble y) ;
+
+ /**
+ * Sets the current samples per unit.
+ * this method tells each item upon the time axis of the change
+ *
+ * @param spu the new samples per canvas unit value
+ */
+ int set_samples_per_unit(gdouble spu) ;
+
+ /**
+ * Returns the current samples per unit of this time axis view helper
+ *
+ * @return the current samples per unit of this time axis view helper
+ */
+ gdouble get_samples_per_unit() { return _samples_per_unit; }
+
+ /**
+ * Sets the color of the items contained upon this view helper
+ *
+ * @param color the new base color
+ */
+ void apply_color(GdkColor& color) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Child MarkerView Accessors/Mutators
+
+ /**
+ * Adds a marker view to the list of items upon this time axis view helper
+ * the new MarkerView is returned
+ *
+ * @param ifv the ImageFrameView that the new item is marking up
+ * @param mark_text the text to be displayed uopn the new marker item
+ * @param mark_id the unique id of the new item
+ * @param start the position the new item should be placed upon the time line
+ * @param duration the duration the new item should be placed upon the timeline
+ * @param src the identity of the object that initiated the change
+ */
+ MarkerView* add_marker_view(ImageFrameView* ifv, std::string mark_type, std::string mark_id, jack_nframes_t start, jack_nframes_t dur, void* src) ;
+
+ /**
+ * Returns the named MarkerView or 0 if the named marker does not exist
+ *
+ * @param item_id the unique id of the item to search for
+ * @return the named MarkerView, or 0 if it is not held upon this view
+ */
+ MarkerView* get_named_marker_view(std::string item_id) ;
+
+ /**
+ * Removes the currently selected MarverView
+ * Note that this method actually destroys the MarkerView too.
+ * We assume that since we own the object, we are allowed to do this
+ *
+ * @param src the identity of the object that initiated the change
+ * @see add_marker_view
+ */
+ void remove_selected_marker_view(void* src) ;
+
+ /**
+ * Removes and returns the named MarkerView from the list of MarkerView held by this view helper
+ *
+ * @param item_id the MarkerView unique id to remove
+ * @param src the identity of the object that initiated the change
+ * @see add_marker_view
+ */
+ MarkerView* remove_named_marker_view(std::string item_id, void* src) ;
+
+ /**
+ * Removes mv from the list of MarkerView upon this TimeAxis
+ *
+ * @param mv the MarkerView to remove
+ * @param src the identity of the object that initiated the change
+ */
+ void remove_marker_view(MarkerView* item, void* src) ;
+
+ //---------------------------------------------------------------------------------------//
+ // Selected item methods
+
+ /**
+ * Sets the currently selected item upon this time axis
+ *
+ * @param mv the item to set selected
+ */
+ void set_selected_time_axis_item(MarkerView* mv) ;
+
+ /**
+ * Clears any selected item upon this time axis
+ *
+ */
+ void clear_selected_time_axis_item() ;
+
+ /**
+ * Returnsthe currently selected item upon this time axis
+ *
+ * @return the currently selected item pon this time axis
+ */
+ MarkerView* get_selected_time_axis_item() ;
+
+
+ /**
+ * Sets the duration of the selected MarkerView to the specified number of seconds
+ *
+ * @param sec the duration to set the MArkerView to, in seconds
+ */
+ void set_marker_duration_sec(double sec) ;
+
+ //---------------------------------------------------------------------------------//
+ // Emitted Signals
+
+ /** Emitted when a MarkerView is Added */
+ SigC::Signal2<void,MarkerView*,void*> MarkerViewAdded ;
+
+ /** Emitted when a MarkerView Item is removed */
+ SigC::Signal2<void,std::string,void*> MarkerViewRemoved ;
+
+ private:
+ /**
+ * convenience method to re-get the samples per unit and tell items upon this view
+ *
+ */
+ void reset_samples_per_unit() ;
+
+ /** The list of items held by this time axis view helper */
+ typedef std::list<MarkerView *> MarkerViewList ;
+ MarkerViewList marker_view_list;
+
+ /** the currently selected time axis item upon this time axis */
+ MarkerView* selected_time_axis_item ;
+
+ /* the TimeAxisView that this object is acting as the view helper for */
+ MarkerTimeAxis& _trackview ;
+
+ GtkCanvasItem *canvas_group ;
+ GtkCanvasItem *canvas_rect ; /* frame around the whole thing */
+
+ /** the current samples per unit */
+ double _samples_per_unit;
+
+ /* XXX why are these different? */
+ GdkColor region_color;
+ uint32_t stream_base_color;
+
+}; /* class MarkerTimeAxisView */
+
+#endif /* __ardour_marker_time_axis_view_h__ */
diff --git a/gtk2_ardour/marker_view.cc b/gtk2_ardour/marker_view.cc
new file mode 100644
index 0000000000..4c9621878e
--- /dev/null
+++ b/gtk2_ardour/marker_view.cc
@@ -0,0 +1,142 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gtk--.h>
+
+#include "imageframe_time_axis.h"
+#include "imageframe_view.h"
+#include "canvas-simplerect.h"
+#include "public_editor.h"
+#include "marker_view.h"
+
+using namespace ARDOUR ;
+using namespace SigC;
+
+SigC::Signal1<void,MarkerView*> MarkerView::GoingAway;
+
+//---------------------------------------------------------------------------------------//
+// Constructor / Desctructor
+
+/**
+ * Constructs a new MarkerView
+ *
+ * @param parent the parent canvas item
+ * @param tv the parent TimeAxisView of this item
+ * @param tavi the TimeAxisViewItem that this item is to be assciated (marking) with
+ * @param spu the current samples per unit
+ * @param base_color
+ * @param mark_type the marker type/name text, eg fade out, pan up etc.
+ * @param mark_id unique name/id of this item
+ * @param start the start time of this item
+ * @param duration the duration of this item
+ */
+MarkerView::MarkerView(GtkCanvasGroup *parent,
+ TimeAxisView* tv,
+ ImageFrameView* marked,
+ double spu,
+ GdkColor& basic_color,
+ std::string mark_type,
+ std::string mark_id,
+ jack_nframes_t start,
+ jack_nframes_t duration)
+ : TimeAxisViewItem(mark_id, parent,*tv,spu,basic_color,start,duration)
+{
+ mark_type_text = mark_type ;
+ marked_item = marked ;
+
+ // set the canvas item text to the marker type, not the id
+ set_name_text(mark_type_text) ;
+
+ // hoo up our canvas events
+ gtk_signal_connect (GTK_OBJECT(frame_handle_start), "event",
+ (GtkSignalFunc) PublicEditor::canvas_markerview_start_handle_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(frame_handle_end), "event",
+ (GtkSignalFunc) PublicEditor::canvas_markerview_end_handle_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(group), "event",
+ (GtkSignalFunc) PublicEditor::canvas_markerview_item_view_event, this);
+
+ /* handle any specific details required by the initial start end duration values */
+ set_position(start, this) ;
+ set_duration(duration, this) ;
+}
+
+/**
+ * Destructor
+ * Destroys this Marker Item and removes the association between itself and the item it is marking.
+ */
+MarkerView::~MarkerView()
+{
+ // remove the association our marked may still have to us
+ if(marked_item)
+ {
+ marked_item->remove_marker_view_item(this, this) ;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Marker Type Methods
+
+/**
+ * Sets the marker Type text of this this MarkerItem, eg fade_out, pan up etc.
+ *
+ * @param type_text the marker type text of this item
+ */
+void
+MarkerView::set_mark_type_text(std::string type_text)
+{
+ mark_type_text = type_text ;
+ MarkTypeChanged(mark_type_text, this) ; /* EMIT_SIGNAL */
+}
+
+/**
+ * Returns the marker Type of this this MarkerItem, eg fade_out, pan up etc.
+ *
+ * @return the marker type text of this item
+ */
+std::string
+MarkerView::get_mark_type_text() const
+{
+ return(mark_type_text) ;
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Marked Item Methods
+
+ImageFrameView*
+MarkerView::set_marked_item(ImageFrameView* item)
+{
+ ImageFrameView* temp = marked_item ;
+ marked_item = item ;
+
+ MarkedItemChanged(marked_item, this) ; /* EMIT_SIGNAL */
+ return(temp) ;
+}
+
+ImageFrameView*
+MarkerView::get_marked_item()
+{
+ return(marked_item) ;
+}
diff --git a/gtk2_ardour/marker_view.h b/gtk2_ardour/marker_view.h
new file mode 100644
index 0000000000..fdd70ffb00
--- /dev/null
+++ b/gtk2_ardour/marker_view.h
@@ -0,0 +1,133 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_marker_view_h__
+#define __gtk_ardour_marker_view_h__
+
+#include <string>
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include "time_axis_view_item.h"
+
+class MarkerTimeAxisView ;
+class ImageFrameView ;
+
+/**
+ * MarkerView defines a marker item that may be placed upon a MarkerTimeAxis.
+ *
+ * The aim of the MarkerView is to provide additional timing details for visual based time axis.
+ * The MarkerView item is associated with one other TimeAxisViewItem and has a start and a duration.
+ */
+class MarkerView : public TimeAxisViewItem
+{
+ public:
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * Constructs a new MarkerView
+ *
+ * @param parent the parent canvas item
+ * @param tv the parent TimeAxisView of this item
+ * @param marked the Item that this item is to be assciated (marking) with
+ * @param spu the current samples per unit
+ * @param base_color
+ * @param mark_type the marker type/name text, eg fade out, pan up etc.
+ * @param mark_id unique name/id of this item
+ * @param start the start time of this item
+ * @param duration the duration of this item
+ */
+ MarkerView(GtkCanvasGroup *parent,
+ TimeAxisView *tv,
+ ImageFrameView* marked,
+ double spu,
+ GdkColor& base_color,
+ std::string mark_type,
+ std::string mark_id,
+ jack_nframes_t start,
+ jack_nframes_t duration) ;
+
+ /**
+ * Destructor
+ * Destroys this Marker Item and removes the association between itself and the item it is marking.
+ */
+ ~MarkerView() ;
+
+ static SigC::Signal1<void,MarkerView*> GoingAway;
+
+ //---------------------------------------------------------------------------------------//
+ // Marker Type Methods
+
+ /**
+ * Sets the marker Type text of this this MarkerItem, eg fade_out, pan up etc.
+ *
+ * @param type_text the marker type text of this item
+ */
+ void set_mark_type_text(std::string type_text) ;
+
+ /**
+ * Returns the marker Type of this this MarkerItem, eg fade_out, pan up etc.
+ *
+ * @return the marker type text of this item
+ */
+ std::string get_mark_type_text() const ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Marked Item Methods
+
+ /**
+ * Returns the time axis item being marked by this item
+ *
+ * @return the time axis item being marked by this item
+ */
+ ImageFrameView* get_marked_item() ;
+
+ /**
+ * Sets the time axis item being marker by this item
+ *
+ * @param item the time axis item to be marked by this item
+ * @return the previously marked item, or 0 if no previous marked item exists
+ */
+ ImageFrameView* set_marked_item(ImageFrameView* item) ;
+
+ //---------------------------------------------------------------------------------//
+ // Emitted Signals
+
+ /** Emitted when the mark type text is changed */
+ SigC::Signal2<void,std::string,void*> MarkTypeChanged ;
+
+ /** Emitted when the Marked Item is changed */
+ SigC::Signal2<void,ImageFrameView*,void*> MarkedItemChanged ;
+
+
+ protected:
+
+ private:
+ /** the unique name/id of this item */
+ std::string mark_type_text ;
+
+ /* a pointer to the time axis item this marker is assoiated(marking up) with */
+ ImageFrameView* marked_item ;
+
+} ; /* class MarkerView */
+
+
+#endif /* __gtk_ardour_imageframe_view_h__ */
diff --git a/gtk2_ardour/meter_bridge.cc b/gtk2_ardour/meter_bridge.cc
new file mode 100644
index 0000000000..7524ba4b35
--- /dev/null
+++ b/gtk2_ardour/meter_bridge.cc
@@ -0,0 +1,256 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/session.h>
+#include <ardour/session_route.h>
+#include <ardour/diskstream.h>
+#include <ardour/audio_track.h>
+
+#include "ardour_ui.h"
+#include "meter_bridge.h"
+#include "meter_bridge_strip.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace SigC;
+
+#define FRAME_SHADOW_STYLE GTK_SHADOW_IN
+#define FRAME_NAME "BaseFrame"
+
+MeterBridge::MeterBridge ()
+ : ArdourDialog ("meter bridge")
+{
+ meter_base.set_name ("MeterBase");
+ meter_frame.set_shadow_type (FRAME_SHADOW_STYLE);
+ meter_frame.set_name (FRAME_NAME);
+ meter_frame.add (meter_base);
+
+ upper_metering_box.set_name ("AboveMeterZone");
+ lower_metering_box.set_name ("BelowMeterZone");
+
+ metering_vbox.set_spacing (5);
+ metering_vbox.set_border_width (10);
+ metering_vbox.pack_start (upper_metering_box, false, false);
+ metering_vbox.pack_start (meter_frame, false, false);
+ metering_vbox.pack_start (lower_metering_box, false, false);
+
+ metering_hbox.pack_start (metering_vbox, false, false);
+
+ meter_scroll_base.set_name ("MeterScrollBase");
+ meter_scroll_base.add (metering_hbox);
+
+ meter_viewport.add (meter_scroll_base);
+ meter_viewport.set_shadow_type (GTK_SHADOW_NONE);
+
+ meter_scroller.add (meter_viewport);
+ meter_scroller.set_name ("MeterBridgeWindow");
+ meter_scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ meter_scroller.set_border_width (5);
+
+ add (meter_scroller);
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+ set_name ("MeterBridgeWindow");
+ set_title (_("ardour: meter bridge"));
+ set_wmclass (_("ardour_meter_bridge"), "Ardour");
+ // set_policy (false, false, false); // no user resizing of any kind
+
+ delete_event.connect (bind (slot (just_hide_it), static_cast<Gtk::Window*>(this)));
+
+ metering = false;
+
+ /* don't show: this window doesn't come up by default */
+}
+
+MeterBridge::~MeterBridge ()
+{
+ stop_metering ();
+}
+
+void
+MeterBridge::set_session (Session *s)
+{
+ ArdourDialog::set_session (s);
+
+ if (session) {
+ // XXX this stuff has to be fixed if we ever use this code again
+ // (refs vs. ptrs)
+ // session->foreach_route (this, &MeterBridge::add_route);
+ session->RouteAdded.connect (slot (*this, &MeterBridge::add_route));
+ session->going_away.connect (slot (*this, &MeterBridge::session_gone));
+ start_metering ();
+ }
+}
+
+void
+MeterBridge::session_gone ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &MeterBridge::session_gone));
+
+ stop_metering ();
+ hide_all ();
+
+ list<MeterBridgeStrip *>::iterator i;
+
+ for (i = meters.begin(); i != meters.end(); ++i) {
+
+ upper_metering_box.remove ((*i)->above_box());
+ meter_base.remove ((*i)->meter_widget());
+ lower_metering_box.remove ((*i)->below_box());
+
+// delete (*i);
+ }
+
+ meters.clear ();
+
+ ArdourDialog::session_gone();
+}
+
+void
+MeterBridge::add_route (ARDOUR::Route* route)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &MeterBridge::add_route), route));
+
+ uint32_t n;
+ char buf[32];
+
+ if (!session || route->hidden() || dynamic_cast<AudioTrack*>(route) == 0) {
+ return;
+ }
+
+ n = meters.size();
+ snprintf (buf, sizeof (buf), "%u", n+1);
+
+ MeterBridgeStrip *meter = new MeterBridgeStrip (session->engine(),
+ *session,
+ *route,
+ buf,
+ session->over_length_long,
+ session->over_length_short,
+ 200);
+
+#define packing_factor 30
+
+ upper_metering_box.put (meter->above_box(), n * packing_factor, 0);
+
+ meter_base.put (meter->meter_widget(), (n * packing_factor) + (meter->meter_width()/2), 0);
+ lower_metering_box.put (meter->below_box(), n * packing_factor, 0);
+
+ meter->above_box().show_all ();
+ meter->meter_widget().show ();
+ meter->below_box().show_all ();
+
+ route->GoingAway.connect (bind (slot (*this, &MeterBridge::remove_route), route));
+ meters.insert (meters.begin(), meter);
+
+ set_default_size (30 + ((n+1) * packing_factor), 315);
+
+ meter->set_meter_on(true);
+
+ session->going_away.connect (slot (*this, &MeterBridge::session_gone));
+}
+
+void
+MeterBridge::remove_route (Route* route)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &MeterBridge::remove_route), route));
+ list<MeterBridgeStrip *>::iterator i;
+
+ for (i = meters.begin(); i != meters.end(); ++i) {
+ if (&((*i)->route()) == route) {
+ delete *i;
+ meters.erase (i);
+ return;
+ }
+ }
+}
+
+void
+MeterBridge::clear_all_meters ()
+{
+ list<MeterBridgeStrip *>::iterator i;
+
+ for (i = meters.begin(); i != meters.end(); ++i) {
+ (*i)->clear_meter ();
+ }
+}
+
+void
+MeterBridge::update ()
+{
+ list<MeterBridgeStrip *>::iterator i;
+
+ for (i = meters.begin(); i != meters.end(); ++i) {
+ (*i)->update ();
+ }
+}
+
+void
+MeterBridge::start_metering ()
+{
+ list<MeterBridgeStrip *>::iterator i;
+
+ for (i = meters.begin(); i != meters.end(); ++i) {
+ (*i)->set_meter_on (true);
+ }
+ metering_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
+ (slot (*this, &MeterBridge::update));
+ metering = true;
+}
+
+void
+MeterBridge::stop_metering ()
+{
+ list<MeterBridgeStrip *>::iterator i;
+
+ for (i = meters.begin(); i != meters.end(); ++i) {
+ (*i)->set_meter_on (false);
+ }
+ metering_connection.disconnect();
+ metering = false;
+}
+
+void
+MeterBridge::toggle_metering ()
+{
+ if (!metering) {
+ start_metering ();
+ } else {
+ stop_metering ();
+ }
+}
+
+gint
+MeterBridge::map_event_impl (GdkEventAny *ev)
+{
+ start_metering ();
+ return Window::map_event_impl (ev);
+}
+
+gint
+MeterBridge::unmap_event_impl (GdkEventAny *ev)
+{
+ stop_metering ();
+ return Window::unmap_event_impl (ev);
+}
+
diff --git a/gtk2_ardour/meter_bridge.h b/gtk2_ardour/meter_bridge.h
new file mode 100644
index 0000000000..3cb72a1629
--- /dev/null
+++ b/gtk2_ardour/meter_bridge.h
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 1999-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_meter_bridge_h__
+#define __ardour_meter_bridge_h__
+
+#include <list>
+
+#include <gtk--/eventbox.h>
+#include <gtk--/viewport.h>
+#include <gtk--/scrolledwindow.h>
+#include <gtk--/box.h>
+#include <gtk--/fixed.h>
+#include <gtk--/frame.h>
+
+#include "keyboard_target.h"
+#include "ardour_dialog.h"
+
+class MeterBridgeStrip;
+
+namespace ARDOUR {
+ class Session;
+ class Route;
+}
+
+class MeterBridge : public ArdourDialog
+{
+
+ public:
+ MeterBridge ();
+ ~MeterBridge ();
+
+ void set_session (ARDOUR::Session*);
+ void clear_all_meters ();
+ void start_metering ();
+ void stop_metering ();
+ void toggle_metering ();
+
+ protected:
+ gint map_event_impl (GdkEventAny *);
+ gint unmap_event_impl (GdkEventAny *);
+
+ private:
+ /* diskstream/recorder display */
+
+ Gtk::Viewport meter_viewport;
+ Gtk::ScrolledWindow meter_scroller;
+ Gtk::EventBox meter_scroll_base;
+ Gtk::HBox meter_scroller_hpacker;
+ Gtk::VBox meter_scroller_vpacker;
+ Gtk::VBox metering_vpacker;
+ Gtk::VBox metering_hpacker;
+
+ Gtk::VBox metering_vbox;
+ Gtk::HBox metering_hbox;
+ Gtk::Fixed upper_metering_box;
+ Gtk::Fixed lower_metering_box;
+ Gtk::Fixed meter_base;
+ Gtk::Frame meter_frame;
+
+ list<MeterBridgeStrip*> meters;
+
+ bool metering;
+ SigC::Connection metering_connection;
+
+ void update ();
+
+ void add_route (ARDOUR::Route*);
+ void remove_route (ARDOUR::Route*);
+ void session_gone(); /* overrides ArdourDialog::session_gone() */
+};
+
+#endif /* __ardour_meter_bridge_h__ (*/
diff --git a/gtk2_ardour/meter_bridge_strip.cc b/gtk2_ardour/meter_bridge_strip.cc
new file mode 100644
index 0000000000..046c138827
--- /dev/null
+++ b/gtk2_ardour/meter_bridge_strip.cc
@@ -0,0 +1,238 @@
+/*
+ Copyright (C) 1999 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <ctime>
+#include <sys/stat.h>
+
+#include <pbd/pathscanner.h>
+#include <pbd/fastlog.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/selector.h>
+
+#include <ardour/audioengine.h>
+#include <ardour/route.h>
+#include <ardour/port.h>
+#include <ardour/utils.h>
+
+#include "meter_bridge_strip.h"
+#include "ardour_ui.h"
+#include "prompter.h"
+#include "logmeter.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+
+MeterBridgeStrip::MeterBridgeStrip (AudioEngine &eng,
+ Session& s,
+ Route& r,
+ string name,
+ jack_nframes_t long_over,
+ jack_nframes_t short_over,
+ jack_nframes_t meter_hold)
+ : engine (eng),
+ session (s),
+ _route (r),
+ meter (meter_hold, 5, FastMeter::Vertical)
+{
+ char buf[64];
+
+ label.set_text (name);
+ label.set_name ("ChannelMeterLabel");
+
+ label_ebox.set_name ("MeterBridgeWindow");
+ label_ebox.set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK);
+ label_ebox.add (label);
+
+ label_ebox.button_release_event.connect (slot (*this, &MeterBridgeStrip::label_button_press_release));
+ ARDOUR_UI::instance()->tooltips().set_tip (label_ebox, _route.name());
+
+ over_long_label.set_text ("0");
+ over_long_label.set_name ("OverMeterLabel");
+ over_long_button.add (over_long_label);
+ over_long_button.set_name ("OverMeter");
+ over_long_frame.add (over_long_button);
+ over_long_frame.set_shadow_type (GTK_SHADOW_IN);
+ over_long_frame.set_name ("BaseFrame");
+ over_long_hbox.pack_start (over_long_frame, false, false);
+
+ snprintf(buf, sizeof(buf)-1, _("# of %u-sample overs"), long_over);
+ ARDOUR_UI::instance()->tooltips().set_tip (over_long_button, buf);
+
+ set_usize_to_display_given_text (over_long_button, "88g", 2, 2);
+
+ over_short_label.set_text ("0");
+ over_short_label.set_name ("OverMeterLabel");
+ over_short_button.add (over_short_label);
+ over_short_button.set_name ("OverMeter");
+ over_short_frame.add (over_short_button);
+ over_short_frame.set_shadow_type (GTK_SHADOW_IN);
+ over_short_frame.set_name ("BaseFrame");
+ over_short_hbox.pack_start (over_short_frame, false, false);
+
+ snprintf(buf, sizeof(buf)-1, _("# of %u-sample overs"), short_over);
+ ARDOUR_UI::instance()->tooltips().set_tip (over_short_button, buf);
+
+ set_usize_to_display_given_text (over_short_button, "88g", 2, 2);
+ above_meter_vbox.set_spacing (5);
+ below_meter_vbox.set_spacing (5);
+
+ above_meter_vbox.pack_start (over_long_hbox, false, false);
+ above_meter_vbox.pack_start (over_short_hbox, false, false);
+
+ below_meter_vbox.pack_start (label_ebox);
+
+ over_short_button.button_release_event.connect (slot (*this,&MeterBridgeStrip::gui_clear_overs));
+ over_long_button.button_release_event.connect (slot (*this,&MeterBridgeStrip::gui_clear_overs));
+
+ last_over_short = 0;
+ last_over_long = 0;
+
+ meter_clear_pending = false;
+ over_clear_pending = false;
+
+ meter_on = true;
+}
+
+void
+MeterBridgeStrip::update ()
+{
+ string buf;
+ Port *port;
+ guint32 over_short = 0;
+ guint32 over_long = 0;
+
+ if ((port = _route.input (0)) == 0) {
+ meter.set (0.0);
+ return;
+ } else {
+ over_short = port->short_overs ();
+ over_long = port->long_overs ();
+ }
+
+ if (meter_on) {
+ float power = minus_infinity();
+
+ if ((power = _route.peak_input_power (0)) != minus_infinity()) {
+ meter.set (log_meter (power));
+
+ if (over_short != last_over_short) {
+ buf = compose("%1", over_short);
+ over_short_label.set_text (buf);
+ last_over_short = over_short;
+ }
+
+ if (over_long != last_over_long) {
+ buf = compose("%1", over_long);
+ over_long_label.set_text (buf);
+ last_over_long = over_long;
+ }
+
+ } else {
+ meter.set (0.0);
+ }
+
+ }
+
+ if (meter_clear_pending) {
+ meter_clear_pending = false;
+ meter.clear ();
+ }
+
+ if (over_clear_pending) {
+ over_clear_pending = false;
+ port->reset_overs ();
+ over_long_label.set_text ("0");
+ over_short_label.set_text ("0");
+ last_over_short = 0;
+ last_over_long = 0;
+ }
+}
+
+gint
+MeterBridgeStrip::gui_clear_overs (GdkEventButton *ev)
+{
+ clear_overs ();
+ return FALSE;
+}
+
+void
+MeterBridgeStrip::clear_meter ()
+
+{
+ meter_clear_pending = true;
+}
+
+void
+MeterBridgeStrip::clear_overs ()
+
+{
+ over_clear_pending = true;
+}
+
+void
+MeterBridgeStrip::set_meter_on (bool yn)
+{
+ Port* port;
+ meter_on = yn;
+
+ if (!meter_on) {
+ meter_clear_pending = true;
+ over_clear_pending = true;
+ }
+
+ if (meter.is_visible()) {
+ if ((port = _route.input (0)) != 0) {
+ if (meter_on) {
+ port->enable_metering ();
+ } else {
+ port->disable_metering ();
+ }
+ }
+ }
+}
+
+gint
+MeterBridgeStrip::label_button_press_release (GdkEventButton *ev)
+{
+ ArdourPrompter prompter (true);
+ prompter.set_prompt (_("New name for meter:"));
+ prompter.set_initial_text (label.get_text());
+ prompter.done.connect (Gtk::Main::quit.slot());
+ prompter.show_all();
+
+ Gtk::Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+
+ prompter.get_result (name);
+
+ if (name.length()) {
+ label.set_text(name);
+ }
+ }
+
+ return FALSE;
+}
+
diff --git a/gtk2_ardour/meter_bridge_strip.h b/gtk2_ardour/meter_bridge_strip.h
new file mode 100644
index 0000000000..932c2de925
--- /dev/null
+++ b/gtk2_ardour/meter_bridge_strip.h
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 1999 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_meterbridgestrip_h__
+#define __ardour_meterbridgestrip_h__
+
+#include <sigc++/signal_system.h>
+#include <gtk--.h>
+#include <gtkmmext/fastmeter.h>
+
+namespace ARDOUR {
+ class AudioEngine;
+ class Session;
+ class Route;
+}
+
+namespace Gtkmmext {
+ class Selector;
+ struct SelectionResult;
+}
+
+class MeterBridgeStrip : public SigC::Object
+
+{
+ public:
+ MeterBridgeStrip (ARDOUR::AudioEngine &,
+ ARDOUR::Session&,
+ ARDOUR::Route&,
+ string label,
+ jack_nframes_t long_over,
+ jack_nframes_t short_over,
+ jack_nframes_t meter_hold);
+
+ void update (); /* called by meter timeout handler from ARDOUR_UI */
+
+ Gtk::Box &above_box() { return above_meter_vbox; }
+ Gtk::Box &below_box() { return below_meter_vbox; }
+ Gtk::Widget &meter_widget() { return meter; }
+
+ guint32 meter_width() const { return 8; }
+
+ void clear_meter ();
+ void clear_overs ();
+
+ void set_meter_on (bool yn);
+ bool get_meter_on () const { return meter_on; }
+
+ ARDOUR::Route& route() const { return _route; }
+
+ private:
+ ARDOUR::AudioEngine& engine;
+ ARDOUR::Session& session;
+ ARDOUR::Route& _route;
+
+ Gtk::EventBox label_ebox;
+ Gtk::Label label;
+ bool meter_clear_pending;
+ bool over_clear_pending;
+
+ Gtkmmext::FastMeter meter;
+ bool meter_on;
+
+ Gtk::VBox above_meter_vbox;
+ Gtk::VBox below_meter_vbox;
+
+ Gtk::HBox over_long_hbox;
+ Gtk::HBox over_long_vbox;
+ Gtk::EventBox over_long_button;
+ Gtk::Frame over_long_frame;
+ Gtk::Label over_long_label;
+
+ Gtk::HBox over_short_hbox;
+ Gtk::HBox over_short_vbox;
+ Gtk::EventBox over_short_button;
+ Gtk::Frame over_short_frame;
+ Gtk::Label over_short_label;
+
+ guint32 last_over_short;
+ guint32 last_over_long;
+
+ gint gui_clear_overs (GdkEventButton *);
+ gint label_button_press_release (GdkEventButton *);
+};
+
+#endif /* __ardour_meterbridgestrip_h__ */
+
+
diff --git a/gtk2_ardour/misc_xpms b/gtk2_ardour/misc_xpms
new file mode 100644
index 0000000000..026303066e
--- /dev/null
+++ b/gtk2_ardour/misc_xpms
@@ -0,0 +1,632 @@
+/* XPM */
+static const char * vslider_rail_xpm[] = {
+"3 200 4 1",
+" c None",
+". c #000000",
+", c #424242",
+"+ c #969393",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+",
+".,+"};
+
+/* XPM */
+static const char * vslider_slider_xpm_16wide[] = {
+"16 32 176 2",
+" c None",
+". c #999991",
+"+ c #A1A198",
+"@ c #A0A097",
+"# c #9E9E95",
+"$ c #9D9D94",
+"% c #9C9C93",
+"& c #9A9A92",
+"* c #999990",
+"= c #98988F",
+"- c #96968E",
+"; c #95958D",
+"> c #94948B",
+", c #93938A",
+"' c #919189",
+") c #575751",
+"! c #97978F",
+"~ c #A3A39A",
+"{ c #A0A098",
+"] c #9F9F96",
+"^ c #989890",
+"/ c #81817A",
+"( c #3D3D39",
+"_ c #94948C",
+": c #B0B0A8",
+"< c #C8C8C1",
+"[ c #C7C7C1",
+"} c #C7C7C0",
+"| c #C6C6C0",
+"1 c #C6C6BF",
+"2 c #C5C5BF",
+"3 c #C5C5BE",
+"4 c #C4C4BD",
+"5 c #71716C",
+"6 c #3C3C38",
+"7 c #93938B",
+"8 c #8F8F87",
+"9 c #858580",
+"0 c #85857F",
+"a c #84847F",
+"b c #5C5C58",
+"c c #3C3C39",
+"d c #878781",
+"e c #878782",
+"f c #5A5A56",
+"g c #3D3D3A",
+"h c #94948F",
+"i c #5B5B57",
+"j c #3E3E3A",
+"k c #9F9F9A",
+"l c #A0A09A",
+"m c #5C5C57",
+"n c #3E3E3B",
+"o c #92928A",
+"p c #9B9B93",
+"q c #AAAAA4",
+"r c #AAAAA5",
+"s c #3F3F3B",
+"t c #B3B3AD",
+"u c #B2B2AD",
+"v c #B2B2AC",
+"w c #3F3F3C",
+"x c #929289",
+"y c #9D9D95",
+"z c #BABAB3",
+"A c #BABAB4",
+"B c #B9B9B3",
+"C c #B8B8B2",
+"D c #40403C",
+"E c #9E9E96",
+"F c #C0C0BA",
+"G c #C0C0B9",
+"H c #BFBFB9",
+"I c #BFBFB8",
+"J c #BEBEB8",
+"K c #40403D",
+"L c #909088",
+"M c #C4C4BE",
+"N c #C3C3BD",
+"O c #C3C3BC",
+"P c #C2C2BC",
+"Q c #5B5B56",
+"R c #41413D",
+"S c #878780",
+"T c #A1A19C",
+"U c #A1A19D",
+"V c #A0A09B",
+"W c #4B4B47",
+"X c #8E8E86",
+"Y c #434340",
+"Z c #323232",
+"` c #333333",
+" . c #1D1D1C",
+".. c #8D8D85",
+"+. c #8C8C84",
+"@. c #A7A7A2",
+"#. c #A6A6A1",
+"$. c #A6A6A0",
+"%. c #A5A5A0",
+"&. c #8B8B83",
+"*. c #D1D1CA",
+"=. c #D0D0C9",
+"-. c #CFCFC9",
+";. c #CFCFC8",
+">. c #CECEC7",
+",. c #8A8A82",
+"'. c #D2D2CB",
+"). c #D2D2CA",
+"!. c #898981",
+"~. c #9F9F97",
+"{. c #D0D0C8",
+"]. c #5D5D59",
+"^. c #D1D1C9",
+"/. c #CFCFC7",
+"(. c #5F5F5A",
+"_. c #86867F",
+":. c #CECEC6",
+"<. c #CDCDC6",
+"[. c #CDCDC5",
+"}. c #60605B",
+"|. c #85857D",
+"1. c #A1A199",
+"2. c #CCCCC5",
+"3. c #CCCCC4",
+"4. c #CBCBC4",
+"5. c #CBCBC3",
+"6. c #CACAC3",
+"7. c #62625D",
+"8. c #83837C",
+"9. c #CACAC2",
+"0. c #C9C9C1",
+"a. c #C8C8C0",
+"b. c #C7C7BF",
+"c. c #64645F",
+"d. c #82827B",
+"e. c #A4A49B",
+"f. c #C5C5BD",
+"g. c #C4C4BC",
+"h. c #C3C3BB",
+"i. c #C2C2BA",
+"j. c #C1C1B9",
+"k. c #C0C0B8",
+"l. c #656560",
+"m. c #818179",
+"n. c #A5A59D",
+"o. c #BDBDB5",
+"p. c #BDBDB4",
+"q. c #BCBCB4",
+"r. c #BBBBB3",
+"s. c #BABAB2",
+"t. c #B9B9B1",
+"u. c #B8B8B0",
+"v. c #666661",
+"w. c #7F7F78",
+"x. c #B6B6AE",
+"y. c #B6B6AD",
+"z. c #B5B5AD",
+"A. c #B5B5AC",
+"B. c #B4B4AC",
+"C. c #B3B3AB",
+"D. c #B2B2AB",
+"E. c #B2B2AA",
+"F. c #B1B1A9",
+"G. c #696964",
+"H. c #7D7D76",
+"I. c #BEBEB7",
+"J. c #BDBDB7",
+"K. c #6E6E6A",
+"L. c #7B7B74",
+"M. c #60605A",
+"N. c #50504B",
+"O. c #4D4D49",
+"P. c #6B6B65",
+"Q. c #484844",
+"R. c #454541",
+"S. c #42423E",
+". + @ # $ % & * * = - ; > , ' ) ",
+"! ~ { ] # $ % & & . ^ ! - ; / ( ",
+"_ : < < [ } } | | 1 1 2 3 4 5 6 ",
+"7 8 9 9 9 9 9 9 9 9 0 0 0 a b c ",
+"7 8 d e e e e e e e e e e d f g ",
+"7 ; h h h h h h h h h h h h i j ",
+"7 ^ k k l l l l l l l k k k m n ",
+"o p q r r r r r r r r q q q m s ",
+"o $ t t t t t t t t u v v v m w ",
+"x y z A A A A B B B B B C C i D ",
+"' E F F F F F F F G H H I J i K ",
+"L E M M M M M 4 4 4 N N O P Q R ",
+"8 E [ [ [ [ [ } } } | | 1 2 f R ",
+"8 S T U U U T T T T T V V V W R ",
+"X Y Z Z Z Z ` ` ` Z Z Z Z Z .R ",
+"..Y Z ` ` ` ` ` ` ` ` ` Z Z .R ",
+"+.S @.@.@.@.#.#.#.#.#.$.%.%.W R ",
+"&.E *.*.*.*.=.=.=.=.-.;.;.>.i R ",
+",.] '.'.'.).*.*.*.*.=.=.;.;.b R ",
+"!.~.'.'.'.'.).*.*.*.=.=.{.;.].K ",
+"S @ ).*.*.*.*.^.^.=.{.;./.>.(.D ",
+"_.+ {.{.{.{.;./././.>.:.<.[.}.w ",
+"|.1.:.:.:.<.[.[.[.2.3.4.5.6.7.s ",
+"8.~ 6.9.9.9.0.0.0.< a.} b.1 c.n ",
+"d.e.f.g.g.g.h.h.h.i.i.j.j.k.l.j ",
+"m.n.o.p.q.q.r.r.r.s.s.t.t.u.v.g ",
+"w.e.x.x.y.z.A.B.B.C.C.D.E.F.G.c ",
+"H.. J J J J J J J J J I.J.J.K.6 ",
+"L.M.N.N.N.N.N.N.N.N.N.N.N.N.O.6 ",
+"P.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.D ",
+"O.R.R.R.R.R.R.R.R.R.R.R.R.R.R.S.",
+"O.R.R.R.R.R.R.R.R.R.R.R.R.R.R.S."};
+
+
+/* XPM */
+static const char * vslider_slider_xpm[] = {
+"15 32 176 2",
+" c None",
+". c #999991",
+"+ c #A1A198",
+"@ c #A0A097",
+"# c #9E9E95",
+"$ c #9D9D94",
+"% c #9C9C93",
+"& c #9A9A92",
+"* c #999990",
+"= c #98988F",
+"- c #96968E",
+"; c #95958D",
+"> c #94948B",
+", c #93938A",
+"' c #919189",
+") c #575751",
+"! c #97978F",
+"~ c #A3A39A",
+"{ c #A0A098",
+"] c #9F9F96",
+"^ c #989890",
+"/ c #81817A",
+"( c #3D3D39",
+"_ c #94948C",
+": c #B0B0A8",
+"< c #C8C8C1",
+"[ c #C7C7C1",
+"} c #C7C7C0",
+"| c #C6C6C0",
+"1 c #C6C6BF",
+"2 c #C5C5BF",
+"3 c #C5C5BE",
+"4 c #C4C4BD",
+"5 c #71716C",
+"6 c #3C3C38",
+"7 c #93938B",
+"8 c #8F8F87",
+"9 c #858580",
+"0 c #85857F",
+"a c #84847F",
+"b c #5C5C58",
+"c c #3C3C39",
+"d c #878781",
+"e c #878782",
+"f c #5A5A56",
+"g c #3D3D3A",
+"h c #94948F",
+"i c #5B5B57",
+"j c #3E3E3A",
+"k c #9F9F9A",
+"l c #A0A09A",
+"m c #5C5C57",
+"n c #3E3E3B",
+"o c #92928A",
+"p c #9B9B93",
+"q c #AAAAA4",
+"r c #AAAAA5",
+"s c #3F3F3B",
+"t c #B3B3AD",
+"u c #B2B2AD",
+"v c #B2B2AC",
+"w c #3F3F3C",
+"x c #929289",
+"y c #9D9D95",
+"z c #BABAB3",
+"A c #BABAB4",
+"B c #B9B9B3",
+"C c #B8B8B2",
+"D c #40403C",
+"E c #9E9E96",
+"F c #C0C0BA",
+"G c #C0C0B9",
+"H c #BFBFB9",
+"I c #BFBFB8",
+"J c #BEBEB8",
+"K c #40403D",
+"L c #909088",
+"M c #C4C4BE",
+"N c #C3C3BD",
+"O c #C3C3BC",
+"P c #C2C2BC",
+"Q c #5B5B56",
+"R c #41413D",
+"S c #878780",
+"T c #A1A19C",
+"U c #A1A19D",
+"V c #A0A09B",
+"W c #4B4B47",
+"X c #8E8E86",
+"Y c #434340",
+"Z c #323232",
+"` c #333333",
+" . c #1D1D1C",
+".. c #8D8D85",
+"+. c #8C8C84",
+"@. c #A7A7A2",
+"#. c #A6A6A1",
+"$. c #A6A6A0",
+"%. c #A5A5A0",
+"&. c #8B8B83",
+"*. c #D1D1CA",
+"=. c #D0D0C9",
+"-. c #CFCFC9",
+";. c #CFCFC8",
+">. c #CECEC7",
+",. c #8A8A82",
+"'. c #D2D2CB",
+"). c #D2D2CA",
+"!. c #898981",
+"~. c #9F9F97",
+"{. c #D0D0C8",
+"]. c #5D5D59",
+"^. c #D1D1C9",
+"/. c #CFCFC7",
+"(. c #5F5F5A",
+"_. c #86867F",
+":. c #CECEC6",
+"<. c #CDCDC6",
+"[. c #CDCDC5",
+"}. c #60605B",
+"|. c #85857D",
+"1. c #A1A199",
+"2. c #CCCCC5",
+"3. c #CCCCC4",
+"4. c #CBCBC4",
+"5. c #CBCBC3",
+"6. c #CACAC3",
+"7. c #62625D",
+"8. c #83837C",
+"9. c #CACAC2",
+"0. c #C9C9C1",
+"a. c #C8C8C0",
+"b. c #C7C7BF",
+"c. c #64645F",
+"d. c #82827B",
+"e. c #A4A49B",
+"f. c #C5C5BD",
+"g. c #C4C4BC",
+"h. c #C3C3BB",
+"i. c #C2C2BA",
+"j. c #C1C1B9",
+"k. c #C0C0B8",
+"l. c #656560",
+"m. c #818179",
+"n. c #A5A59D",
+"o. c #BDBDB5",
+"p. c #BDBDB4",
+"q. c #BCBCB4",
+"r. c #BBBBB3",
+"s. c #BABAB2",
+"t. c #B9B9B1",
+"u. c #B8B8B0",
+"v. c #666661",
+"w. c #7F7F78",
+"x. c #B6B6AE",
+"y. c #B6B6AD",
+"z. c #B5B5AD",
+"A. c #B5B5AC",
+"B. c #B4B4AC",
+"C. c #B3B3AB",
+"D. c #B2B2AB",
+"E. c #B2B2AA",
+"F. c #B1B1A9",
+"G. c #696964",
+"H. c #7D7D76",
+"I. c #BEBEB7",
+"J. c #BDBDB7",
+"K. c #6E6E6A",
+"L. c #7B7B74",
+"M. c #60605A",
+"N. c #50504B",
+"O. c #4D4D49",
+"P. c #6B6B65",
+"Q. c #484844",
+"R. c #454541",
+"S. c #42423E",
+". + @ # $ % & * = - ; > , ' ) ",
+"! ~ { ] # $ % & . ^ ! - ; / ( ",
+"_ : < < [ } } | 1 1 2 3 4 5 6 ",
+"7 8 9 9 9 9 9 9 9 0 0 0 a b c ",
+"7 8 d e e e e e e e e e d f g ",
+"7 ; h h h h h h h h h h h i j ",
+"7 ^ k k l l l l l l k k k m n ",
+"o p q r r r r r r r q q q m s ",
+"o $ t t t t t t t u v v v m w ",
+"x y z A A A A B B B B C C i D ",
+"' E F F F F F F G H H I J i K ",
+"L E M M M M M 4 4 N N O P Q R ",
+"8 E [ [ [ [ [ } } | | 1 2 f R ",
+"8 S T U U U T T T T V V V W R ",
+"X Y Z Z Z Z ` ` Z Z Z Z Z .R ",
+"..Y Z ` ` ` ` ` ` ` ` Z Z .R ",
+"+.S @.@.@.@.#.#.#.#.$.%.%.W R ",
+"&.E *.*.*.*.=.=.=.-.;.;.>.i R ",
+",.] '.'.'.).*.*.*.=.=.;.;.b R ",
+"!.~.'.'.'.'.).*.*.=.=.{.;.].K ",
+"S @ ).*.*.*.*.^.=.{.;./.>.(.D ",
+"_.+ {.{.{.{.;././.>.:.<.[.}.w ",
+"|.1.:.:.:.<.[.[.2.3.4.5.6.7.s ",
+"8.~ 6.9.9.9.0.0.< a.} b.1 c.n ",
+"d.e.f.g.g.g.h.h.i.i.j.j.k.l.j ",
+"m.n.o.p.q.q.r.r.s.s.t.t.u.v.g ",
+"w.e.x.x.y.z.A.B.C.C.D.E.F.G.c ",
+"H.. J J J J J J J J I.J.J.K.6 ",
+"L.M.N.N.N.N.N.N.N.N.N.N.N.O.6 ",
+"P.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.D ",
+"O.R.R.R.R.R.R.R.R.R.R.R.R.R.S.",
+"O.R.R.R.R.R.R.R.R.R.R.R.R.R.S."};
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
new file mode 100644
index 0000000000..d0b3240689
--- /dev/null
+++ b/gtk2_ardour/mixer_strip.cc
@@ -0,0 +1,1466 @@
+/*
+ Copyright (C) 2000-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <glib.h>
+
+#include <sigc++/bind.h>
+
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/choice.h>
+#include <gtkmmext/slider_controller.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/bindable_button.h>
+#include <gtkmmext/doi.h>
+
+#include <ardour/ardour.h>
+#include <ardour/session.h>
+#include <ardour/audioengine.h>
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/diskstream.h>
+#include <ardour/panner.h>
+#include <ardour/send.h>
+#include <ardour/insert.h>
+#include <ardour/ladspa_plugin.h>
+#include <ardour/connection.h>
+#include <ardour/session_connection.h>
+
+#include "ardour_ui.h"
+#include "ardour_dialog.h"
+#include "ardour_message.h"
+#include "mixer_strip.h"
+#include "mixer_ui.h"
+#include "keyboard.h"
+#include "plugin_selector.h"
+#include "public_editor.h"
+
+#include "plugin_ui.h"
+#include "send_ui.h"
+#include "io_selector.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+
+/* XPM */
+static const gchar * small_x_xpm[] = {
+"11 11 2 1",
+" c None",
+". c #cccc99",
+" ",
+" ",
+" . . ",
+" . . ",
+" . . ",
+" . ",
+" . . ",
+" . . ",
+" . . ",
+" ",
+" "};
+
+/* XPM */
+static const gchar * lr_xpm[] = {
+"11 11 2 1",
+" c None",
+". c #cccc99",
+" ",
+" ",
+" . . ",
+" . . ",
+" . . ",
+"...........",
+" . . ",
+" . . ",
+" . . ",
+" ",
+" "};
+
+static void
+speed_printer (char buf[32], Gtk::Adjustment& adj, void* arg)
+{
+ float val = adj.get_value ();
+
+ if (val == 1.0) {
+ strcpy (buf, "1");
+ } else {
+ snprintf (buf, 32, "%.3f", val);
+ }
+}
+
+MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
+ : AxisView(sess),
+ RouteUI (rt, sess, _("mute"), _("solo"), _("RECORD")),
+ _mixer(mx),
+ pre_redirect_box (PreFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer),
+ post_redirect_box (PostFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer),
+ gpm (_route, sess),
+ panners (_route, sess),
+ button_table (8, 2),
+ gain_automation_style_button (""),
+ gain_automation_state_button (""),
+ pan_automation_style_button (""),
+ pan_automation_state_button (""),
+ polarity_button (_("polarity")),
+ comment_button (_("comments")),
+ speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1),
+ speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
+
+{
+ if (set_color_from_route()) {
+ set_color (unique_random_color());
+ }
+
+ input_selector = 0;
+ output_selector = 0;
+ group_menu = 0;
+ _marked_for_display = false;
+ route_ops_menu = 0;
+ ignore_comment_edit = false;
+ ignore_toggle = false;
+ ignore_speed_adjustment = false;
+ comment_window = 0;
+
+ width_button.add (*(manage (new Gtk::Pixmap (lr_xpm))));
+ hide_button.add (*(manage (new Gtk::Pixmap (small_x_xpm))));
+
+
+ input_label.set_text (_("INPUT"));
+ input_button.add (input_label);
+ input_button.set_name ("MixerIOButton");
+ input_label.set_name ("MixerIOButtonLabel");
+
+ output_label.set_text (_("OUTPUT"));
+ output_button.add (output_label);
+ output_button.set_name ("MixerIOButton");
+ output_label.set_name ("MixerIOButtonLabel");
+
+ rec_enable_button->set_name ("MixerRecordEnableButton");
+ rec_enable_button->unset_flags (GTK_CAN_FOCUS);
+
+ solo_button->set_name ("MixerSoloButton");
+ mute_button->set_name ("MixerMuteButton");
+ gain_automation_style_button.set_name ("MixerAutomationModeButton");
+ gain_automation_state_button.set_name ("MixerAutomationPlaybackButton");
+ pan_automation_style_button.set_name ("MixerAutomationModeButton");
+ pan_automation_state_button.set_name ("MixerAutomationPlaybackButton");
+ polarity_button.set_name ("MixerPhaseInvertButton");
+
+ ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_state_button, _("Pan automation mode"));
+ ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_state_button, _("Gain automation mode"));
+
+ ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_style_button, _("Pan automation type"));
+ ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_style_button, _("Gain automation type"));
+
+ hide_button.set_events (hide_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+
+ width_button.unset_flags (GTK_CAN_FOCUS);
+ hide_button.unset_flags (GTK_CAN_FOCUS);
+ input_button.unset_flags (GTK_CAN_FOCUS);
+ output_button.unset_flags (GTK_CAN_FOCUS);
+ solo_button->unset_flags (GTK_CAN_FOCUS);
+ mute_button->unset_flags (GTK_CAN_FOCUS);
+ gain_automation_style_button.unset_flags (GTK_CAN_FOCUS);
+ gain_automation_state_button.unset_flags (GTK_CAN_FOCUS);
+ pan_automation_style_button.unset_flags (GTK_CAN_FOCUS);
+ pan_automation_state_button.unset_flags (GTK_CAN_FOCUS);
+ polarity_button.unset_flags (GTK_CAN_FOCUS);
+
+ button_table.set_homogeneous (true);
+
+ button_table.attach (name_button, 0, 2, 0, 1);
+ button_table.attach (group_button, 0, 2, 1, 2);
+ button_table.attach (input_button, 0, 2, 2, 3);
+
+ button_table.attach (polarity_button, 0, 2, 3, 4);
+
+ button_table.attach (*solo_button, 0, 1, 4, 5);
+ button_table.attach (*mute_button, 1, 2, 4, 5);
+
+ // button_table.attach (gain_automation_style_button, 0, 1, 5, 6);
+ button_table.attach (gain_automation_state_button, 0, 1, 5, 6);
+ // button_table.attach (pan_automation_style_button, 0, 1, 6, 7);
+ button_table.attach (pan_automation_state_button, 1, 2, 5, 6);
+
+ using namespace Menu_Helpers;
+
+ gain_astate_menu.items().push_back (MenuElem (_("off"),
+ bind (slot (_route, &IO::set_gain_automation_state), (AutoState) Off)));
+ gain_astate_menu.items().push_back (MenuElem (_("play"),
+ bind (slot (_route, &IO::set_gain_automation_state), (AutoState) Play)));
+ gain_astate_menu.items().push_back (MenuElem (_("write"),
+ bind (slot (_route, &IO::set_gain_automation_state), (AutoState) Write)));
+ gain_astate_menu.items().push_back (MenuElem (_("touch"),
+ bind (slot (_route, &IO::set_gain_automation_state), (AutoState) Touch)));
+
+ gain_astyle_menu.items().push_back (MenuElem (_("trim")));
+ gain_astyle_menu.items().push_back (MenuElem (_("abs")));
+
+ pan_astate_menu.items().push_back (MenuElem (_("off"),
+ bind (slot (_route.panner(), &Panner::set_automation_state), (AutoState) Off)));
+ pan_astate_menu.items().push_back (MenuElem (_("play"),
+ bind (slot (_route.panner(), &Panner::set_automation_state), (AutoState) Play)));
+ pan_astate_menu.items().push_back (MenuElem (_("write"),
+ bind (slot (_route.panner(), &Panner::set_automation_state), (AutoState) Write)));
+ pan_astate_menu.items().push_back (MenuElem (_("touch"),
+ bind (slot (_route.panner(), &Panner::set_automation_state), (AutoState) Touch)));
+
+ pan_astyle_menu.items().push_back (MenuElem (_("trim")));
+ pan_astyle_menu.items().push_back (MenuElem (_("abs")));
+
+ gain_astate_menu.set_name ("ArdourContextMenu");
+ gain_astyle_menu.set_name ("ArdourContextMenu");
+ pan_astate_menu.set_name ("ArdourContextMenu");
+ pan_astyle_menu.set_name ("ArdourContextMenu");
+
+ ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_style_button, _("gain automation mode"));
+ ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_style_button, _("pan automation mode"));
+ ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_state_button, _("gain automation state"));
+ ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_state_button, _("pan automation state"));
+
+ if (is_audio_track()) {
+
+ AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
+
+ at->FreezeChange.connect (slot (*this, &MixerStrip::map_frozen));
+
+ speed_adjustment.value_changed.connect (slot (*this, &MixerStrip::speed_adjustment_changed));
+
+ speed_frame.set_name ("BaseFrame");
+ speed_frame.set_shadow_type (GTK_SHADOW_IN);
+ speed_frame.add (speed_spinner);
+
+ speed_spinner.set_print_func (speed_printer, 0);
+
+ ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("varispeed"));
+
+ speed_spinner.show ();
+ speed_frame.show ();
+
+ button_table.attach (speed_frame, 0, 2, 6, 7);
+ button_table.attach (*rec_enable_button, 0, 2, 7, 8);
+ }
+
+ name_button.add (name_label);
+ name_button.set_name ("MixerNameButton");
+ Gtkmmext::set_usize_to_display_given_text (name_button, "longest label", 2, 2);
+
+ name_label.set_name ("MixerNameButtonLabel");
+ name_label.set_text (_route.name());
+
+ group_button.add (group_label);
+ group_button.set_name ("MixerGroupButton");
+ group_label.set_name ("MixerGroupButtonLabel");
+
+ comment_button.set_name ("MixerCommentButton");
+ ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route.comment()=="" ?
+ _("click to add/edit comments"):
+ _route.comment());
+ comment_button.clicked.connect (slot (*this, &MixerStrip::comment_button_clicked));
+
+ global_vpacker.set_border_width (4);
+ global_vpacker.set_spacing (4);
+
+ Gtk::VBox *whvbox = manage (new Gtk::VBox);
+
+ width_button.set_name ("MixerWidthButton");
+ hide_button.set_name ("MixerHideButton");
+
+ width_button.clicked.connect (slot (*this, &MixerStrip::width_clicked));
+ hide_button.clicked.connect (slot (*this, &MixerStrip::hide_clicked));
+
+ width_hide_box.pack_start (width_button, false, true);
+ width_hide_box.pack_end (hide_button, false, true);
+
+ whvbox->pack_start (width_hide_box, true, true);
+
+ global_vpacker.pack_start (*whvbox, false, false);
+ global_vpacker.pack_start (button_table, false, false);
+ global_vpacker.pack_start (pre_redirect_box, true, true);
+ global_vpacker.pack_start (gpm, false, false);
+ global_vpacker.pack_start (post_redirect_box, true, true);
+ global_vpacker.pack_start (panners, false, false);
+ global_vpacker.pack_start (output_button, false, false);
+ global_vpacker.pack_start (comment_button, false, false);
+
+ global_frame.add (global_vpacker);
+ global_frame.set_shadow_type (GTK_SHADOW_IN);
+ global_frame.set_name ("BaseFrame");
+
+ add (global_frame);
+
+ /* force setting of visible selected status */
+
+ _selected = true;
+ set_selected (false);
+
+ whvbox->show_all ();
+ name_label.show ();
+ group_label.show();
+ input_label.show ();
+ output_label.show ();
+ pre_redirect_box.show_all ();
+ post_redirect_box.show_all ();
+ button_table.show ();
+ comment_button.show ();
+ name_button.show ();
+ input_button.show ();
+ group_button.show ();
+ output_button.show ();
+ rec_enable_button->show ();
+ solo_button->show ();
+ mute_button->show ();
+ gain_automation_style_button.show ();
+ gain_automation_state_button.show ();
+ pan_automation_style_button.show ();
+ pan_automation_state_button.show ();
+ polarity_button.show ();
+ global_vpacker.show ();
+ global_frame.show ();
+
+ _packed = false;
+ _embedded = false;
+
+ _route.input_changed.connect (slot (*this, &MixerStrip::input_changed));
+ _route.output_changed.connect (slot (*this, &MixerStrip::output_changed));
+ _route.mute_changed.connect (slot (*this, &RouteUI::mute_changed));
+ _route.solo_changed.connect (slot (*this, &RouteUI::solo_changed));
+ _route.solo_safe_changed.connect (slot (*this, &RouteUI::solo_changed));
+ _route.mix_group_changed.connect (slot (*this, &MixerStrip::mix_group_changed));
+ _route.gain_automation_curve().automation_state_changed.connect (slot (*this, &MixerStrip::gain_automation_state_changed));
+ _route.gain_automation_curve().automation_style_changed.connect (slot (*this, &MixerStrip::gain_automation_style_changed));
+ _route.panner().Changed.connect (slot (*this, &MixerStrip::connect_to_pan));
+
+ if (is_audio_track()) {
+ audio_track()->diskstream_changed.connect (slot (*this, &MixerStrip::diskstream_changed));
+ get_diskstream()->speed_changed.connect (slot (*this, &MixerStrip::speed_changed));
+ }
+
+ _route.name_changed.connect (slot (*this, &RouteUI::name_changed));
+ _route.comment_changed.connect (slot (*this, &MixerStrip::comment_changed));
+ _route.gui_changed.connect (slot (*this, &MixerStrip::route_gui_changed));
+
+ input_button.button_release_event.connect (slot (*this, &MixerStrip::input_press));
+ output_button.button_release_event.connect (slot (*this, &MixerStrip::output_press));
+
+ rec_enable_button->button_press_event.connect (slot (*this, &RouteUI::rec_enable_press));
+ solo_button->button_press_event.connect (slot (*this, &RouteUI::solo_press));
+ solo_button->button_release_event.connect (slot (*this, &RouteUI::solo_release));
+ mute_button->button_press_event.connect (slot (*this, &RouteUI::mute_press));
+ mute_button->button_release_event.connect (slot (*this, &RouteUI::mute_release));
+
+ gain_automation_style_button.button_press_event.connect_after (slot (do_not_propagate));
+ pan_automation_style_button.button_press_event.connect_after (slot (do_not_propagate));
+ gain_automation_state_button.button_press_event.connect_after (slot (do_not_propagate));
+ pan_automation_state_button.button_press_event.connect_after (slot (do_not_propagate));
+
+ gain_automation_style_button.button_press_event.connect (slot (*this, &MixerStrip::gain_automation_style_button_event));
+ gain_automation_style_button.button_release_event.connect (slot (*this, &MixerStrip::gain_automation_style_button_event));
+ pan_automation_style_button.button_press_event.connect (slot (*this, &MixerStrip::pan_automation_style_button_event));
+ pan_automation_style_button.button_release_event.connect (slot (*this, &MixerStrip::pan_automation_style_button_event));
+
+ gain_automation_state_button.button_press_event.connect (slot (*this, &MixerStrip::gain_automation_state_button_event));
+ gain_automation_state_button.button_release_event.connect (slot (*this, &MixerStrip::gain_automation_state_button_event));
+ pan_automation_state_button.button_press_event.connect (slot (*this, &MixerStrip::pan_automation_state_button_event));
+ pan_automation_state_button.button_release_event.connect (slot (*this, &MixerStrip::pan_automation_state_button_event));
+
+ polarity_button.toggled.connect (slot (*this, &MixerStrip::polarity_toggled));
+
+ name_button.button_release_event.connect (slot (*this, &MixerStrip::name_button_button_release));
+
+ group_button.button_press_event.connect (slot (*this, &MixerStrip::select_mix_group));
+
+ _width = (Width) -1;
+ set_stuff_from_route ();
+
+ /* start off as a passthru strip. we'll correct this, if necessary,
+ in update_diskstream_display().
+ */
+
+ set_name ("AudioTrackStripBase");
+
+ /* now force an update of all the various elements */
+
+ pre_redirect_box.update();
+ post_redirect_box.update();
+ mute_changed (0);
+ solo_changed (0);
+ name_changed (0);
+ comment_changed (0);
+ mix_group_changed (0);
+ gain_automation_state_changed ();
+ pan_automation_state_changed ();
+ connect_to_pan ();
+
+ panners.setup_pan ();
+
+ if (is_audio_track()) {
+ speed_changed ();
+ }
+
+ /* XXX hack: no phase invert changed signal */
+
+ polarity_button.set_active (_route.phase_invert());
+
+ update_diskstream_display ();
+ update_input_display ();
+ update_output_display ();
+
+ add_events (GDK_BUTTON_RELEASE_MASK);
+}
+
+MixerStrip::~MixerStrip ()
+{
+ GoingAway(); /* EMIT_SIGNAL */
+
+ if (input_selector) {
+ delete input_selector;
+ }
+
+ if (output_selector) {
+ delete output_selector;
+ }
+}
+
+void
+MixerStrip::set_stuff_from_route ()
+{
+ XMLProperty *prop;
+
+ ensure_xml_node ();
+
+ if ((prop = xml_node->property ("strip_width")) != 0) {
+ if (prop->value() == "wide") {
+ set_width (Wide);
+ } else if (prop->value() == "narrow") {
+ set_width (Narrow);
+ }
+ else {
+ error << compose(_("unknown strip width \"%1\" in XML GUI information"), prop->value()) << endmsg;
+ set_width (Wide);
+ }
+ }
+ else {
+ set_width (Wide);
+ }
+
+ if ((prop = xml_node->property ("shown_mixer")) != 0) {
+ if (prop->value() == "no") {
+ _marked_for_display = false;
+ } else {
+ _marked_for_display = true;
+ }
+ }
+ else {
+ /* backwards compatibility */
+ _marked_for_display = true;
+ }
+}
+
+void
+MixerStrip::set_width (Width w)
+{
+ /* always set the gpm width again, things may be hidden */
+ gpm.set_width (w);
+ panners.set_width (w);
+ pre_redirect_box.set_width (w);
+ post_redirect_box.set_width (w);
+
+ if (_width == w) {
+ return;
+ }
+
+ ensure_xml_node ();
+
+ _width = w;
+
+ switch (w) {
+ case Wide:
+ set_usize (-1, -1);
+ xml_node->add_property ("strip_width", "wide");
+
+ static_cast<Gtk::Label*> (rec_enable_button->get_child())->set_text (_("RECORD"));
+ static_cast<Gtk::Label*> (mute_button->get_child())->set_text (_("mute"));
+ static_cast<Gtk::Label*> (solo_button->get_child())->set_text (_("solo"));
+ static_cast<Gtk::Label*> (comment_button.get_child())->set_text (_("comments"));
+ static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (astyle_string(_route.gain_automation_curve().automation_style()));
+ static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (astate_string(_route.gain_automation_curve().automation_state()));
+ static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (astyle_string(_route.panner().automation_style()));
+ static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (astate_string(_route.panner().automation_state()));
+ static_cast<Gtk::Label*> (polarity_button.get_child())->set_text (_("polarity"));
+ Gtkmmext::set_usize_to_display_given_text (name_button, "long", 2, 2);
+ break;
+
+ case Narrow:
+ set_usize (50, -1);
+ xml_node->add_property ("strip_width", "narrow");
+
+ static_cast<Gtk::Label*> (rec_enable_button->get_child())->set_text (_("REC"));
+ static_cast<Gtk::Label*> (mute_button->get_child())->set_text (_("m"));
+ static_cast<Gtk::Label*> (solo_button->get_child())->set_text (_("s"));
+ static_cast<Gtk::Label*> (comment_button.get_child())->set_text (_("cmt"));
+ static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (short_astyle_string(_route.gain_automation_curve().automation_style()));
+ static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (short_astate_string(_route.gain_automation_curve().automation_state()));
+ static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (short_astyle_string(_route.panner().automation_style()));
+ static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (short_astate_string(_route.panner().automation_state()));
+ static_cast<Gtk::Label*> (polarity_button.get_child())->set_text (_("pol"));
+ Gtkmmext::set_usize_to_display_given_text (name_button, "longest label", 2, 2);
+ break;
+ }
+
+ update_input_display ();
+ update_output_display ();
+ mix_group_changed (0);
+ name_changed (0);
+}
+
+void
+MixerStrip::set_packed (bool yn)
+{
+ _packed = yn;
+
+ ensure_xml_node ();
+
+ if (_packed) {
+ xml_node->add_property ("shown_mixer", "yes");
+ } else {
+ xml_node->add_property ("shown_mixer", "no");
+ }
+}
+
+
+gint
+MixerStrip::output_press (GdkEventButton *ev)
+{
+ using namespace Menu_Helpers;
+
+ if (!_session.engine().connected()) {
+ ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
+ return TRUE;
+ }
+
+ MenuList& citems = output_menu.items();
+ output_menu.set_name ("ArdourContextMenu");
+ citems.clear();
+
+ citems.push_back (MenuElem (_("Edit"), slot (*this, &MixerStrip::edit_output_configuration)));
+ citems.push_back (SeparatorElem());
+ citems.push_back (MenuElem (_("Disconnect"), slot (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_output)));
+ citems.push_back (SeparatorElem());
+
+ _session.foreach_connection (this, &MixerStrip::add_connection_to_output_menu);
+
+ output_menu.popup (1, ev->time);
+
+ return TRUE;
+}
+
+void
+MixerStrip::edit_output_configuration ()
+{
+ if (output_selector == 0) {
+ output_selector = new IOSelectorWindow (_session, _route, false);
+ }
+
+ if (output_selector->is_visible()) {
+ output_selector->get_toplevel()->get_window().raise();
+ } else {
+ output_selector->show_all ();
+ }
+}
+
+void
+MixerStrip::edit_input_configuration ()
+{
+ if (input_selector == 0) {
+ input_selector = new IOSelectorWindow (_session, _route, true);
+ }
+
+ if (input_selector->is_visible()) {
+ input_selector->get_toplevel()->get_window().raise();
+ } else {
+ input_selector->show_all ();
+ }
+}
+
+gint
+MixerStrip::input_press (GdkEventButton *ev)
+{
+ using namespace Menu_Helpers;
+
+ MenuList& citems = input_menu.items();
+ input_menu.set_name ("ArdourContextMenu");
+ citems.clear();
+
+ if (!_session.engine().connected()) {
+ ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
+ return TRUE;
+ }
+
+#if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY
+ if (is_audio_track()) {
+ citems.push_back (MenuElem (_("Track"), slot (*this, &MixerStrip::select_stream_input)));
+ }
+#endif
+ citems.push_back (MenuElem (_("Edit"), slot (*this, &MixerStrip::edit_input_configuration)));
+ citems.push_back (SeparatorElem());
+ citems.push_back (MenuElem (_("Disconnect"), slot (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_input)));
+ citems.push_back (SeparatorElem());
+
+ _session.foreach_connection (this, &MixerStrip::add_connection_to_input_menu);
+
+ input_menu.popup (1, ev->time);
+
+ return TRUE;
+}
+
+void
+MixerStrip::connection_input_chosen (ARDOUR::Connection *c)
+{
+ if (!ignore_toggle) {
+
+ try {
+ _route.use_input_connection (*c, this);
+ }
+
+ catch (AudioEngine::PortRegistrationFailure& err) {
+ error << _("could not register new ports required for that connection")
+ << endmsg;
+ }
+ }
+}
+
+void
+MixerStrip::connection_output_chosen (ARDOUR::Connection *c)
+{
+ if (!ignore_toggle) {
+
+ try {
+ _route.use_output_connection (*c, this);
+ }
+
+ catch (AudioEngine::PortRegistrationFailure& err) {
+ error << _("could not register new ports required for that connection")
+ << endmsg;
+ }
+ }
+}
+
+void
+MixerStrip::add_connection_to_input_menu (ARDOUR::Connection* c)
+{
+ using namespace Menu_Helpers;
+
+ if (dynamic_cast<InputConnection *> (c) == 0) {
+ return;
+ }
+
+ MenuList& citems = input_menu.items();
+
+ if (c->nports() == _route.n_inputs()) {
+
+ citems.push_back (CheckMenuElem (c->name(), bind (slot (*this, &MixerStrip::connection_input_chosen), c)));
+
+ ARDOUR::Connection *current = _route.input_connection();
+
+ if (current == c) {
+ ignore_toggle = true;
+ dynamic_cast<CheckMenuItem *> (citems.back())->set_active (true);
+ ignore_toggle = false;
+ }
+ }
+}
+
+void
+MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c)
+{
+ using namespace Menu_Helpers;
+
+ if (dynamic_cast<OutputConnection *> (c) == 0) {
+ return;
+ }
+
+ if (c->nports() == _route.n_outputs()) {
+
+ MenuList& citems = output_menu.items();
+ citems.push_back (CheckMenuElem (c->name(), bind (slot (*this, &MixerStrip::connection_output_chosen), c)));
+
+ ARDOUR::Connection *current = _route.output_connection();
+
+ if (current == c) {
+ ignore_toggle = true;
+ dynamic_cast<CheckMenuItem *> (citems.back())->set_active (true);
+ ignore_toggle = false;
+ }
+ }
+}
+
+void
+MixerStrip::select_stream_input ()
+{
+ using namespace Menu_Helpers;
+
+ Menu *stream_menu = manage (new Menu);
+ MenuList& items = stream_menu->items();
+ stream_menu->set_name ("ArdourContextMenu");
+
+ Session::DiskStreamList streams = _session.disk_streams();
+
+ for (Session::DiskStreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
+
+ if (!(*i)->hidden()) {
+
+ items.push_back (CheckMenuElem ((*i)->name(), bind (slot (*this, &MixerStrip::stream_input_chosen), *i)));
+
+ if (get_diskstream() == *i) {
+ ignore_toggle = true;
+ static_cast<CheckMenuItem *> (items.back())->set_active (true);
+ ignore_toggle = false;
+ }
+ }
+ }
+
+ stream_menu->popup (1, 0);
+}
+
+void
+MixerStrip::stream_input_chosen (DiskStream *stream)
+{
+ if (is_audio_track()) {
+ audio_track()->set_diskstream (*stream, this);
+ }
+}
+
+void
+MixerStrip::update_diskstream_display ()
+{
+ if (is_audio_track()) {
+
+ map_frozen ();
+
+ update_input_display ();
+
+ if (input_selector) {
+ input_selector->hide_all ();
+ }
+
+ show_route_color ();
+
+ } else {
+
+ map_frozen ();
+
+ update_input_display ();
+ show_passthru_color ();
+ }
+}
+
+void
+MixerStrip::connect_to_pan ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &MixerStrip::connect_to_pan));
+
+ panstate_connection.disconnect ();
+ panstyle_connection.disconnect ();
+
+ if (!_route.panner().empty()) {
+ StreamPanner* sp = _route.panner().front();
+
+ panstate_connection = sp->automation().automation_state_changed.connect (slot (*this, &MixerStrip::pan_automation_state_changed));
+ panstyle_connection = sp->automation().automation_style_changed.connect (slot (*this, &MixerStrip::pan_automation_style_changed));
+ }
+
+ panners.pan_changed (this);
+}
+
+void
+MixerStrip::update_input_display ()
+{
+ ARDOUR::Connection *c;
+
+ if ((c = _route.input_connection()) != 0) {
+ input_label.set_text (c->name());
+ } else {
+ switch (_width) {
+ case Wide:
+ input_label.set_text (_("INPUT"));
+ break;
+ case Narrow:
+ input_label.set_text (_("IN"));
+ break;
+ }
+ }
+
+ panners.setup_pan ();
+}
+
+void
+MixerStrip::update_output_display ()
+{
+ ARDOUR::Connection *c;
+
+ if ((c = _route.output_connection()) != 0) {
+ output_label.set_text (c->name());
+ } else {
+ switch (_width) {
+ case Wide:
+ output_label.set_text (_("OUTPUT"));
+ break;
+ case Narrow:
+ output_label.set_text (_("OUT"));
+ break;
+ }
+ }
+
+ gpm.setup_meters ();
+ panners.setup_pan ();
+}
+
+void
+MixerStrip::update ()
+{
+ gpm.update_meters ();
+}
+
+void
+MixerStrip::fast_update ()
+{
+ if (_session.meter_falloff() > 0.0f) {
+ gpm.update_meters_falloff ();
+ }
+}
+
+gint
+MixerStrip::gain_automation_state_button_event (GdkEventButton *ev)
+{
+ if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
+ return TRUE;
+ }
+
+ switch (ev->button) {
+ case 1:
+ switch (ev->button) {
+ case 1:
+ gain_astate_menu.popup (1, ev->time);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+gint
+MixerStrip::gain_automation_style_button_event (GdkEventButton *ev)
+{
+ if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
+ return TRUE;
+ }
+
+ switch (ev->button) {
+ case 1:
+ gain_astyle_menu.popup (1, ev->time);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+gint
+MixerStrip::pan_automation_state_button_event (GdkEventButton *ev)
+{
+ using namespace Menu_Helpers;
+
+ if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
+ return TRUE;
+ }
+
+ switch (ev->button) {
+ case 1:
+ pan_astate_menu.popup (1, ev->time);
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+gint
+MixerStrip::pan_automation_style_button_event (GdkEventButton *ev)
+{
+ switch (ev->button) {
+ case 1:
+ pan_astyle_menu.popup (1, ev->time);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+string
+MixerStrip::astate_string (AutoState state)
+{
+ return _astate_string (state, false);
+}
+
+string
+MixerStrip::short_astate_string (AutoState state)
+{
+ return _astate_string (state, true);
+}
+
+string
+MixerStrip::_astate_string (AutoState state, bool shrt)
+{
+ string sstr;
+
+ switch (state) {
+ case Off:
+ sstr = (shrt ? "--" : _("off"));
+ break;
+ case Play:
+ sstr = (shrt ? "P" : _("aplay"));
+ break;
+ case Touch:
+ sstr = (shrt ? "T" : _("touch"));
+ break;
+ case Write:
+ sstr = (shrt ? "W" : _("awrite"));
+ break;
+ }
+
+ return sstr;
+}
+
+string
+MixerStrip::astyle_string (AutoStyle style)
+{
+ return _astyle_string (style, false);
+}
+
+string
+MixerStrip::short_astyle_string (AutoStyle style)
+{
+ return _astyle_string (style, true);
+}
+
+string
+MixerStrip::_astyle_string (AutoStyle style, bool shrt)
+{
+ if (style & Trim) {
+ return _("trim");
+ } else {
+ /* XXX it might different in different languages */
+
+ return (shrt ? _("abs") : _("abs"));
+ }
+}
+
+void
+MixerStrip::diskstream_changed (void *src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &MixerStrip::update_diskstream_display));
+}
+
+void
+MixerStrip::gain_automation_style_changed ()
+{
+ switch (_width) {
+ case Wide:
+ static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (astyle_string(_route.gain_automation_curve().automation_style()));
+ break;
+ case Narrow:
+ static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (short_astyle_string(_route.gain_automation_curve().automation_style()));
+ break;
+ }
+}
+
+void
+MixerStrip::gain_automation_state_changed ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &MixerStrip::gain_automation_state_changed));
+
+ bool x;
+
+ switch (_width) {
+ case Wide:
+ static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (astate_string(_route.gain_automation_curve().automation_state()));
+ break;
+ case Narrow:
+ static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (short_astate_string(_route.gain_automation_curve().automation_state()));
+ break;
+ }
+
+ x = (_route.gain_automation_state() != Off);
+
+ if (gain_automation_state_button.get_active() != x) {
+ ignore_toggle = true;
+ gain_automation_state_button.set_active (x);
+ ignore_toggle = false;
+ }
+
+ gpm.update_gain_sensitive ();
+
+ /* start watching automation so that things move */
+
+ gain_watching.disconnect();
+
+ if (x) {
+ gain_watching = ARDOUR_UI::RapidScreenUpdate.connect (slot (gpm, &GainMeter::effective_gain_display));
+ }
+}
+
+void
+MixerStrip::pan_automation_style_changed ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &MixerStrip::pan_automation_style_changed));
+
+ switch (_width) {
+ case Wide:
+ static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (astyle_string(_route.panner().automation_style()));
+ break;
+ case Narrow:
+ static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (short_astyle_string(_route.panner().automation_style()));
+ break;
+ }
+}
+
+void
+MixerStrip::pan_automation_state_changed ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &MixerStrip::pan_automation_state_changed));
+
+ bool x;
+
+ switch (_width) {
+ case Wide:
+ static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (astate_string(_route.panner().automation_state()));
+ break;
+ case Narrow:
+ static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (short_astate_string(_route.panner().automation_state()));
+ break;
+ }
+
+ /* when creating a new session, we get to create busses (and
+ sometimes tracks) with no outputs by the time they get
+ here.
+ */
+
+ if (_route.panner().empty()) {
+ return;
+ }
+
+ x = (_route.panner().front()->automation().automation_state() != Off);
+
+ if (pan_automation_state_button.get_active() != x) {
+ ignore_toggle = true;
+ pan_automation_state_button.set_active (x);
+ ignore_toggle = false;
+ }
+
+ panners.update_pan_sensitive ();
+
+ /* start watching automation so that things move */
+
+ pan_watching.disconnect();
+
+ if (x) {
+ pan_watching = ARDOUR_UI::RapidScreenUpdate.connect (slot (panners, &PannerUI::effective_pan_display));
+ }
+}
+
+void
+MixerStrip::input_changed (IOChange change, void *src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &MixerStrip::update_input_display));
+}
+
+void
+MixerStrip::output_changed (IOChange change, void *src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &MixerStrip::update_output_display));
+}
+
+void
+MixerStrip::comment_button_clicked ()
+{
+ if (comment_window == 0) {
+ setup_comment_editor ();
+ }
+
+ if (comment_window->is_visible()) {
+ comment_window->hide ();
+ } else {
+ comment_window->set_position (GTK_WIN_POS_MOUSE);
+ comment_window->show_all ();
+ }
+}
+
+void
+MixerStrip::setup_comment_editor ()
+{
+ comment_window = new Window (GTK_WINDOW_TOPLEVEL);
+
+ string str;
+ str = _route.name();
+ str += _(": comment editor");
+ comment_window->set_title (str);
+
+ comment_area.set_name ("MixerTrackCommentArea");
+ comment_area.set_editable (true);
+ comment_area.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event));
+ comment_area.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event));
+ comment_area.changed.connect (slot (*this, &MixerStrip::comment_edited));
+ comment_area.button_release_event.connect_after (slot (do_not_propagate));
+ comment_area.show ();
+
+ comment_window->add (comment_area);
+ comment_window->delete_event.connect (bind (slot (just_hide_it), comment_window));
+}
+
+void
+MixerStrip::comment_changed (void *src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &MixerStrip::comment_changed), src));
+
+ if (src != this) {
+ ignore_comment_edit = true;
+ comment_area.freeze ();
+ comment_area.delete_text (0, -1);
+ comment_area.set_point (0);
+ comment_area.insert (_route.comment());
+ comment_area.thaw ();
+ ignore_comment_edit = false;
+ }
+}
+
+void
+MixerStrip::comment_edited ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &MixerStrip::comment_edited));
+
+ if (!ignore_comment_edit) {
+ string str = comment_area.get_chars(0,-1);
+ _route.set_comment (str, this);
+ ARDOUR_UI::instance()->tooltips().set_tip (comment_button,
+ str.empty() ? _("click to add/edit comments") : str);
+ }
+}
+
+void
+MixerStrip::set_mix_group (RouteGroup *rg)
+
+{
+ _route.set_mix_group (rg, this);
+ delete group_menu;
+ group_menu = 0;
+}
+
+void
+MixerStrip::add_mix_group_to_menu (RouteGroup *rg)
+{
+ using namespace Menu_Helpers;
+
+ MenuList& items = group_menu->items();
+ items.push_back (MenuElem (rg->name(), bind (slot (*this, &MixerStrip::set_mix_group), rg)));
+}
+
+gint
+MixerStrip::select_mix_group (GdkEventButton *ev)
+{
+ using namespace Menu_Helpers;
+
+ group_menu = new Menu;
+ group_menu->set_name ("ArdourContextMenu");
+ MenuList& items = group_menu->items();
+
+ items.push_back (MenuElem (_("no group"), bind (slot (*this, &MixerStrip::set_mix_group), (RouteGroup *) 0)));
+ _session.foreach_mix_group (this, &MixerStrip::add_mix_group_to_menu);
+
+ group_menu->popup (ev->button, 0);
+ return stop_signal (group_button, "button_press_event");
+}
+
+void
+MixerStrip::mix_group_changed (void *ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &MixerStrip::mix_group_changed), ignored));
+
+ RouteGroup *rg = _route.mix_group();
+
+ if (rg) {
+ group_label.set_text (rg->name());
+ } else {
+ switch (_width) {
+ case Wide:
+ group_label.set_text (_("no group"));
+ break;
+ case Narrow:
+ group_label.set_text (_("~G"));
+ break;
+ }
+ }
+}
+
+void
+MixerStrip::polarity_toggled ()
+{
+ bool x;
+
+ if ((x = polarity_button.get_active()) != _route.phase_invert()) {
+ _route.set_phase_invert (x, this);
+ }
+}
+
+
+void
+MixerStrip::route_gui_changed (string what_changed, void* ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &MixerStrip::route_gui_changed), what_changed, ignored));
+
+ if (what_changed == "color") {
+ if (set_color_from_route () == 0) {
+ show_route_color ();
+ }
+ }
+}
+
+void
+MixerStrip::show_route_color ()
+{
+ Gtk::Style *style;
+
+ name_button.ensure_style ();
+ style = name_button.get_style()->copy();
+ style->set_bg (GTK_STATE_NORMAL, color());
+ name_button.set_style (*style);
+ style->unref();
+
+ route_active_changed ();
+}
+
+void
+MixerStrip::show_passthru_color ()
+{
+ route_active_changed ();
+}
+
+void
+MixerStrip::build_route_ops_menu ()
+{
+ using namespace Menu_Helpers;
+
+ route_ops_menu = new Menu;
+ route_ops_menu->set_name ("ArdourContextMenu");
+
+ MenuList& items = route_ops_menu->items();
+
+ items.push_back (MenuElem (_("Rename"), slot (*this, &RouteUI::route_rename)));
+ items.push_back (SeparatorElem());
+ items.push_back (CheckMenuElem (_("Active"), slot (*this, &RouteUI::toggle_route_active)));
+ route_active_menu_item = dynamic_cast<CheckMenuItem *> (items.back());
+ route_active_menu_item->set_active (_route.active());
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Remove"), slot (*this, &RouteUI::remove_this_route)));
+}
+
+gint
+MixerStrip::name_button_button_release (GdkEventButton* ev)
+{
+ if (ev->button == 3) {
+ list_route_operations ();
+ }
+ return FALSE;
+}
+
+void
+MixerStrip::list_route_operations ()
+{
+ if (route_ops_menu == 0) {
+ build_route_ops_menu ();
+ }
+
+ route_ops_menu->popup (1, 0);
+}
+
+
+void
+MixerStrip::speed_adjustment_changed ()
+{
+ /* since there is a usable speed adjustment, there has to be a diskstream */
+ if (!ignore_speed_adjustment) {
+ get_diskstream()->set_speed (speed_adjustment.get_value());
+ }
+}
+
+void
+MixerStrip::speed_changed ()
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &MixerStrip::update_speed_display));
+}
+
+void
+MixerStrip::update_speed_display ()
+{
+ float val;
+
+ val = get_diskstream()->speed();
+
+ if (val != 1.0) {
+ speed_spinner.set_name ("MixerStripSpeedBaseNotOne");
+ } else {
+ speed_spinner.set_name ("MixerStripSpeedBase");
+ }
+
+ if (speed_adjustment.get_value() != val) {
+ ignore_speed_adjustment = true;
+ speed_adjustment.set_value (val);
+ ignore_speed_adjustment = false;
+ }
+}
+
+
+void
+MixerStrip::set_selected (bool yn)
+{
+ AxisView::set_selected (yn);
+ if (_selected) {
+ global_frame.set_shadow_type (GTK_SHADOW_ETCHED_OUT);
+ global_frame.set_name ("MixerStripSelectedFrame");
+ } else {
+ global_frame.set_shadow_type (GTK_SHADOW_IN);
+ global_frame.set_name ("MixerStripFrame");
+ }
+ global_frame.queue_draw ();
+}
+
+void
+MixerStrip::name_changed (void *src)
+{
+ switch (_width) {
+ case Wide:
+ RouteUI::name_changed (src);
+ break;
+ case Narrow:
+ name_label.set_text (short_version (_route.name(), 5));
+ break;
+ }
+}
+
+void
+MixerStrip::width_clicked ()
+{
+ switch (_width) {
+ case Wide:
+ set_width (Narrow);
+ break;
+ case Narrow:
+ set_width (Wide);
+ break;
+ }
+}
+
+void
+MixerStrip::hide_clicked ()
+{
+ if (_embedded) {
+ Hiding(); /* EMIT_SIGNAL */
+ } else {
+ _mixer.unselect_strip_in_display (this);
+ }
+}
+
+void
+MixerStrip::set_embedded (bool yn)
+{
+ _embedded = yn;
+}
+
+void
+MixerStrip::map_frozen ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &MixerStrip::map_frozen));
+
+ AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
+
+ if (at) {
+ switch (at->freeze_state()) {
+ case AudioTrack::Frozen:
+ pre_redirect_box.set_sensitive (false);
+ post_redirect_box.set_sensitive (false);
+ speed_spinner.set_sensitive (false);
+ break;
+ default:
+ pre_redirect_box.set_sensitive (true);
+ post_redirect_box.set_sensitive (true);
+ speed_spinner.set_sensitive (true);
+ break;
+ }
+ }
+ _route.foreach_redirect (this, &MixerStrip::hide_redirect_editor);
+}
+
+void
+MixerStrip::hide_redirect_editor (Redirect* redirect)
+{
+ void* gui = redirect->get_gui ();
+
+ if (gui) {
+ static_cast<Gtk::Widget*>(gui)->hide ();
+ }
+}
+
+void
+MixerStrip::route_active_changed ()
+{
+ RouteUI::route_active_changed ();
+
+ if (is_audio_track()) {
+ if (_route.active()) {
+ set_name ("AudioTrackStripBase");
+ gpm.set_meter_strip_name ("AudioTrackStripBase");
+ } else {
+ set_name ("AudioTrackStripBaseInactive");
+ gpm.set_meter_strip_name ("AudioTrackStripBaseInactive");
+ }
+ gpm.set_fader_name ("AudioTrackFader");
+ } else {
+ if (_route.active()) {
+ set_name ("AudioBusStripBase");
+ gpm.set_meter_strip_name ("AudioBusStripBase");
+ } else {
+ set_name ("AudioBusStripBaseInactive");
+ gpm.set_meter_strip_name ("AudioBusStripBaseInactive");
+ }
+ gpm.set_fader_name ("AudioBusFader");
+ }
+}
diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h
new file mode 100644
index 0000000000..055fa7a6bb
--- /dev/null
+++ b/gtk2_ardour/mixer_strip.h
@@ -0,0 +1,257 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_mixer_strip__
+#define __ardour_mixer_strip__
+
+#include <vector>
+
+#include <cmath>
+#include <gtk--.h>
+#include <gtkmmext/auto_spin.h>
+#include <gtkmmext/slider_controller.h>
+#include <gtkmmext/click_box.h>
+
+#include <ardour/types.h>
+#include <ardour/ardour.h>
+#include <ardour/io.h>
+#include <ardour/insert.h>
+#include <ardour/stateful.h>
+#include <ardour/redirect.h>
+
+#include <pbd/fastlog.h>
+
+#include "route_ui.h"
+#include "io_selector.h"
+#include "gain_meter.h"
+#include "panner_ui.h"
+#include "enums.h"
+#include "redirect_box.h"
+
+class MotionController;
+
+
+namespace Gtkmmext {
+ class SliderController;
+}
+
+namespace ARDOUR {
+ class Route;
+ class Send;
+ class Insert;
+ class Session;
+ class PortInsert;
+ class Connection;
+ class Plugin;
+}
+
+class Mixer_UI;
+
+class MixerStrip : public RouteUI, public Gtk::EventBox
+{
+ public:
+ MixerStrip (Mixer_UI&, ARDOUR::Session&, ARDOUR::Route &, bool in_mixer = true);
+ ~MixerStrip ();
+
+ void set_width (Width);
+ Width get_width() const { return _width; }
+
+ void update ();
+ void fast_update ();
+ void set_embedded (bool);
+
+ protected:
+ friend class Mixer_UI;
+ void set_packed (bool yn);
+ bool packed () { return _packed; }
+
+ void set_selected(bool yn);
+ void set_stuff_from_route ();
+
+ private:
+ Mixer_UI& _mixer;
+
+ bool _embedded;
+ bool _packed;
+ Width _width;
+
+ Gtk::Button hide_button;
+ Gtk::Button width_button;
+ Gtk::HBox width_hide_box;
+
+ void hide_clicked();
+ void width_clicked ();
+
+ Gtk::Frame global_frame;
+ Gtk::VBox global_vpacker;
+
+ RedirectBox pre_redirect_box;
+ RedirectBox post_redirect_box;
+ GainMeter gpm;
+ PannerUI panners;
+
+ Gtk::Table button_table;
+
+ Gtk::Button diskstream_button;
+ Gtk::Label diskstream_label;
+
+ Gtk::Button input_button;
+ Gtk::Label input_label;
+ Gtk::Button output_button;
+ Gtk::Label output_label;
+
+ Gtk::Button gain_automation_style_button;
+ Gtk::ToggleButton gain_automation_state_button;
+
+ Gtk::Button pan_automation_style_button;
+ Gtk::ToggleButton pan_automation_state_button;
+
+ Gtk::Menu gain_astate_menu;
+ Gtk::Menu gain_astyle_menu;
+ Gtk::Menu pan_astate_menu;
+ Gtk::Menu pan_astyle_menu;
+
+ Gtk::ToggleButton polarity_button;
+
+ SigC::Connection newplug_connection;
+
+ gint mark_update_safe ();
+ guint32 mode_switch_in_progress;
+
+ Gtk::Button name_button;
+
+ Gtk::Window* comment_window;
+ Gtk::Text comment_area;
+ Gtk::Button comment_button;
+
+ void setup_comment_editor ();
+ void comment_button_clicked ();
+
+ Gtk::Button group_button;
+ Gtk::Label group_label;
+ Gtk::Menu *group_menu;
+
+ gint input_press (GdkEventButton *);
+ gint output_press (GdkEventButton *);
+
+ Gtk::Menu input_menu;
+ void add_connection_to_input_menu (ARDOUR::Connection *);
+
+ Gtk::Menu output_menu;
+ void add_connection_to_output_menu (ARDOUR::Connection *);
+
+ void stream_input_chosen (ARDOUR::DiskStream*);
+ void select_stream_input ();
+ void connection_input_chosen (ARDOUR::Connection *);
+ void connection_output_chosen (ARDOUR::Connection *);
+
+ void edit_input_configuration ();
+ void edit_output_configuration ();
+
+ void diskstream_changed (void *src);
+
+ Gtk::Menu *send_action_menu;
+ void build_send_action_menu ();
+
+ void new_send ();
+ void show_send_controls ();
+
+
+ gint gain_automation_style_button_event (GdkEventButton *);
+ gint gain_automation_state_button_event (GdkEventButton *);
+ gint pan_automation_style_button_event (GdkEventButton *);
+ gint pan_automation_state_button_event (GdkEventButton *);
+
+ void input_changed (ARDOUR::IOChange, void *);
+ void output_changed (ARDOUR::IOChange, void *);
+ void gain_automation_state_changed();
+ void pan_automation_state_changed();
+ void gain_automation_style_changed();
+ void pan_automation_style_changed();
+
+ SigC::Connection panstate_connection;
+ SigC::Connection panstyle_connection;
+ void connect_to_pan ();
+
+ std::string astate_string (ARDOUR::AutoState);
+ std::string short_astate_string (ARDOUR::AutoState);
+ std::string _astate_string (ARDOUR::AutoState, bool);
+
+ std::string astyle_string (ARDOUR::AutoStyle);
+ std::string short_astyle_string (ARDOUR::AutoStyle);
+ std::string _astyle_string (ARDOUR::AutoStyle, bool);
+
+ void update_diskstream_display ();
+ void update_input_display ();
+ void update_output_display ();
+
+ void set_automated_controls_sensitivity (bool yn);
+
+ Gtk::Menu *route_ops_menu;
+ void build_route_ops_menu ();
+ gint name_button_button_release (GdkEventButton*);
+ void list_route_operations ();
+
+ gint comment_key_release_handler (GdkEventKey*);
+ void comment_changed (void *src);
+ void comment_edited ();
+ bool ignore_comment_edit;
+
+ void set_mix_group (ARDOUR::RouteGroup *);
+ void add_mix_group_to_menu (ARDOUR::RouteGroup *);
+ gint select_mix_group (GdkEventButton *);
+ void mix_group_changed (void *);
+
+ void polarity_toggled ();
+
+ IOSelectorWindow *input_selector;
+ IOSelectorWindow *output_selector;
+
+ Gtk::Style *passthru_style;
+
+ void route_gui_changed (string, void*);
+ void show_route_color ();
+ void show_passthru_color ();
+
+ void route_active_changed ();
+
+ /* speed control (for tracks only) */
+
+ Gtk::Adjustment speed_adjustment;
+ Gtkmmext::ClickBox speed_spinner;
+ Gtk::Label speed_label;
+ Gtk::Frame speed_frame;
+
+ void speed_adjustment_changed ();
+ void speed_changed ();
+ void name_changed (void *src);
+ void update_speed_display ();
+ void map_frozen ();
+ void hide_redirect_editor (ARDOUR::Redirect* redirect);
+
+ SigC::Connection gain_watching;
+ SigC::Connection pan_watching;
+ bool ignore_speed_adjustment;
+
+ string solo_button_name () const { return "MixerSoloButton"; }
+ string safe_solo_button_name () const { return "MixerSafeSoloButton"; }
+};
+
+#endif /* __ardour_mixer_strip__ */
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
new file mode 100644
index 0000000000..e9eae0b3e2
--- /dev/null
+++ b/gtk2_ardour/mixer_ui.cc
@@ -0,0 +1,1063 @@
+/*
+ Copyright (C) 2000-2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+#include <sigc++/bind.h>
+
+#include <pbd/lockmonitor.h>
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/stop_signal.h>
+
+#include <ardour/audioengine.h>
+#include <ardour/session.h>
+#include <ardour/session_route.h>
+#include <ardour/diskstream.h>
+#include <ardour/plugin_manager.h>
+
+#include "mixer_ui.h"
+#include "mixer_strip.h"
+#include "plugin_selector.h"
+#include "ardour_ui.h"
+#include "check_mark.h"
+#include "prompter.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+using namespace SigC;
+
+static const gchar* track_display_titles[] = {
+ N_("Strips"),
+ 0
+};
+static const gchar* snapshot_display_titles[] = {
+ N_("Snapshots"),
+ 0
+};
+
+static const gchar* group_list_titles[] = {
+ N_("***"),
+ N_("Bar"),
+ 0
+};
+
+GdkPixmap* Mixer_UI::check_pixmap = 0;
+GdkBitmap* Mixer_UI::check_mask = 0;
+GdkPixmap* Mixer_UI::empty_pixmap = 0;
+GdkBitmap* Mixer_UI::empty_mask = 0;
+
+
+Mixer_UI::Mixer_UI (AudioEngine& eng)
+ : Gtk::Window (GTK_WINDOW_TOPLEVEL),
+ KeyboardTarget (*this, "mixer"),
+ engine (eng),
+ track_display_list (internationalize (track_display_titles)),
+ group_list (internationalize (group_list_titles)),
+ snapshot_display (internationalize (snapshot_display_titles))
+
+{
+ _strip_width = Wide;
+ track_menu = 0;
+
+ check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
+ gtk_widget_get_colormap (GTK_WIDGET(group_list.gtkobj())),
+ &check_mask, NULL, (gchar **) check_xpm);
+ empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
+ gtk_widget_get_colormap (GTK_WIDGET(group_list.gtkobj())),
+ &empty_mask, NULL, (gchar **) empty_xpm);
+
+ XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
+ set_state (*node);
+
+ scroller_base.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
+ scroller_base.set_name ("MixerWindow");
+ scroller_base.button_release_event.connect (slot (*this, &Mixer_UI::strip_scroller_button_release));
+ // add as last item of strip packer
+ strip_packer.pack_end (scroller_base, true, true);
+
+ scroller.add_with_viewport (strip_packer);
+ scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ track_display_list.column_titles_active();
+ track_display_list.set_name ("MixerTrackDisplayList");
+ track_display_list.set_shadow_type (GTK_SHADOW_IN);
+ track_display_list.set_selection_mode (GTK_SELECTION_MULTIPLE);
+ track_display_list.set_reorderable (true);
+ track_display_list.set_usize (75, -1);
+ track_display_scroller.add (track_display_list);
+ track_display_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ snapshot_display.column_titles_active();
+ snapshot_display.set_name ("MixerSnapshotDisplayList");
+ snapshot_display.set_shadow_type (GTK_SHADOW_IN);
+ snapshot_display.set_selection_mode (GTK_SELECTION_SINGLE);
+ snapshot_display.set_reorderable (true);
+ snapshot_display.set_usize (75, -1);
+ snapshot_display_scroller.add (snapshot_display);
+ snapshot_display_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ group_list_button_label.set_text (_("Mix Groups"));
+ group_list_button_label.set_name ("MixerGroupTitleButton");
+ group_list_button.add (group_list_button_label);
+ group_list_button.set_name ("MixerGroupTitleButton");
+
+ group_list.column_titles_hide();
+ group_list.set_name ("MixerGroupList");
+ group_list.set_shadow_type (GTK_SHADOW_IN);
+ group_list.set_selection_mode (GTK_SELECTION_MULTIPLE);
+ group_list.set_reorderable (false);
+ group_list.set_usize (75, -1);
+ group_list.set_column_auto_resize (0, true);
+ group_list_scroller.add (group_list);
+ group_list_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ group_list_vbox.pack_start (group_list_button, false, false);
+ group_list_vbox.pack_start (group_list_scroller, true, true);
+
+ list<string> stupid_list;
+
+ stupid_list.push_back ("");
+ stupid_list.push_back (_("-all-"));
+
+ group_list.rows().push_back (stupid_list);
+ group_list.rows().back().set_data (0);
+ group_list.rows().back().select();
+ group_list.cell(0,0).set_pixmap (check_pixmap);
+
+ track_display_frame.set_name("BaseFrame");
+ track_display_frame.set_shadow_type (GTK_SHADOW_IN);
+ track_display_frame.add(track_display_scroller);
+
+ group_list_frame.set_name ("BaseFrame");
+ group_list_frame.set_shadow_type (GTK_SHADOW_IN);
+ group_list_frame.add (group_list_vbox);
+
+ rhs_pane1.add1 (track_display_frame);
+ rhs_pane1.add2 (rhs_pane2);
+
+ rhs_pane2.add1 (group_list_frame);
+ rhs_pane2.add2 (snapshot_display_scroller);
+
+ list_vpacker.pack_start (rhs_pane1, true, true);
+
+ global_hpacker.pack_start (scroller, true, true);
+ global_hpacker.pack_start (out_packer, false, false);
+
+ list_hpane.add1(list_vpacker);
+ list_hpane.add2(global_hpacker);
+
+ rhs_pane1.size_allocate.connect_after (bind (slot (*this, &Mixer_UI::pane_allocation_handler),
+ static_cast<Gtk::Paned*> (&rhs_pane1)));
+ rhs_pane2.size_allocate.connect_after (bind (slot (*this, &Mixer_UI::pane_allocation_handler),
+ static_cast<Gtk::Paned*> (&rhs_pane2)));
+ list_hpane.size_allocate.connect_after (bind (slot (*this, &Mixer_UI::pane_allocation_handler),
+ static_cast<Gtk::Paned*> (&list_hpane)));
+
+
+ rhs_pane1.set_data ("collapse-direction", (gpointer) 0);
+ rhs_pane2.set_data ("collapse-direction", (gpointer) 0);
+ list_hpane.set_data ("collapse-direction", (gpointer) 1);
+
+ rhs_pane1.button_release_event.connect (bind (slot (pane_handler), static_cast<Paned*>(&rhs_pane1)));
+ rhs_pane2.button_release_event.connect (bind (slot (pane_handler), static_cast<Paned*>(&rhs_pane2)));
+ list_hpane.button_release_event.connect (bind (slot (pane_handler), static_cast<Paned*>(&list_hpane)));
+
+ global_vpacker.pack_start (list_hpane, true, true);
+
+ add (global_vpacker);
+ set_name ("MixerWindow");
+ set_title (_("ardour: mixer"));
+ set_wmclass (_("ardour_mixer"), "Ardour");
+
+ delete_event.connect (bind (slot (just_hide_it),
+ static_cast<Gtk::Window *>(this)));
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ snapshot_display.select_row.connect (slot (*this, &Mixer_UI::snapshot_display_selected));
+
+ track_display_list.select_row.connect (slot (*this, &Mixer_UI::track_display_selected));
+ track_display_list.unselect_row.connect (slot (*this, &Mixer_UI::track_display_unselected));
+ track_display_list.row_move.connect (slot (*this, &Mixer_UI::queue_track_display_reordered));
+ track_display_list.click_column.connect (slot (*this, &Mixer_UI::track_column_click));
+
+ group_list_button.clicked.connect (slot (*this, &Mixer_UI::group_list_button_clicked));
+ group_list.button_press_event.connect (slot (*this, &Mixer_UI::group_list_button_press_event));
+ group_list.select_row.connect (slot (*this, &Mixer_UI::group_selected));
+ group_list.unselect_row.connect (slot (*this, &Mixer_UI::group_unselected));
+
+ _plugin_selector = new PluginSelector (PluginManager::the_manager());
+ _plugin_selector->delete_event.connect (bind (slot (just_hide_it),
+ static_cast<Window *> (_plugin_selector)));
+
+ configure_event.connect (slot (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
+
+ _selection.RoutesChanged.connect (slot (*this, &Mixer_UI::follow_strip_selection));
+}
+
+Mixer_UI::~Mixer_UI ()
+{
+}
+
+void
+Mixer_UI::ensure_float (Window& win)
+{
+ win.set_transient_for (*this);
+}
+
+void
+Mixer_UI::show_window ()
+{
+ show_all ();
+
+ /* now reset each strips width so the right widgets are shown */
+ MixerStrip* ms;
+ CList_Helpers::RowList::iterator i;
+
+ for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) {
+ ms = (MixerStrip *) i->get_data ();
+ ms->set_width (ms->get_width());
+ }
+}
+
+void
+Mixer_UI::add_strip (Route* route)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::add_strip), route));
+
+ MixerStrip* strip;
+
+ if (route->hidden()) {
+ return;
+ }
+
+ strip = new MixerStrip (*this, *session, *route);
+ strips.push_back (strip);
+
+ strip->set_width (_strip_width);
+ show_strip (strip);
+
+ const gchar* rowdata[1];
+ rowdata[0] = route->name().c_str();
+
+ track_display_list.freeze ();
+ track_display_list.rows().push_back (rowdata);
+ track_display_list.rows().back().set_data (strip);
+ track_display_list.thaw ();
+
+ if (strip->marked_for_display() || strip->packed()) {
+ track_display_list.rows().back().select ();
+ }
+
+ route->name_changed.connect (bind (slot (*this, &Mixer_UI::strip_name_changed), strip));
+ strip->GoingAway.connect (bind (slot (*this, &Mixer_UI::remove_strip), strip));
+
+ strip->button_release_event.connect (bind (slot (*this, &Mixer_UI::strip_button_release_event), strip));
+
+// if (width() < gdk_screen_width()) {
+// set_usize (width() + (_strip_width == Wide ? 75 : 50), height());
+// }
+}
+
+void
+Mixer_UI::remove_strip (MixerStrip* strip)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::remove_strip), strip));
+
+ CList_Helpers::RowList::iterator ri;
+ list<MixerStrip *>::iterator i;
+
+ if ((i = find (strips.begin(), strips.end(), strip)) != strips.end()) {
+ strips.erase (i);
+ }
+
+ for (ri = track_display_list.rows().begin(); ri != track_display_list.rows().end(); ++ri) {
+ if ((MixerStrip *) ri->get_data () == strip) {
+ track_display_list.rows().erase (ri);
+ break;
+ }
+ }
+}
+
+void
+Mixer_UI::follow_strip_selection ()
+{
+ for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ (*i)->set_selected (_selection.selected (&(*i)->route()));
+ }
+}
+
+gint
+Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
+{
+ if (ev->button == 1) {
+
+ /* this allows the user to click on the strip to terminate comment
+ editing. XXX it needs improving so that we don't select the strip
+ at the same time.
+ */
+
+ ARDOUR_UI::instance()->allow_focus (false);
+
+ if (_selection.selected (&strip->route())) {
+ _selection.remove (&strip->route());
+ } else {
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+ _selection.add (&strip->route());
+ } else {
+ _selection.set (&strip->route());
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+void
+Mixer_UI::connect_to_session (Session* sess)
+{
+ session = sess;
+
+ string wintitle = _("ardour: mixer: ");
+ wintitle += session->name();
+ set_title (wintitle);
+
+ track_display_list.freeze ();
+ track_display_list.clear ();
+
+ session->foreach_route (this, &Mixer_UI::add_strip);
+
+ track_display_list.thaw ();
+
+ session->going_away.connect (slot (*this, &Mixer_UI::disconnect_from_session));
+ session->RouteAdded.connect (slot (*this, &Mixer_UI::add_strip));
+ session->mix_group_added.connect (slot (*this, &Mixer_UI::add_mix_group));
+
+ session->foreach_mix_group(this, &Mixer_UI::add_mix_group);
+
+ session->StateSaved.connect (slot (*this, &Mixer_UI::session_state_saved));
+ redisplay_snapshots ();
+
+ _plugin_selector->set_session (session);
+
+ start_updating ();
+}
+
+void
+Mixer_UI::disconnect_from_session ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &Mixer_UI::disconnect_from_session));
+
+ group_list.clear ();
+ set_title (_("ardour: mixer"));
+ stop_updating ();
+ hide_all_strips (false);
+}
+
+void
+Mixer_UI::hide_all_strips (bool with_select)
+{
+ MixerStrip* ms;
+ CList_Helpers::RowList::iterator i;
+
+ track_display_list.freeze ();
+
+ for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) {
+ ms = (MixerStrip *) i->get_data ();
+
+ if (with_select) {
+ i->unselect ();
+ } else {
+ hide_strip (ms);
+ }
+ }
+
+ track_display_list.thaw ();
+}
+
+void
+Mixer_UI::unselect_all_strips ()
+{
+ hide_all_strips (false);
+}
+
+void
+Mixer_UI::select_all_strips ()
+{
+ CList_Helpers::RowList::iterator i;
+
+ for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) {
+ i->select ();
+ }
+}
+
+void
+Mixer_UI::select_all_audiotrack_strips ()
+{
+ MixerStrip* ms;
+ CList_Helpers::RowList::iterator i;
+
+ track_display_list.freeze ();
+
+ for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) {
+ ms = (MixerStrip *) i->get_data ();
+
+ if (ms->is_audio_track()) {
+ i->select ();
+ }
+ }
+
+ track_display_list.thaw ();
+}
+
+void
+Mixer_UI::unselect_all_audiotrack_strips ()
+{
+ MixerStrip* ms;
+ CList_Helpers::RowList::iterator i;
+
+ track_display_list.freeze ();
+
+ for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) {
+ ms = (MixerStrip *) i->get_data ();
+
+ if (ms->is_audio_track()) {
+ i->unselect ();
+ }
+ }
+
+ track_display_list.thaw ();
+}
+
+void
+Mixer_UI::select_all_audiobus_strips ()
+{
+ MixerStrip* ms;
+ CList_Helpers::RowList::iterator i;
+
+ track_display_list.freeze ();
+
+ for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) {
+ ms = (MixerStrip *) i->get_data ();
+
+ if (!ms->is_audio_track()) {
+ i->select ();
+ }
+ }
+
+ track_display_list.thaw ();
+}
+
+void
+Mixer_UI::unselect_all_audiobus_strips ()
+{
+ MixerStrip* ms;
+ CList_Helpers::RowList::iterator i;
+
+ track_display_list.freeze ();
+
+ for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) {
+ ms = (MixerStrip *) i->get_data ();
+
+ if (!ms->is_audio_track()) {
+ i->unselect ();
+ }
+ }
+
+ track_display_list.thaw ();
+}
+
+void
+Mixer_UI::show_strip (MixerStrip* ms)
+{
+ if (!ms->packed()) {
+
+ if (ms->route().master() || ms->route().control()) {
+ out_packer.pack_start (*ms, false, false);
+ } else {
+ strip_packer.pack_start (*ms, false, false);
+ }
+ ms->set_packed (true);
+ ms->show ();
+
+ }
+}
+
+void
+Mixer_UI::hide_strip (MixerStrip* ms)
+{
+ if (ms->packed()) {
+ if (ms->route().master() || ms->route().control()) {
+ out_packer.remove (*ms);
+ } else {
+ strip_packer.remove (*ms);
+ }
+ ms->set_packed (false);
+ }
+}
+
+gint
+Mixer_UI::start_updating ()
+{
+ screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (slot (*this, &Mixer_UI::update_strips));
+ fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (slot (*this, &Mixer_UI::fast_update_strips));
+ return 0;
+}
+
+gint
+Mixer_UI::stop_updating ()
+{
+ screen_update_connection.disconnect();
+ fast_screen_update_connection.disconnect();
+ return 0;
+}
+
+void
+Mixer_UI::update_strips ()
+{
+ if (is_mapped () && session) {
+ for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ (*i)->update ();
+ }
+ }
+}
+
+void
+Mixer_UI::fast_update_strips ()
+{
+ if (is_mapped () && session) {
+ for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ (*i)->fast_update ();
+ }
+ }
+}
+
+void
+Mixer_UI::snapshot_display_selected (gint row, gint col, GdkEvent* ev)
+{
+ string* snap_name;
+
+ if ((snap_name = (string*) snapshot_display.get_row_data(row)) != 0){
+ if (session->snap_name() == *snap_name){
+ return;
+ }
+ string path = session->path();
+ ARDOUR_UI::instance()->load_session(path, *snap_name);
+ }
+}
+
+void
+Mixer_UI::track_display_selected (gint row, gint col, GdkEvent* ev)
+{
+ MixerStrip* strip;
+
+ if ((strip = (MixerStrip *) track_display_list.get_row_data (row)) != 0) {
+ strip->set_marked_for_display (true);
+ show_strip (strip);
+
+ /* just redraw the whole thing so that we get the right order
+ when we reinsert the strip.
+ */
+
+ track_display_reordered ();
+ }
+}
+
+void
+Mixer_UI::track_display_unselected (gint row, gint col, GdkEvent* ev)
+{
+ MixerStrip* strip;
+
+ if ((strip = (MixerStrip *) track_display_list.get_row_data (row)) != 0) {
+ strip->set_marked_for_display (false);
+ hide_strip (strip);
+ }
+}
+
+void
+Mixer_UI::unselect_strip_in_display (MixerStrip *strip)
+{
+ CList_Helpers::RowIterator i;
+
+ if ((i = track_display_list.rows().find_data (strip)) != track_display_list.rows().end()) {
+ (*i).unselect ();
+ }
+}
+
+void
+Mixer_UI::select_strip_in_display (MixerStrip *strip)
+{
+ CList_Helpers::RowIterator i;
+
+ if ((i = track_display_list.rows().find_data (strip)) != track_display_list.rows().end()) {
+ (*i).select ();
+ }
+}
+
+void
+Mixer_UI::queue_track_display_reordered (gint arg1, gint arg2)
+{
+ /* the problem here is that we are called *before* the
+ list has been reordered. so just queue up
+ the actual re-drawer to happen once the re-ordering
+ is complete.
+ */
+
+ Main::idle.connect (slot (*this, &Mixer_UI::track_display_reordered));
+}
+
+int
+Mixer_UI::track_display_reordered ()
+{
+ CList_Helpers::RowList::iterator i;
+ long order;
+
+ // hide_all_strips (false);
+
+ for (order = 0, i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i, ++order) {
+ MixerStrip* strip = (MixerStrip *) (*i)->get_data ();
+ if (strip->marked_for_display()) {
+ strip->route().set_order_key (N_("signal"), order);
+ strip_packer.reorder_child (*strip, -1); /* put at end */
+ }
+ }
+
+ return FALSE;
+}
+
+void
+Mixer_UI::track_column_click (gint col)
+{
+ if (track_menu == 0) {
+ build_track_menu ();
+ }
+
+ track_menu->popup (0, 0);
+}
+
+void
+Mixer_UI::build_track_menu ()
+{
+ using namespace Menu_Helpers;
+ using namespace Gtk;
+
+ track_menu = new Menu;
+ track_menu->set_name ("ArdourContextMenu");
+ MenuList& items = track_menu->items();
+ track_menu->set_name ("ArdourContextMenu");
+
+ items.push_back (MenuElem (_("Show All"), slot (*this, &Mixer_UI::select_all_strips)));
+ items.push_back (MenuElem (_("Hide All"), slot (*this, &Mixer_UI::unselect_all_strips)));
+ items.push_back (MenuElem (_("Show All AudioTrack MixerStrips"), slot (*this, &Mixer_UI::select_all_audiotrack_strips)));
+ items.push_back (MenuElem (_("Hide All AudioTrack MixerStrips"), slot (*this, &Mixer_UI::unselect_all_audiotrack_strips)));
+ items.push_back (MenuElem (_("Show All AudioBus MixerStrips"), slot (*this, &Mixer_UI::select_all_audiobus_strips)));
+ items.push_back (MenuElem (_("Hide All AudioBus MixerStrips"), slot (*this, &Mixer_UI::unselect_all_audiobus_strips)));
+
+}
+
+void
+Mixer_UI::strip_name_changed (void* src, MixerStrip* mx)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::strip_name_changed), src, mx));
+
+ CList_Helpers::RowList::iterator i;
+
+ if ((i = track_display_list.rows().find_data (mx)) == track_display_list.rows().end()) {
+ error << _("track display list item for renamed strip not found!") << endmsg;
+ return;
+ }
+
+ track_display_list.cell ((*i)->get_row_num(), 0).set_text (mx->route().name());
+}
+
+void
+Mixer_UI::new_mix_group ()
+{
+ ArdourPrompter prompter;
+ string result;
+
+ prompter.set_prompt (_("Name for new mix group"));
+ prompter.done.connect (Main::quit.slot());
+
+ prompter.show_all ();
+
+ Main::run ();
+
+ if (prompter.status != Gtkmmext::Prompter::entered) {
+ return;
+ }
+
+ prompter.get_result (result);
+
+ if (result.length()) {
+ session->add_mix_group (result);
+ }
+}
+
+void
+Mixer_UI::group_list_button_clicked ()
+{
+ if (session) {
+ new_mix_group ();
+ }
+}
+
+gint
+Mixer_UI::group_list_button_press_event (GdkEventButton* ev)
+{
+ gint row, col;
+ RouteGroup* group;
+
+ if (group_list.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) {
+ return FALSE;
+ }
+
+ switch (col) {
+ case 1:
+ if (Keyboard::is_edit_event (ev)) {
+ // RouteGroup* group = (RouteGroup *) group_list.row(row).get_data ();
+
+ // edit_mix_group (group);
+
+ return stop_signal (group_list, "button_press_event");
+
+ } else {
+ /* allow regular select to occur */
+ return FALSE;
+ }
+
+ case 0:
+ stop_signal (group_list, "button_press_event");
+ if ((group = (RouteGroup *) group_list.row(row).get_data ()) != 0) {
+ group->set_active (!group->is_active (), this);
+ }
+ break;
+ }
+
+ return TRUE;
+}
+
+void
+Mixer_UI::group_selected (gint row, gint col, GdkEvent* ev)
+{
+ RouteGroup* group = (RouteGroup *) group_list.row(row).get_data ();
+
+ if (group) {
+ group->set_hidden (false, this);
+ } else {
+ /* the master group */
+
+ for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ show_strip (*i);
+ }
+
+ track_display_reordered ();
+ }
+}
+
+void
+Mixer_UI::group_unselected (gint row, gint col, GdkEvent* ev)
+
+{
+ RouteGroup* group = (RouteGroup *) group_list.row(row).get_data ();
+
+ if (group) {
+ group->set_hidden (true, this);
+ } else {
+ /* the master group */
+
+ for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ hide_strip (*i);
+ }
+ }
+}
+
+void
+Mixer_UI::group_flags_changed (void* src, RouteGroup* group)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::group_flags_changed), src, group));
+
+ if (src != this) {
+ // select row
+ }
+
+ CList_Helpers::RowIterator ri = group_list.rows().find_data (group);
+
+ for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ if ((*i)->route().mix_group() == group) {
+ if (group->is_hidden ()) {
+ unselect_strip_in_display(*i);
+ } else {
+ select_strip_in_display(*i);
+ (*ri)->select();
+ }
+ }
+ }
+
+ if (group->is_active()) {
+ group_list.cell (ri->get_row_num(),0).set_pixmap (check_pixmap, check_mask);
+ } else {
+ group_list.cell (ri->get_row_num(),0).set_pixmap (empty_pixmap, empty_mask);
+ }
+}
+
+void
+Mixer_UI::add_mix_group (RouteGroup* group)
+
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::add_mix_group), group));
+
+ list<string> names;
+
+ names.push_back ("");
+ names.push_back (group->name());
+
+ group_list.rows().push_back (names);
+ group_list.rows().back().set_data (group);
+
+ /* update display to reflect group flags */
+
+ group_flags_changed (0, group);
+
+ group->FlagsChanged.connect (bind (slot (*this, &Mixer_UI::group_flags_changed), group));
+}
+
+void
+Mixer_UI::redisplay_snapshots ()
+{
+ if (session == 0) {
+ return;
+ }
+
+ vector<string*>* states;
+ if ((states = session->possible_states()) == 0) {
+ return;
+ }
+
+ snapshot_display.freeze();
+ snapshot_display.rows().clear ();
+
+ for (vector<string*>::iterator i = states->begin(); i != states->end(); ++i) {
+ string statename = *(*i);
+ const char *rowtext[1];
+
+ rowtext[0] = statename.c_str();
+
+ snapshot_display.rows().push_back (rowtext);
+ snapshot_display.rows().back().set_data (new string (statename), deferred_delete<string>);
+
+ delete *i;
+ }
+
+ delete states;
+ snapshot_display.thaw();
+}
+
+void
+Mixer_UI::session_state_saved (string snap_name)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &Mixer_UI::session_state_saved), snap_name));
+ redisplay_snapshots ();
+}
+
+gint
+Mixer_UI::strip_scroller_button_release (GdkEventButton* ev)
+{
+ using namespace Menu_Helpers;
+
+ if (Keyboard::is_context_menu_event (ev)) {
+ ARDOUR_UI::instance()->add_route();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+Mixer_UI::set_strip_width (Width w)
+{
+ _strip_width = w;
+
+ for (list<MixerStrip*>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ (*i)->set_width (w);
+ }
+}
+
+
+int
+Mixer_UI::set_state (const XMLNode& node)
+{
+ const XMLProperty* prop;
+ XMLNode* geometry;
+ int x, y, width, height, xoff, yoff;
+
+ if ((geometry = find_named_node (node, "geometry")) == 0) {
+
+ width = default_width;
+ height = default_height;
+ x = 1;
+ y = 1;
+ xoff = 0;
+ yoff = 21;
+
+ } else {
+
+ width = atoi(geometry->property("x_size")->value().c_str());
+ height = atoi(geometry->property("y_size")->value().c_str());
+ x = atoi(geometry->property("x_pos")->value().c_str());
+ y = atoi(geometry->property("y_pos")->value().c_str());
+ xoff = atoi(geometry->property("x_off")->value().c_str());
+ yoff = atoi(geometry->property("y_off")->value().c_str());
+ }
+
+ set_default_size(width, height);
+ set_uposition(x, y-yoff);
+
+ if ((prop = node.property ("narrow-strips"))) {
+ if (prop->value() == "yes") {
+ set_strip_width (Narrow);
+ } else {
+ set_strip_width (Wide);
+ }
+ }
+
+ return 0;
+}
+
+XMLNode&
+Mixer_UI::get_state (void)
+{
+ XMLNode* node = new XMLNode ("Mixer");
+
+ if (is_realized()) {
+ Gdk_Window win = get_window();
+
+ int x, y, xoff, yoff, width, height;
+ win.get_root_origin(x, y);
+ win.get_position(xoff, yoff);
+ win.get_size(width, height);
+
+ XMLNode* geometry = new XMLNode ("geometry");
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%d", width);
+ geometry->add_property(X_("x_size"), string(buf));
+ snprintf(buf, sizeof(buf), "%d", height);
+ geometry->add_property(X_("y_size"), string(buf));
+ snprintf(buf, sizeof(buf), "%d", x);
+ geometry->add_property(X_("x_pos"), string(buf));
+ snprintf(buf, sizeof(buf), "%d", y);
+ geometry->add_property(X_("y_pos"), string(buf));
+ snprintf(buf, sizeof(buf), "%d", xoff);
+ geometry->add_property(X_("x_off"), string(buf));
+ snprintf(buf, sizeof(buf), "%d", yoff);
+ geometry->add_property(X_("y_off"), string(buf));
+
+ snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&rhs_pane1)->gtkobj()));
+ geometry->add_property(X_("mixer_rhs_pane1_pos"), string(buf));
+ snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&rhs_pane2)->gtkobj()));
+ geometry->add_property(X_("mixer_rhs_pane2_pos"), string(buf));
+ snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&list_hpane)->gtkobj()));
+ geometry->add_property(X_("mixer_list_hpane_pos"), string(buf));
+
+ node->add_child_nocopy (*geometry);
+ }
+
+ node->add_property ("narrow-strips", _strip_width == Narrow ? "yes" : "no");
+
+ return *node;
+}
+
+
+void
+Mixer_UI::pane_allocation_handler (GtkAllocation *alloc, Gtk::Paned* which)
+{
+ int pos;
+ XMLProperty* prop = 0;
+ char buf[32];
+ XMLNode* node = ARDOUR_UI::instance()->mixer_settings();
+ XMLNode* geometry;
+ int width, height;
+ static int32_t done[3] = { 0, 0, 0 };
+
+ if ((geometry = find_named_node (*node, "geometry")) == 0) {
+ width = default_width;
+ height = default_height;
+ } else {
+ width = atoi(geometry->property("x_size")->value());
+ height = atoi(geometry->property("y_size")->value());
+ }
+
+ if (which == static_cast<Gtk::Paned*> (&rhs_pane1)) {
+
+ if (done[0]) {
+ return;
+ }
+
+ if (!geometry || (prop = geometry->property("mixer_rhs_pane1_pos")) == 0) {
+ pos = height / 3;
+ snprintf (buf, sizeof(buf), "%d", pos);
+ } else {
+ pos = atoi (prop->value());
+ }
+
+ if ((done[0] = GTK_WIDGET(rhs_pane1.gtkobj())->allocation.height > pos)) {
+ rhs_pane1.set_position (pos);
+ }
+
+ } else if (which == static_cast<Gtk::Paned*> (&rhs_pane2)) {
+
+ if (done[1]) {
+ return;
+ }
+
+ if (!geometry || (prop = geometry->property("mixer_rhs_pane2_pos")) == 0) {
+ pos = height / 3;
+ snprintf (buf, sizeof(buf), "%d", pos);
+ } else {
+ pos = atoi (prop->value());
+ }
+
+ if ((done[1] = GTK_WIDGET(rhs_pane2.gtkobj())->allocation.height > pos)) {
+ rhs_pane2.set_position (pos);
+ }
+
+ } else if (which == static_cast<Gtk::Paned*> (&list_hpane)) {
+
+ if (done[2]) {
+ return;
+ }
+
+ if (!geometry || (prop = geometry->property("mixer_list_hpane_pos")) == 0) {
+ pos = 75;
+ snprintf (buf, sizeof(buf), "%d", pos);
+ } else {
+ pos = atoi (prop->value());
+ }
+
+ if ((done[2] = GTK_WIDGET(list_hpane.gtkobj())->allocation.width > pos)) {
+ list_hpane.set_position (pos);
+ }
+ }
+}
+
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
new file mode 100644
index 0000000000..2027f905f3
--- /dev/null
+++ b/gtk2_ardour/mixer_ui.h
@@ -0,0 +1,180 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_mixer_ui_h__
+#define __ardour_mixer_ui_h__
+
+#include <list>
+
+#include <gtk--.h>
+
+#include <ardour/ardour.h>
+#include <ardour/stateful.h>
+#include <ardour/io.h>
+
+#include "keyboard_target.h"
+#include "route_redirect_selection.h"
+#include "enums.h"
+
+namespace ARDOUR {
+ class Route;
+ class RouteGroup;
+ class Session;
+ class DiskStream;
+ class AudioEngine;
+};
+
+class MixerStrip;
+class PluginSelector;
+
+class Mixer_UI : public Gtk::Window, public KeyboardTarget
+{
+ public:
+ Mixer_UI (ARDOUR::AudioEngine&);
+ ~Mixer_UI();
+
+ void connect_to_session (ARDOUR::Session *);
+
+ PluginSelector& plugin_selector() { return *_plugin_selector; }
+
+ void set_strip_width (Width);
+ Width get_strip_width () const { return _strip_width; }
+
+ void unselect_strip_in_display (MixerStrip*);
+ void select_strip_in_display (MixerStrip*);
+
+ XMLNode& get_state (void);
+ int set_state (const XMLNode& );
+
+ void show_window ();
+
+ void ensure_float (Gtk::Window&);
+
+ RouteRedirectSelection& selection() { return _selection; }
+
+ private:
+ ARDOUR::AudioEngine& engine;
+ ARDOUR::Session *session;
+
+ Gtk::HBox global_hpacker;
+ Gtk::VBox global_vpacker;
+ Gtk::ScrolledWindow scroller;
+ Gtk::EventBox scroller_base;
+ Gtk::HBox scroller_hpacker;
+ Gtk::VBox mixer_scroller_vpacker;
+ Gtk::VBox list_vpacker;
+ Gtk::CList track_display_list;
+ Gtk::CList group_list;
+ Gtk::Label group_list_button_label;
+ Gtk::Button group_list_button;
+ Gtk::ScrolledWindow track_display_scroller;
+ Gtk::ScrolledWindow group_list_scroller;
+ Gtk::VBox group_list_vbox;
+ Gtk::Frame track_display_frame;
+ Gtk::Frame group_list_frame;
+ Gtk::VPaned rhs_pane1;
+ Gtk::VPaned rhs_pane2;
+ Gtk::HBox strip_packer;
+ Gtk::HBox out_packer;
+ Gtk::HPaned list_hpane;
+
+ void pane_allocation_handler (GtkAllocation*, Gtk::Paned*);
+
+ list<MixerStrip *> strips;
+
+ gint strip_scroller_button_release (GdkEventButton*);
+
+ void add_strip (ARDOUR::Route*);
+ void remove_strip (MixerStrip *);
+
+ void show_strip (MixerStrip *);
+ void hide_strip (MixerStrip *);
+
+ void hide_all_strips (bool with_select);
+ void unselect_all_strips();
+ void select_all_strips ();
+ void unselect_all_audiotrack_strips ();
+ void select_all_audiotrack_strips ();
+ void unselect_all_audiobus_strips ();
+ void select_all_audiobus_strips ();
+
+ void follow_strip_selection ();
+
+ gint start_updating ();
+ gint stop_updating ();
+
+ void disconnect_from_session ();
+
+ SigC::Connection screen_update_connection;
+ void update_strips ();
+ SigC::Connection fast_screen_update_connection;
+ void fast_update_strips ();
+
+ void snapshot_display_selected (gint row, gint col, GdkEvent* ev);
+
+ void track_display_selected (gint row, gint col, GdkEvent *ev);
+ void track_display_unselected (gint row, gint col, GdkEvent *ev);
+ void queue_track_display_reordered (gint row, gint col);
+ gint track_display_reordered ();
+ void track_name_changed (MixerStrip *);
+
+ void group_selected (gint row, gint col, GdkEvent *ev);
+ void group_unselected (gint row, gint col, GdkEvent *ev);
+ gint group_list_button_press_event (GdkEventButton *);
+ void group_list_button_clicked();
+ void new_mix_group ();
+ void add_mix_group (ARDOUR::RouteGroup *);
+
+ Gtk::Menu *track_menu;
+ void track_column_click (gint);
+ void build_track_menu ();
+
+ PluginSelector *_plugin_selector;
+
+ void strip_name_changed (void *src, MixerStrip *);
+
+ static GdkPixmap *check_pixmap;
+ static GdkBitmap *check_mask;
+ static GdkPixmap *empty_pixmap;
+ static GdkBitmap *empty_mask;
+
+ void group_flags_changed (void *src, ARDOUR::RouteGroup *);
+
+ /* snapshots */
+
+ Gtk::CList snapshot_display;
+ Gtk::ScrolledWindow snapshot_display_scroller;
+
+ void redisplay_snapshots();
+ void session_state_saved (string);
+
+ gint strip_button_release_event (GdkEventButton*, MixerStrip*);
+
+ RouteRedirectSelection _selection;
+
+ Width _strip_width;
+
+ static const int32_t default_width = -1;
+ static const int32_t default_height = 765;
+};
+
+#endif /* __ardour_mixer_ui_h__ */
+
+
diff --git a/gtk2_ardour/new_session_dialog.cc b/gtk2_ardour/new_session_dialog.cc
new file mode 100644
index 0000000000..2d3888c731
--- /dev/null
+++ b/gtk2_ardour/new_session_dialog.cc
@@ -0,0 +1,342 @@
+/*
+ Copyright (C) 1999-2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <list>
+#include <string>
+#include <ardour/session.h>
+#include <ardour/audioengine.h>
+
+#include "prompter.h"
+#include "new_session_dialog.h"
+
+using namespace Gtkmmext;
+using namespace Gtk;
+using namespace ARDOUR;
+
+#include "i18n.h"
+
+extern std::vector<string> channel_combo_strings;
+
+NewSessionDialog::NewSessionDialog (ARDOUR::AudioEngine& engine, bool startup, string given_path)
+ : ArdourDialog ("new session dialog"),
+ file_selector (_("Session name:"), _("Create")),
+ use_control_button (_("use control outs")),
+ use_master_button (_("use master outs")),
+ connect_to_physical_inputs_button (_("automatically connect track inputs to physical ports")),
+ connect_to_master_button (_("automatically connect track outputs to master outs")),
+ connect_to_physical_outputs_button (_("automatically connect track outputs to physical ports")),
+ manual_connect_outputs_button (_("manually connect track outputs")),
+ in_count_adjustment (2, 1, 1000, 1, 2),
+ out_count_adjustment (2, 1, 1000, 1, 2),
+ output_label (_("Output Connections")),
+ input_label (_("Input Connections")),
+ expansion_button (_("Advanced...")),
+ out_table (2, 2),
+ show_again (_("show again")),
+ in_count_spinner (in_count_adjustment),
+ out_count_spinner (out_count_adjustment),
+ in_count_label (_("Hardware Inputs: use")),
+ out_count_label (_("Hardware Outputs: use"))
+
+{
+ using namespace Notebook_Helpers;
+
+ set_name ("NewSessionDialog");
+ set_title (_("new session setup"));
+ set_wmclass (_("ardour_new_session"), "Ardour");
+ set_position (GTK_WIN_POS_MOUSE);
+ set_keyboard_input (true);
+ set_policy (false, true, false);
+ set_modal (true);
+
+ /* sample rate */
+
+ sr_label1.set_text (compose
+ (_("This session will playback and record at %1 Hz"),
+ engine.frame_rate()));
+ sr_label2.set_text (_("This rate is set by JACK and cannot be changed.\n"
+ "If you want to use a different sample rate\n"
+ "please exit and restart JACK"));
+ sr_box.set_spacing (12);
+ sr_box.set_border_width (12);
+ sr_box.pack_start (sr_label1, false, false);
+ sr_box.pack_start (sr_label2, false, false);
+ sr_frame.add (sr_box);
+
+ /* input */
+
+ connect_to_physical_inputs_button.set_active (true);
+ connect_to_physical_inputs_button.set_name ("NewSessionDialogButton");
+
+ HBox* input_limit_box = manage (new HBox);
+ input_limit_box->set_spacing (7);
+ input_limit_box->pack_start (in_count_label, false, false);
+ input_limit_box->pack_start (in_count_spinner, false, false);
+
+ input_label.set_alignment (0.1, 0.5);
+ input_vbox.pack_start (input_label, false, false, 7);
+ input_vbox.pack_start (connect_to_physical_inputs_button, false, false);
+
+ if (engine.n_physical_inputs() > 2) {
+ input_vbox.pack_start (*input_limit_box, false, false);
+ }
+
+ /* output */
+
+ use_master_button.set_active (true);
+ use_master_button.set_name ("NewSessionDialogButton");
+
+ connect_to_physical_outputs_button.set_group (connect_to_master_button.group());
+ manual_connect_outputs_button.set_group (connect_to_master_button.group());
+ connect_to_master_button.set_active (true);
+
+ connect_to_physical_outputs_button.set_name ("NewSessionDialogButton");
+ manual_connect_outputs_button.set_name ("NewSessionDialogButton");
+ connect_to_master_button.set_name ("NewSessionDialogButton");
+ use_control_button.set_name ("NewSessionDialogButton");
+
+ out_count_adjustment.set_value (engine.n_physical_outputs());
+ in_count_adjustment.set_value (engine.n_physical_inputs());
+
+ control_out_channel_combo.set_popdown_strings (channel_combo_strings);
+ control_out_channel_combo.set_name (X_("NewSessionChannelCombo"));
+ control_out_channel_combo.get_entry()->set_name (X_("NewSessionChannelCombo"));
+ control_out_channel_combo.get_popwin()->set_name (X_("NewSessionChannelCombo"));
+ // use stereo as default
+ control_out_channel_combo.get_list()->select_item (1);
+
+ master_out_channel_combo.set_popdown_strings (channel_combo_strings);
+ master_out_channel_combo.set_name (X_("NewSessionChannelCombo"));
+ master_out_channel_combo.get_entry()->set_name (X_("NewSessionChannelCombo"));
+ master_out_channel_combo.get_popwin()->set_name (X_("NewSessionChannelCombo"));
+ // use stereo as default
+ master_out_channel_combo.get_list()->select_item (1);
+
+
+ out_table.set_col_spacings (7);
+ out_table.set_row_spacings (7);
+ if (engine.n_physical_outputs() > 2) {
+ out_table.attach (out_count_label, 0, 1, 0, 1, 0, 0);
+ out_table.attach (out_count_spinner, 1, 2, 0, 1, 0, 0);
+ }
+ out_table.attach (use_control_button, 0, 1, 1, 2, 0, 0);
+ out_table.attach (control_out_channel_combo, 1, 2, 1, 2, 0, 0);
+ out_table.attach (use_master_button, 0, 1, 2, 3, 0, 0);
+ out_table.attach (master_out_channel_combo, 1, 2, 2, 3, 0, 0);
+
+ output_label.set_alignment (0.1, 0.5);
+ output_vbox.pack_start (output_label, true, true, 7);
+ output_vbox.pack_start (out_table, false, false, 5);
+ output_vbox.pack_start (connect_to_master_button, false);
+ output_vbox.pack_start (connect_to_physical_outputs_button, false);
+ output_vbox.pack_start (manual_connect_outputs_button, false);
+
+ input_hbox.pack_start (input_vbox, false, false);
+ output_hbox.pack_start (output_vbox, false, false);
+
+ VBox* template_vbox = manage (new VBox);
+ Label* template_label = manage (new Label (_("Session template")));
+
+ template_label->set_alignment (0.1, 0.5);
+ template_vbox->pack_start (*template_label, true, true, 7);
+ template_vbox->pack_start (template_combo, false, false);
+
+ io_box.set_border_width (12);
+ io_box.set_spacing (7);
+ io_box.pack_start (*template_vbox);
+
+ io_box.pack_start (input_hbox);
+ io_box.pack_start (output_hbox);
+
+ reset_templates();
+
+ option_hbox.set_spacing (7);
+ option_hbox.pack_start (io_box);
+
+ fsbox.set_border_width (12);
+ fsbox.set_spacing (7);
+ fsbox.pack_start (file_selector.table, false, false);
+
+ notebook.pages().push_back (TabElem (fsbox, _("Location")));
+ notebook.pages().push_back (TabElem (option_hbox, _("Configuration")));
+
+ if (startup) {
+ show_again.set_active(true);
+ show_again.toggled.connect (slot (*this, &NewSessionDialog::show_again_toggled));
+ file_selector.button_box.pack_end(show_again, false, false);
+ }
+
+ main_vbox.set_border_width (12);
+ main_vbox.set_border_width (12);
+ main_vbox.set_spacing (7);
+ main_vbox.pack_start (sr_frame, false, false);
+ main_vbox.pack_start (notebook, false, false);
+ main_vbox.pack_start (file_selector.button_box, false, false);
+
+ add (main_vbox);
+
+// template_selector.shift_made.connect (
+// slot (*this, &NewSessionDialog::mix_template_shift));
+// template_selector.control_made.connect (
+// slot (*this, &NewSessionDialog::mix_template_control));
+
+ file_selector.cancel_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), -1));
+ file_selector.op_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 0));
+ file_selector.Expanded.connect (slot (*this, &NewSessionDialog::file_selector_expansion));
+
+ delete_event.connect (slot (*this, &ArdourDialog::wm_close_event));
+ show.connect (slot (*this, &NewSessionDialog::fixup_at_show));
+
+ file_selector.entry_label.set_name ("NewSessionMainLabel");
+ file_selector.where_label.set_name ("NewSessionMainLabel");
+ template_label->set_name ("NewSessionIOLabel");
+ input_label.set_name ("NewSessionIOLabel");
+ output_label.set_name ("NewSessionIOLabel");
+ sr_label1.set_name ("NewSessionSR1Label");
+ sr_label2.set_name ("NewSessionSR2Label");
+
+ if (given_path.empty()) {
+ Session::FavoriteDirs favs;
+ Session::read_favorite_dirs (favs);
+ file_selector.set_favorites (favs);
+ } else {
+ file_selector.set_path (given_path, true);
+ notebook.set_page (-1);
+ notebook.show.connect (bind (slot (notebook, &Notebook::set_page), -1));
+ }
+
+ set_default_size(531, 358);
+}
+
+void
+NewSessionDialog::file_selector_expansion (bool expanded)
+{
+ if (expanded) {
+ fsbox.pack_start (file_selector.expansion_vbox);
+ fsbox.reorder_child (file_selector.expansion_vbox, 2);
+ } else {
+ fsbox.remove (file_selector.expansion_vbox);
+ }
+}
+
+void
+NewSessionDialog::fixup_at_show ()
+{
+// if (template_selector.clist().rows().size() == 0) {
+// use_template_button.set_sensitive (false);
+// }
+
+ Session::FavoriteDirs favs;
+ Session::read_favorite_dirs (favs);
+ file_selector.set_favorites (favs);
+
+ file_selector.entry.grab_focus ();
+}
+
+void
+NewSessionDialog::_mix_template_refiller (CList &clist, void *arg)
+
+{
+ ((NewSessionDialog*) arg)->mix_template_refiller (clist);
+}
+
+void
+NewSessionDialog::mix_template_refiller (CList &clist)
+{
+ const gchar *rowdata[2];
+ list<string> templates;
+ list<string>::iterator i;
+
+ Session::get_template_list(templates);
+
+ rowdata[0] = _("blank");
+ clist.insert_row (0, rowdata);
+
+ guint row;
+ for (row=1, i=templates.begin(); i != templates.end(); ++row, ++i) {
+ rowdata[0] = (*i).c_str();
+ clist.insert_row (row, rowdata);
+ }
+}
+
+void
+NewSessionDialog::mix_template_shift (Gtkmmext::Selector* selector, Gtkmmext::SelectionResult* res)
+{
+ if (res && res->text){
+ Session::delete_template(*res->text);
+ // template_selector.rescan();
+ }
+}
+
+void
+NewSessionDialog::mix_template_control (Gtkmmext::Selector* selector, Gtkmmext::SelectionResult* res)
+{
+#if 0
+ if (res && res->text) {
+ ArdourPrompter prompter (true);
+ prompter.set_prompt(_("Name for mix template:"));
+
+ string old_name = *(res->text);
+ prompter.set_initial_text (old_name);
+ prompter.done.connect (Gtk::Main::quit.slot());
+ prompter.show_all();
+
+ Gtk::Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+
+ prompter.get_result (name);
+
+ if (name.length() && name != old_name) {
+ Session::rename_template(old_name, name);
+ template_selector.rescan();
+ }
+ }
+ }
+#endif
+}
+
+void
+NewSessionDialog::show_again_toggled ()
+{
+ Config->set_no_new_session_dialog(!show_again.get_active());
+ Config->save_state();
+}
+
+void
+NewSessionDialog::reset_templates ()
+{
+ templates.clear ();
+ templates.push_back (_("No template - create tracks/busses manually"));
+ Session::get_template_list (templates);
+ template_combo.set_popdown_strings (templates);
+}
+
+string
+NewSessionDialog::get_template_name()
+{
+ string str = template_combo.get_entry()->get_text();
+ if (str.substr (0, 11) == _("No template")) {
+ return "";
+ } else {
+ return str;
+ }
+}
diff --git a/gtk2_ardour/new_session_dialog.h b/gtk2_ardour/new_session_dialog.h
new file mode 100644
index 0000000000..c253861ef6
--- /dev/null
+++ b/gtk2_ardour/new_session_dialog.h
@@ -0,0 +1,98 @@
+#ifndef __gtk_ardour_new_session_dialog_h__
+#define __gtk_ardour_new_session_dialog_h__
+
+#include <gtk--/adjustment.h>
+#include <gtk--/radiobutton.h>
+#include <gtk--/frame.h>
+#include <gtk--/box.h>
+#include <gtk--/checkbutton.h>
+
+namespace Gtk {
+ class CList;
+}
+
+namespace ARDOUR {
+ class AudioEngine;
+}
+
+#include <gtkmmext/click_box.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/newsavedialog.h>
+#include "ardour_dialog.h"
+
+class NewSessionDialog : public ArdourDialog
+{
+ public:
+ NewSessionDialog (ARDOUR::AudioEngine&, bool startup, std::string path);
+
+ Gtkmmext::NewSaveDialog file_selector;
+ Gtk::Combo control_out_channel_combo;
+ Gtk::Combo master_out_channel_combo;
+ Gtk::CheckButton use_control_button;
+ Gtk::CheckButton use_master_button;
+ Gtk::CheckButton connect_to_physical_inputs_button;
+
+ Gtk::RadioButton connect_to_master_button;
+ Gtk::RadioButton connect_to_physical_outputs_button;
+ Gtk::RadioButton manual_connect_outputs_button;
+
+ Gtk::VBox input_vbox;
+ Gtk::VBox manual_vbox;
+ Gtk::VBox output_vbox;
+ Gtk::VBox vbox;
+
+ Gtk::Adjustment in_count_adjustment;
+ Gtk::Adjustment out_count_adjustment;
+
+ string get_template_name ();
+
+ private:
+ Gtk::Notebook notebook;
+ Gtk::VBox main_vbox;
+ Gtk::VBox fsbox;
+
+ Gtk::Frame control_out_config_frame;
+ Gtk::Frame master_out_config_frame;
+ Gtk::Label output_label;
+ Gtk::Label input_label;
+ Gtk::Frame sr_frame;
+ Gtk::Frame template_frame;
+ Gtk::Frame manual_frame;
+ Gtk::HBox control_hbox;
+ Gtk::HBox master_hbox;
+ Gtk::Table io_table;
+ Gtk::VBox template_box;
+ Gtk::HBox output_hbox;
+ Gtk::HBox input_hbox;
+ Gtk::HBox option_hbox;
+ Gtk::VBox io_box;
+ Gtk::Label sr_label2;
+ Gtk::Label sr_label1;
+ Gtk::VBox sr_box;
+ Gtk::Button expansion_button;
+ Gtk::Table out_table;
+ Gtk::CheckButton show_again;
+ Gtk::Combo template_combo;
+ list<string> templates;
+ Gtk::SpinButton in_count_spinner;
+ Gtk::SpinButton out_count_spinner;
+ Gtk::Label in_count_label;
+ Gtk::Label out_count_label;
+
+ void reset_templates ();
+
+ static void _mix_template_refiller (Gtk::CList &clist, void *);
+ void mix_template_refiller (Gtk::CList &clist);
+
+ void mix_template_shift (Gtkmmext::Selector *, Gtkmmext::SelectionResult*);
+ void mix_template_control (Gtkmmext::Selector *, Gtkmmext::SelectionResult*);
+
+ void fixup_at_realize ();
+ void fixup_at_show ();
+ void toggle_expansion ();
+ void file_selector_expansion (bool);
+
+ void show_again_toggled ();
+};
+
+#endif // __gtk_ardour_new_session_dialog_h__ */
diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc
new file mode 100644
index 0000000000..fba414ebc8
--- /dev/null
+++ b/gtk2_ardour/option_editor.cc
@@ -0,0 +1,2051 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/session.h>
+#include <ardour/audioengine.h>
+#include <ardour/configuration.h>
+#include <ardour/auditioner.h>
+#include <ardour/crossfade.h>
+#include <midi++/manager.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/utils.h>
+
+#include "public_editor.h"
+#include "mixer_ui.h"
+#include "ardour_ui.h"
+#include "io_selector.h"
+#include "gain_meter.h"
+#include "library_ui.h"
+#include "utils.h"
+#include "editing.h"
+#include "option_editor.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Editing;
+using namespace Gtkmmext;
+
+static const gchar *psync_strings[] = {
+ N_("Internal"),
+ N_("Slave to MTC"),
+ N_("Sync with JACK"),
+ N_("never used but stops crashes"),
+ 0
+};
+
+static const gchar *lmode_strings[] = {
+ N_("Later regions are higher"),
+ N_("Most recently added/moved/trimmed regions are higher"),
+ N_("Most recently added regions are higher"),
+ 0
+};
+
+static const gchar *xfl_strings[] = {
+ N_("Span entire region overlap"),
+ N_("Short fades at the start of the overlap"),
+ 0
+};
+
+static vector<string> positional_sync_strings;
+static vector<string> layer_mode_strings;
+static vector<string> xfade_model_strings;
+
+OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
+ : ArdourDialog ("option editor"),
+ ui (uip),
+ editor (ed),
+ mixer (mixui),
+
+ path_table (9, 2),
+
+ /* Fades */
+
+ auto_xfade_button (_("Automatically create crossfades")),
+ xfade_active_button (_("New full-overlap crossfades are unmuted")),
+ layer_mode_label (_("Region layering mode")),
+ xfade_model_label (_("Crossfade model")),
+ short_xfade_adjustment (0, 1.0, 500.0, 5.0, 100.0),
+ short_xfade_slider (short_xfade_adjustment),
+
+ /* solo */
+ solo_latched_button (_("Latched solo")),
+ solo_via_bus_button (_("Solo via bus")),
+
+ /* display */
+
+ show_waveforms_button (_("Show waveforms")),
+ show_waveforms_recording_button (_("Show waveforms while recording")),
+ mixer_strip_width_button (_("Narrow mixer strips")),
+ show_measures_button (_("Show measure lines")),
+ follow_playhead_button (_("Follow playhead")),
+
+ /* Sync */
+
+ send_mtc_button (_("Send MTC")),
+ send_mmc_button (_("Send MMC")),
+ jack_time_master_button (_("JACK time master")),
+ smpte_offset_clock (X_("SMPTEOffsetClock"), true, true),
+ smpte_offset_negative_button (_("SMPTE offset is negative")),
+
+ /* MIDI */
+
+ midi_feedback_button (_("Send MIDI parameter feedback")),
+ midi_control_button (_("MIDI parameter control")),
+ mmc_control_button (_("MMC control")),
+
+ /* Click */
+
+ click_table (2, 3),
+ click_browse_button (_("Browse")),
+ click_emphasis_browse_button (_("Browse")),
+
+ /* kbd/mouse */
+
+ keyboard_mouse_table (3, 4),
+ delete_button_adjustment (3, 1, 5),
+ delete_button_spin (delete_button_adjustment),
+ edit_button_adjustment (3, 1, 5),
+ edit_button_spin (edit_button_adjustment),
+
+ /* Misc */
+
+ auto_connect_inputs_button (_("Auto-connect new track inputs to hardware")),
+ auto_connect_output_physical_button (_("Auto-connect new track outputs to hardware")),
+ auto_connect_output_master_button (_("Auto-connect new track outputs to master bus")),
+ auto_connect_output_manual_button (_("Manually connect new track outputs")),
+ hw_monitor_button(_("Use Hardware Monitoring")),
+ sw_monitor_button(_("Use Software Monitoring")),
+ plugins_stop_button (_("Stop plugins with transport")),
+ plugins_on_rec_button (_("Run plugins while recording")),
+ verify_remove_last_capture_button (_("Verify remove last capture")),
+ stop_rec_on_xrun_button (_("Stop recording on xrun")),
+ stop_at_end_button (_("Stop transport at end of session")),
+ debug_keyboard_button (_("Debug keyboard events")),
+ speed_quieten_button (_("-12dB gain reduction for ffwd/rew"))
+
+{
+ using namespace Notebook_Helpers;
+
+ click_io_selector = 0;
+ auditioner_io_selector = 0;
+
+ set_default_size (300, 300);
+ set_title (_("ardour: options editor"));
+ set_wmclass (_("ardour_option_editor"), "Ardour");
+
+ set_name ("OptionsWindow");
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ layer_mode_label.set_name ("OptionsLabel");
+ xfade_model_label.set_name ("OptionsLabel");
+
+ VBox *vbox = manage(new VBox);
+ add (*vbox);
+ set_border_width (3);
+
+ vbox->set_spacing (4);
+ vbox->pack_start(notebook);
+
+ delete_event.connect (slot (*this, &OptionEditor::wm_close));
+
+ notebook.set_show_tabs (true);
+ notebook.set_show_border (true);
+ notebook.set_name ("OptionsNotebook");
+
+ setup_sync_options();
+ setup_path_options();
+ setup_fade_options ();
+ setup_solo_options ();
+ setup_display_options ();
+ setup_misc_options ();
+ setup_keyboard_options ();
+ setup_auditioner_editor ();
+
+ notebook.pages().push_back (TabElem (misc_packer, _("Misc")));
+ notebook.pages().push_back (TabElem (sync_packer, _("Sync")));
+ notebook.pages().push_back (TabElem (path_table, _("Paths/Files")));
+ notebook.pages().push_back (TabElem (display_packer, _("Display")));
+ notebook.pages().push_back (TabElem (keyboard_mouse_table, _("Kbd/Mouse")));
+ notebook.pages().push_back (TabElem (click_packer, _("Click")));
+ notebook.pages().push_back (TabElem (audition_packer, _("Audition")));
+ notebook.pages().push_back (TabElem (fade_packer, _("Layers & Fades")));
+ notebook.pages().push_back (TabElem (solo_packer, _("Solo")));
+
+ if (!MIDI::Manager::instance()->get_midi_ports().empty()) {
+ setup_midi_options ();
+ notebook.pages().push_back (TabElem (midi_packer, _("MIDI")));
+ }
+
+ set_session (0);
+}
+
+void
+OptionEditor::set_session (Session *s)
+{
+ clear_click_editor ();
+ clear_auditioner_editor ();
+
+ click_path_entry.set_text ("");
+ click_emphasis_path_entry.set_text ("");
+ session_raid_entry.set_text ("");
+
+ send_mtc_button.set_sensitive (false);
+ send_mmc_button.set_sensitive (false);
+ midi_feedback_button.set_sensitive (false);
+ midi_control_button.set_sensitive (false);
+ mmc_control_button.set_sensitive (false);
+ click_path_entry.set_sensitive (false);
+ click_emphasis_path_entry.set_sensitive (false);
+ session_raid_entry.set_sensitive (false);
+ plugins_on_rec_button.set_sensitive (false);
+ verify_remove_last_capture_button.set_sensitive (false);
+ slave_type_combo.set_sensitive (false);
+ solo_latched_button.set_sensitive (false);
+ solo_via_bus_button.set_sensitive (false);
+ smpte_fps_combo.set_sensitive (false);
+ meter_hold_combo.set_sensitive (false);
+ meter_falloff_combo.set_sensitive (false);
+ auto_connect_inputs_button.set_sensitive (false);
+ auto_connect_output_physical_button.set_sensitive (false);
+ auto_connect_output_master_button.set_sensitive (false);
+ auto_connect_output_manual_button.set_sensitive (false);
+ layer_mode_combo.set_sensitive (false);
+ short_xfade_slider.set_sensitive (false);
+ smpte_offset_negative_button.set_sensitive (false);
+
+ smpte_offset_clock.set_session (s);
+
+ if ((session = s) == 0) {
+ return;
+ }
+
+ send_mtc_button.set_sensitive (true);
+ send_mmc_button.set_sensitive (true);
+ midi_feedback_button.set_sensitive (true);
+ midi_control_button.set_sensitive (true);
+ mmc_control_button.set_sensitive (true);
+ click_path_entry.set_sensitive (true);
+ click_emphasis_path_entry.set_sensitive (true);
+ session_raid_entry.set_sensitive (true);
+ plugins_on_rec_button.set_sensitive (true);
+ verify_remove_last_capture_button.set_sensitive (true);
+ slave_type_combo.set_sensitive (true);
+ solo_latched_button.set_sensitive (true);
+ solo_via_bus_button.set_sensitive (true);
+ smpte_fps_combo.set_sensitive (true);
+ meter_hold_combo.set_sensitive (true);
+ meter_falloff_combo.set_sensitive (true);
+ auto_connect_inputs_button.set_sensitive (true);
+ auto_connect_output_physical_button.set_sensitive (true);
+ auto_connect_output_master_button.set_sensitive (true);
+ auto_connect_output_manual_button.set_sensitive (true);
+ layer_mode_combo.set_sensitive (true);
+ short_xfade_slider.set_sensitive (true);
+ smpte_offset_negative_button.set_sensitive (true);
+
+ if (!s->smpte_drop_frames) {
+ // non-drop frames
+ if (s->smpte_frames_per_second == 24.0)
+ smpte_fps_combo.get_entry ()->set_text (_("24 FPS"));
+ else if (s->smpte_frames_per_second == 25.0)
+ smpte_fps_combo.get_entry ()->set_text (_("25 FPS"));
+ else if (s->smpte_frames_per_second == 30.0)
+ smpte_fps_combo.get_entry ()->set_text (_("30 FPS"));
+ else
+ smpte_fps_combo.get_entry ()->set_text (_("???"));
+ } else {
+ // drop frames
+ if (floor(s->smpte_frames_per_second) == 29.0)
+ smpte_fps_combo.get_entry ()->set_text (_("30 FPS drop"));
+ else
+ smpte_fps_combo.get_entry ()->set_text (_("???"));
+ }
+
+ smpte_offset_clock.set_session (s);
+ smpte_offset_clock.set (s->smpte_offset (), true);
+
+ smpte_offset_negative_button.set_active (session->smpte_offset_negative());
+ send_mtc_button.set_active (session->get_send_mtc());
+
+ /* MIDI I/O */
+
+ send_mmc_button.set_active (session->get_send_mmc());
+ midi_control_button.set_active (session->get_midi_control());
+ midi_feedback_button.set_active (session->get_midi_feedback());
+ mmc_control_button.set_active (session->get_mmc_control());
+
+ /* set up port assignments */
+
+ map<MIDI::Port*,vector<RadioButton*> >::iterator res;
+
+ if (session->mtc_port()) {
+ if ((res = port_toggle_buttons.find (session->mtc_port())) != port_toggle_buttons.end()) {
+ (*res).second[MtcIndex]->set_active (true);
+ }
+ }
+
+ if (session->mmc_port ()) {
+ if ((res = port_toggle_buttons.find (session->mmc_port())) != port_toggle_buttons.end()) {
+ (*res).second[MmcIndex]->set_active (true);
+ }
+ }
+
+ if (session->midi_port()) {
+ if ((res = port_toggle_buttons.find (session->midi_port())) != port_toggle_buttons.end()) {
+ (*res).second[MidiIndex]->set_active (true);
+ }
+ }
+
+ auto_connect_inputs_button.set_active (session->get_input_auto_connect());
+
+ Session::AutoConnectOption oac = session->get_output_auto_connect();
+ if (oac & Session::AutoConnectPhysical) {
+ auto_connect_output_physical_button.set_active (true);
+ } else if (oac & Session::AutoConnectMaster) {
+ auto_connect_output_master_button.set_active (true);
+ } else {
+ auto_connect_output_manual_button.set_active (true);
+ }
+
+ setup_click_editor ();
+ connect_audition_editor ();
+
+ plugins_on_rec_button.set_active (session->get_recording_plugins ());
+ verify_remove_last_capture_button.set_active (Config->get_verify_remove_last_capture());
+
+ layer_mode_combo.get_entry()->set_text (layer_mode_strings[session->get_layer_model()]);
+ xfade_model_combo.get_entry()->set_text (xfade_model_strings[session->get_xfade_model()]);
+
+ short_xfade_adjustment.set_value ((Crossfade::short_xfade_length() / (float) session->frame_rate()) * 1000.0);
+
+ xfade_active_button.set_active (session->get_crossfades_active());
+ solo_latched_button.set_active (session->solo_latched());
+ solo_via_bus_button.set_active (session->solo_model() == Session::SoloBus);
+
+ add_session_paths ();
+
+ vector<string> dumb;
+ dumb.push_back (positional_sync_strings[Session::None]);
+ dumb.push_back (positional_sync_strings[Session::JACK]);
+ if (session->mtc_port()) {
+ dumb.push_back (positional_sync_strings[Session::MTC]);
+ }
+ slave_type_combo.set_popdown_strings (dumb);
+
+ // meter stuff
+ if (session->meter_falloff() == 0.0f) {
+ meter_falloff_combo.get_entry ()->set_text (_("Off"));
+ } else if (session->meter_falloff() <= 0.3f) {
+ meter_falloff_combo.get_entry ()->set_text (_("Slowest"));
+ } else if (session->meter_falloff() <= 0.4f) {
+ meter_falloff_combo.get_entry ()->set_text (_("Slow"));
+ } else if (session->meter_falloff() <= 0.8f) {
+ meter_falloff_combo.get_entry ()->set_text (_("Medium"));
+ } else if (session->meter_falloff() <= 1.4f) {
+ meter_falloff_combo.get_entry ()->set_text (_("Fast"));
+ } else if (session->meter_falloff() <= 2.0f) {
+ meter_falloff_combo.get_entry ()->set_text (_("Faster"));
+ } else {
+ meter_falloff_combo.get_entry ()->set_text (_("Fastest"));
+ }
+
+ switch ((int) floor (session->meter_hold())) {
+ case 0:
+ meter_hold_combo.get_entry ()->set_text (_("Off"));
+ break;
+ case 40:
+ meter_hold_combo.get_entry ()->set_text (_("Short"));
+ break;
+ case 100:
+ meter_hold_combo.get_entry ()->set_text (_("Medium"));
+ break;
+ case 200:
+ meter_hold_combo.get_entry ()->set_text (_("Long"));
+ break;
+ }
+
+ session_control_changed (Session::SlaveType);
+ session_control_changed (Session::AlignChoice);
+ session->ControlChanged.connect (slot (*this, &OptionEditor::queue_session_control_changed));
+}
+
+OptionEditor::~OptionEditor ()
+{
+}
+
+static const gchar *native_format_strings[] = {
+ N_("Broadcast WAVE/floating point"),
+ N_("WAVE/floating point"),
+ 0
+};
+
+void
+OptionEditor::setup_path_options()
+{
+ Gtk::Label* label;
+
+ path_table.set_homogeneous (true);
+ path_table.set_border_width (12);
+ path_table.set_row_spacings (5);
+
+ session_raid_entry.set_name ("OptionsEntry");
+
+ session_raid_entry.activate.connect (slot (*this, &OptionEditor::raid_path_changed));
+
+ session_raid_entry.focus_in_event.connect (slot (Keyboard::the_keyboard(), &Keyboard::focus_in_handler));
+ session_raid_entry.focus_out_event.connect (bind (slot (*this, &OptionEditor::focus_out_event_handler), &OptionEditor::raid_path_changed));
+
+ label = manage(new Label(_("session RAID path")));
+ label->set_name ("OptionsLabel");
+ path_table.attach (*label, 0, 1, 0, 1, 0, 0);
+ path_table.attach (session_raid_entry, 1, 3, 0, 1, GTK_FILL|GTK_EXPAND, 0);
+
+ label = manage(new Label(_("Native Format")));
+ label->set_name ("OptionsLabel");
+ path_table.attach (*label, 0, 1, 1, 2, 0, 0);
+ path_table.attach (native_format_combo, 1, 3, 1, 2, GTK_FILL|GTK_EXPAND, 0);
+
+ vector<string> nfstrings = internationalize (native_format_strings);
+
+ native_format_combo.set_popdown_strings (nfstrings),
+ native_format_combo.get_entry()->set_editable (false);
+ native_format_combo.get_entry()->set_name ("OptionsEntry");
+ native_format_combo.set_use_arrows_always (true);
+ native_format_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::native_format_chosen));
+
+ fixup_combo_size (native_format_combo, nfstrings);
+
+ if (Config->get_native_format_is_bwf()) {
+ native_format_combo.get_entry()->set_text (native_format_strings[0]);
+ } else {
+ native_format_combo.get_entry()->set_text (native_format_strings[1]);
+ }
+
+ path_table.show_all();
+}
+
+void
+OptionEditor::add_session_paths ()
+{
+ click_path_entry.set_sensitive (true);
+ click_emphasis_path_entry.set_sensitive (true);
+ session_raid_entry.set_sensitive (true);
+
+ if (session->click_sound.length() == 0) {
+ click_path_entry.set_text (_("internal"));
+ } else {
+ click_path_entry.set_text (session->click_sound);
+ }
+
+ if (session->click_emphasis_sound.length() == 0) {
+ click_emphasis_path_entry.set_text (_("internal"));
+ } else {
+ click_emphasis_path_entry.set_text (session->click_emphasis_sound);
+ }
+
+ session_raid_entry.set_text(session->raid_path());
+}
+
+void
+OptionEditor::setup_fade_options ()
+{
+ Gtk::HBox* hbox;
+ vector<string> dumb;
+
+ auto_xfade_button.set_name ("OptionEditorToggleButton");
+ xfade_active_button.set_name ("OptionEditorToggleButton");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (12);
+ hbox->pack_start (auto_xfade_button, false, false);
+ fade_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (12);
+ hbox->pack_start (xfade_active_button, false, false);
+ fade_packer.pack_start (*hbox, false, false);
+
+ layer_mode_strings = internationalize (lmode_strings);
+
+ dumb.push_back (lmode_strings[Session::LaterHigher]);
+ dumb.push_back (lmode_strings[Session::MoveAddHigher]);
+ dumb.push_back (lmode_strings[Session::AddHigher]);
+ layer_mode_combo.set_popdown_strings (dumb);
+
+ layer_mode_combo.set_use_arrows_always (true);
+ layer_mode_combo.set_value_in_list (true, false);
+ layer_mode_combo.get_entry()->set_editable (false);
+ layer_mode_combo.get_entry()->set_name ("OptionsEntry");
+ layer_mode_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::layer_mode_chosen));
+
+ fixup_combo_size (layer_mode_combo, layer_mode_strings);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (layer_mode_label, false, false);
+ hbox->pack_start (layer_mode_combo, false, false);
+ fade_packer.pack_start (*hbox, false, false);
+
+ xfade_model_strings = internationalize (xfl_strings);
+
+ dumb.clear ();
+ dumb.push_back (xfade_model_strings[FullCrossfade]);
+ dumb.push_back (xfade_model_strings[ShortCrossfade]);
+ xfade_model_combo.set_popdown_strings (dumb);
+
+ xfade_model_combo.set_use_arrows_always (true);
+ xfade_model_combo.set_value_in_list (true, false);
+ xfade_model_combo.get_entry()->set_editable (false);
+ xfade_model_combo.get_entry()->set_name ("OptionsEntry");
+ xfade_model_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::xfade_model_chosen));
+
+ fixup_combo_size (xfade_model_combo, xfade_model_strings);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (xfade_model_label, false, false);
+ hbox->pack_start (xfade_model_combo, false, false);
+ fade_packer.pack_start (*hbox, false, false);
+
+ auto_xfade_button.set_active (Config->get_auto_xfade());
+ /* xfade and layer mode active requires session */
+
+ auto_xfade_button.clicked.connect (slot (*this, &OptionEditor::auto_xfade_clicked));
+ xfade_active_button.clicked.connect (slot (*this, &OptionEditor::xfade_active_clicked));
+
+ Label* short_xfade_label = manage (new Label (_("Short crossfade length (msecs)")));
+ short_xfade_label->set_name ("OptionsLabel");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (*short_xfade_label, false, false);
+ hbox->pack_start (short_xfade_slider, true, true);
+ fade_packer.pack_start (*hbox, false, false);
+
+ short_xfade_adjustment.value_changed.connect (slot (*this, &OptionEditor::short_xfade_adjustment_changed));
+
+ fade_packer.show_all ();
+}
+
+void
+OptionEditor::short_xfade_adjustment_changed ()
+{
+ if (session) {
+ float val = short_xfade_adjustment.get_value();
+
+ /* val is in msecs */
+
+ Crossfade::set_short_xfade_length ((jack_nframes_t) floor (session->frame_rate() * (val / 1000.0)));
+ }
+}
+
+gint
+OptionEditor::layer_mode_chosen (GdkEventAny* ev)
+{
+ if (!session) {
+ return FALSE;
+ }
+
+ string which = layer_mode_combo.get_entry()->get_text ();
+
+ if (which == layer_mode_strings[Session::LaterHigher]) {
+ session->set_layer_model (Session::LaterHigher);
+ } else if (which == layer_mode_strings[Session::MoveAddHigher]) {
+ session->set_layer_model (Session::MoveAddHigher);
+ } else if (which == layer_mode_strings[Session::AddHigher]) {
+ session->set_layer_model (Session::AddHigher);
+ }
+ return FALSE;
+}
+
+gint
+OptionEditor::xfade_model_chosen (GdkEventAny* ev)
+{
+ if (!session) {
+ return FALSE;
+ }
+
+ string which = xfade_model_combo.get_entry()->get_text ();
+
+ if (which == xfade_model_strings[FullCrossfade]) {
+ session->set_xfade_model (FullCrossfade);
+ } else if (which == xfade_model_strings[ShortCrossfade]) {
+ session->set_xfade_model (ShortCrossfade);
+ }
+ return FALSE;
+}
+
+void
+OptionEditor::auto_xfade_clicked ()
+{
+ Config->set_auto_xfade (auto_xfade_button.get_active());
+}
+
+void
+OptionEditor::xfade_active_clicked ()
+{
+ if (session) {
+ session->set_crossfades_active (xfade_active_button.get_active());
+ }
+}
+
+void
+OptionEditor::setup_solo_options ()
+{
+ Gtk::HBox* hbox;
+
+ solo_via_bus_button.set_name ("OptionEditorToggleButton");
+ solo_latched_button.set_name ("OptionEditorToggleButton");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (12);
+ hbox->pack_start (solo_via_bus_button, false, false);
+ solo_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (12);
+ hbox->pack_start (solo_latched_button, false, false);
+ solo_packer.pack_start (*hbox, false, false);
+
+ solo_via_bus_button.clicked.connect
+ (slot (*this, &OptionEditor::solo_via_bus_clicked));
+ solo_latched_button.clicked.connect
+ (slot (*this, &OptionEditor::solo_latched_clicked));
+
+ solo_packer.show_all ();
+}
+
+void
+OptionEditor::solo_via_bus_clicked ()
+{
+ if (!session) {
+ return;
+ }
+
+ if (solo_via_bus_button.get_active()) {
+ session->set_solo_model (Session::SoloBus);
+ } else {
+ session->set_solo_model (Session::InverseMute);
+ }
+}
+
+void
+OptionEditor::solo_latched_clicked ()
+{
+ if (!session) {
+ return;
+ }
+
+ bool x = solo_latched_button.get_active();
+
+ if (x != session->solo_latched()) {
+ session->set_solo_latched (x);
+ }
+}
+
+void
+OptionEditor::setup_display_options ()
+{
+ HBox* hbox;
+ vector<string> dumb;
+
+ display_packer.set_border_width (12);
+ display_packer.set_spacing (5);
+
+ show_waveforms_button.set_name ("OptionEditorToggleButton");
+ show_waveforms_recording_button.set_name ("OptionEditorToggleButton");
+ show_measures_button.set_name ("OptionEditorToggleButton");
+ follow_playhead_button.set_name ("OptionEditorToggleButton");
+ mixer_strip_width_button.set_name ("OptionEditorToggleButton");
+
+ mixer_strip_width_button.set_active (mixer.get_strip_width() == Narrow);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (8);
+ hbox->pack_start (show_waveforms_button, false, false);
+ display_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (8);
+ hbox->pack_start (show_waveforms_recording_button, false, false);
+ display_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (8);
+ hbox->pack_start (show_measures_button, false, false);
+ display_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (8);
+ hbox->pack_start (mixer_strip_width_button, false, false);
+ display_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (8);
+ hbox->pack_start (follow_playhead_button, false, false);
+ display_packer.pack_start (*hbox, false, false);
+
+ Label *meter_hold_label = manage (new Label (_("Meter Peak Hold")));
+ meter_hold_label->set_name ("OptionsLabel");
+ dumb.clear ();
+ dumb.push_back (_("Off"));
+ dumb.push_back (_("Short"));
+ dumb.push_back (_("Medium"));
+ dumb.push_back (_("Long"));
+ meter_hold_combo.set_popdown_strings (dumb);
+ meter_hold_combo.set_use_arrows_always (true);
+ meter_hold_combo.set_value_in_list (true, false);
+ meter_hold_combo.get_entry()->set_editable (false);
+ meter_hold_combo.get_entry()->set_name ("OptionsEntry");
+ meter_hold_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::meter_hold_chosen));
+ hbox = manage (new HBox);
+ hbox->set_border_width (8);
+ hbox->set_spacing (8);
+ hbox->pack_start (*meter_hold_label, false, false);
+ hbox->pack_start (meter_hold_combo, false, false);
+ display_packer.pack_start (*hbox, false, false);
+
+ Label *meter_falloff_label = manage (new Label (_("Meter Falloff")));
+ meter_falloff_label->set_name ("OptionsLabel");
+ dumb.clear ();
+ dumb.push_back (_("Off"));
+ dumb.push_back (_("Slowest"));
+ dumb.push_back (_("Slow"));
+ dumb.push_back (_("Medium"));
+ dumb.push_back (_("Fast"));
+ dumb.push_back (_("Faster"));
+ dumb.push_back (_("Fastest"));
+ meter_falloff_combo.set_popdown_strings (dumb);
+ meter_falloff_combo.set_use_arrows_always (true);
+ meter_falloff_combo.set_value_in_list (true, false);
+ meter_falloff_combo.get_entry()->set_editable (false);
+ meter_falloff_combo.get_entry()->set_name ("OptionsEntry");
+ meter_falloff_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::meter_falloff_chosen));
+ hbox = manage (new HBox);
+ hbox->set_border_width (8);
+ hbox->set_spacing (8);
+ hbox->pack_start (*meter_falloff_label, false, false);
+ hbox->pack_start (meter_falloff_combo, false, false);
+ display_packer.pack_start (*hbox, false, false);
+
+
+ show_waveforms_button.clicked.connect (slot (*this, &OptionEditor::show_waveforms_clicked));
+ show_waveforms_recording_button.clicked.connect (slot (*this, &OptionEditor::show_waveforms_recording_clicked));
+ show_measures_button.clicked.connect (slot (*this, &OptionEditor::show_measures_clicked));
+ mixer_strip_width_button.clicked.connect (slot (*this, &OptionEditor::strip_width_clicked));
+ follow_playhead_button.clicked.connect (slot (*this, &OptionEditor::follow_playhead_clicked));
+
+ editor.DisplayControlChanged.connect (slot (*this, &OptionEditor::display_control_changed));
+
+ show_measures_button.set_active (editor.show_measures());
+ show_waveforms_button.set_active (editor.show_waveforms());
+ show_waveforms_recording_button.set_active (editor.show_waveforms_recording());
+ follow_playhead_button.set_active (editor.follow_playhead());
+}
+
+gint
+OptionEditor::meter_hold_chosen (GdkEventAny* ev)
+{
+ if (session) {
+ string str = meter_hold_combo.get_entry()->get_text();
+
+ if (str == _("Off")) {
+ session->set_meter_hold (0);
+ } else if (str == _("Short")) {
+ session->set_meter_hold (40);
+ } else if (str == _("Medium")) {
+ session->set_meter_hold (100);
+ } else if (str == _("Long")) {
+ session->set_meter_hold (200);
+ }
+ }
+
+ return TRUE;
+}
+
+gint
+OptionEditor::meter_falloff_chosen (GdkEventAny* ev)
+{
+ if (session) {
+ string str = meter_falloff_combo.get_entry()->get_text();
+
+ if (str == _("Off")) {
+ session->set_meter_falloff (0.0f);
+ } else if (str == _("Slowest")) {
+ session->set_meter_falloff (0.266f); // 6.6 dB/sec falloff at update rate of 40 ms
+ } else if (str == _("Slow")) {
+ session->set_meter_falloff (0.342f); // 8.6 dB/sec falloff at update rate of 40 ms
+ } else if (str == _("Medium")) {
+ session->set_meter_falloff (0.7f);
+ } else if (str == _("Fast")) {
+ session->set_meter_falloff (1.1f);
+ } else if (str == _("Faster")) {
+ session->set_meter_falloff (1.5f);
+ } else if (str == _("Fastest")) {
+ session->set_meter_falloff (2.5f);
+ }
+ }
+
+ return TRUE;
+}
+
+void
+OptionEditor::display_control_changed (Editing::DisplayControl dc)
+{
+ ToggleButton* button = 0;
+ bool val = true;
+
+ switch (dc) {
+ case ShowMeasures:
+ val = editor.show_measures ();
+ button = &show_measures_button;
+ break;
+ case ShowWaveforms:
+ val = editor.show_waveforms ();
+ button = &show_waveforms_button;
+ break;
+ case ShowWaveformsRecording:
+ val = editor.show_waveforms_recording ();
+ button = &show_waveforms_recording_button;
+ break;
+ case FollowPlayhead:
+ val = editor.follow_playhead ();
+ button = &follow_playhead_button;
+ break;
+ }
+
+ if (button->get_active() != val) {
+ button->set_active (val);
+ }
+}
+
+void
+OptionEditor::setup_sync_options ()
+{
+ Label *slave_type_label = manage (new Label (_("Positional Sync")));
+ HBox* hbox;
+ vector<string> dumb;
+
+ slave_type_label->set_name("OptionsLabel");
+ positional_sync_strings = internationalize (psync_strings);
+
+ slave_type_combo.set_use_arrows_always (true);
+ slave_type_combo.set_value_in_list (true, false);
+ slave_type_combo.get_entry()->set_editable (false);
+ slave_type_combo.get_entry()->set_name ("OptionsEntry");
+ slave_type_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::slave_type_chosen));
+
+ dumb.clear ();
+ dumb.push_back (X_("24 FPS"));
+ dumb.push_back (X_("25 FPS"));
+ dumb.push_back (X_("30 FPS drop"));
+ dumb.push_back (X_("30 FPS non-drop"));
+
+ smpte_fps_combo.set_popdown_strings (dumb);
+ smpte_fps_combo.set_use_arrows_always (true);
+ smpte_fps_combo.set_value_in_list (true, false);
+ smpte_fps_combo.get_entry()->set_editable (false);
+ smpte_fps_combo.get_entry()->set_name ("OptionsEntry");
+ smpte_fps_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::smpte_fps_chosen));
+
+ smpte_offset_clock.set_mode (AudioClock::SMPTE);
+ smpte_offset_clock.ValueChanged.connect (slot (*this, &OptionEditor::smpte_offset_chosen));
+
+ send_mtc_button.set_name ("OptionEditorToggleButton");
+ jack_time_master_button.set_name ("OptionEditorToggleButton");
+ smpte_offset_negative_button.set_name ("OptionEditorToggleButton");
+
+ send_mtc_button.unset_flags (GTK_CAN_FOCUS);
+ jack_time_master_button.unset_flags (GTK_CAN_FOCUS);
+ smpte_offset_negative_button.unset_flags (GTK_CAN_FOCUS);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (*slave_type_label, false, false);
+ hbox->pack_start (slave_type_combo, false, false);
+
+ sync_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->pack_start (send_mtc_button, false, false);
+ sync_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->pack_start (jack_time_master_button, false, false);
+ sync_packer.pack_start (*hbox, false, false);
+
+ Label *smpte_fps_label = manage (new Label (_("SMPTE Frames/second")));
+ Label *smpte_offset_label = manage (new Label (_("SMPTE Offset")));
+ smpte_fps_label->set_name("OptionsLabel");
+ smpte_offset_label->set_name("OptionsLabel");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (*smpte_fps_label, false, false);
+ hbox->pack_start (smpte_fps_combo, false, false);
+
+ sync_packer.pack_start (*hbox, false, false);
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (*smpte_offset_label, false, false);
+ hbox->pack_start (smpte_offset_clock, false, false);
+ hbox->pack_start (smpte_offset_negative_button, false, false);
+
+ sync_packer.pack_start (*hbox, false, false);
+
+ jack_time_master_button.set_active (Config->get_jack_time_master());
+
+ send_mtc_button.button_press_event.connect (bind (slot (*this, &OptionEditor::send_mtc_toggled), &send_mtc_button));
+ jack_time_master_button.clicked.connect (slot (*this, &OptionEditor::jack_time_master_clicked));
+ smpte_offset_negative_button.clicked.connect (slot (*this, &OptionEditor::smpte_offset_negative_clicked));
+}
+
+void
+OptionEditor::smpte_offset_negative_clicked ()
+{
+ if (session) {
+ session->set_smpte_offset_negative (smpte_offset_negative_button.get_active());
+ }
+}
+
+gint
+OptionEditor::smpte_fps_chosen (GdkEventAny* ev)
+{
+ if (session) {
+ string str = smpte_fps_combo.get_entry()->get_text();
+
+ if (str == X_("24 FPS")) {
+ session->set_smpte_type (24.0, false);
+ } else if (str == X_("25 FPS")) {
+ session->set_smpte_type (25.0, false);
+ } else if (str == X_("30 FPS drop")) {
+ session->set_smpte_type (29.97, true);
+ } else if (str == X_("30 FPS non-drop")) {
+ session->set_smpte_type (30.0, false);
+ }
+ }
+
+ return TRUE;
+}
+
+void
+OptionEditor::smpte_offset_chosen()
+{
+ if (session) {
+ jack_nframes_t frames = smpte_offset_clock.current_duration();
+ session->set_smpte_offset (frames);
+ }
+}
+
+
+void
+OptionEditor::setup_midi_options ()
+{
+ HBox* hbox;
+ MIDI::Manager::PortMap::const_iterator i;
+ const MIDI::Manager::PortMap& ports = MIDI::Manager::instance()->get_midi_ports();
+ int n;
+ ToggleButton* tb;
+ RadioButton* rb;
+ RadioButton* first_mtc_button = 0;
+ RadioButton* first_mmc_button = 0;
+ RadioButton* first_midi_button = 0;
+
+ Gtk::Table* table = manage (new Table (ports.size() + 4, 9));
+
+ table->set_row_spacings (6);
+ table->set_col_spacings (10);
+
+ table->attach (*(manage (new Label (X_("Port")))), 0, 1, 0, 1);
+ table->attach (*(manage (new Label (X_("Offline")))), 1, 2, 0, 1);
+ table->attach (*(manage (new Label (X_("Trace\nInput")))), 2, 3, 0, 1);
+ table->attach (*(manage (new Label (X_("Trace\nOutput")))), 3, 4, 0, 1);
+ table->attach (*(manage (new Label (X_("MTC")))), 4, 5, 0, 1);
+ table->attach (*(manage (new Label (X_("MMC")))), 6, 7, 0, 1);
+ table->attach (*(manage (new Label (X_("MIDI Parameter\nControl")))), 8, 9, 0, 1);
+
+ table->attach (*(manage (new HSeparator())), 0, 9, 1, 2);
+ table->attach (*(manage (new VSeparator())), 5, 6, 0, 8);
+ table->attach (*(manage (new VSeparator())), 7, 8, 0, 8);
+
+ for (n = 0, i = ports.begin(); i != ports.end(); ++n, ++i) {
+
+ pair<MIDI::Port*,vector<RadioButton*> > newpair;
+
+ newpair.first = i->second;
+
+ table->attach (*(manage (new Label (i->first))), 0, 1, n+2, n+3, 0, 0);
+ tb = manage (new ToggleButton (_("online")));
+ tb->set_name ("OptionEditorToggleButton");
+
+ /* remember, we have to handle the i18n case where the relative
+ lengths of the strings in language N is different than in english.
+ */
+
+ if (strlen (_("offline")) > strlen (_("online"))) {
+ set_usize_to_display_given_text (*tb, _("offline"), 15, 12);
+ } else {
+ set_usize_to_display_given_text (*tb, _("online"), 15, 12);
+ }
+
+ tb->set_active (!(*i).second->input()->offline());
+ tb->button_press_event.connect (bind (slot (*this, &OptionEditor::port_online_toggled), (*i).second, tb));
+ (*i).second->input()->OfflineStatusChanged.connect (bind (slot (*this, &OptionEditor::map_port_online), (*i).second, tb));
+ table->attach (*tb, 1, 2, n+2, n+3, 0, 0);
+
+ tb = manage (new ToggleButton ());
+ tb->set_name ("OptionEditorToggleButton");
+ tb->button_press_event.connect (bind (slot (*this, &OptionEditor::port_trace_in_toggled), (*i).second, tb));
+ tb->set_usize (10, 10);
+ table->attach (*tb, 2, 3, n+2, n+3, 0, 0);
+
+ tb = manage (new ToggleButton ());
+ tb->set_name ("OptionEditorToggleButton");
+ tb->button_press_event.connect (bind (slot (*this, &OptionEditor::port_trace_out_toggled), (*i).second, tb));
+ tb->set_usize (10, 10);
+ table->attach (*tb, 3, 4, n+2, n+3, 0, 0);
+
+ rb = manage (new RadioButton ());
+ newpair.second.push_back (rb);
+ rb->set_name ("OptionEditorToggleButton");
+ if (n == 0) {
+ first_mtc_button = rb;
+ } else {
+ rb->set_group (first_mtc_button->group());
+ }
+ table->attach (*rb, 4, 5, n+2, n+3, 0, 0);
+ rb->button_press_event.connect (bind (slot (*this, &OptionEditor::mtc_port_chosen), (*i).second, rb));
+
+ if (Config->get_mtc_port_name() == i->first) {
+ rb->set_active (true);
+ }
+
+ rb = manage (new RadioButton ());
+ newpair.second.push_back (rb);
+ rb->set_name ("OptionEditorToggleButton");
+ if (n == 0) {
+ first_mmc_button = rb;
+ } else {
+ rb->set_group (first_mmc_button->group());
+ }
+ table->attach (*rb, 6, 7, n+2, n+3, 0, 0);
+ rb->button_press_event.connect (bind (slot (*this, &OptionEditor::mmc_port_chosen), (*i).second, rb));
+
+ if (Config->get_mmc_port_name() == i->first) {
+ rb->set_active (true);
+ }
+
+ rb = manage (new RadioButton ());
+ newpair.second.push_back (rb);
+ rb->set_name ("OptionEditorToggleButton");
+ if (n == 0) {
+ first_midi_button = rb;
+ } else {
+ rb->set_group (first_midi_button->group());
+ }
+ table->attach (*rb, 8, 9, n+2, n+3, 0, 0);
+ rb->button_press_event.connect (bind (slot (*this, &OptionEditor::midi_port_chosen), (*i).second, rb));
+
+ if (Config->get_midi_port_name() == i->first) {
+ rb->set_active (true);
+ }
+
+ port_toggle_buttons.insert (newpair);
+ }
+
+ table->show_all ();
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (6);
+ hbox->pack_start (*table, true, false);
+ midi_packer.pack_start (*hbox, false, false);
+
+ VBox* mmcbuttonbox = manage (new VBox);
+
+ mmc_control_button.set_name ("OptionEditorToggleButton");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (6);
+ hbox->pack_start (mmc_control_button, false, false, 36);
+ mmcbuttonbox->pack_start (*hbox, false, false);
+
+ midi_control_button.set_name ("OptionEditorToggleButton");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (6);
+ hbox->pack_start (midi_control_button, false, false, 36);
+ mmcbuttonbox->pack_start (*hbox, false, false);
+
+ send_mmc_button.set_name ("OptionEditorToggleButton");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (6);
+ hbox->pack_start (send_mmc_button, false, false, 36);
+ mmcbuttonbox->pack_start (*hbox, false, false);
+
+ midi_feedback_button.set_name ("OptionEditorToggleButton");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (6);
+ hbox->pack_start (midi_feedback_button, false, false, 36);
+ mmcbuttonbox->pack_start (*hbox, false, false);
+
+ midi_packer.pack_start (*mmcbuttonbox, false, false);
+
+ mmc_control_button.toggled.connect (bind (slot (*this, &OptionEditor::mmc_control_toggled), &mmc_control_button));
+ midi_control_button.toggled.connect (bind (slot (*this, &OptionEditor::midi_control_toggled), &midi_control_button));
+ send_mmc_button.toggled.connect (bind (slot (*this, &OptionEditor::send_mmc_toggled), &send_mmc_button));
+ midi_feedback_button.toggled.connect (bind (slot (*this, &OptionEditor::midi_feedback_toggled), &midi_feedback_button));
+}
+
+gint
+OptionEditor::mtc_port_chosen (GdkEventButton* ev, MIDI::Port *port, Gtk::RadioButton* rb)
+{
+ if (session) {
+ if (!rb->get_active()) {
+ if (port) {
+ session->set_mtc_port (port->name());
+ Config->set_mtc_port_name (port->name());
+ } else {
+ session->set_mtc_port ("");
+ }
+
+ /* update sync options to reflect MTC port availability */
+
+ vector<string> dumb;
+ dumb.push_back (positional_sync_strings[Session::None]);
+ dumb.push_back (positional_sync_strings[Session::JACK]);
+
+ if (session->mtc_port()) {
+ dumb.push_back (positional_sync_strings[Session::MTC]);
+ }
+ slave_type_combo.set_popdown_strings (dumb);
+
+ rb->set_active (true);
+ }
+ }
+
+ return stop_signal (*rb, "button_press_event");
+}
+
+gint
+OptionEditor::mmc_port_chosen (GdkEventButton* ev, MIDI::Port* port, Gtk::RadioButton* rb)
+{
+ if (session) {
+ if (!rb->get_active()) {
+ if (port) {
+ session->set_mmc_port (port->name());
+ Config->set_mtc_port_name (port->name());
+ } else {
+ session->set_mmc_port ("");
+ }
+ rb->set_active (true);
+ }
+ }
+ return stop_signal (*rb, "button_press_event");
+}
+
+gint
+OptionEditor::midi_port_chosen (GdkEventButton* ev, MIDI::Port* port, Gtk::RadioButton* rb)
+{
+ if (session) {
+ if (!rb->get_active()) {
+ if (port) {
+ session->set_midi_port (port->name());
+ Config->set_midi_port_name (port->name());
+ } else {
+ session->set_midi_port ("");
+ }
+ rb->set_active (true);
+ }
+ }
+ return stop_signal (*rb, "button_press_event");
+}
+
+gint
+OptionEditor::port_online_toggled (GdkEventButton* ev, MIDI::Port* port, ToggleButton* tb)
+{
+ bool wanted = tb->get_active(); /* it hasn't changed at this point */
+
+ if (wanted != port->input()->offline()) {
+ port->input()->set_offline (wanted);
+ }
+ return stop_signal (*tb, "button_press_event");
+}
+
+void
+OptionEditor::map_port_online (MIDI::Port* port, ToggleButton* tb)
+{
+ if (port->input()->offline()) {
+ static_cast<Label*>(tb->get_child())->set_text (_("offline"));
+ tb->set_active (false);
+ } else {
+ static_cast<Label*>(tb->get_child())->set_text (_("online"));
+ tb->set_active (true);
+ }
+}
+
+gint
+OptionEditor::port_trace_in_toggled (GdkEventButton* ev, MIDI::Port* port, ToggleButton* tb)
+{
+ /* XXX not very good MVC style here */
+
+ port->input()->trace (!tb->get_active(), &cerr, string (port->name()) + string (" input: "));
+ tb->set_active (!tb->get_active());
+ return stop_signal (*tb, "button_press_event");
+}
+
+gint
+OptionEditor::port_trace_out_toggled (GdkEventButton* ev,MIDI::Port* port, ToggleButton* tb)
+{
+ /* XXX not very good MVC style here */
+
+ port->output()->trace (!tb->get_active(), &cerr, string (port->name()) + string (" output: "));
+ tb->set_active (!tb->get_active());
+ return stop_signal (*tb, "button_press_event");
+}
+
+gint
+OptionEditor::send_mtc_toggled (GdkEventButton *ev, CheckButton *button)
+{
+ if (session) {
+ session->set_send_mtc (!button->get_active());
+ }
+ return stop_signal (*button, "button_press_event");
+}
+
+void
+OptionEditor::send_mmc_toggled (CheckButton *button)
+{
+ if (session) {
+ session->set_send_mmc (button->get_active());
+ }
+}
+
+void
+OptionEditor::mmc_control_toggled (CheckButton *button)
+{
+ if (session) {
+ session->set_mmc_control (button->get_active());
+ }
+}
+
+void
+OptionEditor::midi_control_toggled (CheckButton *button)
+{
+ if (session) {
+ session->set_midi_control (button->get_active());
+ }
+}
+
+void
+OptionEditor::midi_feedback_toggled (CheckButton *button)
+{
+ if (session) {
+ session->set_midi_feedback (button->get_active());
+ }
+}
+
+void
+OptionEditor::save ()
+{
+ /* XXX a bit odd that we save the entire session state here */
+
+ ui.save_state ("");
+}
+
+gint
+OptionEditor::wm_close (GdkEventAny *ev)
+{
+ save ();
+ just_close_win();
+ return TRUE;
+}
+
+void
+OptionEditor::jack_time_master_clicked ()
+{
+ bool yn = jack_time_master_button.get_active();
+
+ Config->set_jack_time_master (yn);
+
+ if (session) {
+ session->engine().reset_timebase ();
+ }
+}
+
+void
+OptionEditor::raid_path_changed ()
+{
+ if (session) {
+ session->set_raid_path (session_raid_entry.get_text());
+ }
+}
+
+void
+OptionEditor::click_browse_clicked ()
+{
+ SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window());
+ SigC::Connection c = sfdb.Action.connect (slot (*this, &OptionEditor::click_chosen));
+
+ sfdb.run (_("Use as click"), false, true);
+ c.disconnect ();
+}
+
+void
+OptionEditor::click_chosen (vector<string> paths, bool ignore)
+{
+ string path;
+
+ if (!paths.empty()) {
+ path = paths.front();
+ } else {
+ return;
+ }
+
+ click_path_entry.set_text (path);
+ click_sound_changed ();
+}
+
+void
+OptionEditor::click_emphasis_browse_clicked ()
+{
+ SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window());
+ SigC::Connection c = sfdb.Action.connect (slot (*this, &OptionEditor::click_emphasis_chosen));
+
+ sfdb.run (_("Use as click emphasis"), false, true);
+ c.disconnect ();
+
+}
+
+void
+OptionEditor::click_emphasis_chosen (vector<string> paths, bool ignore)
+{
+ string path;
+
+ if (!paths.empty()) {
+ path = paths.front();
+ } else {
+ return;
+ }
+
+ click_emphasis_path_entry.set_text (path);
+ click_emphasis_sound_changed ();
+}
+
+void
+OptionEditor::click_sound_changed ()
+{
+ if (session) {
+ string path = click_path_entry.get_text();
+
+ if (path == session->click_sound) {
+ return;
+ }
+
+ if (path.length() == 0) {
+
+ session->set_click_sound ("");
+
+ } else {
+
+ strip_whitespace_edges (path);
+
+ if (path == _("internal")) {
+ session->set_click_sound ("");
+ } else {
+ session->set_click_sound (path);
+ }
+ }
+ }
+}
+
+void
+OptionEditor::click_emphasis_sound_changed ()
+{
+ if (session) {
+ string path = click_emphasis_path_entry.get_text();
+
+ if (path == session->click_emphasis_sound) {
+ return;
+ }
+
+ if (path.length() == 0) {
+
+ session->set_click_emphasis_sound ("");
+
+ } else {
+
+ strip_whitespace_edges (path);
+
+ if (path == _("internal")) {
+ session->set_click_emphasis_sound ("");
+ } else {
+ session->set_click_emphasis_sound (path);
+ }
+ }
+ }
+}
+
+void
+OptionEditor::show_waveforms_clicked ()
+{
+ editor.set_show_waveforms (show_waveforms_button.get_active());
+}
+
+void
+OptionEditor::show_waveforms_recording_clicked ()
+{
+ editor.set_show_waveforms_recording (show_waveforms_recording_button.get_active());
+}
+
+void
+OptionEditor::show_measures_clicked ()
+{
+ editor.set_show_measures (show_measures_button.get_active());
+}
+
+void
+OptionEditor::follow_playhead_clicked ()
+{
+ editor.set_follow_playhead (follow_playhead_button.get_active());
+}
+
+void
+OptionEditor::strip_width_clicked ()
+{
+ mixer.set_strip_width (mixer_strip_width_button.get_active() ? Narrow : Wide);
+}
+
+
+void
+OptionEditor::just_close_win()
+{
+ hide_all();
+ ARDOUR_UI::instance()->allow_focus(false);
+}
+
+void
+OptionEditor::queue_session_control_changed (Session::ControlType t)
+{
+ ui.call_slot (bind (slot (*this, &OptionEditor::session_control_changed), t));
+}
+
+void
+OptionEditor::session_control_changed (Session::ControlType t)
+{
+ switch (t) {
+ case Session::SlaveType:
+ switch (session->slave_source()) {
+ case Session::None:
+ slave_type_combo.get_entry()->set_text (positional_sync_strings[Session::None]);
+ break;
+ case Session::MTC:
+ slave_type_combo.get_entry()->set_text (positional_sync_strings[Session::MTC]);
+ break;
+ case Session::JACK:
+ slave_type_combo.get_entry()->set_text (positional_sync_strings[Session::JACK]);
+ break;
+ default:
+ slave_type_combo.get_entry()->set_text (_("--unknown--"));
+ break;
+ }
+
+ break;
+
+ case Session::SendMTC:
+ map_some_session_state (send_mtc_button, &Session::get_send_mtc);
+ break;
+
+ case Session::SendMMC:
+ map_some_session_state (send_mmc_button, &Session::get_send_mmc);
+ break;
+
+ case Session::MMCControl:
+ map_some_session_state (mmc_control_button, &Session::get_mmc_control);
+ break;
+
+ case Session::MidiFeedback:
+ map_some_session_state (midi_feedback_button, &Session::get_midi_feedback);
+ break;
+
+ case Session::MidiControl:
+ map_some_session_state (midi_control_button, &Session::get_midi_control);
+ break;
+
+ default:
+ break;
+ }
+}
+
+gint
+OptionEditor::native_format_chosen (GdkEventAny *ignored)
+{
+ string which;
+
+ if (session == 0) {
+ return FALSE;
+ }
+
+ bool use_bwf = (native_format_combo.get_entry()->get_text() == native_format_strings[0]);
+
+ if (use_bwf != Config->get_native_format_is_bwf()) {
+ Config->set_native_format_is_bwf (use_bwf);
+ session->reset_native_file_format ();
+ }
+
+ return TRUE;
+}
+
+gint
+OptionEditor::slave_type_chosen (GdkEventAny *ignored)
+{
+ string which;
+
+ if (session == 0) {
+ return FALSE;
+ }
+
+ which = slave_type_combo.get_entry()->get_text();
+
+ if (which == positional_sync_strings[Session::None]) {
+ session->request_slave_source (Session::None);
+ } else if (which == positional_sync_strings[Session::MTC]) {
+ session->request_slave_source (Session::MTC);
+ } else if (which == positional_sync_strings[Session::JACK]) {
+ session->request_slave_source (Session::JACK);
+ }
+ return FALSE;
+}
+
+void
+OptionEditor::clear_click_editor ()
+{
+ if (click_io_selector) {
+ click_packer.remove (*click_io_selector);
+ click_packer.remove (*click_gpm);
+ delete click_io_selector;
+ delete click_gpm;
+ click_io_selector = 0;
+ click_gpm = 0;
+ }
+}
+
+void
+OptionEditor::setup_click_editor ()
+{
+ Label* label;
+ HBox* hpacker = manage (new HBox);
+
+ click_path_entry.set_sensitive (true);
+ click_emphasis_path_entry.set_sensitive (true);
+
+ click_path_entry.set_name ("OptionsEntry");
+ click_emphasis_path_entry.set_name ("OptionsEntry");
+
+ click_path_entry.activate.connect (slot (*this, &OptionEditor::click_sound_changed));
+ click_emphasis_path_entry.activate.connect (slot (*this, &OptionEditor::click_emphasis_sound_changed));
+
+ click_path_entry.focus_in_event.connect (slot (Keyboard::the_keyboard(), &Keyboard::focus_in_handler));
+ click_path_entry.focus_out_event.connect (bind (slot (*this, &OptionEditor::focus_out_event_handler), &OptionEditor::click_sound_changed));
+ click_emphasis_path_entry.focus_in_event.connect (slot (Keyboard::the_keyboard(), &Keyboard::focus_in_handler));
+ click_emphasis_path_entry.focus_out_event.connect (bind (slot (*this, &OptionEditor::focus_out_event_handler), &OptionEditor::click_emphasis_sound_changed));
+
+ click_browse_button.set_name ("EditorGTKButton");
+ click_emphasis_browse_button.set_name ("EditorGTKButton");
+ click_browse_button.clicked.connect (slot (*this, &OptionEditor::click_browse_clicked));
+ click_emphasis_browse_button.clicked.connect (slot (*this, &OptionEditor::click_emphasis_browse_clicked));
+
+ click_packer.set_border_width (12);
+ click_packer.set_spacing (5);
+
+ click_io_selector = new IOSelector (*session, session->click_io(), false);
+ click_gpm = new GainMeter (session->click_io(), *session);
+
+ click_table.set_col_spacings (10);
+
+ label = manage(new Label(_("Click audio file")));
+ label->set_name ("OptionsLabel");
+ click_table.attach (*label, 0, 1, 0, 1, 0, 0);
+ click_table.attach (click_path_entry, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0);
+ click_table.attach (click_browse_button, 2, 3, 0, 1, 0, 0);
+
+ label = manage(new Label(_("Click emphasis audiofile")));
+ label->set_name ("OptionsLabel");
+ click_table.attach (*label, 0, 1, 1, 2, 0, 0);
+ click_table.attach (click_emphasis_path_entry, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, 0);
+ click_table.attach (click_emphasis_browse_button, 2, 3, 1, 2, 0, 0);
+
+ hpacker->set_spacing (10);
+ hpacker->pack_start (*click_io_selector, false, false);
+ hpacker->pack_start (*click_gpm, false, false);
+
+ click_packer.pack_start (click_table, false, false);
+ click_packer.pack_start (*hpacker, false, false);
+
+ click_packer.show_all ();
+}
+
+void
+OptionEditor::clear_auditioner_editor ()
+{
+ if (auditioner_io_selector) {
+ audition_hpacker.remove (*auditioner_io_selector);
+ audition_hpacker.remove (*auditioner_gpm);
+ delete auditioner_io_selector;
+ delete auditioner_gpm;
+ auditioner_io_selector = 0;
+ auditioner_gpm = 0;
+ }
+}
+
+void
+OptionEditor::setup_auditioner_editor ()
+{
+ audition_packer.set_border_width (12);
+ audition_packer.set_spacing (5);
+ audition_hpacker.set_spacing (10);
+
+ audition_label.set_name ("OptionEditorAuditionerLabel");
+ audition_label.set_text (_("The auditioner is a dedicated mixer strip used\n"
+ "for listening to specific regions outside the context\n"
+ "of the overall mix. It can be connected just like any\n"
+ "other mixer strip."));
+
+ audition_packer.pack_start (audition_label, false, false, 10);
+ audition_packer.pack_start (audition_hpacker, false, false);
+}
+
+void
+OptionEditor::connect_audition_editor ()
+{
+ auditioner_io_selector = new IOSelector (*session, session->the_auditioner(), false);
+ auditioner_gpm = new GainMeter (session->the_auditioner(), *session);
+
+ audition_hpacker.pack_start (*auditioner_io_selector, false, false);
+ audition_hpacker.pack_start (*auditioner_gpm, false, false);
+
+ auditioner_io_selector->show_all ();
+ auditioner_gpm->show_all ();
+}
+
+gint
+OptionEditor::focus_out_event_handler (GdkEventFocus* ev, void (OptionEditor::*pmf)())
+{
+ (this->*pmf)();
+ return Keyboard::the_keyboard().focus_out_handler (ev);
+}
+
+void
+OptionEditor::setup_misc_options()
+{
+ Gtk::Table* table = manage (new Table (4, 2));
+ table->set_homogeneous (true);
+
+ misc_packer.set_border_width (8);
+ misc_packer.set_spacing (3);
+ misc_packer.pack_start (*table, true, true);
+
+ table->attach (hw_monitor_button, 0, 1, 0, 1, GTK_FILL, 0, 8, 0);
+ table->attach (sw_monitor_button, 0, 1, 1, 2, GTK_FILL, 0, 8, 0);
+ table->attach (plugins_stop_button, 0, 1, 2, 3, GTK_FILL, 0, 8, 0);
+ table->attach (plugins_on_rec_button, 0, 1, 3, 4, GTK_FILL, 0, 8, 0);
+ table->attach (verify_remove_last_capture_button, 0, 1, 4, 5, GTK_FILL, 0, 8, 0);
+
+ table->attach (stop_rec_on_xrun_button, 1, 2, 0, 1, GTK_FILL, 0, 8, 0);
+ table->attach (stop_at_end_button, 1, 2, 1, 2, GTK_FILL, 0, 8, 0);
+ table->attach (debug_keyboard_button, 1, 2, 2, 3, GTK_FILL, 0, 8, 0);
+ table->attach (speed_quieten_button, 1, 2, 3, 4, GTK_FILL, 0, 8, 0);
+
+ Gtk::VBox* connect_box = manage (new VBox);
+ connect_box->set_spacing (3);
+ connect_box->set_border_width (8);
+
+ auto_connect_output_manual_button.set_group (auto_connect_output_master_button.group());
+ auto_connect_output_physical_button.set_group (auto_connect_output_master_button.group());
+
+ Gtk::HBox* useless_box = manage (new HBox);
+ useless_box->pack_start (auto_connect_inputs_button, false, false);
+ connect_box->pack_start (*useless_box, false, false);
+ connect_box->pack_start (auto_connect_output_master_button, false, false);
+ connect_box->pack_start (auto_connect_output_physical_button, false, false);
+ connect_box->pack_start (auto_connect_output_manual_button, false);
+
+ misc_packer.pack_start (*connect_box, false, false);
+
+ hw_monitor_button.set_name ("OptionEditorToggleButton");
+ sw_monitor_button.set_name ("OptionEditorToggleButton");
+ plugins_stop_button.set_name ("OptionEditorToggleButton");
+ plugins_on_rec_button.set_name ("OptionEditorToggleButton");
+ verify_remove_last_capture_button.set_name ("OptionEditorToggleButton");
+ auto_connect_inputs_button.set_name ("OptionEditorToggleButton");
+ auto_connect_output_physical_button.set_name ("OptionEditorToggleButton");
+ auto_connect_output_master_button.set_name ("OptionEditorToggleButton");
+ auto_connect_output_manual_button.set_name ("OptionEditorToggleButton");
+ stop_rec_on_xrun_button.set_name ("OptionEditorToggleButton");
+ stop_at_end_button.set_name ("OptionEditorToggleButton");
+ debug_keyboard_button.set_name ("OptionEditorToggleButton");
+ speed_quieten_button.set_name ("OptionEditorToggleButton");
+
+ hw_monitor_button.set_active (Config->get_use_hardware_monitoring());
+ sw_monitor_button.set_active (!Config->get_no_sw_monitoring());
+ plugins_stop_button.set_active (Config->get_plugins_stop_with_transport());
+ stop_rec_on_xrun_button.set_active (Config->get_stop_recording_on_xrun());
+ stop_at_end_button.set_active (Config->get_stop_at_session_end());
+ debug_keyboard_button.set_active (false);
+ speed_quieten_button.set_active (Config->get_quieten_at_speed() != 1.0f);
+
+ hw_monitor_button.clicked.connect (slot (*this, &OptionEditor::hw_monitor_clicked));
+ sw_monitor_button.clicked.connect (slot (*this, &OptionEditor::sw_monitor_clicked));
+ plugins_stop_button.clicked.connect (slot (*this, &OptionEditor::plugins_stop_with_transport_clicked));
+ plugins_on_rec_button.clicked.connect (slot (*this, &OptionEditor::plugins_on_while_recording_clicked));
+ verify_remove_last_capture_button.clicked.connect (slot (*this, &OptionEditor::verify_remove_last_capture_clicked));
+ auto_connect_inputs_button.clicked.connect (slot (*this, &OptionEditor::auto_connect_inputs_clicked));
+ auto_connect_output_physical_button.clicked.connect (slot (*this, &OptionEditor::auto_connect_output_physical_clicked));
+ auto_connect_output_master_button.clicked.connect (slot (*this, &OptionEditor::auto_connect_output_master_clicked));
+ auto_connect_output_manual_button.clicked.connect (slot (*this, &OptionEditor::auto_connect_output_manual_clicked));
+ stop_rec_on_xrun_button.clicked.connect (slot (*this, &OptionEditor::stop_rec_on_xrun_clicked));
+ stop_at_end_button.clicked.connect (slot (*this, &OptionEditor::stop_at_end_clicked));
+ debug_keyboard_button.clicked.connect (slot (*this, &OptionEditor::debug_keyboard_clicked));
+ speed_quieten_button.clicked.connect (slot (*this, &OptionEditor::speed_quieten_clicked));
+}
+
+void
+OptionEditor::speed_quieten_clicked ()
+{
+ if (speed_quieten_button.get_active()) {
+ Config->set_quieten_at_speed (0.251189); // -12dB reduction for ffwd or rewind
+ } else {
+ Config->set_quieten_at_speed (1.0); /* no change */
+ }
+}
+
+void
+OptionEditor::debug_keyboard_clicked ()
+{
+ extern bool debug_keyboard;
+ debug_keyboard = debug_keyboard_button.get_active ();
+}
+
+void
+OptionEditor::auto_connect_inputs_clicked ()
+{
+ if (session) {
+ session->set_input_auto_connect (auto_connect_inputs_button.get_active());
+ }
+}
+
+void
+OptionEditor::auto_connect_output_master_clicked ()
+{
+ if (session) {
+ if (auto_connect_output_master_button.get_active()) {
+ session->set_output_auto_connect (Session::AutoConnectMaster);
+ }
+ }
+}
+
+void
+OptionEditor::auto_connect_output_physical_clicked ()
+{
+ if (session) {
+ if (auto_connect_output_physical_button.get_active()) {
+ session->set_output_auto_connect (Session::AutoConnectPhysical);
+ }
+ }
+}
+
+void
+OptionEditor::auto_connect_output_manual_clicked ()
+{
+ if (session) {
+ if (auto_connect_output_manual_button.get_active()) {
+ session->set_output_auto_connect (Session::AutoConnectOption (0));
+ }
+ }
+}
+
+void
+OptionEditor::hw_monitor_clicked ()
+{
+ Config->set_use_hardware_monitoring (hw_monitor_button.get_active());
+}
+
+void
+OptionEditor::sw_monitor_clicked ()
+{
+ Config->set_no_sw_monitoring (!sw_monitor_button.get_active());
+}
+
+void
+OptionEditor::plugins_stop_with_transport_clicked ()
+{
+ Config->set_plugins_stop_with_transport (plugins_stop_button.get_active());
+}
+
+void
+OptionEditor::plugins_on_while_recording_clicked ()
+{
+ if (session) {
+ session->set_recording_plugins (plugins_on_rec_button.get_active());
+ }
+}
+
+void
+OptionEditor::verify_remove_last_capture_clicked ()
+{
+ Config->set_verify_remove_last_capture(verify_remove_last_capture_button.get_active());
+}
+
+void
+OptionEditor::stop_rec_on_xrun_clicked ()
+{
+ Config->set_stop_recording_on_xrun (stop_rec_on_xrun_button.get_active());
+}
+
+void
+OptionEditor::stop_at_end_clicked ()
+{
+ Config->set_stop_at_session_end (stop_at_end_button.get_active());
+}
+
+static const struct {
+ const char *name;
+ guint modifier;
+} modifiers[] = {
+ { "Shift", GDK_SHIFT_MASK },
+ { "Control", GDK_CONTROL_MASK },
+ { "Alt (Mod1)", GDK_MOD1_MASK },
+ { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
+ { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
+ { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
+ { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
+ { "Mod2", GDK_MOD2_MASK },
+ { "Mod3", GDK_MOD3_MASK },
+ { "Mod4", GDK_MOD4_MASK },
+ { "Mod5", GDK_MOD5_MASK },
+ { 0, 0 }
+};
+
+void
+OptionEditor::setup_keyboard_options ()
+{
+ vector<string> dumb;
+ Label* label;
+
+ keyboard_mouse_table.set_border_width (12);
+ keyboard_mouse_table.set_row_spacings (5);
+ keyboard_mouse_table.set_col_spacings (5);
+
+ /* internationalize and prepare for use with combos */
+
+ for (int i = 0; modifiers[i].name; ++i) {
+ dumb.push_back (_(modifiers[i].name));
+ }
+
+ edit_modifier_combo.set_popdown_strings (dumb);
+ edit_modifier_combo.get_entry()->set_editable (false);
+ edit_modifier_combo.get_entry()->set_name ("OptionsEntry");
+ edit_modifier_combo.set_use_arrows_always (true);
+ edit_modifier_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::edit_modifier_chosen));
+
+ for (int x = 0; modifiers[x].name; ++x) {
+ if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
+ edit_modifier_combo.get_entry()->set_text (_(modifiers[x].name));
+ break;
+ }
+ }
+
+ label = manage (new Label (_("Edit using")));
+ label->set_name ("OptionsLabel");
+ label->set_alignment (1.0, 0.5);
+
+ keyboard_mouse_table.attach (*label, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND, 0);
+ keyboard_mouse_table.attach (edit_modifier_combo, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0);
+
+ label = manage (new Label (_("+ button")));
+ label->set_name ("OptionsLabel");
+
+ keyboard_mouse_table.attach (*label, 3, 4, 0, 1, GTK_FILL|GTK_EXPAND, 0);
+ keyboard_mouse_table.attach (edit_button_spin, 4, 5, 0, 1, GTK_FILL|GTK_EXPAND, 0);
+
+ edit_button_spin.set_name ("OptionsEntry");
+ edit_button_adjustment.set_value (Keyboard::edit_button());
+ edit_button_adjustment.value_changed.connect (slot (*this, &OptionEditor::edit_button_changed));
+
+ delete_modifier_combo.set_popdown_strings (dumb);
+ delete_modifier_combo.get_entry()->set_editable (false);
+ delete_modifier_combo.get_entry()->set_name ("OptionsEntry");
+ delete_modifier_combo.set_use_arrows_always (true);
+ delete_modifier_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::delete_modifier_chosen));
+
+ for (int x = 0; modifiers[x].name; ++x) {
+ if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
+ delete_modifier_combo.get_entry()->set_text (_(modifiers[x].name));
+ break;
+ }
+ }
+
+ label = manage (new Label (_("Delete using")));
+ label->set_name ("OptionsLabel");
+ label->set_alignment (1.0, 0.5);
+
+ keyboard_mouse_table.attach (*label, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, 0);
+ keyboard_mouse_table.attach (delete_modifier_combo, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, 0);
+
+ label = manage (new Label (_("+ button")));
+ label->set_name ("OptionsLabel");
+
+ keyboard_mouse_table.attach (*label, 3, 4, 1, 2, GTK_FILL|GTK_EXPAND, 0);
+ keyboard_mouse_table.attach (delete_button_spin, 4, 5, 1, 2, GTK_FILL|GTK_EXPAND, 0);
+
+ delete_button_spin.set_name ("OptionsEntry");
+ delete_button_adjustment.set_value (Keyboard::delete_button());
+ delete_button_adjustment.value_changed.connect (slot (*this, &OptionEditor::delete_button_changed));
+
+ snap_modifier_combo.set_popdown_strings (dumb);
+ snap_modifier_combo.get_entry()->set_editable (false);
+ snap_modifier_combo.get_entry()->set_name ("OptionsEntry");
+ snap_modifier_combo.set_use_arrows_always (true);
+ snap_modifier_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::snap_modifier_chosen));
+
+ for (int x = 0; modifiers[x].name; ++x) {
+ if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
+ snap_modifier_combo.get_entry()->set_text (_(modifiers[x].name));
+ break;
+ }
+ }
+
+ label = manage (new Label (_("Ignore snap using")));
+ label->set_name ("OptionsLabel");
+ label->set_alignment (1.0, 0.5);
+
+ keyboard_mouse_table.attach (*label, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, 0);
+ keyboard_mouse_table.attach (snap_modifier_combo, 1, 2, 2, 3, GTK_FILL|GTK_EXPAND, 0);
+}
+
+gint
+OptionEditor::edit_modifier_chosen (GdkEventAny *ev)
+{
+ string txt;
+
+ txt = edit_modifier_combo.get_entry()->get_text();
+
+ for (int i = 0; modifiers[i].name; ++i) {
+ if (txt == _(modifiers[i].name)) {
+ Keyboard::set_edit_modifier (modifiers[i].modifier);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+gint
+OptionEditor::delete_modifier_chosen (GdkEventAny *ev)
+{
+ string txt;
+
+ txt = delete_modifier_combo.get_entry()->get_text();
+
+ for (int i = 0; modifiers[i].name; ++i) {
+ if (txt == _(modifiers[i].name)) {
+ Keyboard::set_delete_modifier (modifiers[i].modifier);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+gint
+OptionEditor::snap_modifier_chosen (GdkEventAny *ev)
+{
+ string txt;
+
+ txt = snap_modifier_combo.get_entry()->get_text();
+
+ for (int i = 0; modifiers[i].name; ++i) {
+ if (txt == _(modifiers[i].name)) {
+ Keyboard::set_snap_modifier (modifiers[i].modifier);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+void
+OptionEditor::delete_button_changed ()
+{
+ Keyboard::set_delete_button ((guint) delete_button_adjustment.get_value());
+}
+
+void
+OptionEditor::edit_button_changed ()
+{
+ Keyboard::set_edit_button ((guint) edit_button_adjustment.get_value());
+}
+
+void
+OptionEditor::fixup_combo_size (Gtk::Combo& combo, vector<string>& strings)
+{
+ /* find the widest string */
+
+ string::size_type maxlen = 0;
+ string maxstring;
+
+ for (vector<string>::iterator i = strings.begin(); i != strings.end(); ++i) {
+ string::size_type l;
+
+ if ((l = (*i).length()) > maxlen) {
+ maxlen = l;
+ maxstring = *i;
+ }
+ }
+
+ /* try to include ascenders and descenders */
+
+ if (maxstring.length() > 2) {
+ maxstring[0] = 'g';
+ maxstring[1] = 'l';
+ }
+
+ const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
+
+ set_usize_to_display_given_text (*combo.get_entry(), maxstring.c_str(), 10 + FUDGE, 10);
+}
+
+void
+OptionEditor::map_some_session_state (CheckButton& button, bool (Session::*get)() const)
+{
+ if (session) {
+ button.set_active ((session->*get)());
+ }
+}
+
diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h
new file mode 100644
index 0000000000..e4ed7de1b2
--- /dev/null
+++ b/gtk2_ardour/option_editor.h
@@ -0,0 +1,282 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_option_editor_h__
+#define __gtk_ardour_option_editor_h__
+
+#include <gtk--.h>
+
+#include <ardour/session.h>
+
+#include "ardour_dialog.h"
+#include "editing.h"
+#include "audio_clock.h"
+
+class ARDOUR_UI;
+class PublicEditor;
+class Mixer_UI;
+class IOSelector;
+class GainMeter;
+class PannerUI;
+
+class OptionEditor : public ArdourDialog
+{
+ public:
+ OptionEditor (ARDOUR_UI&, PublicEditor&, Mixer_UI&);
+ ~OptionEditor ();
+
+ void set_session (ARDOUR::Session *);
+ void save ();
+
+ private:
+ ARDOUR::Session *session;
+ ARDOUR_UI& ui;
+ PublicEditor& editor;
+ Mixer_UI& mixer;
+
+ Gtk::Notebook notebook;
+
+ /* Generic */
+
+ void session_control_changed (ARDOUR::Session::ControlType);
+ void queue_session_control_changed (ARDOUR::Session::ControlType);
+ void map_some_session_state (Gtk::CheckButton& button, bool (ARDOUR::Session::*get)() const);
+ gint wm_close (GdkEventAny *);
+ void just_close_win();
+ gint focus_out_event_handler (GdkEventFocus*, void (OptionEditor::*pmf)());
+
+ /* paths */
+
+ Gtk::Table path_table;
+
+ Gtk::Entry session_raid_entry;
+
+ Gtk::Combo native_format_combo;
+
+ void setup_path_options();
+ void add_session_paths ();
+ void remove_session_paths ();
+ gint native_format_chosen (GdkEventAny *);
+ void raid_path_changed ();
+
+ /* fades */
+
+ // Gtk::Table fade_table;
+
+ Gtk::VBox fade_packer;
+ Gtk::CheckButton auto_xfade_button;
+ Gtk::CheckButton xfade_active_button;
+ Gtk::Label layer_mode_label;
+ Gtk::Combo layer_mode_combo;
+ Gtk::Label xfade_model_label;
+ Gtk::Combo xfade_model_combo;
+ Gtk::Adjustment short_xfade_adjustment;
+ Gtk::HScale short_xfade_slider;
+
+ void auto_xfade_clicked ();
+ void xfade_active_clicked ();
+ gint layer_mode_chosen (GdkEventAny*);
+ gint xfade_model_chosen (GdkEventAny*);
+ void setup_fade_options();
+ void short_xfade_adjustment_changed ();
+
+ /* solo */
+
+ Gtk::VBox solo_packer;
+ Gtk::CheckButton solo_latched_button;
+ Gtk::CheckButton solo_via_bus_button;
+
+ void solo_latched_clicked();
+ void solo_via_bus_clicked ();
+
+ void setup_solo_options();
+
+ /* display */
+
+ Gtk::VBox display_packer;
+ Gtk::CheckButton show_waveforms_button;
+ Gtk::CheckButton show_waveforms_recording_button;
+ Gtk::CheckButton mixer_strip_width_button;
+ Gtk::CheckButton show_measures_button;
+ Gtk::CheckButton follow_playhead_button;
+ Gtk::Combo meter_hold_combo;
+ Gtk::Combo meter_falloff_combo;
+
+ void setup_display_options();
+ void show_waveforms_clicked ();
+ void show_waveforms_recording_clicked ();
+ void show_measures_clicked ();
+ void strip_width_clicked ();
+ void follow_playhead_clicked ();
+ gint meter_hold_chosen (GdkEventAny *);
+ gint meter_falloff_chosen (GdkEventAny *);
+
+ void display_control_changed (Editing::DisplayControl);
+
+ /* Sync */
+
+ Gtk::VBox sync_packer;
+
+ Gtk::CheckButton send_mtc_button;
+ Gtk::CheckButton send_mmc_button;
+ Gtk::CheckButton jack_time_master_button;
+ Gtk::Combo slave_type_combo;
+ Gtk::Combo smpte_fps_combo;
+ AudioClock smpte_offset_clock;
+ Gtk::CheckButton smpte_offset_negative_button;
+
+ void setup_sync_options ();
+ gint send_mtc_toggled (GdkEventButton*, Gtk::CheckButton*);
+
+ gint slave_type_chosen (GdkEventAny*);
+ void jack_time_master_clicked ();
+ void jack_transport_master_clicked ();
+ gint smpte_fps_chosen (GdkEventAny*);
+ void smpte_offset_chosen ();
+ void smpte_offset_negative_clicked ();
+
+ /* MIDI */
+
+ Gtk::VBox midi_packer;
+ Gtk::CheckButton midi_feedback_button;
+ Gtk::CheckButton midi_control_button;
+ Gtk::CheckButton mmc_control_button;
+
+ void send_mmc_toggled (Gtk::CheckButton*);
+ void mmc_control_toggled (Gtk::CheckButton*);
+ void midi_control_toggled (Gtk::CheckButton*);
+ void midi_feedback_toggled (Gtk::CheckButton*);
+
+ gint port_online_toggled (GdkEventButton*,MIDI::Port*,Gtk::ToggleButton*);
+ gint port_trace_in_toggled (GdkEventButton*,MIDI::Port*,Gtk::ToggleButton*);
+ gint port_trace_out_toggled (GdkEventButton*,MIDI::Port*,Gtk::ToggleButton*);
+
+ gint mmc_port_chosen (GdkEventButton*,MIDI::Port*,Gtk::RadioButton*);
+ gint mtc_port_chosen (GdkEventButton*,MIDI::Port*,Gtk::RadioButton*);
+ gint midi_port_chosen (GdkEventButton*,MIDI::Port*,Gtk::RadioButton*);
+
+ void map_port_online (MIDI::Port*, Gtk::ToggleButton*);
+
+ void setup_midi_options();
+
+ enum PortIndex {
+ MtcIndex = 0,
+ MmcIndex = 1,
+ MidiIndex = 2
+ };
+
+ std::map<MIDI::Port*,vector<Gtk::RadioButton*> > port_toggle_buttons;
+
+ /* Click */
+
+ IOSelector* click_io_selector;
+ GainMeter* click_gpm;
+ PannerUI* click_panner;
+ Gtk::VBox click_packer;
+ Gtk::Table click_table;
+ Gtk::Entry click_path_entry;
+ Gtk::Entry click_emphasis_path_entry;
+ Gtk::Button click_browse_button;
+ Gtk::Button click_emphasis_browse_button;
+
+ void setup_click_editor ();
+ void clear_click_editor ();
+
+ void click_chosen (vector<string> paths, bool ignore);
+ void click_emphasis_chosen (vector<string> paths, bool ignore);
+
+ void click_browse_clicked ();
+ void click_emphasis_browse_clicked ();
+
+ void click_sound_changed ();
+ void click_emphasis_sound_changed ();
+
+ /* Auditioner */
+
+ Gtk::VBox audition_packer;
+ Gtk::HBox audition_hpacker;
+ Gtk::Label audition_label;
+ IOSelector* auditioner_io_selector;
+ GainMeter* auditioner_gpm;
+ PannerUI* auditioner_panner;
+
+ void setup_auditioner_editor ();
+ void clear_auditioner_editor ();
+ void connect_audition_editor ();
+
+ /* keyboard/mouse */
+
+ Gtk::Table keyboard_mouse_table;
+ Gtk::Combo edit_modifier_combo;
+ Gtk::Combo delete_modifier_combo;
+ Gtk::Combo snap_modifier_combo;
+ Gtk::Adjustment delete_button_adjustment;
+ Gtk::SpinButton delete_button_spin;
+ Gtk::Adjustment edit_button_adjustment;
+ Gtk::SpinButton edit_button_spin;
+
+ void setup_keyboard_options ();
+ gint delete_modifier_chosen (GdkEventAny*);
+ gint edit_modifier_chosen (GdkEventAny*);
+ gint snap_modifier_chosen (GdkEventAny*);
+ void edit_button_changed ();
+ void delete_button_changed ();
+
+ /* Miscellany */
+
+ Gtk::VBox misc_packer;
+
+ Gtk::CheckButton auto_connect_inputs_button;
+
+ Gtk::RadioButton auto_connect_output_physical_button;
+ Gtk::RadioButton auto_connect_output_master_button;
+ Gtk::RadioButton auto_connect_output_manual_button;
+
+ Gtk::CheckButton hw_monitor_button;
+ Gtk::CheckButton sw_monitor_button;
+ Gtk::CheckButton plugins_stop_button;
+ Gtk::CheckButton plugins_on_rec_button;
+ Gtk::CheckButton verify_remove_last_capture_button;
+ Gtk::CheckButton stop_rec_on_xrun_button;
+ Gtk::CheckButton stop_at_end_button;
+ Gtk::CheckButton debug_keyboard_button;
+ Gtk::CheckButton speed_quieten_button;
+
+ void setup_misc_options ();
+ void plugins_stop_with_transport_clicked ();
+ void verify_remove_last_capture_clicked ();
+ void plugins_on_while_recording_clicked ();
+ void auto_connect_inputs_clicked ();
+ void auto_connect_output_physical_clicked ();
+ void auto_connect_output_master_clicked ();
+ void auto_connect_output_manual_clicked ();
+ void hw_monitor_clicked ();
+ void sw_monitor_clicked ();
+ void stop_rec_on_xrun_clicked ();
+ void stop_at_end_clicked ();
+ void debug_keyboard_clicked ();
+ void speed_quieten_clicked ();
+
+ void fixup_combo_size (Gtk::Combo&, vector<string>& strings);
+};
+
+#endif /* __gtk_ardour_option_editor_h__ */
+
+
diff --git a/gtk2_ardour/opts.cc b/gtk2_ardour/opts.cc
new file mode 100644
index 0000000000..48245651e8
--- /dev/null
+++ b/gtk2_ardour/opts.cc
@@ -0,0 +1,154 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <getopt.h>
+#include <iostream>
+#include <cstdlib>
+
+#include "opts.h"
+
+#include "i18n.h"
+
+using namespace std;
+
+string GTK_ARDOUR::session_name = "";
+string GTK_ARDOUR::jack_client_name = "ardour";
+bool GTK_ARDOUR::show_key_actions = false;
+bool GTK_ARDOUR::no_splash = true;
+bool GTK_ARDOUR::just_version = false;
+bool GTK_ARDOUR::use_vst = true;
+bool GTK_ARDOUR::new_session = false;
+char* GTK_ARDOUR::curvetest_file = 0;
+bool GTK_ARDOUR::try_hw_optimization = false;
+
+using namespace GTK_ARDOUR;
+
+int
+print_help (const char *execname)
+{
+ cout << _("Usage: ") << execname << "\n"
+ << _(" -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")
+ << _(" -N, --new session-name Create a new session from the command line\n")
+ << _(" -o, --use-hw-optimizations Try to use h/w specific optimizations\n")
+#ifdef VST_SUPPORT
+ << _(" -V, --novst Do not use VST support\n")
+#endif
+ << _(" [session-name] Name of session to load\n")
+ << _(" -C, --curvetest filename Curve algorithm debugger\n")
+ ;
+ return 1;
+
+}
+
+int
+GTK_ARDOUR::parse_opts (int argc, char *argv[])
+
+{
+ const char *optstring = "U:hbvVnoc:C:N:";
+ const char *execname = strrchr (argv[0], '/');
+
+ if (execname == 0) {
+ execname = argv[0];
+ } else {
+ execname++;
+ }
+
+ const struct option longopts[] = {
+ { "version", 0, 0, 'v' },
+ { "help", 0, 0, 'h' },
+ { "bindings", 0, 0, 'b' },
+ { "show-splash", 0, 0, 'n' },
+ { "name", 1, 0, 'c' },
+ { "novst", 0, 0, 'V' },
+ { "new", 1, 0, 'N' },
+ { "use-hw-optimizations", 0, 0, 'o' },
+ { "curvetest", 1, 0, 'C' },
+ { 0, 0, 0, 0 }
+ };
+
+ int option_index = 0;
+ int c = 0;
+
+ while (1) {
+ c = getopt_long (argc, argv, optstring, longopts, &option_index);
+
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 0:
+ break;
+
+ case 'v':
+ just_version = true;
+ break;
+
+ case 'h':
+ print_help (execname);
+ exit (0);
+ break;
+ case 'b':
+ show_key_actions = true;
+ break;
+
+ case 'n':
+ no_splash = false;
+ break;
+
+ case 'N':
+ new_session = true;
+ session_name = optarg;
+ break;
+
+ case 'o':
+ try_hw_optimization = true;
+ break;
+
+ case 'V':
+#ifdef VST_SUPPORT
+ use_vst = false;
+#endif /* VST_SUPPORT */
+ break;
+
+ case 'c':
+ jack_client_name = optarg;
+ break;
+
+ case 'C':
+ curvetest_file = optarg;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ session_name = argv[optind++];
+ }
+
+ return 0;
+}
+
diff --git a/gtk2_ardour/opts.h b/gtk2_ardour/opts.h
new file mode 100644
index 0000000000..c07dcc3664
--- /dev/null
+++ b/gtk2_ardour/opts.h
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_opts_h__
+#define __ardour_opts_h__
+
+#include <string>
+
+using std::string;
+
+namespace GTK_ARDOUR {
+
+extern string session_name;
+extern bool show_key_actions;
+extern bool no_splash;
+extern bool just_version;
+extern string jack_client_name;
+extern bool use_vst;
+extern bool new_session;
+extern char* curvetest_file;
+extern bool try_hw_optimization;
+
+extern int32_t parse_opts (int argc, char *argv[]);
+
+}
+
+#endif /* __ardour_opts_h__ */
diff --git a/gtk2_ardour/pan_automation_time_axis.cc b/gtk2_ardour/pan_automation_time_axis.cc
new file mode 100644
index 0000000000..f691307e9c
--- /dev/null
+++ b/gtk2_ardour/pan_automation_time_axis.cc
@@ -0,0 +1,92 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/curve.h>
+#include <ardour/route.h>
+#include <ardour/panner.h>
+
+#include <gtkmmext/popup.h>
+
+#include "pan_automation_time_axis.h"
+#include "automation_line.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+
+PanAutomationTimeAxisView::PanAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, Widget* p, std::string n)
+
+ : AxisView (s),
+ AutomationTimeAxisView (s, r, e, parent, p, n, X_("pan"), "")
+{
+}
+
+PanAutomationTimeAxisView::~PanAutomationTimeAxisView ()
+{
+}
+
+void
+PanAutomationTimeAxisView::add_automation_event (GtkCanvasItem* item, GdkEvent* event, jack_nframes_t when, double y)
+{
+ if (lines.empty()) {
+ /* no data, possibly caused by no outputs/inputs */
+ return;
+ }
+
+ if (lines.size() > 1) {
+
+ Gtkmmext::PopUp* msg = new Gtkmmext::PopUp (GTK_WIN_POS_MOUSE, 5000, true);
+
+ msg->set_text (_("You can't graphically edit panning of more than stream"));
+ msg->touch ();
+
+ return;
+ }
+
+ double x = 0;
+
+ gtk_canvas_item_w2i (canvas_display, &x, &y);
+
+ /* compute vertical fractional position */
+
+ y = 1.0 - (y / height);
+
+ /* map using line */
+
+ lines.front()->view_to_model_y (y);
+
+ AutomationList& alist (lines.front()->the_list());
+
+ _session.begin_reversible_command (_("add pan automation event"));
+ _session.add_undo (alist.get_memento());
+ alist.add (when, y);
+ _session.add_undo (alist.get_memento());
+ _session.commit_reversible_command ();
+ _session.set_dirty ();
+}
+
+void
+PanAutomationTimeAxisView::set_automation_state (AutoState state)
+{
+ if (!ignore_state_request) {
+ route.panner().set_automation_state (state);
+ }
+}
diff --git a/gtk2_ardour/pan_automation_time_axis.h b/gtk2_ardour/pan_automation_time_axis.h
new file mode 100644
index 0000000000..16b0808148
--- /dev/null
+++ b/gtk2_ardour/pan_automation_time_axis.h
@@ -0,0 +1,29 @@
+#ifndef __ardour_gtk_pan_automation_time_axis_h__
+#define __ardour_gtk_pan_automation_time_axis_h__
+
+#include "automation_time_axis.h"
+
+namespace ARDOUR {
+ class Redirect;
+}
+
+class PanAutomationTimeAxisView : public AutomationTimeAxisView
+{
+ public:
+ PanAutomationTimeAxisView (ARDOUR::Session&,
+ ARDOUR::Route&,
+ PublicEditor&,
+ TimeAxisView& parent_axis,
+ Gtk::Widget* parent,
+ std::string name);
+
+ ~PanAutomationTimeAxisView();
+
+ void add_automation_event (GtkCanvasItem *item, GdkEvent *event, jack_nframes_t, double);
+
+ private:
+ void automation_changed ();
+ void set_automation_state (ARDOUR::AutoState);
+};
+
+#endif /* __ardour_gtk_pan_automation_time_axis_h__ */
diff --git a/gtk2_ardour/panner2d.cc b/gtk2_ardour/panner2d.cc
new file mode 100644
index 0000000000..ceec33868b
--- /dev/null
+++ b/gtk2_ardour/panner2d.cc
@@ -0,0 +1,636 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <climits>
+#include <string.h>
+
+#include <pbd/error.h>
+#include <ardour/panner.h>
+#include <gtkmmext/gtk_ui.h>
+
+#include "panner2d.h"
+#include "keyboard.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtk;
+using namespace SigC;
+using namespace ARDOUR;
+
+Panner2d::Target::Target (float xa, float ya, const char *txt)
+ : x (xa), y (ya), text (txt ? strdup (txt) : 0)
+{
+ if (text) {
+ textlen = strlen (txt);
+ } else {
+ textlen = 0;
+ }
+}
+
+Panner2d::Target::~Target ()
+{
+ if (text) {
+ free (text);
+ }
+}
+
+Panner2d::Panner2d (Panner& p, int32_t w, int32_t h)
+ : panner (p), width (w), height (h)
+{
+ context_menu = 0;
+ bypass_menu_item = 0;
+
+ allow_x = false;
+ allow_y = false;
+ allow_target = false;
+
+ panner.StateChanged.connect (slot (*this, &Panner2d::handle_state_change));
+
+ drag_target = 0;
+ set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK);
+
+}
+
+Panner2d::~Panner2d()
+{
+ for (Targets::iterator i = targets.begin(); i != targets.end(); ++i) {
+ delete i->second;
+ }
+}
+
+void
+Panner2d::reset (uint32_t n_inputs)
+{
+ /* add pucks */
+
+ drop_pucks ();
+
+ switch (n_inputs) {
+ case 0:
+ break;
+
+ case 1:
+ add_puck ("", 0.0f, 0.5f);
+ break;
+
+ case 2:
+ add_puck ("L", 0.5f, 0.25f);
+ add_puck ("R", 0.25f, 0.5f);
+ show_puck (0);
+ show_puck (1);
+ break;
+
+ default:
+ for (uint32_t i = 0; i < n_inputs; ++i) {
+ char buf[64];
+ snprintf (buf, sizeof (buf), "%" PRIu32, i);
+ add_puck (buf, 0.0f, 0.5f);
+ show_puck (i);
+ }
+ break;
+ }
+
+ /* add all outputs */
+
+ drop_targets ();
+
+ for (uint32_t n = 0; n < panner.nouts(); ++n) {
+ add_target (panner.output (n).x, panner.output (n).y);
+ }
+
+ allow_x_motion (true);
+ allow_y_motion (true);
+ allow_target_motion (true);
+}
+
+void
+Panner2d::size_allocate_impl (GtkAllocation *alloc)
+{
+ width = alloc->width;
+ height = alloc->height;
+
+ DrawingArea::size_allocate_impl (alloc);
+}
+
+int
+Panner2d::add_puck (const char* text, float x, float y)
+{
+ Target* puck = new Target (x, y, text);
+
+ pair<int,Target *> newpair;
+ newpair.first = pucks.size();
+ newpair.second = puck;
+
+ pucks.insert (newpair);
+ puck->visible = true;
+
+ return 0;
+}
+
+int
+Panner2d::add_target (float x, float y)
+{
+ Target *target = new Target (x, y, "");
+
+ pair<int,Target *> newpair;
+ newpair.first = targets.size();
+ newpair.second = target;
+
+ targets.insert (newpair);
+ target->visible = true;
+ queue_draw ();
+
+ return newpair.first;
+}
+
+void
+Panner2d::drop_targets ()
+{
+ for (Targets::iterator i = targets.begin(); i != targets.end(); ) {
+
+ Targets::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ delete i->second;
+ targets.erase (i);
+
+ i = tmp;
+ }
+
+ queue_draw ();
+}
+
+void
+Panner2d::drop_pucks ()
+{
+ for (Targets::iterator i = pucks.begin(); i != pucks.end(); ) {
+
+ Targets::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ delete i->second;
+ pucks.erase (i);
+
+ i = tmp;
+ }
+
+ queue_draw ();
+}
+
+void
+Panner2d::remove_target (int which)
+{
+ Targets::iterator i = targets.find (which);
+
+ if (i != targets.end()) {
+ delete i->second;
+ targets.erase (i);
+ queue_draw ();
+ }
+}
+
+void
+Panner2d::handle_state_change ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &Panner2d::handle_state_change));
+
+ queue_draw ();
+}
+
+void
+Panner2d::move_target (int which, float x, float y)
+{
+ Targets::iterator i = targets.find (which);
+ Target *target;
+
+ if (!allow_target) {
+ return;
+ }
+
+ if (i != targets.end()) {
+ target = i->second;
+ target->x = x;
+ target->y = y;
+
+ queue_draw ();
+ }
+}
+
+void
+Panner2d::move_puck (int which, float x, float y)
+{
+ Targets::iterator i = pucks.find (which);
+ Target *target;
+
+ if (i != pucks.end()) {
+ target = i->second;
+ target->x = x;
+ target->y = y;
+
+ queue_draw ();
+ }
+}
+
+void
+Panner2d::show_puck (int which)
+{
+ Targets::iterator i = pucks.find (which);
+
+ if (i != pucks.end()) {
+ Target* puck = i->second;
+ if (!puck->visible) {
+ puck->visible = true;
+ queue_draw ();
+ }
+ }
+}
+
+void
+Panner2d::hide_puck (int which)
+{
+ Targets::iterator i = pucks.find (which);
+
+ if (i != pucks.end()) {
+ Target* puck = i->second;
+ if (!puck->visible) {
+ puck->visible = false;
+ queue_draw ();
+ }
+ }
+}
+
+void
+Panner2d::show_target (int which)
+{
+ Targets::iterator i = targets.find (which);
+ if (i != targets.end()) {
+ if (!i->second->visible) {
+ i->second->visible = true;
+ queue_draw ();
+ }
+ }
+}
+
+void
+Panner2d::hide_target (int which)
+{
+ Targets::iterator i = targets.find (which);
+ if (i != targets.end()) {
+ if (i->second->visible) {
+ i->second->visible = false;
+ queue_draw ();
+ }
+ }
+}
+
+Panner2d::Target *
+Panner2d::find_closest_object (gdouble x, gdouble y, int& which, bool& is_puck) const
+{
+ gdouble efx, efy;
+ Target *closest = 0;
+ Target *candidate;
+ float distance;
+ float best_distance = FLT_MAX;
+ int pwhich;
+
+ efx = x/width;
+ efy = y/height;
+ which = 0;
+ pwhich = 0;
+ is_puck = false;
+
+ for (Targets::const_iterator i = targets.begin(); i != targets.end(); ++i, ++which) {
+ candidate = i->second;
+
+ distance = sqrt ((candidate->x - efx) * (candidate->x - efx) +
+ (candidate->y - efy) * (candidate->y - efy));
+
+ if (distance < best_distance) {
+ closest = candidate;
+ best_distance = distance;
+ }
+ }
+
+ for (Targets::const_iterator i = pucks.begin(); i != pucks.end(); ++i, ++pwhich) {
+ candidate = i->second;
+
+ distance = sqrt ((candidate->x - efx) * (candidate->x - efx) +
+ (candidate->y - efy) * (candidate->y - efy));
+
+ if (distance < best_distance) {
+ closest = candidate;
+ best_distance = distance;
+ is_puck = true;
+ which = pwhich;
+ }
+ }
+
+ return closest;
+}
+
+gint
+Panner2d::motion_notify_event_impl (GdkEventMotion *ev)
+{
+ gint x, y;
+ GdkModifierType state;
+
+ if (ev->is_hint) {
+ gdk_window_get_pointer (ev->window, &x, &y, &state);
+ } else {
+ x = (int) floor (ev->x);
+ y = (int) floor (ev->y);
+ state = (GdkModifierType) ev->state;
+ }
+ return handle_motion (x, y, state);
+}
+gint
+Panner2d::handle_motion (gint evx, gint evy, GdkModifierType state)
+{
+ if (drag_target == 0 || (state & GDK_BUTTON1_MASK) == 0) {
+ return FALSE;
+ }
+
+ int x, y;
+ bool need_move = false;
+
+ if (!drag_is_puck && !allow_target) {
+ return TRUE;
+ }
+
+ if (allow_x || !drag_is_puck) {
+ float new_x;
+ x = min (evx, width - 1);
+ x = max (x, 0);
+ new_x = (float) x / (width - 1);
+ if (new_x != drag_target->x) {
+ drag_target->x = new_x;
+ need_move = true;
+ }
+ }
+
+ if (allow_y || drag_is_puck) {
+ float new_y;
+ y = min (evy, height - 1);
+ y = max (y, 0);
+ new_y = (float) y / (height - 1);
+ if (new_y != drag_target->y) {
+ drag_target->y = new_y;
+ need_move = true;
+ }
+ }
+
+ if (need_move) {
+ queue_draw ();
+
+ if (drag_is_puck) {
+
+ panner[drag_index]->set_position (drag_target->x, drag_target->y);
+
+ } else {
+
+ TargetMoved (drag_index);
+ }
+ }
+
+ return TRUE;
+}
+
+gint
+Panner2d::expose_event_impl (GdkEventExpose *event)
+{
+ gint x, y;
+ float fx, fy;
+
+ /* redraw the background */
+
+ get_window().draw_rectangle (get_style()->get_bg_gc(get_state()),
+ true,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+
+ if (!panner.bypassed()) {
+
+ for (Targets::iterator i = pucks.begin(); i != pucks.end(); ++i) {
+
+ Target* puck = i->second;
+
+ if (puck->visible) {
+ /* redraw puck */
+
+ fx = min (puck->x, 1.0f);
+ fx = max (fx, -1.0f);
+ x = (gint) floor (width * fx - 4);
+
+ fy = min (puck->y, 1.0f);
+ fy = max (fy, -1.0f);
+ y = (gint) floor (height * fy - 4);
+
+ get_window().draw_arc (get_style()->get_fg_gc(GTK_STATE_NORMAL),
+ true,
+ x, y,
+ 8, 8,
+ 0, 360 * 64);
+ get_window().draw_text (get_style()->get_font(),
+ get_style()->get_fg_gc(GTK_STATE_NORMAL),
+ x + 6, y + 6,
+ puck->text,
+ puck->textlen);
+ }
+ }
+
+ /* redraw any visible targets */
+
+ for (Targets::iterator i = targets.begin(); i != targets.end(); ++i) {
+ Target *target = i->second;
+
+ if (target->visible) {
+
+ /* why -8 ??? why is this necessary ? */
+
+ fx = min (target->x, 1.0f);
+ fx = max (fx, -1.0f);
+ x = (gint) floor ((width - 8) * fx);
+
+ fy = min (target->y, 1.0f);
+ fy = max (fy, -1.0f);
+ y = (gint) floor ((height - 8) * fy);
+
+ get_window().draw_rectangle (get_style()->get_fg_gc(GTK_STATE_ACTIVE),
+ true,
+ x, y,
+ 4, 4);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+gint
+Panner2d::button_press_event_impl (GdkEventButton *ev)
+{
+ switch (ev->button) {
+ case 1:
+ gint x, y;
+ GdkModifierType state;
+
+ drag_target = find_closest_object (ev->x, ev->y, drag_index, drag_is_puck);
+
+ x = (int) floor (ev->x);
+ y = (int) floor (ev->y);
+ state = (GdkModifierType) ev->state;
+
+ return handle_motion (x, y, state);
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+gint
+Panner2d::button_release_event_impl (GdkEventButton *ev)
+{
+ switch (ev->button) {
+ case 1:
+ gint x, y;
+ int ret;
+ GdkModifierType state;
+
+ x = (int) floor (ev->x);
+ y = (int) floor (ev->y);
+ state = (GdkModifierType) ev->state;
+
+ if (drag_is_puck && (Keyboard::modifier_state_contains (state, Keyboard::Shift))) {
+
+ for (Targets::iterator i = pucks.begin(); i != pucks.end(); ++i) {
+ Target* puck = i->second;
+ puck->x = 0.5;
+ puck->y = 0.5;
+ }
+
+ queue_draw ();
+ PuckMoved (-1);
+ ret = TRUE;
+
+ } else {
+ ret = handle_motion (x, y, state);
+ }
+
+ drag_target = 0;
+
+ return ret;
+ break;
+ case 2:
+ toggle_bypass ();
+ return TRUE;
+
+ case 3:
+ show_context_menu ();
+ break;
+
+ }
+
+ return FALSE;
+}
+
+void
+Panner2d::toggle_bypass ()
+{
+ if (bypass_menu_item && (panner.bypassed() != bypass_menu_item->get_active())) {
+ panner.set_bypassed (!panner.bypassed());
+ }
+}
+
+void
+Panner2d::show_context_menu ()
+{
+ using namespace Menu_Helpers;
+
+ if (context_menu == 0) {
+ context_menu = manage (new Menu);
+ context_menu->set_name ("ArdourContextMenu");
+ MenuList& items = context_menu->items();
+
+ items.push_back (CheckMenuElem (_("Bypass")));
+ bypass_menu_item = static_cast<CheckMenuItem*> (items.back());
+ bypass_menu_item->toggled.connect (slot (*this, &Panner2d::toggle_bypass));
+
+ }
+
+ bypass_menu_item->set_active (panner.bypassed());
+ context_menu->popup (1, 0);
+}
+
+void
+Panner2d::allow_x_motion (bool yn)
+{
+ allow_x = yn;
+}
+
+void
+Panner2d::allow_target_motion (bool yn)
+{
+ allow_target = yn;
+}
+
+void
+Panner2d::allow_y_motion (bool yn)
+{
+ allow_y = yn;
+}
+
+int
+Panner2d::puck_position (int which, float& x, float& y)
+{
+ Targets::iterator i;
+
+ if ((i = pucks.find (which)) != pucks.end()) {
+ x = i->second->x;
+ y = i->second->y;
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+Panner2d::target_position (int which, float& x, float& y)
+{
+ Targets::iterator i;
+
+ if ((i = targets.find (which)) != targets.end()) {
+ x = i->second->x;
+ y = i->second->y;
+ return 0;
+ }
+
+ return -1;
+}
+
diff --git a/gtk2_ardour/panner2d.h b/gtk2_ardour/panner2d.h
new file mode 100644
index 0000000000..8161be29f2
--- /dev/null
+++ b/gtk2_ardour/panner2d.h
@@ -0,0 +1,115 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_panner_2d_h__
+#define __ardour_panner_2d_h__
+
+#include <sys/types.h>
+#include <map>
+#include <string>
+#include <gtk--.h>
+
+using std::map;
+using std::string;
+
+namespace ARDOUR {
+ class Panner;
+}
+
+class Panner2d : public Gtk::DrawingArea
+{
+ public:
+ Panner2d (ARDOUR::Panner&, int32_t width, int32_t height);
+ ~Panner2d ();
+
+ int puck_position (int which_puck, float& x, float& y);
+ int target_position (int which_target, float& x, float& y);
+
+ void allow_x_motion(bool);
+ void allow_y_motion(bool);
+ void allow_target_motion (bool);
+
+ void hide_puck (int which);
+ void show_puck (int which);
+ int add_target (float x, float y);
+ int add_puck (const char* text, float x, float y);
+ void hide_target (int);
+ void show_target (int);
+ void remove_target (int);
+ void drop_targets ();
+ void drop_pucks ();
+ void move_target (int, float x, float y);
+ void move_puck (int, float x, float y);
+ void reset (uint32_t n_inputs);
+
+ SigC::Signal1<void,int> PuckMoved;
+ SigC::Signal1<void,int> TargetMoved;
+
+ protected:
+ gint expose_event_impl (GdkEventExpose *);
+ gint button_press_event_impl (GdkEventButton *);
+ gint button_release_event_impl (GdkEventButton *);
+ gint motion_notify_event_impl (GdkEventMotion *);
+ void size_allocate_impl (GtkAllocation* alloc);
+
+ private:
+ struct Target {
+ float x;
+ float y;
+ bool visible;
+ char* text;
+ size_t textlen;
+
+ Target (float xa, float ya, const char* txt = 0);
+ ~Target ();
+ };
+
+ ARDOUR::Panner& panner;
+ Gtk::Menu* context_menu;
+ Gtk::CheckMenuItem* bypass_menu_item;
+
+ typedef map<int,Target *> Targets;
+ Targets targets;
+ Targets pucks;
+
+ Target *drag_target;
+ int drag_index;
+ bool drag_is_puck;
+ bool allow_x;
+ bool allow_y;
+ bool allow_target;
+ int width;
+ int height;
+
+ bool bypassflag;
+
+ gint compute_x (float);
+ gint compute_y (float);
+
+ Target *find_closest_object (gdouble x, gdouble y, int& which, bool& is_puck) const;
+
+ gint handle_motion (gint, gint, GdkModifierType);
+
+ void toggle_bypass ();
+ void show_context_menu ();
+ void handle_state_change ();
+};
+
+#endif /* __ardour_panner_2d_h__ */
diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc
new file mode 100644
index 0000000000..42525466c6
--- /dev/null
+++ b/gtk2_ardour/panner_ui.cc
@@ -0,0 +1,658 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <limits.h>
+
+#include <ardour/io.h>
+#include <ardour/dB.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/barcontroller.h>
+#include <midi++/manager.h>
+#include <pbd/fastlog.h>
+
+#include "ardour_ui.h"
+#include "panner_ui.h"
+#include "panner2d.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include <ardour/session.h>
+#include <ardour/route.h>
+#include <ardour/panner.h>
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtkmmext;
+using namespace Gtk;
+using namespace SigC;
+
+/* XPM */
+static const gchar * forwdblarrow_xpm[] = {
+"20 11 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" .. ",
+" .+. ",
+" .++. ",
+" ..............+++. ",
+" .+++++++++++++++++.",
+" ...................",
+" .+++++++++++++++++.",
+" ..............+++. ",
+" .++. ",
+" .+. ",
+" .. "};
+
+/* XPM */
+static const gchar * revdblarrow_xpm[] = {
+"20 11 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" .. ",
+" .+. ",
+" .++. ",
+" ..............+++. ",
+" .+++++++++++++++++.",
+" ...................",
+" .+++++++++++++++++.",
+" .+++..............",
+" .++. ",
+" .+. ",
+" .. "};
+
+
+PannerUI::PannerUI (IO& io, Session& s)
+ : _io (io),
+ _session (s),
+ panning_up_arrow (GTK_ARROW_UP, GTK_SHADOW_OUT),
+ panning_down_arrow (GTK_ARROW_DOWN, GTK_SHADOW_OUT),
+ panning_link_button (_("link"))
+
+{
+ ignore_toggle = false;
+ pan_menu = 0;
+ in_pan_update = false;
+
+ pan_bar_packer.set_usize (-1, 61);
+ panning_viewport.set_usize (61, 61);
+
+ panning_viewport.set_name (X_("BaseFrame"));
+
+ ARDOUR_UI::instance()->tooltips().set_tip (panning_link_button,
+ _("panning link control"));
+ ARDOUR_UI::instance()->tooltips().set_tip (panning_link_direction_button,
+ _("panning link direction"));
+
+ panning_link_box.pack_start (panning_link_button, true, true);
+ panning_link_box.pack_start (panning_link_direction_button, true, true);
+
+ panning_link_button.set_name (X_("PanningLinkButton"));
+ panning_link_direction_button.set_name (X_("PanningLinkDirectionButton"));
+
+ /* the pixmap will be reset at some point, but the key thing is that
+ we need a pixmap in the button just to get started.
+ */
+
+ panning_link_direction_button.add (*(manage (new Pixmap (forwdblarrow_xpm))));
+
+ panning_link_direction_button.clicked.connect
+ (slot (*this, &PannerUI::panning_link_direction_clicked));
+
+ panning_link_button.button_press_event.connect
+ (slot (*this, &PannerUI::panning_link_button_press));
+ panning_link_button.button_release_event.connect
+ (slot (*this, &PannerUI::panning_link_button_release));
+
+ panning_up.set_border_width (3);
+ panning_down.set_border_width (3);
+ panning_up.add (panning_up_arrow);
+ panning_down.add (panning_down_arrow);
+ panning_up.set_name (X_("PanScrollerBase"));
+ panning_down.set_name (X_("PanScrollerBase"));
+ panning_up_arrow.set_name (X_("PanScrollerArrow"));
+ panning_down_arrow.set_name (X_("PanScrollerArrow"));
+
+ pan_vbox.set_spacing (4);
+ pan_vbox.pack_start (panning_viewport, false, false);
+ pan_vbox.pack_start (panning_link_box, false, false);
+
+ pack_start (pan_vbox, true, false);
+ pan_vbox.show_all ();
+ show ();
+
+ panner = 0;
+
+ _io.panner().Changed.connect (slot (*this, &PannerUI::panner_changed));
+ _io.panner().LinkStateChanged.connect (slot (*this, &PannerUI::update_pan_linkage));
+ _io.panner().StateChanged.connect (slot (*this, &PannerUI::update_pan_state));
+
+ pan_changed (0);
+ update_pan_sensitive ();
+ update_pan_linkage ();
+}
+
+gint
+PannerUI::panning_link_button_press (GdkEventButton* ev)
+{
+ return stop_signal (panning_link_button, "button-press-event");
+}
+
+gint
+PannerUI::panning_link_button_release (GdkEventButton* ev)
+{
+ if (!ignore_toggle) {
+ _io.panner().set_linked (!_io.panner().linked());
+ }
+ return TRUE;
+}
+
+void
+PannerUI::panning_link_direction_clicked()
+{
+ switch (_io.panner().link_direction()) {
+ case Panner::SameDirection:
+ _io.panner().set_link_direction (Panner::OppositeDirection);
+ break;
+ default:
+ _io.panner().set_link_direction (Panner::SameDirection);
+ break;
+ }
+}
+
+void
+PannerUI::update_pan_linkage ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &PannerUI::update_pan_linkage));
+
+ bool x = _io.panner().linked();
+ bool bx = panning_link_button.get_active();
+
+ if (x != bx) {
+
+ ignore_toggle = true;
+ panning_link_button.set_active (x);
+ ignore_toggle = false;
+ }
+
+ panning_link_direction_button.set_sensitive (x);
+
+ switch (_io.panner().link_direction()) {
+ case Panner::SameDirection:
+ static_cast<Pixmap*> (panning_link_direction_button.get_child())->set (forwdblarrow_xpm);
+ break;
+ default:
+ static_cast<Pixmap*> (panning_link_direction_button.get_child())->set (revdblarrow_xpm);
+ break;
+ }
+}
+
+void
+PannerUI::set_width (Width w)
+{
+ switch (w) {
+ case Wide:
+ panning_viewport.set_usize (61, 61);
+ if (panner) {
+ panner->set_usize (61, 61);
+ }
+ for (vector<BarController*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
+ (*i)->set_usize (61, 15);
+ }
+ static_cast<Gtk::Label*> (panning_link_button.get_child())->set_text (_("link"));
+ break;
+ case Narrow:
+ panning_viewport.set_usize (31, 61);
+ if (panner) {
+ panner->set_usize (31, 61);
+ }
+ for (vector<BarController*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
+ (*i)->set_usize (31, 15);
+ }
+ static_cast<Gtk::Label*> (panning_link_button.get_child())->set_text (_("L"));
+ break;
+ }
+
+ _width = w;
+}
+
+
+PannerUI::~PannerUI ()
+{
+ for (vector<Adjustment*>::iterator i = pan_adjustments.begin(); i != pan_adjustments.end(); ++i) {
+ delete (*i);
+ }
+
+ for (vector<BarController*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
+ delete (*i);
+ }
+
+ if (panner) {
+ delete panner;
+ }
+
+ if (pan_menu) {
+ delete pan_menu;
+ }
+
+}
+
+
+gint
+PannerUI::entry_focus_event (GdkEventFocus* ev)
+{
+ if (ev->in) {
+ ARDOUR_UI::instance()->allow_focus (true);
+ } else {
+ ARDOUR_UI::instance()->allow_focus (false);
+ }
+ return TRUE;
+}
+
+void
+PannerUI::panner_changed ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &PannerUI::panner_changed));
+ setup_pan ();
+}
+
+void
+PannerUI::update_pan_state ()
+{
+ /* currently nothing to do */
+ // ENSURE_GUI_THREAD (slot (*this, &PannerUI::update_panner_state));
+}
+
+void
+PannerUI::setup_pan ()
+{
+ uint32_t nouts = _io.n_outputs ();
+
+ if (nouts == 0 || nouts == 1) {
+
+ while (!pan_adjustments.empty()) {
+ delete pan_bars.back();
+ pan_bars.pop_back ();
+ delete pan_adjustments.back();
+ pan_adjustments.pop_back ();
+ }
+
+ } else if (nouts == 2) {
+
+ vector<Adjustment*>::size_type asz;
+ uint32_t npans = _io.panner().size();
+
+ while (!pan_adjustments.empty()) {
+ delete pan_bars.back();
+ pan_bars.pop_back ();
+ delete pan_adjustments.back();
+ pan_adjustments.pop_back ();
+ }
+
+ while ((asz = pan_adjustments.size()) < npans) {
+
+ float x;
+ BarController* bc;
+
+ /* initialize adjustment with current value of panner */
+
+ _io.panner()[asz]->get_position (x);
+
+ pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.05, 0.1));
+ pan_adjustments.back()->value_changed.connect (bind (slot (*this, &PannerUI::pan_adjustment_changed), (uint32_t) asz));
+
+ _io.panner()[asz]->Changed.connect (bind (slot (*this, &PannerUI::pan_value_changed), (uint32_t) asz));
+
+ bc = new BarController (*pan_adjustments[asz],
+ &_io.panner()[asz]->midi_control(),
+ bind (slot (*this, &PannerUI::pan_printer), pan_adjustments[asz]));
+
+ if (_session.midi_port()) {
+ _io.panner()[asz]->reset_midi_control (_session.midi_port(), true);
+ }
+
+ bc->set_name ("PanSlider");
+ bc->set_shadow_type (GTK_SHADOW_NONE);
+ bc->set_style (BarController::Line);
+ bc->get_spin_button().focus_in_event.connect (slot (*this, &PannerUI::entry_focus_event));
+ bc->get_spin_button().focus_out_event.connect (slot (*this, &PannerUI::entry_focus_event));
+
+ bc->StartGesture.connect (bind (slot (_io, &IO::start_pan_touch), (uint32_t) asz));
+ bc->StopGesture.connect (bind (slot (_io, &IO::end_pan_touch), (uint32_t) asz));
+
+ char buf[64];
+ snprintf (buf, sizeof (buf), _("panner for channel %u"), asz + 1);
+ ARDOUR_UI::instance()->tooltips().set_tip (bc->event_widget(), buf);
+
+ bc->event_widget().button_release_event.connect
+ (bind (slot (*this, &PannerUI::pan_button_event), (uint32_t) asz));
+
+ pan_bars.push_back (bc);
+ switch (_width) {
+ case Wide:
+ pan_bars.back()->set_usize (61, 15);
+ break;
+ case Narrow:
+ pan_bars.back()->set_usize (31, 15);
+ break;
+ }
+
+ pan_bar_packer.pack_start (*pan_bars.back(), false, false);
+ }
+
+ /* now that we actually have the pan bars,
+ set their sensitivity based on current
+ automation state.
+ */
+
+ update_pan_sensitive ();
+
+ panning_viewport.remove ();
+ panning_viewport.add (pan_bar_packer);
+ panning_viewport.show_all ();
+
+ } else {
+
+ int w = 0;
+
+ switch (_width) {
+ case Wide:
+ w = 61;
+ break;
+ case Narrow:
+ w = 31;
+ break;
+ }
+
+ if (panner == 0) {
+ panner = new Panner2d (_io.panner(), w, 61);
+ panner->set_name ("MixerPanZone");
+ panner->show ();
+ }
+
+ update_pan_sensitive ();
+ panner->reset (_io.n_inputs());
+ panner->set_usize (w, 61);
+
+ /* and finally, add it to the panner frame */
+
+ panning_viewport.remove ();
+ panning_viewport.add (*panner);
+ panning_viewport.show_all ();
+ }
+}
+
+gint
+PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which)
+{
+ switch (ev->button) {
+ case 3:
+ if (pan_menu == 0) {
+ pan_menu = manage (new Menu);
+ pan_menu->set_name ("ArdourContextMenu");
+ }
+ build_pan_menu (which);
+ pan_menu->popup (1, ev->time);
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return FALSE; // what's wrong with gcc?
+}
+
+void
+PannerUI::build_pan_menu (uint32_t which)
+{
+ using namespace Menu_Helpers;
+ MenuList& items (pan_menu->items());
+
+ items.clear ();
+
+ items.push_back (CheckMenuElem (_("Mute")));
+
+ /* set state first, connect second */
+
+ (dynamic_cast<CheckMenuItem*> (items.back()))->set_active (_io.panner()[which]->muted());
+ (dynamic_cast<CheckMenuItem*> (items.back()))->toggled.connect
+ (bind (slot (*this, &PannerUI::pan_mute), which));
+
+ items.push_back (CheckMenuElem (_("Bypass"), slot (*this, &PannerUI::pan_bypass_toggle)));
+ bypass_menu_item = static_cast<CheckMenuItem*> (items.back());
+
+ /* set state first, connect second */
+
+ bypass_menu_item->set_active (_io.panner().bypassed());
+ bypass_menu_item->toggled.connect (slot (*this, &PannerUI::pan_bypass_toggle));
+
+ items.push_back (MenuElem (_("Reset"), slot (*this, &PannerUI::pan_reset)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Reset all")));
+}
+
+void
+PannerUI::pan_mute (uint32_t which)
+{
+ StreamPanner* sp = _io.panner()[which];
+ sp->set_muted (!sp->muted());
+}
+
+void
+PannerUI::pan_bypass_toggle ()
+{
+ if (bypass_menu_item && (_io.panner().bypassed() != bypass_menu_item->get_active())) {
+ _io.panner().set_bypassed (!_io.panner().bypassed());
+ }
+}
+
+void
+PannerUI::pan_reset ()
+{
+}
+
+void
+PannerUI::effective_pan_display ()
+{
+ if (_io.panner().empty()) {
+ return;
+ }
+
+ switch (_io.n_outputs()) {
+ case 0:
+ case 1:
+ /* relax */
+ break;
+
+ case 2:
+ update_pan_bars (true);
+ break;
+
+ default:
+ //panner->move_puck (pan_value (v, right), 0.5);
+ break;
+ }
+}
+
+void
+PannerUI::pan_changed (void *src)
+{
+ if (src == this) {
+ return;
+ }
+
+ switch (_io.panner().size()) {
+ case 0:
+ panning_link_box.set_sensitive (false);
+ return;
+ case 1:
+ panning_link_box.set_sensitive (false);
+ break;
+ default:
+ panning_link_box.set_sensitive (true);
+ }
+
+ uint32_t nouts = _io.n_outputs();
+
+ switch (nouts) {
+ case 0:
+ case 1:
+ /* relax */
+ break;
+
+ case 2:
+ update_pan_bars (false);
+ break;
+
+ default:
+ // panner->move_puck (pan_value (pans[0], pans[1]), 0.5);
+ break;
+ }
+}
+
+void
+PannerUI::pan_adjustment_changed (uint32_t which)
+{
+ if (!in_pan_update && which < _io.panner().size()) {
+
+ float xpos;
+ float val = pan_adjustments[which]->get_value ();
+ _io.panner()[which]->get_position (xpos);
+
+ /* add a kinda-sorta detent for the middle */
+
+ if (val != 0.5 && Panner::equivalent (val, 0.5)) {
+ /* this is going to be reentrant, so just
+ return after it.
+ */
+
+ in_pan_update = true;
+ pan_adjustments[which]->set_value (0.5);
+ in_pan_update = false;
+ return;
+ }
+
+ if (!Panner::equivalent (val, xpos)) {
+
+ _io.panner()[which]->set_position (val);
+ /* XXX
+ the panner objects have no access to the session,
+ so do this here. ick.
+ */
+ _session.set_dirty();
+ }
+ }
+}
+
+void
+PannerUI::pan_value_changed (uint32_t which)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &PannerUI::pan_value_changed), which));
+
+ if (which < _io.panner().size()) {
+ float xpos;
+ float val = pan_adjustments[which]->get_value ();
+
+ _io.panner()[which]->get_position (xpos);
+
+ if (!Panner::equivalent (val, xpos)) {
+ in_pan_update = true;
+ pan_adjustments[which]->set_value (xpos);
+ in_pan_update = false;
+ }
+ }
+}
+
+void
+PannerUI::update_pan_bars (bool only_if_aplay)
+{
+ uint32_t n;
+ vector<Adjustment*>::iterator i;
+
+ in_pan_update = true;
+
+ /* this runs during automation playback, and moves the bar controllers
+ and/or pucks around.
+ */
+
+ for (i = pan_adjustments.begin(), n = 0; i != pan_adjustments.end(); ++i, ++n) {
+ float xpos, val;
+
+ if (only_if_aplay) {
+ AutomationList& alist (_io.panner()[n]->automation());
+
+ if (!alist.automation_playback()) {
+ continue;
+ }
+ }
+
+ _io.panner()[n]->get_effective_position (xpos);
+ val = (*i)->get_value ();
+
+ if (!Panner::equivalent (val, xpos)) {
+ (*i)->set_value (xpos);
+ }
+ }
+
+ in_pan_update = false;
+}
+
+void
+PannerUI::pan_printer (char *buf, uint32_t len, Adjustment* adj)
+{
+ float val = adj->get_value();
+
+ if (val == 0.0f) {
+ snprintf (buf, len, X_("L"));
+ } else if (val == 1.0f) {
+ snprintf (buf, len, X_("R"));
+ } else if (Panner::equivalent (val, 0.5f)) {
+ snprintf (buf, len, X_("C"));
+ } else {
+ /* don't print anything */
+ buf[0] = '\0';
+ }
+}
+
+void
+PannerUI::update_pan_sensitive ()
+{
+ bool sensitive = !(_io.panner().automation_state() & Play);
+
+ switch (_io.n_outputs()) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ for (vector<BarController*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
+ (*i)->set_sensitive (sensitive);
+ }
+ break;
+ default:
+ if (panner) {
+ panner->set_sensitive (sensitive);
+ }
+ break;
+ }
+}
+
diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h
new file mode 100644
index 0000000000..4a4078bb74
--- /dev/null
+++ b/gtk2_ardour/panner_ui.h
@@ -0,0 +1,121 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_panner_ui_h__
+#define __ardour_gtk_panner_ui_h__
+
+#include <vector>
+#include <gtk--.h>
+#include <gtkmmext/slider_controller.h>
+#include <gtkmmext/click_box.h>
+
+#include "enums.h"
+
+class Panner2d;
+
+namespace ARDOUR {
+ class IO;
+ class Session;
+}
+namespace Gtkmmext {
+ class FastMeter;
+ class BarController;
+}
+
+class PannerUI : public Gtk::HBox
+{
+ public:
+ PannerUI (ARDOUR::IO&, ARDOUR::Session&);
+ ~PannerUI ();
+
+ void pan_changed (void *);
+
+ void update_pan_sensitive ();
+ void update_gain_sensitive ();
+
+ void set_width (Width);
+ void setup_pan ();
+
+ void effective_pan_display ();
+
+ void set_meter_strip_name (string name);
+
+ private:
+ ARDOUR::IO& _io;
+ ARDOUR::Session& _session;
+
+ bool ignore_toggle;
+ bool in_pan_update;
+
+ Panner2d* panner;
+
+ Gtk::VBox pan_bar_packer;
+ Gtk::Viewport panning_viewport;
+ Gtk::EventBox panning_up;
+ Gtk::Arrow panning_up_arrow;
+ Gtk::EventBox panning_down;
+ Gtk::Arrow panning_down_arrow;
+ Gtk::VBox pan_vbox;
+ Width _width;
+
+ gint panning_scroll_button_press_event (GdkEventButton*, int32_t dir);
+ gint panning_scroll_button_release_event (GdkEventButton*, int32_t dir);
+
+ Gtk::ToggleButton panning_link_button;
+ Gtk::Button panning_link_direction_button;
+ Gtk::HBox panning_link_box;
+
+ gint panning_link_button_press (GdkEventButton*);
+ gint panning_link_button_release (GdkEventButton*);
+ void panning_link_direction_clicked ();
+
+ vector<Gtk::Adjustment*> pan_adjustments;
+ vector<Gtkmmext::BarController*> pan_bars;
+
+ void pan_adjustment_changed (uint32_t which);
+ void pan_value_changed (uint32_t which);
+ void pan_printer (char* buf, uint32_t, Gtk::Adjustment*);
+ void update_pan_bars (bool only_if_aplay);
+ void update_pan_linkage ();
+ void update_pan_state ();
+
+ void panner_changed ();
+
+ void hide_pans ();
+
+ void panner_moved (int which);
+ void panner_bypass_toggled ();
+
+ gint start_pan_touch (GdkEventButton*);
+ gint end_pan_touch (GdkEventButton*);
+
+ gint entry_focus_event (GdkEventFocus* ev);
+
+ gint pan_button_event (GdkEventButton*, uint32_t which);
+ Gtk::Menu* pan_menu;
+ Gtk::CheckMenuItem* bypass_menu_item;
+ void build_pan_menu (uint32_t which);
+ void pan_mute (uint32_t which);
+ void pan_reset ();
+ void pan_bypass_toggle ();
+};
+
+#endif /* __ardour_gtk_panner_ui_h__ */
+
diff --git a/gtk2_ardour/pixmaps/SConscript b/gtk2_ardour/pixmaps/SConscript
new file mode 100644
index 0000000000..c532d3551a
--- /dev/null
+++ b/gtk2_ardour/pixmaps/SConscript
@@ -0,0 +1,10 @@
+# -*- python -*-
+
+import os
+import glob
+pixmap_files = glob.glob('*.xpm')
+
+Import('env install_prefix')
+env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour/pixmaps'), pixmap_files))
+
+env.Alias('tarball', env.Distribute(env['DISTTREE'], [ 'SConscript' ] + pixmap_files))
diff --git a/gtk2_ardour/pixmaps/hslider00.xpm b/gtk2_ardour/pixmaps/hslider00.xpm
new file mode 100644
index 0000000000..47d40e1df4
--- /dev/null
+++ b/gtk2_ardour/pixmaps/hslider00.xpm
@@ -0,0 +1,179 @@
+/* XPM */
+static char * hslider00_xpm[] = {
+"38 19 157 2",
+" c None",
+". c #8B8B8B",
+"+ c #8C8C8C",
+"@ c #949494",
+"# c #3C3C3C",
+"$ c #808080",
+"% c #858585",
+"& c #A7A7A7",
+"* c #B8B8B8",
+"= c #CCCCCC",
+"- c #DBDBDB",
+"; c #DEDEDE",
+"> c #FFFFFF",
+", c #E6E6E6",
+"' c #E5E5E5",
+") c #848484",
+"! c #2A2A2A",
+"~ c #383838",
+"{ c #DFDFDF",
+"] c #E2E2E2",
+"^ c #CBCBCB",
+"/ c #888888",
+"( c #626262",
+"_ c #090909",
+": c #6C6C6C",
+"< c #818181",
+"[ c #A1A1A1",
+"} c #ADADAD",
+"| c #C7C7C7",
+"1 c #D4D4D4",
+"2 c #D9D9D9",
+"3 c #D7D7D7",
+"4 c #D1D1D1",
+"5 c #D2D2D2",
+"6 c #CFCFCF",
+"7 c #DCDCDC",
+"8 c #BBBBBB",
+"9 c #696969",
+"0 c #000000",
+"a c #7C7C7C",
+"b c #D8D8D8",
+"c c #D5D5D5",
+"d c #DADADA",
+"e c #C5C5C5",
+"f c #B1B1B1",
+"g c #666666",
+"h c #515151",
+"i c #797979",
+"j c #A8A8A8",
+"k c #C8C8C8",
+"l c #DDDDDD",
+"m c #CACACA",
+"n c #B9B9B9",
+"o c #BDBDBD",
+"p c #646464",
+"q c #A2A2A2",
+"r c #D0D0D0",
+"s c #C2C2C2",
+"t c #D6D6D6",
+"u c #BEBEBE",
+"v c #A6A6A6",
+"w c #5D5D5D",
+"x c #4A4A4A",
+"y c #5C5C5C",
+"z c #6D6D6D",
+"A c #828282",
+"B c #A3A3A3",
+"C c #D3D3D3",
+"D c #AFAFAF",
+"E c #B6B6B6",
+"F c #CDCDCD",
+"G c #C0C0C0",
+"H c #9B9B9B",
+"I c #535353",
+"J c #3D3D3D",
+"K c #545454",
+"L c #7B7B7B",
+"M c #9E9E9E",
+"N c #E7E7E7",
+"O c #9F9F9F",
+"P c #636363",
+"Q c #BABABA",
+"R c #919191",
+"S c #4C4C4C",
+"T c #4E4E4E",
+"U c #787878",
+"V c #999999",
+"W c #BFBFBF",
+"X c #E8E8E8",
+"Y c #C3C3C3",
+"Z c #989898",
+"` c #C6C6C6",
+" . c #ABABAB",
+".. c #B5B5B5",
+"+. c #8A8A8A",
+"@. c #494949",
+"#. c #595959",
+"$. c #959595",
+"%. c #C4C4C4",
+"&. c #B4B4B4",
+"*. c #616161",
+"=. c #CECECE",
+"-. c #B2B2B2",
+";. c #555555",
+">. c #929292",
+",. c #8D8D8D",
+"'. c #5E5E5E",
+"). c #C9C9C9",
+"!. c #A5A5A5",
+"~. c #8F8F8F",
+"{. c #BCBCBC",
+"]. c #898989",
+"^. c #B3B3B3",
+"/. c #AEAEAE",
+"(. c #B7B7B7",
+"_. c #B0B0B0",
+":. c #A9A9A9",
+"<. c #AAAAAA",
+"[. c #585858",
+"}. c #7F7F7F",
+"|. c #7D7D7D",
+"1. c #565656",
+"2. c #ACACAC",
+"3. c #9C9C9C",
+"4. c #878787",
+"5. c #979797",
+"6. c #505050",
+"7. c #7A7A7A",
+"8. c #8E8E8E",
+"9. c #969696",
+"0. c #6B6B6B",
+"a. c #838383",
+"b. c #A0A0A0",
+"c. c #747474",
+"d. c #757575",
+"e. c #3F3F3F",
+"f. c #727272",
+"g. c #909090",
+"h. c #717171",
+"i. c #484848",
+"j. c #4D4D4D",
+"k. c #707070",
+"l. c #686868",
+"m. c #353535",
+"n. c #656565",
+"o. c #606060",
+"p. c #5B5B5B",
+"q. c #6A6A6A",
+"r. c #5F5F5F",
+"s. c #4B4B4B",
+"t. c #373737",
+"u. c #202020",
+"v. c #131313",
+"w. c #0B0B0B",
+"x. c #060606",
+"y. c #030303",
+"z. c #010101",
+" . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + # ",
+"$ % & * = - ; > > > > > > > , ' > ) ! ~ % > { ; ] > > > > > > > > > ^ / ( _ ",
+": < [ } | 1 - 2 3 3 4 4 5 5 6 7 8 9 0 0 a * b 7 c c 7 d c c - 2 4 e f g h 0 ",
+"g i + j k c l 3 1 1 ^ = m m n l o p 0 0 a n 1 q r r ; s r r t f | u v w x 0 ",
+"y z A B s t ' C l l m 6 ^ ^ & d D p 0 0 a E t q F F 7 q ^ ^ 5 f G 8 H I J 0 ",
+"K p L M G b N 3 - - e ^ | | O b o P 0 0 a * b q ^ ^ - q | | 4 f n Q R S ~ 0 ",
+"T w U V W d X b 2 2 G k Y Y Z b D ( 0 0 a * b q ^ ^ - q ` ` r ...n +.S ~ 0 ",
+"@.#.U $.o - X b 3 3 8 %.W W R 3 &.*.0 0 a ..3 q m m d q ` ` =.& -...% S ~ 0 ",
+"@.;.z >.8 7 X d c c E G Q Q ,.b f '.0 0 a -.c q ).).2 q ` ` = !.D f A S ~ 0 ",
+"@.K z ~.n l X 2 C C f {.&.&.].2 &.w 0 0 a ^.C q k k b q m m = B /.} $ S ~ 0 ",
+"@.K z + (.l { ; 4 4 } .././.% 2 E #.0 0 a _.4 q k k 3 q ).).= B } :.$ S ~ 0 ",
+"@.I z +.E l l 7 r r <.D j j < 2 o [.0 0 a /.6 q | | c q ).).F q } & }.S ~ 0 ",
+"@.I z ].E 7 - 3 6 6 & j q q |.2 E 1.0 0 a 2.= q ` ` 5 q k k F q } & }.S ~ 0 ",
+"@.I z / E - b 5 = = !.[ 3.3.a 2 /.I 0 0 a :.| q s s =.q Y Y m q 2.& }.S ~ 0 ",
+"@.I z 4.E l 7 b k ).@ 5.$.$.L t !.6.0 0 a !.G q o o ).q Q Q e q .j }.S ~ 0 ",
+"@.I z 4.^.5 k Y o ^.~.+.+.+.7./.5.@.0 0 a V [ 3.v v &.8.B B -.q 9.+.0.S ~ 0 ",
+"@.I ( a.3.b.~.a.|.|.7.7.c.% i c.d.e.0 0 a + ~.d.a a ].f.7.7.g.|.i h.P i.~ 0 ",
+"i.j.P ( 0.: : 0.k.: 9 ( w l.p 0.P m.0 0 i.n.g o.P w p.p p.q.'.r.p *.r.p.S 0 ",
+" o.s.t.u.v.w.x.y.z.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "};
diff --git a/gtk2_ardour/pixmaps/hslider01.xpm b/gtk2_ardour/pixmaps/hslider01.xpm
new file mode 100644
index 0000000000..65b51b7310
--- /dev/null
+++ b/gtk2_ardour/pixmaps/hslider01.xpm
@@ -0,0 +1,25 @@
+/* XPM */
+static char * hslider01_xpm[] = {
+"149 20 2 1",
+" c None",
+". c #000000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+".....................................................................................................................................................",
+".....................................................................................................................................................",
+".....................................................................................................................................................",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/gtk2_ardour/pixmaps/set-next-button.xpm b/gtk2_ardour/pixmaps/set-next-button.xpm
new file mode 100644
index 0000000000..ab1a47b08b
--- /dev/null
+++ b/gtk2_ardour/pixmaps/set-next-button.xpm
@@ -0,0 +1,1833 @@
+/* XPM */
+static char * set_next_button_xpm[] = {
+"131 34 1796 2",
+" c None",
+". c #526770",
+"+ c #52666E",
+"@ c #4D5F67",
+"# c #495A62",
+"$ c #3C5159",
+"% c #384D56",
+"& c #344954",
+"* c #334853",
+"= c #334852",
+"- c #334750",
+"; c #33474F",
+"> c #33474C",
+", c #33484F",
+"' c #334950",
+") c #33484E",
+"! c #33484D",
+"~ c #33464C",
+"{ c #33464B",
+"] c #33454A",
+"^ c #334349",
+"/ c #334348",
+"( c #334445",
+"_ c #334244",
+": c #334144",
+"< c #304044",
+"[ c #2F4044",
+"} c #2F4145",
+"| c #2F4246",
+"1 c #2F3E44",
+"2 c #2F3F44",
+"3 c #2D3F42",
+"4 c #2C3E42",
+"5 c #2A3C40",
+"6 c #2A3D40",
+"7 c #2B3F40",
+"8 c #2E3E40",
+"9 c #2F3E40",
+"0 c #2C3E40",
+"a c #2B3E40",
+"b c #2A3E40",
+"c c #2A3B40",
+"d c #2A3A40",
+"e c #2A3A41",
+"f c #2A3B41",
+"g c #2A3B3F",
+"h c #2A3A3F",
+"i c #2A383B",
+"j c #2A393B",
+"k c #2A3B3E",
+"l c #2A393C",
+"m c #2A393A",
+"n c #2A383A",
+"o c #28383A",
+"p c #27383A",
+"q c #25393A",
+"r c #25383B",
+"s c #25363C",
+"t c #25343B",
+"u c #25333A",
+"v c #25343A",
+"w c #25353A",
+"x c #25363A",
+"y c #25373A",
+"z c #243538",
+"A c #213133",
+"B c #203032",
+"C c #203031",
+"D c #202E31",
+"E c #1F2D31",
+"F c #1D2D31",
+"G c #1E2E31",
+"H c #202F34",
+"I c #223036",
+"J c #2A3940",
+"K c #314048",
+"L c #48565E",
+"M c #4D5A62",
+"N c #485E63",
+"O c #40575C",
+"P c #2E4247",
+"Q c #26383D",
+"R c #1E3136",
+"S c #1E3036",
+"T c #1F3138",
+"U c #1E3138",
+"V c #1D3138",
+"W c #1F3139",
+"X c #203139",
+"Y c #203035",
+"Z c #202F32",
+"` c #1F2E31",
+" . c #1F2E30",
+".. c #1F2C30",
+"+. c #1E2C30",
+"@. c #1C2C30",
+"#. c #1A2C30",
+"$. c #192C30",
+"%. c #1B2C30",
+"&. c #1B2D2F",
+"*. c #1C2D2E",
+"=. c #1D2C2B",
+"-. c #1B2C2A",
+";. c #192C2A",
+">. c #1A2C2A",
+",. c #1D2C2A",
+"'. c #1E2D2A",
+"). c #1B2C2B",
+"!. c #192C2B",
+"~. c #1B2D2A",
+"{. c #1A2D2A",
+"]. c #1D2D2A",
+"^. c #1B2C2C",
+"/. c #1C2C2D",
+"(. c #202E2F",
+"_. c #1E2D2F",
+":. c #1D2D2F",
+"<. c #1B2B2D",
+"[. c #1A2B2C",
+"}. c #1E2D2D",
+"|. c #1F2C2F",
+"1. c #1E2B2D",
+"2. c #1F2B2C",
+"3. c #202C2A",
+"4. c #202D2B",
+"5. c #202B2B",
+"6. c #202B2A",
+"7. c #1E2B28",
+"8. c #1E2B29",
+"9. c #1D2B2B",
+"0. c #1F2D2E",
+"a. c #1B2A2B",
+"b. c #1A2A2D",
+"c. c #192B2F",
+"d. c #1A2C2C",
+"e. c #192C29",
+"f. c #1C2C2A",
+"g. c #1F2A2A",
+"h. c #1E292A",
+"i. c #1D292A",
+"j. c #1C292A",
+"k. c #1B292A",
+"l. c #1B2A2A",
+"m. c #1A2A2A",
+"n. c #1A2A2B",
+"o. c #19292E",
+"p. c #19292D",
+"q. c #1A292E",
+"r. c #1B292F",
+"s. c #1A2A2C",
+"t. c #1A2B2A",
+"u. c #192C28",
+"v. c #1D2D2C",
+"w. c #1E2E2F",
+"x. c #202E32",
+"y. c #203133",
+"z. c #1F2F32",
+"A. c #1E2E33",
+"B. c #1F2F34",
+"C. c #233338",
+"D. c #35444A",
+"E. c #39474E",
+"F. c #3B4E51",
+"G. c #2C3E41",
+"H. c #203436",
+"I. c #1C3031",
+"J. c #1F3031",
+"K. c #1F3032",
+"L. c #1C3032",
+"M. c #1A3032",
+"N. c #1B3033",
+"O. c #1D3033",
+"P. c #1F2E34",
+"Q. c #1D2C33",
+"R. c #1C282E",
+"S. c #1B262B",
+"T. c #1A262A",
+"U. c #192629",
+"V. c #1A282A",
+"W. c #1D2A2A",
+"X. c #1E2B2A",
+"Y. c #1C2A2A",
+"Z. c #1D2B2A",
+"`. c #1E2B2B",
+" + c #1E2B2F",
+".+ c #1E2B2C",
+"++ c #202D2A",
+"@+ c #212D2A",
+"#+ c #1F2C2A",
+"$+ c #212C2A",
+"%+ c #212B2A",
+"&+ c #212B2B",
+"*+ c #212B2E",
+"=+ c #212B2F",
+"-+ c #202B2F",
+";+ c #202C2E",
+">+ c #212D2C",
+",+ c #212C2E",
+"'+ c #212D2F",
+")+ c #212F2D",
+"!+ c #212F2C",
+"~+ c #212F2B",
+"{+ c #212F29",
+"]+ c #202E29",
+"^+ c #1E2C28",
+"/+ c #1F2D2B",
+"(+ c #212F2E",
+"_+ c #212E2F",
+":+ c #212C2F",
+"<+ c #202C2F",
+"[+ c #1E2C2F",
+"}+ c #1F2E2F",
+"|+ c #202F2F",
+"1+ c #212F2F",
+"2+ c #1F2F2E",
+"3+ c #1E2E2D",
+"4+ c #222F2E",
+"5+ c #24302F",
+"6+ c #222E30",
+"7+ c #202D30",
+"8+ c #1E2D30",
+"9+ c #1E2E30",
+"0+ c #1E2F30",
+"a+ c #212F30",
+"b+ c #232F30",
+"c+ c #272F30",
+"d+ c #262F30",
+"e+ c #242F30",
+"f+ c #223030",
+"g+ c #213030",
+"h+ c #1F3230",
+"i+ c #203230",
+"j+ c #223230",
+"k+ c #23312E",
+"l+ c #24312D",
+"m+ c #25322E",
+"n+ c #26322F",
+"o+ c #23302C",
+"p+ c #1E2C27",
+"q+ c #1C2A28",
+"r+ c #1A2928",
+"s+ c #1A282B",
+"t+ c #1D292E",
+"u+ c #1F2C31",
+"v+ c #253237",
+"w+ c #263539",
+"x+ c #26373A",
+"y+ c #223639",
+"z+ c #213538",
+"A+ c #223338",
+"B+ c #233339",
+"C+ c #26343A",
+"D+ c #213337",
+"E+ c #223438",
+"F+ c #24363A",
+"G+ c #313F44",
+"H+ c #334146",
+"I+ c #314244",
+"J+ c #223435",
+"K+ c #213134",
+"L+ c #203034",
+"M+ c #223336",
+"N+ c #243439",
+"O+ c #243539",
+"P+ c #243639",
+"Q+ c #24353A",
+"R+ c #23343A",
+"S+ c #203136",
+"T+ c #182628",
+"U+ c #19252A",
+"V+ c #1A262B",
+"W+ c #212E33",
+"X+ c #263338",
+"Y+ c #2D3A40",
+"Z+ c #313E43",
+"`+ c #364346",
+" @ c #384548",
+".@ c #394749",
+"+@ c #394649",
+"@@ c #39494A",
+"#@ c #39484A",
+"$@ c #394849",
+"%@ c #39484C",
+"&@ c #39484D",
+"*@ c #39494D",
+"=@ c #394A4D",
+"-@ c #3B4A4D",
+";@ c #3C4A4D",
+">@ c #3D4A4D",
+",@ c #3E4A4D",
+"'@ c #3E4C4D",
+")@ c #3D4C4D",
+"!@ c #3D4B4D",
+"~@ c #3E4B4E",
+"{@ c #3F4B4F",
+"]@ c #414D51",
+"^@ c #414E52",
+"/@ c #414F50",
+"(@ c #415051",
+"_@ c #3F4D50",
+":@ c #3E4C4F",
+"<@ c #404E51",
+"[@ c #414F52",
+"}@ c #415155",
+"|@ c #415055",
+"1@ c #435055",
+"2@ c #455257",
+"3@ c #445257",
+"4@ c #425256",
+"5@ c #435255",
+"6@ c #455255",
+"7@ c #455256",
+"8@ c #455359",
+"9@ c #455259",
+"0@ c #455459",
+"a@ c #45555A",
+"b@ c #45545D",
+"c@ c #45545E",
+"d@ c #45555E",
+"e@ c #45555F",
+"f@ c #465661",
+"g@ c #485762",
+"h@ c #495862",
+"i@ c #4A5862",
+"j@ c #4B5862",
+"k@ c #4D5861",
+"l@ c #4C585E",
+"m@ c #4A585B",
+"n@ c #47585B",
+"o@ c #45585C",
+"p@ c #465960",
+"q@ c #475961",
+"r@ c #4B5A62",
+"s@ c #4C5A62",
+"t@ c #4D5962",
+"u@ c #4D5B62",
+"v@ c #4A595F",
+"w@ c #425356",
+"x@ c #3B4B4F",
+"y@ c #344347",
+"z@ c #273939",
+"A@ c #203332",
+"B@ c #1B2C2D",
+"C@ c #1F3033",
+"D@ c #2B3C42",
+"E@ c #304047",
+"F@ c #35444C",
+"G@ c #2F4347",
+"H@ c #2D4145",
+"I@ c #2E3E45",
+"J@ c #2E3D45",
+"K@ c #2F3D45",
+"L@ c #2E3B43",
+"M@ c #2D3A41",
+"N@ c #2C3B42",
+"O@ c #2D3C44",
+"P@ c #34434B",
+"Q@ c #36444D",
+"R@ c #324548",
+"S@ c #27393C",
+"T@ c #2A383F",
+"U@ c #2B3940",
+"V@ c #2E3D43",
+"W@ c #303F45",
+"X@ c #334149",
+"Y@ c #33424A",
+"Z@ c #33424B",
+"`@ c #29383C",
+" # c #223232",
+".# c #182824",
+"+# c #22302F",
+"@# c #2B3838",
+"## c #434F57",
+"$# c #515C67",
+"%# c #606D7B",
+"&# c #667583",
+"*# c #6C7D8C",
+"=# c #71818E",
+"-# c #748390",
+";# c #728290",
+"># c #718290",
+",# c #718391",
+"'# c #718390",
+")# c #718491",
+"!# c #718592",
+"~# c #718593",
+"{# c #728693",
+"]# c #728792",
+"^# c #768791",
+"/# c #788891",
+"(# c #7A8C93",
+"_# c #7A8B93",
+":# c #7A8993",
+"<# c #798894",
+"[# c #788794",
+"}# c #798996",
+"|# c #798B98",
+"1# c #7A8D9C",
+"2# c #7A8C9C",
+"3# c #7A8B9B",
+"4# c #798997",
+"5# c #788895",
+"6# c #7A8C99",
+"7# c #7B8D9B",
+"8# c #7D8E9D",
+"9# c #7C8D9D",
+"0# c #7A8B9A",
+"a# c #7B8C9D",
+"b# c #7D8D9F",
+"c# c #808FA2",
+"d# c #8192A3",
+"e# c #8193A4",
+"f# c #8293A4",
+"g# c #8292A4",
+"h# c #8394A4",
+"i# c #8395A4",
+"j# c #8697A8",
+"k# c #8393A4",
+"l# c #8192A2",
+"m# c #7F91A0",
+"n# c #8294A3",
+"o# c #8495A5",
+"p# c #8496A7",
+"q# c #8496A8",
+"r# c #8596A8",
+"s# c #8497AA",
+"t# c #8597AA",
+"u# c #8897A9",
+"v# c #8997AA",
+"w# c #8A98AC",
+"x# c #8799AC",
+"y# c #8699AC",
+"z# c #8398AA",
+"A# c #8297A8",
+"B# c #8296A5",
+"C# c #8497A8",
+"D# c #8395A6",
+"E# c #8496A5",
+"F# c #8194A2",
+"G# c #7B909C",
+"H# c #738790",
+"I# c #6B7D85",
+"J# c #4F5F63",
+"K# c #3D4E4E",
+"L# c #203430",
+"M# c #223533",
+"N# c #364449",
+"O# c #3B494F",
+"P# c #404D54",
+"Q# c #3C4D54",
+"R# c #3A4C54",
+"S# c #3A4852",
+"T# c #3A4751",
+"U# c #39464E",
+"V# c #36434B",
+"W# c #324049",
+"X# c #32404A",
+"Y# c #35464E",
+"Z# c #36474F",
+"`# c #3A4C51",
+" $ c #314348",
+".$ c #354249",
+"+$ c #38434B",
+"@$ c #3A474F",
+"#$ c #3D4952",
+"$$ c #404B56",
+"%$ c #404B57",
+"&$ c #404B58",
+"*$ c #3F4C57",
+"=$ c #3C4B52",
+"-$ c #304042",
+";$ c #273736",
+">$ c #192A24",
+",$ c #2E3C39",
+"'$ c #3E4A4A",
+")$ c #5F6974",
+"!$ c #717B8C",
+"~$ c #8795AC",
+"{$ c #8F9FB7",
+"]$ c #95A9C2",
+"^$ c #98AAC3",
+"/$ c #9AABC3",
+"($ c #9AABC2",
+"_$ c #9BACC3",
+":$ c #9DAFC5",
+"<$ c #9EAFC6",
+"[$ c #9EAEC6",
+"}$ c #9EADC6",
+"|$ c #9DADC6",
+"1$ c #9CADC6",
+"2$ c #9AADC5",
+"3$ c #99ADC4",
+"4$ c #99ACC4",
+"5$ c #99ACC3",
+"6$ c #9BAEC3",
+"7$ c #9BAFC4",
+"8$ c #9CB1C8",
+"9$ c #9CB0C8",
+"0$ c #9BAEC7",
+"a$ c #98ABC4",
+"b$ c #97AAC3",
+"c$ c #9BADC6",
+"d$ c #9DAEC8",
+"e$ c #9FB0CB",
+"f$ c #9EAFCB",
+"g$ c #9CADCA",
+"h$ c #9BADC9",
+"i$ c #A0B1CC",
+"j$ c #9EB1CE",
+"k$ c #9DAFCB",
+"l$ c #9BADC8",
+"m$ c #9BACC5",
+"n$ c #9BADC4",
+"o$ c #9BADC5",
+"p$ c #9BADCA",
+"q$ c #9CADC9",
+"r$ c #9DADC8",
+"s$ c #9EAFCA",
+"t$ c #9EB0CB",
+"u$ c #9EAFC9",
+"v$ c #9EAEC8",
+"w$ c #9DACC7",
+"x$ c #9DADC7",
+"y$ c #9EAFC8",
+"z$ c #9FB1C7",
+"A$ c #9FB2C7",
+"B$ c #9FB3C9",
+"C$ c #9EB2C9",
+"D$ c #9BAFC7",
+"E$ c #9AAFC5",
+"F$ c #99AEC3",
+"G$ c #9AB0C6",
+"H$ c #9AB1C8",
+"I$ c #9BB0CA",
+"J$ c #99AEC8",
+"K$ c #98ACC6",
+"L$ c #99AAC3",
+"M$ c #9AABC4",
+"N$ c #99ADC5",
+"O$ c #98ADC5",
+"P$ c #95ABC3",
+"Q$ c #94AAC3",
+"R$ c #94A9C3",
+"S$ c #95A9C3",
+"T$ c #96A9C3",
+"U$ c #98ACC5",
+"V$ c #99ADC6",
+"W$ c #99AEC7",
+"X$ c #9AAFC7",
+"Y$ c #9DB1C6",
+"Z$ c #95A8B9",
+"`$ c #8D9EAB",
+" % c #6D7F85",
+".% c #57696A",
+"+% c #293E39",
+"@% c #273B38",
+"#% c #425259",
+"$% c #485760",
+"%% c #45575F",
+"&% c #44565D",
+"*% c #42515A",
+"=% c #414F59",
+"-% c #404D58",
+";% c #3D4A54",
+">% c #3A4750",
+",% c #384550",
+"'% c #384551",
+")% c #3B4754",
+"!% c #3C4855",
+"~% c #3C4F56",
+"{% c #34484F",
+"]% c #3A4A53",
+"^% c #3E4C56",
+"/% c #425059",
+"(% c #45525B",
+"_% c #49545E",
+":% c #4A555E",
+"<% c #49565E",
+"[% c #45535B",
+"}% c #37454B",
+"|% c #2E3C3E",
+"1% c #202E2B",
+"2% c #394344",
+"3% c #4D5459",
+"4% c #6C7484",
+"5% c #7C869A",
+"6% c #8D9AB2",
+"7% c #909EB7",
+"8% c #919FB9",
+"9% c #8F9DB7",
+"0% c #8E9BB6",
+"a% c #8A9AB5",
+"b% c #8899B4",
+"c% c #8798B4",
+"d% c #8797B4",
+"e% c #8796B4",
+"f% c #8696B4",
+"g% c #8596B4",
+"h% c #8395B4",
+"i% c #8395B3",
+"j% c #8395B1",
+"k% c #8395B2",
+"l% c #8596B0",
+"m% c #8596B1",
+"n% c #8696B2",
+"o% c #8495B0",
+"p% c #8394B0",
+"q% c #8393B0",
+"r% c #8495B4",
+"s% c #8595B4",
+"t% c #8695B4",
+"u% c #8496B0",
+"v% c #8395AB",
+"w% c #8394AB",
+"x% c #8393AB",
+"y% c #8392AB",
+"z% c #8494AC",
+"A% c #8695AE",
+"B% c #8796AF",
+"C% c #8594AE",
+"D% c #8593AD",
+"E% c #8595AE",
+"F% c #8594AC",
+"G% c #8594AB",
+"H% c #8396AB",
+"I% c #8397AB",
+"J% c #8395AD",
+"K% c #8394AE",
+"L% c #8395B0",
+"M% c #8394AF",
+"N% c #8393AD",
+"O% c #8392AC",
+"P% c #8193A9",
+"Q% c #8293A9",
+"R% c #8394A9",
+"S% c #8495A7",
+"T% c #76878E",
+"U% c #68787B",
+"V% c #374844",
+"W% c #324340",
+"X% c #405153",
+"Y% c #45585D",
+"Z% c #4A5D65",
+"`% c #495C63",
+" & c #485B62",
+".& c #485962",
+"+& c #465660",
+"@& c #43535D",
+"#& c #40505A",
+"$& c #3E4D57",
+"%& c #3A4953",
+"&& c #3A4853",
+"*& c #3D4B56",
+"=& c #3E4C57",
+"-& c #44545C",
+";& c #3E4E57",
+">& c #404F59",
+",& c #42515B",
+"'& c #49575E",
+")& c #4A5960",
+"!& c #4A5A62",
+"~& c #4A5B62",
+"{& c #47585E",
+"]& c #303D41",
+"^& c #252E31",
+"/& c #3D464E",
+"(& c #505964",
+"_& c #6B7785",
+":& c #778495",
+"<& c #808EA4",
+"[& c #8290A8",
+"}& c #8390A9",
+"|& c #838FA7",
+"1& c #828EA6",
+"2& c #808CA4",
+"3& c #808DA4",
+"4& c #808FA4",
+"5& c #7D8DA3",
+"6& c #7B8CA2",
+"7& c #7B8DA4",
+"8& c #7B8CA4",
+"9& c #7B8CA3",
+"0& c #7B8DA3",
+"a& c #7C8DA4",
+"b& c #8290A4",
+"c& c #838FA4",
+"d& c #838EA4",
+"e& c #838DA4",
+"f& c #818DA2",
+"g& c #808DA1",
+"h& c #828DA3",
+"i& c #828FA3",
+"j& c #818EA2",
+"k& c #7F8CA0",
+"l& c #7E8CA0",
+"m& c #7F8DA1",
+"n& c #7F8DA2",
+"o& c #7F8EA3",
+"p& c #8090A6",
+"q& c #8090A7",
+"r& c #8090A9",
+"s& c #8090A8",
+"t& c #808FA6",
+"u& c #808FA5",
+"v& c #808EA3",
+"w& c #808DA2",
+"x& c #808CA1",
+"y& c #808EA0",
+"z& c #7F8E9D",
+"A& c #75848D",
+"B& c #69777C",
+"C& c #394647",
+"D& c #344142",
+"E& c #415053",
+"F& c #46585E",
+"G& c #4A5F67",
+"H& c #4A5E67",
+"I& c #4A5D66",
+"J& c #475B61",
+"K& c #42585F",
+"L& c #41545B",
+"M& c #415058",
+"N& c #3D4C54",
+"O& c #3D4B54",
+"P& c #404D56",
+"Q& c #414E57",
+"R& c #45595E",
+"S& c #41545A",
+"T& c #42555B",
+"U& c #43565C",
+"V& c #4A5D64",
+"W& c #4B6067",
+"X& c #4D6068",
+"Y& c #4E6068",
+"Z& c #4E5F67",
+"`& c #37484D",
+" * c #2E3E42",
+".* c #253035",
+"+* c #3D464F",
+"@* c #4F5863",
+"#* c #677684",
+"$* c #738494",
+"%* c #818DA3",
+"&* c #828CA4",
+"** c #7C89A2",
+"=* c #7B8AA2",
+"-* c #7B8AA1",
+";* c #7B8BA2",
+">* c #7B89A1",
+",* c #7B89A0",
+"'* c #7B899F",
+")* c #7B889C",
+"!* c #7B889B",
+"~* c #7B8799",
+"{* c #7B879A",
+"]* c #7C8AA2",
+"^* c #7F8CA2",
+"/* c #808CA2",
+"(* c #818CA2",
+"_* c #7E8C9F",
+":* c #7D8C9E",
+"<* c #7E8D9F",
+"[* c #7D8D9E",
+"}* c #7B8B9C",
+"|* c #7B8C9C",
+"1* c #7D8C9D",
+"2* c #7F8C9F",
+"3* c #808B9F",
+"4* c #808A9F",
+"5* c #7F8B9F",
+"6* c #7C8C9D",
+"7* c #7C8B9D",
+"8* c #7C8A9C",
+"9* c #7B889A",
+"0* c #7B8697",
+"a* c #7B8696",
+"b* c #7B8797",
+"c* c #7B8999",
+"d* c #7B8C9E",
+"e* c #7B8BA0",
+"f* c #7B8BA1",
+"g* c #7B8DA2",
+"h* c #7B8B9F",
+"i* c #7B8A9D",
+"j* c #7B8A9C",
+"k* c #7C8A9D",
+"l* c #7B8B9B",
+"m* c #7B8B99",
+"n* c #74838B",
+"o* c #3C4647",
+"p* c #364142",
+"q* c #3E5053",
+"r* c #45575E",
+"s* c #4A5D67",
+"t* c #4A5D68",
+"u* c #4A5C63",
+"v* c #495962",
+"w* c #45565E",
+"x* c #41535B",
+"y* c #3D4E56",
+"z* c #404E57",
+"A* c #475960",
+"B* c #495E64",
+"C* c #4C616A",
+"D* c #4D616A",
+"E* c #4B5B62",
+"F* c #374849",
+"G* c #2F3F3F",
+"H* c #263336",
+"I* c #39474B",
+"J* c #48575D",
+"K* c #667684",
+"L* c #748495",
+"M* c #7C8B9F",
+"N* c #7D8CA0",
+"O* c #7E8B9F",
+"P* c #7D8B9E",
+"Q* c #7B899C",
+"R* c #7B8B9D",
+"S* c #7B8A9E",
+"T* c #7B8595",
+"U* c #7B8594",
+"V* c #7B8695",
+"W* c #7B8798",
+"X* c #7B8698",
+"Y* c #7B8998",
+"Z* c #7C8999",
+"`* c #7E899A",
+" = c #7C8A9A",
+".= c #7B8B9A",
+"+= c #7B899A",
+"@= c #7B8A9A",
+"#= c #7D8898",
+"$= c #7C8797",
+"%= c #7C8696",
+"&= c #7B8897",
+"*= c #7B899B",
+"== c #7B8D9C",
+"-= c #74828B",
+";= c #3D4647",
+">= c #4A5C67",
+",= c #4A5E69",
+"'= c #4A5F69",
+")= c #4A5F65",
+"!= c #4A5E63",
+"~= c #475860",
+"{= c #44555F",
+"]= c #3E4F57",
+"^= c #3D4D54",
+"/= c #425962",
+"(= c #3C535C",
+"_= c #435760",
+":= c #475A62",
+"<= c #4A6065",
+"[= c #4A6166",
+"}= c #4A6066",
+"|= c #4A5F66",
+"1= c #37494C",
+"2= c #304144",
+"3= c #29383B",
+"4= c #3A484D",
+"5= c #48565C",
+"6= c #647481",
+"7= c #718291",
+"8= c #798A9A",
+"9= c #7A8B9C",
+"0= c #7A899A",
+"a= c #798998",
+"b= c #73828B",
+"c= c #4A5D69",
+"d= c #4A5D62",
+"e= c #485960",
+"f= c #46555F",
+"g= c #3F4F57",
+"h= c #45595F",
+"i= c #40555C",
+"j= c #445960",
+"k= c #475C62",
+"l= c #4B5F65",
+"m= c #4D6066",
+"n= c #4F6169",
+"o= c #4C6067",
+"p= c #4A5D63",
+"q= c #47595E",
+"r= c #3B494E",
+"s= c #344145",
+"t= c #29383A",
+"u= c #3A4A50",
+"v= c #485861",
+"w= c #64737F",
+"x= c #71808D",
+"y= c #7A889A",
+"z= c #7B869C",
+"A= c #7B879C",
+"B= c #8190A2",
+"C= c #8E9EB0",
+"D= c #8E9DAF",
+"E= c #8E9DAE",
+"F= c #8E9DAD",
+"G= c #8E9BAA",
+"H= c #8793A2",
+"I= c #818C9B",
+"J= c #818E9F",
+"K= c #8797A9",
+"L= c #8E9DB0",
+"M= c #8D9DAF",
+"N= c #7B859C",
+"O= c #7A8A98",
+"P= c #69777D",
+"Q= c #3D474D",
+"R= c #364148",
+"S= c #3C4D55",
+"T= c #42555D",
+"U= c #475C63",
+"V= c #495F63",
+"W= c #4A6063",
+"X= c #4A5E62",
+"Y= c #485A60",
+"Z= c #46575F",
+"`= c #3F5159",
+" - c #3D4E57",
+".- c #404E59",
+"+- c #414E5A",
+"@- c #455A5F",
+"#- c #41565C",
+"$- c #455A60",
+"%- c #495E65",
+"&- c #4A6067",
+"*- c #4B616A",
+"=- c #344245",
+"-- c #293A39",
+";- c #3B4C4F",
+">- c #495A61",
+",- c #65727D",
+"'- c #727D8B",
+")- c #7A8598",
+"!- c #7B879B",
+"~- c #7B859B",
+"{- c #A2B2C4",
+"]- c #B6C9D8",
+"^- c #7A899B",
+"/- c #8E9EAF",
+"(- c #A2B2C1",
+"_- c #9BAAB9",
+":- c #7C8796",
+"<- c #7D8897",
+"[- c #818C9C",
+"}- c #7B8596",
+"|- c #9BAABB",
+"1- c #95A4B6",
+"2- c #7B8896",
+"3- c #74828C",
+"4- c #6A777F",
+"5- c #3F494E",
+"6- c #374448",
+"7- c #3D4F55",
+"8- c #42565C",
+"9- c #475B62",
+"0- c #495F62",
+"a- c #4A6163",
+"b- c #4C5F65",
+"c- c #42535B",
+"d- c #40515A",
+"e- c #41505A",
+"f- c #455B5F",
+"g- c #41575C",
+"h- c #455860",
+"i- c #4A616A",
+"j- c #4A5C61",
+"k- c #47585D",
+"l- c #3B484E",
+"m- c #344146",
+"n- c #293A3B",
+"o- c #3C4C50",
+"p- c #4B5A61",
+"q- c #66717D",
+"r- c #727C8B",
+"s- c #7A8397",
+"t- c #7B859A",
+"u- c #95A3B3",
+"v- c #A2B2C3",
+"w- c #8E9CAF",
+"x- c #9BABBB",
+"y- c #798797",
+"z- c #778594",
+"A- c #8D9BAC",
+"B- c #A8B9C9",
+"C- c #A8B9C8",
+"D- c #AFC1D0",
+"E- c #84909F",
+"F- c #7C8695",
+"G- c #9BAABA",
+"H- c #818C9E",
+"I- c #818EA1",
+"J- c #8D9CAC",
+"K- c #8E9CAC",
+"L- c #8E9BAE",
+"M- c #7B8598",
+"N- c #74828E",
+"O- c #6A7781",
+"P- c #3F4A4E",
+"Q- c #394548",
+"R- c #405055",
+"S- c #45565C",
+"T- c #4A5F62",
+"U- c #4C6066",
+"V- c #4B5E65",
+"W- c #41515A",
+"X- c #3A494F",
+"Y- c #485661",
+"Z- c #656F7D",
+"`- c #727B8B",
+" ; c #7A8297",
+".; c #7B849A",
+"+; c #7B8597",
+"@; c #8F9CAB",
+"#; c #8E9BAB",
+"$; c #8E9AAA",
+"%; c #7B8294",
+"&; c #7B8496",
+"*; c #7B8A97",
+"=; c #74828A",
+"-; c #6A777D",
+";; c #394448",
+">; c #4A6062",
+",; c #4A5E64",
+"'; c #41535A",
+"); c #4D6067",
+"!; c #4F616A",
+"~; c #4C6167",
+"{; c #4A6165",
+"]; c #495D63",
+"^; c #3A484E",
+"/; c #334145",
+"(; c #3A484C",
+"_; c #48555B",
+":; c #646F7B",
+"<; c #717B8A",
+"[; c #7A8396",
+"}; c #7B8499",
+"|; c #7B8599",
+"1; c #95A3B2",
+"2; c #7B8494",
+"3; c #8D99AA",
+"4; c #788194",
+"5; c #798694",
+"6; c #73818C",
+"7; c #6A7780",
+"8; c #3F4B4E",
+"9; c #384648",
+"0; c #3F5155",
+"a; c #4A5F63",
+"b; c #485A61",
+"c; c #46585F",
+"d; c #445359",
+"e; c #4A6167",
+"f; c #465D63",
+"g; c #42575E",
+"h; c #36464E",
+"i; c #303F47",
+"j; c #29383E",
+"k; c #38464D",
+"l; c #636D79",
+"m; c #707A88",
+"n; c #798292",
+"o; c #7B8495",
+"p; c #7B8394",
+"q; c #768394",
+"r; c #798494",
+"s; c #74828D",
+"t; c #697881",
+"u; c #3D4D4E",
+"v; c #364748",
+"w; c #3E5155",
+"x; c #4A5E68",
+"y; c #4A5F6A",
+"z; c #4A5E6A",
+"A; c #46595F",
+"B; c #42545A",
+"C; c #425258",
+"D; c #455557",
+"E; c #465557",
+"F; c #37494E",
+"G; c #304147",
+"H; c #626D79",
+"I; c #6F7A88",
+"J; c #788192",
+"K; c #7A8394",
+"L; c #3D4D50",
+"M; c #36474A",
+"N; c #3E5156",
+"O; c #45565D",
+"P; c #4A5D6A",
+"Q; c #465C5F",
+"R; c #42595C",
+"S; c #475A60",
+"T; c #495C62",
+"U; c #4A5E65",
+"V; c #606D79",
+"W; c #6D7988",
+"X; c #748092",
+"Y; c #778294",
+"Z; c #7A8294",
+"`; c #7B8194",
+" > c #74818D",
+".> c #697882",
+"+> c #36474E",
+"@> c #3E5157",
+"#> c #4A5C65",
+"$> c #465C63",
+"%> c #435960",
+"&> c #4A5C62",
+"*> c #4A6169",
+"=> c #475A5E",
+"-> c #455159",
+";> c #5D6C79",
+">> c #6A7888",
+",> c #768092",
+"'> c #798294",
+")> c #788294",
+"!> c #758194",
+"~> c #778194",
+"{> c #798194",
+"]> c #7A8194",
+"^> c #3D4D55",
+"/> c #4A5C64",
+"(> c #42595F",
+"_> c #465A61",
+":> c #485C62",
+"<> c #4A6064",
+"[> c #4A6168",
+"}> c #47595F",
+"|> c #37494F",
+"1> c #304247",
+"2> c #29393D",
+"3> c #35464C",
+"4> c #405159",
+"5> c #5E6C79",
+"6> c #6C7988",
+"7> c #778292",
+"8> c #7A8494",
+"9> c #748194",
+"0> c #748294",
+"a> c #778394",
+"b> c #A2B1C1",
+"c> c #808B9B",
+"d> c #9AAAB9",
+"e> c #7A8594",
+"f> c #A1B1C1",
+"g> c #8B9AAA",
+"h> c #758394",
+"i> c #768494",
+"j> c #778494",
+"k> c #788494",
+"l> c #798393",
+"m> c #788293",
+"n> c #727F8B",
+"o> c #687680",
+"p> c #3F4D55",
+"q> c #39484F",
+"r> c #3F515A",
+"s> c #455761",
+"t> c #4A5C66",
+"u> c #415159",
+"v> c #445458",
+"w> c #41585C",
+"x> c #496062",
+"y> c #4A6164",
+"z> c #47585F",
+"A> c #374A50",
+"B> c #304347",
+"C> c #293C3C",
+"D> c #35484C",
+"E> c #405259",
+"F> c #616D79",
+"G> c #6F7988",
+"H> c #788394",
+"I> c #8391A2",
+"J> c #7D8B9B",
+"K> c #758294",
+"L> c #A0B1C1",
+"M> c #8999AA",
+"N> c #738394",
+"O> c #738294",
+"P> c #758494",
+"Q> c #798594",
+"R> c #768393",
+"S> c #748292",
+"T> c #707E8A",
+"U> c #68757E",
+"V> c #424B52",
+"W> c #3B464E",
+"X> c #3F515C",
+"Y> c #455864",
+"Z> c #475A5F",
+"`> c #374B50",
+" , c #304449",
+"., c #293C40",
+"+, c #36484E",
+"@, c #415259",
+"#, c #738194",
+"$, c #788594",
+"%, c #748393",
+"&, c #748392",
+"*, c #737E8A",
+"=, c #6B757E",
+"-, c #434B52",
+";, c #455964",
+">, c #4A6068",
+",, c #455C5F",
+"', c #41595C",
+"), c #394C52",
+"!, c #32454B",
+"~, c #293C41",
+"{, c #38484E",
+"], c #636C76",
+"^, c #707884",
+"/, c #798192",
+"(, c #768294",
+"_, c #748394",
+":, c #768594",
+"<, c #768493",
+"[, c #788492",
+"}, c #757E8A",
+"|, c #6C757F",
+"1, c #444F54",
+"2, c #3C4950",
+"3, c #40515C",
+"4, c #455963",
+"5, c #4A5F68",
+"6, c #455C64",
+"7, c #415962",
+"8, c #455A62",
+"9, c #3B4C54",
+"0, c #34454C",
+"a, c #778393",
+"b, c #788393",
+"c, c #788493",
+"d, c #758392",
+"e, c #727E8A",
+"f, c #6A757F",
+"g, c #444E54",
+"h, c #3C494F",
+"i, c #405157",
+"j, c #455660",
+"k, c #4A5B67",
+"l, c #465E62",
+"m, c #425A5E",
+"n, c #475C61",
+"o, c #495E62",
+"p, c #4A5F64",
+"q, c #394C55",
+"r, c #33454B",
+"s, c #2C3A3D",
+"t, c #444E52",
+"u, c #616C73",
+"v, c #6E7983",
+"w, c #768191",
+"x, c #778293",
+"y, c #778192",
+"z, c #798293",
+"A, c #7A8293",
+"B, c #798493",
+"C, c #748192",
+"D, c #738192",
+"E, c #738291",
+"F, c #738392",
+"G, c #748492",
+"H, c #758492",
+"I, c #748493",
+"J, c #768293",
+"K, c #758192",
+"L, c #778092",
+"M, c #788092",
+"N, c #788093",
+"O, c #778094",
+"P, c #768094",
+"Q, c #758094",
+"R, c #7A8393",
+"S, c #7A8492",
+"T, c #7B828F",
+"U, c #7A838E",
+"V, c #77848D",
+"W, c #76838E",
+"X, c #75828E",
+"Y, c #75828F",
+"Z, c #75818F",
+"`, c #73838D",
+" ' c #6F7D85",
+".' c #66737C",
+"+' c #394651",
+"@' c #3E5057",
+"#' c #45585E",
+"$' c #4C6267",
+"%' c #4D6269",
+"&' c #465761",
+"*' c #42535D",
+"=' c #41525B",
+"-' c #41545E",
+";' c #41555E",
+">' c #465E63",
+",' c #435A60",
+"'' c #485C61",
+")' c #475B60",
+"!' c #394B52",
+"~' c #324348",
+"{' c #354247",
+"]' c #404B50",
+"^' c #5C6971",
+"/' c #697681",
+"(' c #737F8E",
+"_' c #758191",
+":' c #768194",
+"<' c #798394",
+"[' c #768192",
+"}' c #737F90",
+"|' c #738190",
+"1' c #758193",
+"2' c #738290",
+"3' c #738391",
+"4' c #738191",
+"5' c #73828F",
+"6' c #73838E",
+"7' c #73828E",
+"8' c #73818E",
+"9' c #738193",
+"0' c #738091",
+"a' c #737F8D",
+"b' c #737F8B",
+"c' c #74808C",
+"d' c #74808E",
+"e' c #768093",
+"f' c #767F94",
+"g' c #757E92",
+"h' c #757E94",
+"i' c #757F94",
+"j' c #768292",
+"k' c #768290",
+"l' c #76818B",
+"m' c #76828F",
+"n' c #768392",
+"o' c #768391",
+"p' c #738094",
+"q' c #73828D",
+"r' c #6A7883",
+"s' c #606D77",
+"t' c #3B4651",
+"u' c #36434C",
+"v' c #45575D",
+"w' c #485A63",
+"x' c #465762",
+"y' c #42535E",
+"z' c #41535C",
+"A' c #41565F",
+"B' c #41575F",
+"C' c #495C64",
+"D' c #475962",
+"E' c #485A62",
+"F' c #496069",
+"G' c #455B64",
+"H' c #384A53",
+"I' c #324249",
+"J' c #29373C",
+"K' c #344046",
+"L' c #3D494F",
+"M' c #54646B",
+"N' c #607179",
+"O' c #6F7D88",
+"P' c #72808B",
+"Q' c #73818B",
+"R' c #73808B",
+"S' c #737E8B",
+"T' c #73808D",
+"U' c #727F8A",
+"V' c #707F88",
+"W' c #6F7F88",
+"X' c #6F808C",
+"Y' c #6F818E",
+"Z' c #6F8290",
+"`' c #6F8190",
+" ) c #6F8090",
+".) c #717F8E",
+"+) c #737F8F",
+"@) c #73808C",
+"#) c #737F89",
+"$) c #737F87",
+"%) c #727F87",
+"&) c #707F87",
+"*) c #6F7F89",
+"=) c #6F7F8A",
+"-) c #717F8B",
+";) c #74818C",
+">) c #758091",
+",) c #748091",
+"') c #737E90",
+")) c #717C90",
+"!) c #727C90",
+"~) c #737D91",
+"{) c #737E91",
+"]) c #737F92",
+"^) c #737F91",
+"/) c #727F90",
+"() c #727F8F",
+"_) c #717F8D",
+":) c #738092",
+"<) c #6F7E8C",
+"[) c #6C7C85",
+"}) c #616F77",
+"|) c #57646B",
+"1) c #35424A",
+"2) c #4A6069",
+"3) c #43565F",
+"4) c #43575F",
+"5) c #465D64",
+"6) c #435961",
+"7) c #50616A",
+"8) c #4E616A",
+"9) c #4B606A",
+"0) c #485D67",
+"a) c #3D4F58",
+"b) c #35454D",
+"c) c #2A373D",
+"d) c #2E3A41",
+"e) c #323E45",
+"f) c #4A5760",
+"g) c #57656E",
+"h) c #667681",
+"i) c #6A7A85",
+"j) c #6C7C87",
+"k) c #717E89",
+"l) c #717D89",
+"m) c #717C89",
+"n) c #707C89",
+"o) c #6E7C88",
+"p) c #6E7B87",
+"q) c #707C88",
+"r) c #6D7C89",
+"s) c #6C7C89",
+"t) c #6B7C89",
+"u) c #6B7C88",
+"v) c #6A7C84",
+"w) c #697C88",
+"x) c #697C89",
+"y) c #687C89",
+"z) c #6A7B88",
+"A) c #6B7B87",
+"B) c #6B7B86",
+"C) c #6B7C84",
+"D) c #6B7C83",
+"E) c #6B7C82",
+"F) c #6B7B82",
+"G) c #6B7A81",
+"H) c #6A7B81",
+"I) c #687B82",
+"J) c #697B82",
+"K) c #6C7E82",
+"L) c #6E7F82",
+"M) c #6E7E83",
+"N) c #6A7B83",
+"O) c #697A82",
+"P) c #6A7A82",
+"Q) c #6B7A82",
+"R) c #697A84",
+"S) c #6A7B86",
+"T) c #6E7C89",
+"U) c #6F7D87",
+"V) c #6D7D86",
+"W) c #6A7982",
+"X) c #697680",
+"Y) c #65747D",
+"Z) c #617279",
+"`) c #4D5D66",
+" ! c #42505A",
+".! c #33414A",
+"+! c #45555D",
+"@! c #4B626A",
+"#! c #42535C",
+"$! c #475E62",
+"%! c #435A5E",
+"&! c #495E68",
+"*! c #435660",
+"=! c #334246",
+"-! c #2E3B40",
+";! c #2C373D",
+">! c #35424B",
+",! c #3D4B55",
+"'! c #4F5F69",
+")! c #56666F",
+"!! c #5C6D74",
+"~! c #5F6F77",
+"{! c #617079",
+"]! c #627179",
+"^! c #627079",
+"/! c #607079",
+"(! c #5E7078",
+"_! c #5B6E75",
+":! c #5A6D74",
+"<! c #5A6C72",
+"[! c #5E6E76",
+"}! c #5E7079",
+"|! c #5D7078",
+"1! c #5C6E76",
+"2! c #5C6D75",
+"3! c #5C6F76",
+"4! c #5B6D74",
+"5! c #596D74",
+"6! c #596C74",
+"7! c #5B6B72",
+"8! c #5C6B70",
+"9! c #5C696C",
+"0! c #5C6A6C",
+"a! c #5C6A6D",
+"b! c #5B696F",
+"c! c #5B6870",
+"d! c #596870",
+"e! c #586870",
+"f! c #58696D",
+"g! c #58696B",
+"h! c #59696B",
+"i! c #57696B",
+"j! c #55696B",
+"k! c #54696B",
+"l! c #56696B",
+"m! c #5A696B",
+"n! c #5B696B",
+"o! c #58686C",
+"p! c #57686C",
+"q! c #56696D",
+"r! c #56696A",
+"s! c #546767",
+"t! c #556766",
+"u! c #586766",
+"v! c #576766",
+"w! c #566766",
+"x! c #556665",
+"y! c #556465",
+"z! c #536165",
+"A! c #515E62",
+"B! c #4C5A5C",
+"C! c #3D4E54",
+"D! c #37464E",
+"E! c #3F4A54",
+"F! c #434F5A",
+"G! c #4A606A",
+"H! c #455760",
+"I! c #465861",
+"J! c #455B62",
+"K! c #4D6369",
+"L! c #50656A",
+"M! c #4D646A",
+"N! c #4A646A",
+"O! c #4C6069",
+"P! c #47565D",
+"Q! c #415056",
+"R! c #3D4B50",
+"S! c #39474A",
+"T! c #313E41",
+"U! c #2D3A3D",
+"V! c #2A363A",
+"W! c #2B373B",
+"X! c #2E3A3F",
+"Y! c #303E40",
+"Z! c #314041",
+"`! c #334141",
+" ~ c #334041",
+".~ c #303D3F",
+"+~ c #313E3F",
+"@~ c #334140",
+"#~ c #344041",
+"$~ c #333E41",
+"%~ c #323D40",
+"&~ c #303C3E",
+"*~ c #303B3D",
+"=~ c #303C3F",
+"-~ c #303D40",
+";~ c #30393D",
+">~ c #2F393D",
+",~ c #2E393D",
+"'~ c #2D383C",
+")~ c #2C383B",
+"!~ c #2C393C",
+"~~ c #2C3739",
+"{~ c #2C3639",
+"]~ c #2B3639",
+"^~ c #2A3639",
+"/~ c #293639",
+"(~ c #283639",
+"_~ c #283637",
+":~ c #283635",
+"<~ c #283538",
+"[~ c #283439",
+"}~ c #283437",
+"|~ c #283435",
+"1~ c #283431",
+"2~ c #283331",
+"3~ c #283131",
+"4~ c #283231",
+"5~ c #222D30",
+"6~ c #202B2E",
+"7~ c #263439",
+"8~ c #2D3B40",
+"9~ c #334147",
+"0~ c #394A4F",
+"a~ c #485961",
+"b~ c #4A5A63",
+"c~ c #4D5F69",
+"d~ c #4E606A",
+"e~ c #40575F",
+"f~ c #405760",
+"g~ c #455B63",
+"h~ c #465C64",
+"i~ c #4E646A",
+"j~ c #4A5E66",
+"k~ c #48575F",
+"l~ c #47545C",
+"m~ c #435258",
+"n~ c #404F55",
+"o~ c #3A474D",
+"p~ c #354248",
+"q~ c #26353B",
+"r~ c #223035",
+"s~ c #1D2E30",
+"t~ c #1A2C2D",
+"u~ c #19292B",
+"v~ c #19282A",
+"w~ c #192829",
+"x~ c #202A2B",
+"y~ c #20292B",
+"z~ c #1C282A",
+"A~ c #19292C",
+"B~ c #192A2C",
+"C~ c #1B2B2C",
+"D~ c #19282C",
+"E~ c #18292C",
+"F~ c #182A2B",
+"G~ c #192929",
+"H~ c #18292B",
+"I~ c #18282C",
+"J~ c #18282B",
+"K~ c #18292A",
+"L~ c #192A29",
+"M~ c #1D2A29",
+"N~ c #1C2A29",
+"O~ c #1A2A29",
+"P~ c #1A292A",
+"Q~ c #1B292B",
+"R~ c #1B292C",
+"S~ c #1D2B2F",
+"T~ c #223034",
+"U~ c #2C393E",
+"V~ c #36454A",
+"W~ c #3C4B53",
+"X~ c #3E4E58",
+"Y~ c #455862",
+"Z~ c #4B5D68",
+"`~ c #4F616C",
+" { c #52646F",
+".{ c #546570",
+"+{ c #556570",
+"@{ c #556871",
+"#{ c #536770",
+"${ c #4E646E",
+"%{ c #4D636D",
+"&{ c #4D626D",
+"*{ c #4B606B",
+"={ c #4B616C",
+"-{ c #51676D",
+";{ c #51656B",
+">{ c #51646A",
+",{ c #51646B",
+"'{ c #526671",
+"){ c #526872",
+"!{ c #536972",
+"~{ c #506772",
+"{{ c #4E6672",
+"]{ c #4C6270",
+"^{ c #4B606D",
+"/{ c #485C65",
+"({ c #465961",
+"_{ c #43545C",
+":{ c #3F5057",
+"<{ c #3C4D53",
+"[{ c #37474F",
+"}{ c #34444C",
+"|{ c #2E3F47",
+"1{ c #2B3C43",
+"2{ c #27373D",
+"3{ c #203134",
+"4{ c #1C2D2F",
+"5{ c #192C2D",
+"6{ c #192C2C",
+"7{ c #192B2D",
+"8{ c #192A2E",
+"9{ c #1A2A30",
+"0{ c #1A2A31",
+"a{ c #1B2A31",
+"b{ c #1B2B31",
+"c{ c #1B2C31",
+"d{ c #192C32",
+"e{ c #192B32",
+"f{ c #192A32",
+"g{ c #192932",
+"h{ c #192D30",
+"i{ c #192D32",
+"j{ c #192D31",
+"k{ c #192C31",
+"l{ c #1B2D32",
+"m{ c #1C2D31",
+"n{ c #1D2D30",
+"o{ c #1B2D30",
+"p{ c #1A2D30",
+"q{ c #1D2E32",
+"r{ c #223237",
+"s{ c #24333A",
+"t{ c #28363E",
+"u{ c #2C3A43",
+"v{ c #35434D",
+"w{ c #394851",
+"x{ c #51666F",
+"y{ c #5F737E",
+"z{ c #657682",
+"A{ c #6A7985",
+"B{ c #6A7B89",
+"C{ c #697C8A",
+"D{ c #677988",
+"E{ c #637784",
+"F{ c #5B717D",
+"G{ c #5A6E7A",
+"H{ c #596C78",
+"I{ c #546874",
+"J{ c #526772",
+"K{ c #516572",
+"L{ c #536A74",
+"M{ c #546A74",
+"N{ c #5A6E77",
+"O{ c #5D6F79",
+"P{ c #5F727F",
+"Q{ c #5F7280",
+"R{ c #5F7380",
+"S{ c #5C7280",
+"T{ c #5A7280",
+"U{ c #586F7D",
+"V{ c #576D7B",
+"W{ c #566B75",
+"X{ c #546872",
+"Y{ c #51636D",
+"Z{ c #4C5E67",
+"`{ c #394952",
+" ] c #304149",
+".] c #2C3D44",
+"+] c #293A3F",
+"@] c #28393D",
+"#] c #253638",
+"$] c #253536",
+"%] c #253537",
+"&] c #253539",
+"*] c #25353B",
+"=] c #25373E",
+"-] c #25373C",
+";] c #25373B",
+">] c #25393D",
+",] c #25393E",
+"'] c #25383E",
+")] c #253940",
+"!] c #253941",
+"~] c #253B43",
+"{] c #263B43",
+"]] c #283B43",
+"^] c #293B43",
+"/] c #2A3B43",
+"(] c #2A3C43",
+"_] c #2A3D43",
+":] c #2B3D43",
+"<] c #2C3D43",
+"[] c #2F3F47",
+"}] c #32414B",
+"|] c #33434C",
+"1] c #34454D",
+"2] c #485862",
+"3] c #50636B",
+"4] c #536771",
+"5] c #556A74",
+"6] c #5A6E79",
+"7] c #5B6F7B",
+"8] c #5B6F7C",
+"9] c #5C717D",
+"0] c #5D727E",
+"a] c #5D737F",
+"b] c #5D7380",
+"c] c #5C727F",
+"d] c #5B6F7E",
+"e] c #5C707D",
+"f] c #596C7A",
+"g] c #576978",
+"h] c #536674",
+"i] c #526573",
+". + @ # $ % & * = - ; > > > > > , ' ) ! > ~ ~ { ] ^ / ( _ : < [ [ [ [ } | [ [ 1 1 1 2 2 3 4 5 6 7 8 9 0 a b 6 5 c d c c e f 5 g h i j 5 5 5 5 5 5 5 6 k l j m m m m m m m m n n n n n n n o p q q q q q q r s t u v w w x y y y y y y z A B C D E F F G H I J K L M M ",
+"N O P Q R S T U U V V W X X Y Z ` ...+.@.#.$.#.%.&.*.=.-.;.;.>.,.,.'.).!.~.~.~.{.;.~.].^./.(.(.(._.:.<.[.>.>.-.}.(.|.|.1.2.3.4.4.5.6.7.8.9.0.(./.<.a.b.c.d.>.~.~.>.>.e.-.f.g.g.h.h.h.h.h.i.j.k.k.l.l.l.m.n.o.p.p.q.r.s.t.u.~.v.w. .x.Z B y.y.B Z z.z.A.B.H Y C.D.E.E.",
+"F.G.H.I.J.C K.L.M.N.O.B.P.Q.R.S.T.U.V.V.k.W.X.g.g.Y.Y.Z.X.X.X.X.`.1. +.+X.++++@+3.X.#+#+$+$+%+%+&+*+=+-+-+|.;+>+>+>+,+'+)+!+~+~+~+{+]+^+/+(+_+_+:+:+:+<+[+}+|+1+1+|+2+3+4+5+6+7+8+8+9+0+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+m+o+p+q+r+V.s+t+u+v+w+x+y+z+A+B+C+C.D+E+F+G+H+H+",
+"I+J+K+L+M+C.N+O+P+Q+R+S+F T+U+V+W+X+Y+Z+`+ @.@+@.@@@@@#@$@$@$@#@%@%@&@*@=@=@=@-@;@>@,@,@'@'@)@!@>@~@{@]@^@/@/@(@_@:@<@[@}@}@|@|@|@1@1@2@3@4@5@5@6@6@7@2@8@8@8@9@9@8@8@0@a@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@M t@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@Q@",
+"R@S@T@U@V@W@X@Y@Z@Z@K `@ #.#+#@###$#%#&#*#=#-#;#>#,#,#'#>#>#'#'#)#)#)#!#~#~#~#~#~#{#]#]#^#/#(#_#:#<#[#}#|#1#2#3#4#5#6#7#8#9#2#3#0#3#3#a#b#c#d#e#f#f#g#g#f#h#i#j#j#k#l#m#n#o#p#p#p#p#q#r#r#s#t#u#v#w#x#y#z#A#B#C#t#p#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#X@W#X#Y#Z#Z#",
+"`# $.$+$@$#$$$%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$($($($_$:$<$<$[$}$}$|$1$2$3$4$4$4$4$4$5$5$6$7$8$9$0$a$b$c$d$e$f$g$h$h$e$i$j$k$l$m$_$n$o$p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$H$I$I$I$I$I$I$I$J$K$L$M$o$N$O$P$Q$R$S$T$U$V$W$X$Y$Z$`$ %.%+%@%x@#%$%%%&%*%=%-%;%>%,%'%)%!%!%",
+"~%{%]%^%/%(%_%:%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%c%c%c%d%d%e%e%e%e%e%f%g%h%h%h%i%j%k%k%l%m%e%n%o%p%q%i%h%r%s%e%e%e%t%t%g%u%v%w%x%y%y%y%x%z%A%B%C%D%x%z%E%F%G%v%v%v%H%I%H%H%v%v%v%v%v%v%v%J%K%q%q%p%L%L%L%M%N%O%y%x%w%P%Q%R%S%o#T%U%V%W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&=&",
+"-&;&>&,&'&)&!&~&~&~&{&&@]&^&/&(&_&:&<&[&}&}&}&|&1&2&3&4&4&4&4&4&4&4&4&5&6&7&7&8&9&6&0&7&7&a&3&3&<&4&4&4&4&3&3&3&<&<&4&4&b&b&c&d&e&e&e&e&e&e&e&e&f&g&h&h&e&e&e&e&e&c&c&i&j&j&k&l&m&n&o&4&4&p&q&r&s&t&u&4&4&v&w&x&x&f&h&e&e&h&y&z&A&B&C&D&E&F&G&H&I&`%J&K&L&M&N&O&P&Q&Q&",
+"R&S&T&U&# V&W&X&Y&Z&~&`& *.*+*@*#*$*l&%*e&e&e&e&&***=*6&6&6&6&6&6&6&6&6&6&7&7&0&6&-*;*9&=*=*=*=*>*,*'*)*!*~*{*)*'*>*=*]*^*/*(*k&_*:*_*f&f&f&<*[*}*}*|*1*2*3*4*3*5*6*7*8*9*~*0*a*b*c*}*a#d*e*f*=*;*g*g*g*7&9&h*i*j*6*9#[*:*k*l*m*n*B&o*p*q*r*s*t*t*V&u*v*w*x*y*N&z*Q&Q&",
+"R&S&r*A*B*W&C*D*D*Y&E*F*G*H*I*J*K*L*M*N*O*O*O*O*P*j*j*Q*Q*Q*Q*Q*Q*Q*Q*i*R*h*h*R*R*j*i*S*Q*Q*!*9*~*a*T*U*U*U*U*U*V*a*0*0*W*W*0*0*0*X*W*Y*Z*`* =.=+=+=@=Z*#=$=%=V*V*V*V*U*U*U*U*U*U*V*&=+=*=Q*Q*Q*Q*j*}*}*d*d*R*}*}*|*==}*j*Q**=c*-=B&;=p*q*r*>=,='=)=!=~&~={=]=^=z*Q&Q&",
+"/=(=_=:=B*<=[=}=|=)=J&1=2=3=4=5=6=7=8=9=}*j*j*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*j*j*j*j*Q*j*j*!*9*W*a*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*a*0*T*T*U*U*U*U*U*U*U*U*U*U*U*U*U*U*T*W*9*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*)*0=a=b=B&;=p*q*r*>=c=c=)=!=d=e=f=g=^=z*Q&Q&",
+"h=i=j=k=l=m=n=o=<=p=q=r=s=t=u=v=w=x=y=Q*j*Q*Q*Q*Q*Q*)*z=z=z=A=)*Q*B=C=C=C=C=Q*Q*B=C=D=D=E=F=G=H=I=G=G=G=G=G=G=G=G=G=G=U*U*U*U*U*U*H=G=H=U*U*U*U*G=G=U*U*I=G=G=G=G=G=G=H=U*G=G=G=I=U*T*J=E=C=K=C=C=C=C=C=C=L=M=L=L=)*)*z=z=N=y=O=-=P=Q=R=S=T=U=V=W=[=<=X=Y=Z=`= -.-+-+-",
+"@-#-$-k=%-&-*-&-)=u*{&r==---;->-,-'-)-!-Q*Q*Q*Q*Q*)*A=~-~-~-N=N={-]-]-]-]-]-Q*^-/-]-]-]-]-]-]-(-G=]-]-]-]-]-]-]-]-]-]-U*U*U*U*U*U*(-]-]-_-U*:-<-]-]-U*U*G=]-]-]-]-]-]-(-U*H=]-]-]-[-}-|-]-1-L=]-]-]-]-]-]-]-]-]-]-A=)*z=N=N=~*2-3-4-5-6-7-8-9-0-a-m=b-d=Y=Z=c-d-e-e-e-",
+"f-g-h-:=%-&-i-&-)=j-k-l-m-n-o-p-q-r-s-t-A=)*Q*Q*)*N=t-}-T*U*T*u-]-]-v-w-L=x-y-z-A-]-]-B-G=G=G=H=I=G=G=G=C-]-]-_-G=G=G=U*U*U*U*U*U*(-]-]-D-E-F-U*]-]-U*U*G=]-]-C-G=G=G=H=U*U*C-]-]-G-H-D-D-!-I-D=E=J-B-]-]-x-K-L-L-~-~-M-M-t-~*Y*N-O-P-Q-R-S-~&T-a-U-V-~&e=Z=c-W-e-e-e-",
+"@-#-$-k=%-W&C*W&)=u*{&r==---X-Y-Z-`- ;.;N=z=A=z=z=N=t-}-T*U*U*(-]-]-G-t-N=+;T*U*G=]-]-(-U*U*U*U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-]-]-]-U*U*]-]-U*U*G=]-]-(-U*U*U*U*U*U*@;]-]-]-C-]-#;0*0*T*T*U*(-]-]-$;%;&;+;t-t-T*U*U*2-*;=;-;5-;;R-S-~&T->;<=,;~&e=Z=c-W-';';';",
+"@-#-$-k=l=);!;~;{;];F&^;/;t=(;_;:;<;[;};N=N=N=~-~-~-|;T*U*U*U*1;]-]-]-D-L-M-}-U*G=]-]-C-G=G=G=U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-]-]-]-_-U*]-]-U*U*G=]-]-C-G=G=G=U*U*U*V*G-]-]-]-_-2;2;2;U*U*U*(-]-]-3;4;[;+;M-M-T*U*U*5;[#6;7;8;9;0;S-~&!=a;!=!=p=b;c;c-*%d;8@8@",
+"@-#-$-k=%-&-i-e;{;f;g;h;i;j;k;9@l;m;n;o;+;M-|;T*U*2;2;p;2;2;U*U*_-]-]-]-]-_-U*U*G=]-]-]-]-]-]-U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-(-]-]-]-H=]-]-U*U*G=]-]-]-]-]-]-U*U*U*U*U*]-]-]-G=U*U*U*U*U*U*(-]-]-G=q;r;U*U*U*U*U*U*U*U*s;t;u;v;w;S-~&x;y;z;x;Z% &A;B;C;D;E;E;",
+"@-#-$-k=%-&-i-e;{;p={&F;G;j;k;9@H;I;J;K;2;U*U*U*U*U*2;%;%;%;2;U*U*G=C-]-]-]-C-U*G=]-]-C-G=G=G=U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=1;]-]-D-]-]-U*U*G=]-]-C-G=G=G=U*U*U*U*I=]-]-]-C-I=U*U*U*U*U*(-]-]-G=q;r;U*U*U*U*U*U*U*U*s;t;L;M;N;O;~&t*z;P;t*Z% &A;B;C;D;E;E;",
+"Q;R;S;T;U;&-i-e;{;!=q=F;G;j;k;9@V;W;X;Y;p;2;U*U*U*U*2;Z;`;`;%;p;U*U*I=_-]-]-]-U*G=]-]-(-U*U*U*U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=I=D-]-]-]-]-U*U*G=]-]-(-U*U*U*U*U*U*U*_-]-]-]-]-1;U*U*U*U*U*(-]-]-G=q;r;U*U*U*U*U*U*2;2; >.>^=+>@>O;~&#>s*c=t*Z% &A;B;C;D;E;E;",
+"$>%>b;&>!=<=*>e;{;a;=>F;G;j;k;->;>>>,>'>2;U*U*U*2;Z;)>!>~>{>]>`;p;2;U*U*]-]-]-U*G=]-]-(-U*U*U*U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=U*H=]-]-]-]-U*U*G=]-]-(-U*U*U*U*U*U*G=]-_-G=]-]-]-U*U*U*U*U*(-]-]-G=q;r;U*U*U*U*U*U*2;p; >.>^>Z#@>O;~&/>I&c=t*Z% &A;B;C;D;E;E;",
+"$>(>_>:>T-<>[>[>[>,;}>|>1>2>3>4>5>6>7>8>U*U*U*2;K;9>0>q;a>a>K;b>C-b>(-C-]-]-1;U*G=]-]-D-(-(-(-(-U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=U*U*1;]-]-]-U*U*G=]-]-D-(-(-(-(-U*U*D-D-c>8>C-]-]-d>8>U*e>r;f>]-]-g>h>i>j>a>a>j>k>U*l>m>n>o>p>q>r>s>t>Z%,;I&Z%V&b;c;c-u>v>v>v>",
+"f-w>$-k=x>y>[>*>i-V&z>A>B>C>D>E>F>G>,>Y;a>r;U*U*U*e>e>U*U*U*U*(-]-]-]-]-C-1;U*U*G=]-]-]-]-]-]-]-U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=U*U*U*C-]-]-U*U*G=]-]-]-]-]-]-]-U*_-]-d>H>a>I>]-]-]-J>U*k>K>L>]-]-M>N>O>O>O>O>$*P>Q>R>S>T>U>V>W>X>Y>P;U;a;X=X=d=Y=Z=c-W-';';';",
+"f-g-$-k=x>y>[>*>i-,;Z>`> ,.,+,@,F>m;n;K;8>U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*8>8>r;H>K>0>#,#,#,9>9>K>0>#,#,#,#,#,#,O>N>i>$,Q>z-$*%,&,*,=,-,W>X>;,y;>,}=!=X=d=Y=Z=c-W-';';';",
+",,',$-k=x>y>[>*>i-,;Z>),!,~,{,9@],^,/,2;U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*8>8>8>8>8>8>8>8>8>8>8>8>U*U*U*U*U*U*U*U*U*U*U*U*U*8>r;r;(,0>#,#,#,#,#,#,#,#,#,#,#,#,q;q;K>_,N>P>:,z-:,$*<,[,},|,1,2,3,4,5,&-[=!=X=d=Y=Z=c-W-';';';",
+"6,7,8,k=x>y>[>*>i-,;S;9,0,~,{,9@],^,J;'>H>r;e>U*U*U*U*U*U*U*r;H>r;8>U*U*U*U*U*U*U*U*U*U*U*e>H>H>a>(,(,a,a,b,l>8>U*U*r;r;H>H>H>r;r;H>H>H>H>r;8>8>8>8>8>8>8>8>8>8>8>8>r;H>(,K>#,#,#,#,#,#,#,#,#,#,#,#,K>a>e>e>:,_,O>#,#,N>P>U*c,d,e,f,g,h,i,j,k,H&|=p=d=d=Y=Z=c-W-';';';",
+"l,m,n,o,<=[=[>}=p,U;:=q,r,s,Q-t,u,v,w,x,y,z,A,2;U*U*2;%;%;%;]>{>Z;Z;p;A,/,n;n;A,A,p;2;2;B,b,C,D,D,D,D,E,E,F,F,G,H,H,H,H,I,I,N>O>O>#,#,#,#,O>K>(,a>a>x,J,K,L,M,M,M,J;J;J;N,N,{>{>{>{>{>{>{>O,P,Q,O,{>R,S,T,U,V,W,X,Y,Y,Y,Y,Z,N-`, '.'$$+'@'#'!=$'%'G&U;d=b;&'*'='-';';'",
+">','''d=<=}=*>}=<>a;)'!'~'`@{']'^'/'('_':'Y;Y;8>U*r;H>:':':'Y;<'U*U*U*['}'|'|'K,1':'!>!>D,D,2'2'3'3'3'|'|'4'4'4'4'4'4'4'5'5'6'6'6'7'7'8'|'9'#,#,#,9'0'0'}'a'b'b'b'b'b'b'c'd'e'P,f'f'f'f'f'g'g'h'i':'(,q;j'k'l'm'n'o'o'J,!>p'|'q'r's't'u'@'v'd=}=[>5,H&V&w'x'y'z'A'B'B'",
+"C'D'E':>U;W&D*C**-F'G'H'I'J'K'L'M'N'O'P'Q'Q'Q'Q'Q'Q'R'S'b'R'Q'Q'6;8'|'T'b'b'b'b'b'b'U'U'V'W'X'Y'Z'`' ).).)}'}'}'}'}'}'+)T'@)b'b'b'#)#)$)%)&)*)=)-)-)b'b'b'R'Q'Q'Q'Q'Q'Q';) >>),)}'}'}'')')))!)~){)])^)}'/)()_)()}'}'}'')^):)<)[)})|)+$1)i,Y%X=}=[>2)5,Z%w'x'y'z'3)4)4)",
+"5)6) &&>)=o=7)8)D*9)0)a)b)c)d)e)f)g)h)i)j)O'k)l)m)m)m)m)m)m)n)n)o)o)p)q)m)m)n)r)s)t)u)u)v)v)w)x)y)y)y)z)z)A)A)A)A)A)A)B)C)D)E)F)F)G)G)G)G)H)H)H)I)I)J)J)J)K)L)L)L)L)L)L)M)M)C)N)O)P)Q)Q)Q)R)S)s)T)m)U)V)N)J)P)Q)Q)F)F)W)O-X)Y)Z)`) !.!Q@+!E'G&*>@!D*X&Z%w'&'*'#!w*Z=Z=",
+"$!%!''X=<=~;7)8)D*9)&!*!y*=!-!;!>!,!'!)!!!~!{!]!]!{!{!^!^!^!/!(!_!:!<![!{!}!|!1!1!2!2!2!3!3!4!:!5!6!6!7!8!9!9!9!9!9!9!9!0!0!0!0!0!0!0!0!a!b!c!c!d!e!e!e!e!f!g!g!g!g!g!g!h!h!i!j!k!l!h!m!n!o!p!q!q!q!l!r!s!t!u!v!w!x!y!z!A!B!v>C!D!Q@E!F!# t>z;G!*-8)X&U;E'Z=#!#!H!I!I!",
+"B*J!T;p=~;K!L!M!N!@!O!!&P!Q!R!S!T!U!V!W!X!Y!Z!`! ~.~+~@~#~#~$~%~&~&~*~=~]&-~=~;~>~,~'~)~s,!~~~~~{~]~^~^~^~~~~~~~~~~~~~~~^~/~(~(~(~(~(~(~_~:~:~:~:~:~:~:~:~<~[~[~[~[~[~[~[~[~[~[~[~[~[~[~[~}~|~1~1~1~2~2~3~3~4~4~4~e+5~6~6+7~8~9~0~7-w*a~b~t>x;c~d~%'~;,;9-j=e~f~g~h~h~",
+"%')=!=!=%'i~L!M!N!>,j~E'k~l~m~n~o~p~J q~r~s~t~u~v~w~k.2.x~y~z~V.w~w~w~u~A~B~B~C~C~^.[.[.A~D~D~D~D~E~E~F~F~G~G~G~G~G~G~G~H~H~I~I~I~I~I~I~J~K~L~L~L~L~L~L~L~u~D~D~D~D~D~D~D~D~D~D~D~D~D~D~D~n.l.M~N~O~L~L~w~w~w~P~m.Q~R~S~T~U~G+V~W~X~;'Y~Z~`~ {.{+{@{#{${%{&{*{y;={={={",
+"-{;{>{,{'{){!{~{{{]{^{/{({_{:{<{[{}{|{1{2{C.3{G 4{5{t~^.).).-.-.!.!.6{7{8{9{0{a{a{a{b{c{d{d{d{e{f{g{g{e{e{h{h{h{h{h{h{h{i{i{d{d{d{d{d{d{d{j{h{h{h{h{h{h{h{k{d{d{d{d{d{d{d{d{d{d{d{d{d{d{d{l{m{8+n{o{p{h{h{h{#.q{L+r{s{t{u{v{w{S=*'s>x;x{y{z{A{B{C{D{E{F{G{H{I{J{K{K{K{",
+"L{M{N{O{P{Q{R{S{T{U{V{W{X{Y{Z{# c-]=`{Y# ].]f +]@]y #]$]$]$]%]&]*]s =]-]y y y y y y ;];]>],],]']=]=]=])]!]~]~]~]~]~]~]{]]]^]/]/]/]/]/]/](]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]:]<][]}]|]1]`{;&2]Z{3]4]5]6]7]8]9]0]a]b]a]c]d]e]9]f]g]h]i]i]"};
diff --git a/gtk2_ardour/pixmaps/small-round-button-01.xpm b/gtk2_ardour/pixmaps/small-round-button-01.xpm
new file mode 100644
index 0000000000..871f90ce55
--- /dev/null
+++ b/gtk2_ardour/pixmaps/small-round-button-01.xpm
@@ -0,0 +1,598 @@
+/* XPM */
+static char * t_small_round_button_01_xpm[] = {
+"28 30 565 2",
+" c None",
+". c #3C4B52",
+"+ c #465960",
+"@ c #44575D",
+"# c #45565D",
+"$ c #4A5961",
+"% c #3A4B53",
+"& c #39464D",
+"* c #32424A",
+"= c #34464D",
+"- c #36454C",
+"; c #34434C",
+"> c #35464E",
+", c #34444C",
+"' c #34434D",
+") c #35454F",
+"! c #374750",
+"~ c #314248",
+"{ c #34444A",
+"] c #2A343A",
+"^ c #3A454C",
+"/ c #37464F",
+"( c #394850",
+"_ c #3E4F55",
+": c #405157",
+"< c #3E5259",
+"[ c #46585F",
+"} c #41545A",
+"| c #3E5057",
+"1 c #3E4E57",
+"2 c #3E4C56",
+"3 c #39494F",
+"4 c #36434A",
+"5 c #273437",
+"6 c #2F3A41",
+"7 c #394952",
+"8 c #3A4E58",
+"9 c #40525C",
+"0 c #41515A",
+"a c #45555B",
+"b c #42565B",
+"c c #41555A",
+"d c #45575E",
+"e c #43575C",
+"f c #45545E",
+"g c #45525A",
+"h c #42525A",
+"i c #415158",
+"j c #3D4E56",
+"k c #3C4D55",
+"l c #354750",
+"m c #2D3B45",
+"n c #2E3B43",
+"o c #404F58",
+"p c #42545D",
+"q c #43595D",
+"r c #42585B",
+"s c #45545B",
+"t c #414E54",
+"u c #35454E",
+"v c #2E3E44",
+"w c #2A3C42",
+"x c #2F4048",
+"y c #324249",
+"z c #39454B",
+"A c #404D51",
+"B c #425257",
+"C c #43565B",
+"D c #41555B",
+"E c #41505A",
+"F c #394955",
+"G c #2D3943",
+"H c #324147",
+"I c #405259",
+"J c #47565F",
+"K c #46585C",
+"L c #475A5A",
+"M c #3B4D4F",
+"N c #2C3B3D",
+"O c #293B3E",
+"P c #33434A",
+"Q c #394A52",
+"R c #44525B",
+"S c #49565D",
+"T c #364649",
+"U c #2C3D41",
+"V c #2D3E41",
+"W c #394B4F",
+"X c #425659",
+"Y c #465561",
+"Z c #44545F",
+"` c #40515C",
+" . c #303D45",
+".. c #232F33",
+"+. c #43535B",
+"@. c #4A5C62",
+"#. c #4A5B62",
+"$. c #485458",
+"%. c #354144",
+"&. c #223034",
+"*. c #31404A",
+"=. c #506069",
+"-. c #617380",
+";. c #738492",
+">. c #7F8E9C",
+",. c #7D8C9C",
+"'. c #7E8D9C",
+"). c #71828E",
+"!. c #5D6F79",
+"~. c #44555B",
+"{. c #2B3C41",
+"]. c #344548",
+"^. c #43515C",
+"/. c #4A5660",
+"(. c #43555C",
+"_. c #415058",
+":. c #263035",
+"<. c #40535A",
+"[. c #4A5A62",
+"}. c #46555E",
+"|. c #2D393F",
+"1. c #414F5A",
+"2. c #687686",
+"3. c #8293A5",
+"4. c #93A5BC",
+"5. c #9DB1C8",
+"6. c #9CB1C8",
+"7. c #96ABC2",
+"8. c #95ABC3",
+"9. c #98A9C0",
+"0. c #93A5BA",
+"a. c #818E9F",
+"b. c #576570",
+"c. c #35424A",
+"d. c #314144",
+"e. c #42535A",
+"f. c #4A5A61",
+"g. c #495A5F",
+"h. c #405158",
+"i. c #303D42",
+"j. c #485A68",
+"k. c #4A5B5F",
+"l. c #4B5B5D",
+"m. c #334345",
+"n. c #233037",
+"o. c #485660",
+"p. c #6C7B8A",
+"q. c #8A9AB1",
+"r. c #92A1BB",
+"s. c #91A3BB",
+"t. c #8EA0B6",
+"u. c #8799B2",
+"v. c #8597B0",
+"w. c #8598B0",
+"x. c #8C9BB1",
+"y. c #90A0B7",
+"z. c #95A4B9",
+"A. c #8090A4",
+"B. c #5D6C7C",
+"C. c #2D3F3E",
+"D. c #35444C",
+"E. c #4A5860",
+"F. c #4E5D63",
+"G. c #475A61",
+"H. c #2C3A3D",
+"I. c #3C4C52",
+"J. c #4F6271",
+"K. c #4A5E61",
+"L. c #415051",
+"M. c #263437",
+"N. c #334149",
+"O. c #687583",
+"P. c #7F90A1",
+"Q. c #899AAF",
+"R. c #8393AC",
+"S. c #8594AA",
+"T. c #8393A7",
+"U. c #8391A7",
+"V. c #8394AA",
+"W. c #8393A8",
+"X. c #8696AC",
+"Y. c #8496AB",
+"Z. c #7A8DA0",
+"`. c #526264",
+" + c #2A3A3F",
+".+ c #424E53",
+"++ c #4F5D63",
+"@+ c #4D5E62",
+"#+ c #3A4B4D",
+"$+ c #4D5F66",
+"%+ c #4A616A",
+"&+ c #485D5D",
+"*+ c #2E3F3E",
+"=+ c #253238",
+"-+ c #7C8A9B",
+";+ c #8191A2",
+">+ c #8190A4",
+",+ c #8091A5",
+"'+ c #7E8EA3",
+")+ c #7B8DA2",
+"!+ c #7C8DA4",
+"~+ c #808DA4",
+"{+ c #808FA4",
+"]+ c #828EA4",
+"^+ c #8390A4",
+"/+ c #8392A8",
+"(+ c #8392A6",
+"_+ c #76858D",
+":+ c #404E51",
+"<+ c #314245",
+"[+ c #48595F",
+"}+ c #505F6A",
+"|+ c #4A5E64",
+"1+ c #2D363A",
+"2+ c #52626A",
+"3+ c #50646A",
+"4+ c #435656",
+"5+ c #253736",
+"6+ c #364148",
+"7+ c #6D7A8A",
+"8+ c #7C8B9D",
+"9+ c #7B8B9E",
+"0+ c #7C8EA2",
+"a+ c #7C8D9D",
+"b+ c #7B8B9C",
+"c+ c #7B8C9D",
+"d+ c #7B8B9D",
+"e+ c #808EA3",
+"f+ c #7B8AA1",
+"g+ c #7C8BA3",
+"h+ c #808EA4",
+"i+ c #818D9E",
+"j+ c #556668",
+"k+ c #2B3E3B",
+"l+ c #45565A",
+"m+ c #52616A",
+"n+ c #4C6065",
+"o+ c #283336",
+"p+ c #52636A",
+"q+ c #52656A",
+"r+ c #3A504F",
+"s+ c #253437",
+"t+ c #48545E",
+"u+ c #798496",
+"v+ c #7B899D",
+"w+ c #7B899E",
+"x+ c #7B8A9C",
+"y+ c #7A8C9B",
+"z+ c #7A899B",
+"A+ c #7B899C",
+"B+ c #7E8BA3",
+"C+ c #808BA3",
+"D+ c #7D8AA2",
+"E+ c #7E8A9F",
+"F+ c #7E8AA2",
+"G+ c #7C889D",
+"H+ c #6C7B7D",
+"I+ c #32443E",
+"J+ c #3A4C4F",
+"K+ c #4D626A",
+"L+ c #4C6068",
+"M+ c #4F636A",
+"N+ c #50656B",
+"O+ c #52666B",
+"P+ c #3B4B4A",
+"Q+ c #263536",
+"R+ c #516067",
+"S+ c #778698",
+"T+ c #7B889C",
+"U+ c #7B8898",
+"V+ c #73828B",
+"W+ c #394A4F",
+"X+ c #374A4F",
+"Y+ c #50656A",
+"Z+ c #4C6365",
+"`+ c #374844",
+" @ c #263537",
+".@ c #52636E",
+"+@ c #768596",
+"@@ c #7B8595",
+"#@ c #7B859A",
+"$@ c #7A879A",
+"%@ c #79889C",
+"&@ c #7A889C",
+"*@ c #79879C",
+"=@ c #75859A",
+"-@ c #7A8594",
+";@ c #75838C",
+">@ c #3E4E51",
+",@ c #3A4A4F",
+"'@ c #51646A",
+")@ c #4C626A",
+"!@ c #4F6468",
+"~@ c #3B4A48",
+"{@ c #253536",
+"]@ c #52626D",
+"^@ c #768398",
+"/@ c #768294",
+"(@ c #7A8294",
+"_@ c #7B8294",
+":@ c #7B8494",
+"<@ c #7B8696",
+"[@ c #7B8698",
+"}@ c #7B869C",
+"|@ c #78859B",
+"1@ c #7A859C",
+"2@ c #79859A",
+"3@ c #74838B",
+"4@ c #3E4F51",
+"5@ c #3B4C4F",
+"6@ c #52676A",
+"7@ c #52666A",
+"8@ c #3F4F4E",
+"9@ c #253436",
+"0@ c #495863",
+"a@ c #728091",
+"b@ c #778194",
+"c@ c #7B8194",
+"d@ c #7B8594",
+"e@ c #7B8596",
+"f@ c #7B859C",
+"g@ c #7A859B",
+"h@ c #788496",
+"i@ c #7B8499",
+"j@ c #798596",
+"k@ c #6B7B84",
+"l@ c #39484B",
+"m@ c #3F5052",
+"n@ c #52666D",
+"o@ c #52686D",
+"p@ c #54666D",
+"q@ c #435451",
+"r@ c #263736",
+"s@ c #394950",
+"t@ c #70798A",
+"u@ c #788092",
+"v@ c #788194",
+"w@ c #7B8396",
+"x@ c #7B8598",
+"y@ c #7B8599",
+"z@ c #7B849A",
+"A@ c #7A8399",
+"B@ c #7B8498",
+"C@ c #758194",
+"D@ c #758393",
+"E@ c #5E7076",
+"F@ c #334448",
+"G@ c #52656D",
+"H@ c #52676D",
+"I@ c #526973",
+"J@ c #536973",
+"K@ c #475C5B",
+"L@ c #304340",
+"M@ c #2D3B41",
+"N@ c #626D7C",
+"O@ c #717D8D",
+"P@ c #738194",
+"Q@ c #7A849A",
+"R@ c #7A8396",
+"S@ c #7B8394",
+"T@ c #7B859B",
+"U@ c #798194",
+"V@ c #7A8497",
+"W@ c #778191",
+"X@ c #737F88",
+"Y@ c #4C5A5D",
+"Z@ c #304346",
+"`@ c #4B5A62",
+" # c #526673",
+".# c #526972",
+"+# c #2D393A",
+"@# c #526A73",
+"## c #4F6265",
+"$# c #3B4C4D",
+"%# c #2A383B",
+"&# c #6B7787",
+"*# c #737F8F",
+"=# c #737F91",
+"-# c #7A8394",
+";# c #788497",
+"># c #7A8495",
+",# c #738191",
+"'# c #75818F",
+")# c #707D88",
+"!# c #697579",
+"~# c #394947",
+"{# c #374B4A",
+"]# c #4F6165",
+"^# c #526670",
+"/# c #43585D",
+"(# c #536D73",
+"_# c #526771",
+":# c #485861",
+"<# c #324142",
+"[# c #334043",
+"}# c #525F6A",
+"|# c #6B7A84",
+"1# c #737D8B",
+"2# c #737F90",
+"3# c #738090",
+"4# c #738190",
+"5# c #768390",
+"6# c #788390",
+"7# c #73808B",
+"8# c #707E8A",
+"9# c #657580",
+"0# c #48575E",
+"a# c #374647",
+"b# c #4B5D5C",
+"c# c #57696F",
+"d# c #576975",
+"e# c #44565D",
+"f# c #37474E",
+"g# c #536D7A",
+"h# c #52697A",
+"i# c #4F636F",
+"j# c #425351",
+"k# c #2F3E3C",
+"l# c #344148",
+"m# c #505E69",
+"n# c #69747F",
+"o# c #6B7784",
+"p# c #6F7C88",
+"q# c #717D89",
+"r# c #717D8B",
+"s# c #6C7D86",
+"t# c #6C7D89",
+"u# c #6B7C83",
+"v# c #485961",
+"w# c #334150",
+"x# c #435258",
+"y# c #54646A",
+"z# c #596D78",
+"A# c #5A6B7A",
+"B# c #39474E",
+"C# c #526B78",
+"D# c #546C79",
+"E# c #576B72",
+"F# c #4D6062",
+"G# c #384C4D",
+"H# c #29383F",
+"I# c #2E3C46",
+"J# c #4C5960",
+"K# c #636D73",
+"L# c #65757D",
+"M# c #677882",
+"N# c #657982",
+"O# c #687985",
+"P# c #677983",
+"Q# c #69777D",
+"R# c #68757B",
+"S# c #59686D",
+"T# c #3C4E54",
+"U# c #324348",
+"V# c #3A4C59",
+"W# c #52636F",
+"X# c #5A707D",
+"Y# c #586B78",
+"Z# c #35434C",
+"`# c #586E7B",
+" $ c #5A707A",
+".$ c #576A71",
+"+$ c #4E5F65",
+"@$ c #3E4C51",
+"#$ c #2E3C40",
+"$$ c #293637",
+"%$ c #334041",
+"&$ c #435156",
+"*$ c #505E65",
+"=$ c #56666B",
+"-$ c #576A6E",
+";$ c #556567",
+">$ c #4F5B5F",
+",$ c #3C4A4D",
+"'$ c #2D3C44",
+")$ c #314149",
+"!$ c #3E515A",
+"~$ c #4E626C",
+"{$ c #5B6F78",
+"]$ c #5D737B",
+"^$ c #5A727B",
+"/$ c #38464C",
+"($ c #4C5E66",
+"_$ c #5D727C",
+":$ c #5E717D",
+"<$ c #596D75",
+"[$ c #516569",
+"}$ c #455858",
+"|$ c #334343",
+"1$ c #273636",
+"2$ c #233132",
+"3$ c #273334",
+"4$ c #2B3536",
+"5$ c #273536",
+"6$ c #273333",
+"7$ c #273439",
+"8$ c #29373D",
+"9$ c #384550",
+"0$ c #495B66",
+"a$ c #576A73",
+"b$ c #5C717C",
+"c$ c #61737D",
+"d$ c #61757D",
+"e$ c #4B5F66",
+"f$ c #4F5C68",
+"g$ c #627183",
+"h$ c #61727F",
+"i$ c #5E7178",
+"j$ c #556970",
+"k$ c #506266",
+"l$ c #45585B",
+"m$ c #3D4E50",
+"n$ c #384648",
+"o$ c #364246",
+"p$ c #344347",
+"q$ c #3B484A",
+"r$ c #45555D",
+"s$ c #51616A",
+"t$ c #586976",
+"u$ c #5F7280",
+"v$ c #617582",
+"w$ c #637884",
+"x$ c #4F5F6A",
+"y$ c #4F5E6D",
+"z$ c #627787",
+"A$ c #637A87",
+"B$ c #617785",
+"C$ c #627683",
+"D$ c #64747F",
+"E$ c #5E7078",
+"F$ c #5C6D73",
+"G$ c #5F7077",
+"H$ c #5F7178",
+"I$ c #62747B",
+"J$ c #677784",
+"K$ c #6A7B87",
+"L$ c #687B87",
+"M$ c #6A7E8E",
+"N$ c #677B8B",
+"O$ c #6A798B",
+"P$ c #52606C",
+"Q$ c #3D4D52",
+"R$ c #5E7383",
+"S$ c #687A8B",
+"T$ c #6A7D8B",
+"U$ c #6A7C8B",
+"V$ c #677A8A",
+"W$ c #6A7A8A",
+"X$ c #6A7B8B",
+"Y$ c #6A7C8E",
+"Z$ c #6A808E",
+"`$ c #6A7F8B",
+" % c #6A7E8C",
+".% c #6A7E8B",
+"+% c #637683",
+"@% c #404E55",
+"#% c #566672",
+"$% c #60717E",
+"%% c #6A7D8C",
+"&% c #6A8092",
+"*% c #6A8190",
+"=% c #6E8191",
+"-% c #637584",
+";% c #576873",
+">% c #566671",
+" . + @ # $ % ",
+" & * = - ; > , ' ) ! ~ { ",
+" ] ^ / ( _ : < [ } | 1 2 3 / 4 5 ",
+" 6 7 8 9 0 a b c d e f g h i j k l m ",
+" n o p q r s t u v w x y z A B C D E F G ",
+" H I J K L M N O P Q R S g T U V W X Y Z ` . ",
+" ..+.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:. ",
+" <.#.[.}.n |.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h. ",
+" i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H. ",
+" I.J.K.L.M.N.O.P.Q.R.S.T.U.U.V.W.T.X.Y.Z.`. +.+++@+#+ ",
+" $+%+&+*+=+b.-+;+>+,+'+)+!+~+{+]+{+^+/+(+_+:+<+[+}+|+ ",
+"1+2+3+4+5+6+7+8+9+0+a+b+c+c+c+d+e+f+g+^+h+i+j+k+l+m+n+o+",
+"p+p+q+r+s+t+u+v+w+x+y+z+A+A+A+A+B+C+D+E+F+G+H+I+J+m+K+L+",
+"M+N+O+P+Q+R+S+A+A+A+A+A+A+A+A+A+A+A+A+x+T+U+V+W+X+2+3+%+",
+"q+Y+Z+`+ @.@+@@@@@#@#@$@A+A+A+A+A+%@&@*@=@-@;@>@,@2+'@)@",
+"q+Y+!@~@{@]@^@/@(@_@:@-@<@[@}@}@}@|@1@1@2@-@3@4@5@2+q+q+",
+"q+6@7@8@9@0@a@b@b@c@c@:@d@e@f@f@g@h@f@f@i@j@k@l@m@2+q+7@",
+"n@o@p@q@r@s@t@u@v@c@w@@@d@x@y@y@f@z@A@B@C@D@E@F@l+G@n@H@",
+"|.I@J@K@L@M@N@O@P@b@Q@R@(@S@:@d@T@i@U@V@W@X@Y@Z@`@ #.#+#",
+" @#I@##$#%#/.&#*#=#U@C@C@-#:@d@;#>#,#'#)#!#~#{#]#^#I@ ",
+" /#(#_#:#<#[#}#|#1#2#3#4#4#5#6#3#4#7#8#9#0#a#b#c#d#e# ",
+" f#g#h#i#j#k#l#m#n#o#p#q#r#r#r#s#t#u#E@v#w#x#y#z#A#B# ",
+" C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#z#X#Y# ",
+" Z#`# $.$+$@$#$$$%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$ ",
+" ($_$:$<$[$}$|$1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$ ",
+" f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$u$v$w$w$x$ ",
+" y$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$ ",
+" Q$R$S$T$U$V$W$W$X$Y$Z$`$ %.%+%@% ",
+" #%$%T$T$T$T$%%&%*%=%-%;% ",
+" >%T$T$T$T$>% "};
diff --git a/gtk2_ardour/pixmaps/toggle-button-00.xpm b/gtk2_ardour/pixmaps/toggle-button-00.xpm
new file mode 100644
index 0000000000..7606152f3f
--- /dev/null
+++ b/gtk2_ardour/pixmaps/toggle-button-00.xpm
@@ -0,0 +1,354 @@
+/* XPM */
+static char * toggle_button_00_xpm[] = {
+"21 22 329 2",
+" c None",
+". c #52646A",
+"+ c #56686E",
+"@ c #506268",
+"# c #4C5E66",
+"$ c #4E626A",
+"% c #52646C",
+"& c #52636A",
+"* c #52636C",
+"= c #52636E",
+"- c #50626C",
+"; c #4E6166",
+"> c #4E5F66",
+", c #4C5D66",
+"' c #4E5E66",
+") c #505F68",
+"! c #52656A",
+"~ c #52676C",
+"{ c #54676C",
+"] c #415156",
+"^ c #2B3A41",
+"/ c #24343D",
+"( c #28363D",
+"_ c #24363D",
+": c #24383D",
+"< c #29363D",
+"[ c #24363F",
+"} c #27363F",
+"| c #27343B",
+"1 c #2D3944",
+"2 c #37464E",
+"3 c #485960",
+"4 c #42545A",
+"5 c #29383F",
+"6 c #2F3C46",
+"7 c #2F4143",
+"8 c #334246",
+"9 c #2F3F46",
+"0 c #314046",
+"a c #354246",
+"b c #313F46",
+"c c #314048",
+"d c #333F48",
+"e c #313F48",
+"f c #33404A",
+"g c #2F3B46",
+"h c #2B393F",
+"i c #3B4A52",
+"j c #394C54",
+"k c #394752",
+"l c #415058",
+"m c #415252",
+"n c #29393F",
+"o c #28383F",
+"p c #28373D",
+"q c #2D383D",
+"r c #2D373D",
+"s c #2D3A3D",
+"t c #2D393D",
+"u c #2B373F",
+"v c #2A373D",
+"w c #283837",
+"x c #283A3D",
+"y c #3B4952",
+"z c #3D4D56",
+"A c #394750",
+"B c #3F5258",
+"C c #44565E",
+"D c #46585E",
+"E c #39474A",
+"F c #3B4B56",
+"G c #4E5A66",
+"H c #525C66",
+"I c #525E6A",
+"J c #52606A",
+"K c #56606A",
+"L c #525E68",
+"M c #48585E",
+"N c #2F3E3D",
+"O c #202F31",
+"P c #2A3B42",
+"Q c #46545E",
+"R c #435260",
+"S c #3D4D58",
+"T c #43575E",
+"U c #4A5A62",
+"V c #4E5B5E",
+"W c #37484E",
+"X c #62707F",
+"Y c #8190A8",
+"Z c #8C9AB4",
+"` c #8E9EB4",
+" . c #8E9EB8",
+".. c #8C9CB4",
+"+. c #8C9EB4",
+"@. c #90A0B8",
+"#. c #90A2B6",
+"$. c #90A0B4",
+"%. c #90A2B0",
+"&. c #627379",
+"*. c #2B363D",
+"=. c #2D3A46",
+"-. c #465766",
+";. c #465762",
+">. c #3F4F5A",
+",. c #465860",
+"'. c #4A5D62",
+"). c #4E6164",
+"!. c #6A7A8E",
+"~. c #92A0BE",
+"{. c #94A2C0",
+"]. c #94A6C4",
+"^. c #94A6C9",
+"/. c #94A4C3",
+"(. c #94A4C0",
+"_. c #96A6C2",
+":. c #96A4C2",
+"<. c #909EB8",
+"[. c #8392A0",
+"}. c #424C54",
+"|. c #2F3F48",
+"1. c #4A5B66",
+"2. c #4A5962",
+"3. c #3F515C",
+"4. c #4A5F62",
+"5. c #4C5F62",
+"6. c #37414A",
+"7. c #68748C",
+"8. c #7F8EAA",
+"9. c #7F8FA8",
+"0. c #7F8EA8",
+"a. c #7F8DA8",
+"b. c #7F8BA6",
+"c. c #7D88A2",
+"d. c #7D8998",
+"e. c #46565E",
+"f. c #2D4048",
+"g. c #3D505A",
+"h. c #465B5E",
+"i. c #4A5F66",
+"j. c #313D4A",
+"k. c #667184",
+"l. c #7B87A2",
+"m. c #7B89A4",
+"n. c #7987A2",
+"o. c #7785A0",
+"p. c #7B879C",
+"q. c #7B88A0",
+"r. c #7B869E",
+"s. c #7B8596",
+"t. c #46565A",
+"u. c #2D3D42",
+"v. c #465B66",
+"w. c #4A5E66",
+"x. c #313C48",
+"y. c #64707F",
+"z. c #79859A",
+"A. c #798598",
+"B. c #738598",
+"C. c #738398",
+"D. c #73849A",
+"E. c #73859C",
+"F. c #75859A",
+"G. c #778798",
+"H. c #77859A",
+"I. c #79849C",
+"J. c #758490",
+"K. c #46585A",
+"L. c #2B3C42",
+"M. c #465A62",
+"N. c #465B62",
+"O. c #4A5C66",
+"P. c #2F3C43",
+"Q. c #606C7D",
+"R. c #778294",
+"S. c #798394",
+"T. c #758394",
+"U. c #738394",
+"V. c #738294",
+"W. c #738194",
+"X. c #738494",
+"Y. c #738396",
+"Z. c #738496",
+"`. c #73818B",
+" + c #263A40",
+".+ c #485B64",
+"++ c #4A5C62",
+"@+ c #3F505A",
+"#+ c #2D3D43",
+"$+ c #5E6C78",
+"%+ c #778094",
+"&+ c #778194",
+"*+ c #738192",
+"=+ c #737E8B",
+"-+ c #283A42",
+";+ c #41505A",
+">+ c #465A5E",
+",+ c #2D3D41",
+"'+ c #5E6B76",
+")+ c #738190",
+"!+ c #737D8B",
+"~+ c #465656",
+"{+ c #2D3B42",
+"]+ c #465A64",
+"^+ c #4A5B62",
+"/+ c #41515A",
+"(+ c #465B64",
+"_+ c #4A5D64",
+":+ c #2D3D3D",
+"<+ c #5C6A74",
+"[+ c #737F8B",
+"}+ c #73808B",
+"|+ c #73808D",
+"1+ c #737F90",
+"2+ c #737F92",
+"3+ c #737F8D",
+"4+ c #6E7D87",
+"5+ c #445256",
+"6+ c #2D3C42",
+"7+ c #465962",
+"8+ c #41525A",
+"9+ c #4A5E62",
+"0+ c #46595E",
+"a+ c #2B3B41",
+"b+ c #5A6A72",
+"c+ c #6C7B87",
+"d+ c #6E7C89",
+"e+ c #6E7B87",
+"f+ c #6C7C89",
+"g+ c #6A7B89",
+"h+ c #6A7987",
+"i+ c #6A7B87",
+"j+ c #687B87",
+"k+ c #6A7A83",
+"l+ c #404A4E",
+"m+ c #2F3D44",
+"n+ c #485A64",
+"o+ c #41545A",
+"p+ c #2D3D46",
+"q+ c #647581",
+"r+ c #647783",
+"s+ c #627583",
+"t+ c #647681",
+"u+ c #62757F",
+"v+ c #60757F",
+"w+ c #64757F",
+"x+ c #62737B",
+"y+ c #334248",
+"z+ c #2F3F44",
+"A+ c #4A5D66",
+"B+ c #485C66",
+"C+ c #2A3D44",
+"D+ c #31414A",
+"E+ c #526268",
+"F+ c #56676E",
+"G+ c #56696E",
+"H+ c #56656E",
+"I+ c #54666E",
+"J+ c #56666C",
+"K+ c #4E5C64",
+"L+ c #374A52",
+"M+ c #4C6068",
+"N+ c #3F525A",
+"O+ c #4A5D6A",
+"P+ c #3D5056",
+"Q+ c #2F3F41",
+"R+ c #273639",
+"S+ c #223133",
+"T+ c #203033",
+"U+ c #203437",
+"V+ c #203335",
+"W+ c #203235",
+"X+ c #223135",
+"Y+ c #2D393F",
+"Z+ c #394B52",
+"`+ c #445862",
+" @ c #4C6268",
+".@ c #41555A",
+"+@ c #465D66",
+"@@ c #485D66",
+"#@ c #4A5F6A",
+"$@ c #3B4D54",
+"%@ c #2D3A42",
+"&@ c #28373E",
+"*@ c #283840",
+"=@ c #26363E",
+"-@ c #24363E",
+";@ c #2B3840",
+">@ c #35454E",
+",@ c #48575E",
+"'@ c #4E606A",
+")@ c #4C606A",
+"!@ c #465C64",
+"~@ c #3D525C",
+"{@ c #4A606A",
+"]@ c #4A616A",
+"^@ c #485B62",
+"/@ c #435660",
+"(@ c #3D4E56",
+"_@ c #3D4C56",
+":@ c #4A5B64",
+"<@ c #4C5F68",
+"[@ c #4A5E68",
+"}@ c #485F68",
+"|@ c #506773",
+"1@ c #526875",
+"2@ c #566A77",
+"3@ c #566975",
+"4@ c #526570",
+"5@ c #4E636C",
+"6@ c #4A5F68",
+"7@ c #546670",
+"8@ c #566A72",
+"9@ c #566B75",
+"0@ c #546973",
+"a@ c #50656E",
+"b@ c #526971",
+"c@ c #526A75",
+"d@ c #546C77",
+"e@ c #566D7B",
+"f@ c #586D7B",
+"g@ c #586C79",
+"h@ c #546A73",
+"i@ c #566B73",
+"j@ c #566C77",
+"k@ c #566D77",
+"l@ c #566B77",
+"m@ c #546777",
+"n@ c #526673",
+". + @ # $ % & * = - ; > , # > > > ' ) ! ~ ",
+"{ ] ^ / ( _ : < [ } < < < < < < < | 1 2 3 ",
+"4 5 6 7 8 9 0 a b b 0 0 0 c d b e f g h i ",
+"j k l m n o ( p q r s s t u v w x y z A k ",
+"B C D E F G H H I I J K J L M N O P Q R S ",
+"T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.",
+",.'.).y !.~.{.].^./.(.(._.:.<.[.}.|.1.2.3.",
+";.4.5.6.7.8.9.9.9.0.a.a.9.b.c.d.e.f.1.2.g.",
+"h.i.'.j.k.l.m.m.m.n.o.p.p.q.r.s.t.u.v.2.g.",
+"h.w.1.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.U g.",
+"N.O.1.P.Q.R.S.T.U.V.W.U.X.Y.Z.`.t. +.+++@+",
+"v.1.M.#+$+%+&+W.V.V.W.W.W.W.*+=+t.-+v.++;+",
+"v.O.>+,+'+%+&+W.W.W.W.W.W.W.)+!+~+{+]+^+/+",
+"(+_+h.:+<+=+[+}+`.|+1+1+1+2+3+4+5+6+7+^+8+",
+"N.9+0+a+b+c+d+e+f+g+h+i+i+d+j+k+l+m+n+++o+",
+"N.'.o+p+% q+r+s+s+t+u+u+u+v+w+x+y+z+A+++8+",
+"N.'.B+C+D+E+F++ G+F+H+H+H+I+J+K+D+L+M+'.N+",
+"N.A+O+P+Q+R+S+T+U+V+W+W+W+X+Y+Z+`+w. @'..@",
+"+@@@#@T $@y+%@&@*@&@=@-@=@;@>@,@'@)@M+!@~@",
+"{@]@]@#@^@/@@+z P+(@z _@z g./@:@<@'@[@}@M.",
+"|@1@2@3@4@5@<@i.6@i.i.i.i.<@'@7@8@9@3@0@a@",
+"b@c@d@e@f@g@h@h@i@i@i@i@i@i@i@j@k@l@2@m@n@"};
diff --git a/gtk2_ardour/pixmaps/toggle-button-01.xpm b/gtk2_ardour/pixmaps/toggle-button-01.xpm
new file mode 100644
index 0000000000..e1050839be
--- /dev/null
+++ b/gtk2_ardour/pixmaps/toggle-button-01.xpm
@@ -0,0 +1,365 @@
+/* XPM */
+static char * toggle_button_01_xpm[] = {
+"21 22 340 2",
+" c None",
+". c #52646A",
+"+ c #56686E",
+"@ c #506268",
+"# c #4C5E66",
+"$ c #4E626A",
+"% c #52646C",
+"& c #52636A",
+"* c #52636C",
+"= c #52636E",
+"- c #50626C",
+"; c #4E6166",
+"> c #4E5F66",
+", c #4C5D66",
+"' c #4E5E66",
+") c #505F68",
+"! c #52656A",
+"~ c #52676C",
+"{ c #54676C",
+"] c #415156",
+"^ c #2B3A41",
+"/ c #24343D",
+"( c #28363D",
+"_ c #24363D",
+": c #24383D",
+"< c #29363D",
+"[ c #24363F",
+"} c #27363F",
+"| c #27343B",
+"1 c #2D3944",
+"2 c #37464E",
+"3 c #485960",
+"4 c #42545A",
+"5 c #29383F",
+"6 c #2F3C46",
+"7 c #2F4143",
+"8 c #334246",
+"9 c #2F3F46",
+"0 c #314046",
+"a c #354246",
+"b c #313F46",
+"c c #314048",
+"d c #333F48",
+"e c #313F48",
+"f c #33404A",
+"g c #2F3B46",
+"h c #2B393F",
+"i c #3B4A52",
+"j c #394C54",
+"k c #394752",
+"l c #415058",
+"m c #415252",
+"n c #29393F",
+"o c #28383F",
+"p c #28373D",
+"q c #2D383D",
+"r c #2D373D",
+"s c #2D3A3D",
+"t c #2D393D",
+"u c #2B373F",
+"v c #2A373D",
+"w c #283837",
+"x c #283A3D",
+"y c #3B4952",
+"z c #3D4D56",
+"A c #394750",
+"B c #3F5258",
+"C c #44565E",
+"D c #46585E",
+"E c #39474A",
+"F c #3B4B56",
+"G c #4E5A66",
+"H c #525C66",
+"I c #525E6A",
+"J c #52606A",
+"K c #56606A",
+"L c #525E68",
+"M c #48585E",
+"N c #2F3E3D",
+"O c #202F31",
+"P c #2A3B42",
+"Q c #46545E",
+"R c #435260",
+"S c #3D4D58",
+"T c #43575E",
+"U c #4A5A62",
+"V c #4E5B5E",
+"W c #37484E",
+"X c #62707F",
+"Y c #8190A8",
+"Z c #8C9AB4",
+"` c #8E9EB4",
+" . c #8E9EB8",
+".. c #8C9CB4",
+"+. c #8C9EB4",
+"@. c #90A0B8",
+"#. c #90A2B6",
+"$. c #90A0B4",
+"%. c #90A2B0",
+"&. c #627379",
+"*. c #2B363D",
+"=. c #2D3A46",
+"-. c #465766",
+";. c #465762",
+">. c #3F4F5A",
+",. c #465860",
+"'. c #4A5D62",
+"). c #4E6164",
+"!. c #6A7A8E",
+"~. c #92A0BE",
+"{. c #94A2C0",
+"]. c #94A6C4",
+"^. c #94A6C9",
+"/. c #94A4C3",
+"(. c #94A4C0",
+"_. c #96A6C2",
+":. c #96A4C2",
+"<. c #909EB8",
+"[. c #8392A0",
+"}. c #424C54",
+"|. c #2F3F48",
+"1. c #4A5B66",
+"2. c #4A5962",
+"3. c #3F515C",
+"4. c #4A5F62",
+"5. c #4C5F62",
+"6. c #37414A",
+"7. c #68748C",
+"8. c #7F8EAA",
+"9. c #7F8FA8",
+"0. c #7F8EA8",
+"a. c #7F8DA8",
+"b. c #7F8BA6",
+"c. c #7D88A2",
+"d. c #7D8998",
+"e. c #46565E",
+"f. c #2D4048",
+"g. c #3D505A",
+"h. c #465B5E",
+"i. c #4A5F66",
+"j. c #313D4A",
+"k. c #667184",
+"l. c #7B87A2",
+"m. c #7B89A4",
+"n. c #7B88A3",
+"o. c #7B86A0",
+"p. c #7A85A0",
+"q. c #7B879C",
+"r. c #7B88A0",
+"s. c #7B869E",
+"t. c #7B8596",
+"u. c #46565A",
+"v. c #2D3D42",
+"w. c #465B66",
+"x. c #4A5E66",
+"y. c #313C48",
+"z. c #64707F",
+"A. c #79859A",
+"B. c #798598",
+"C. c #748599",
+"D. c #A97E7F",
+"E. c #E7765A",
+"F. c #E67256",
+"G. c #A97B7B",
+"H. c #788799",
+"I. c #77859A",
+"J. c #79849C",
+"K. c #758490",
+"L. c #46585A",
+"M. c #2B3C42",
+"N. c #465A62",
+"O. c #465B62",
+"P. c #4A5C66",
+"Q. c #2F3C43",
+"R. c #606C7D",
+"S. c #778294",
+"T. c #798394",
+"U. c #788498",
+"V. c #E66141",
+"W. c #E45A38",
+"X. c #E46A4C",
+"Y. c #768598",
+"Z. c #738396",
+"`. c #738496",
+" + c #73818B",
+".+ c #263A40",
+"++ c #485B64",
+"@+ c #4A5C62",
+"#+ c #3F505A",
+"$+ c #2D3D43",
+"%+ c #5E6C78",
+"&+ c #778094",
+"*+ c #778194",
+"=+ c #768298",
+"-+ c #E24E2A",
+";+ c #E46547",
+">+ c #738194",
+",+ c #738192",
+"'+ c #737E8B",
+")+ c #283A42",
+"!+ c #41505A",
+"~+ c #465A5E",
+"{+ c #2D3D41",
+"]+ c #5E6B76",
+"^+ c #748195",
+"/+ c #A87A7A",
+"(+ c #A77675",
+"_+ c #738190",
+":+ c #737D8B",
+"<+ c #465656",
+"[+ c #2D3B42",
+"}+ c #465A64",
+"|+ c #4A5B62",
+"1+ c #41515A",
+"2+ c #465B64",
+"3+ c #4A5D64",
+"4+ c #2D3D3D",
+"5+ c #5C6A74",
+"6+ c #737F8B",
+"7+ c #73808B",
+"8+ c #74818D",
+"9+ c #768293",
+"0+ c #768093",
+"a+ c #747F90",
+"b+ c #737F90",
+"c+ c #737F92",
+"d+ c #737F8D",
+"e+ c #6E7D87",
+"f+ c #445256",
+"g+ c #2D3C42",
+"h+ c #465962",
+"i+ c #41525A",
+"j+ c #4A5E62",
+"k+ c #46595E",
+"l+ c #2B3B41",
+"m+ c #5A6A72",
+"n+ c #6C7B87",
+"o+ c #6E7C89",
+"p+ c #6E7B87",
+"q+ c #6C7C89",
+"r+ c #6A7B89",
+"s+ c #6A7987",
+"t+ c #6A7B87",
+"u+ c #687B87",
+"v+ c #6A7A83",
+"w+ c #404A4E",
+"x+ c #2F3D44",
+"y+ c #485A64",
+"z+ c #41545A",
+"A+ c #2D3D46",
+"B+ c #647581",
+"C+ c #647783",
+"D+ c #627583",
+"E+ c #647681",
+"F+ c #62757F",
+"G+ c #60757F",
+"H+ c #64757F",
+"I+ c #62737B",
+"J+ c #334248",
+"K+ c #2F3F44",
+"L+ c #4A5D66",
+"M+ c #485C66",
+"N+ c #2A3D44",
+"O+ c #31414A",
+"P+ c #526268",
+"Q+ c #56676E",
+"R+ c #56696E",
+"S+ c #56656E",
+"T+ c #54666E",
+"U+ c #56666C",
+"V+ c #4E5C64",
+"W+ c #374A52",
+"X+ c #4C6068",
+"Y+ c #3F525A",
+"Z+ c #4A5D6A",
+"`+ c #3D5056",
+" @ c #2F3F41",
+".@ c #273639",
+"+@ c #223133",
+"@@ c #203033",
+"#@ c #203437",
+"$@ c #203335",
+"%@ c #203235",
+"&@ c #223135",
+"*@ c #2D393F",
+"=@ c #394B52",
+"-@ c #445862",
+";@ c #4C6268",
+">@ c #41555A",
+",@ c #465D66",
+"'@ c #485D66",
+")@ c #4A5F6A",
+"!@ c #3B4D54",
+"~@ c #2D3A42",
+"{@ c #28373E",
+"]@ c #283840",
+"^@ c #26363E",
+"/@ c #24363E",
+"(@ c #2B3840",
+"_@ c #35454E",
+":@ c #48575E",
+"<@ c #4E606A",
+"[@ c #4C606A",
+"}@ c #465C64",
+"|@ c #3D525C",
+"1@ c #4A606A",
+"2@ c #4A616A",
+"3@ c #485B62",
+"4@ c #435660",
+"5@ c #3D4E56",
+"6@ c #3D4C56",
+"7@ c #4A5B64",
+"8@ c #4C5F68",
+"9@ c #4A5E68",
+"0@ c #485F68",
+"a@ c #506773",
+"b@ c #526875",
+"c@ c #566A77",
+"d@ c #566975",
+"e@ c #526570",
+"f@ c #4E636C",
+"g@ c #4A5F68",
+"h@ c #546670",
+"i@ c #566A72",
+"j@ c #566B75",
+"k@ c #546973",
+"l@ c #50656E",
+"m@ c #526971",
+"n@ c #526A75",
+"o@ c #546C77",
+"p@ c #566D7B",
+"q@ c #586D7B",
+"r@ c #586C79",
+"s@ c #546A73",
+"t@ c #566B73",
+"u@ c #566C77",
+"v@ c #566D77",
+"w@ c #566B77",
+"x@ c #546777",
+"y@ c #526673",
+". + @ # $ % & * = - ; > , # > > > ' ) ! ~ ",
+"{ ] ^ / ( _ : < [ } < < < < < < < | 1 2 3 ",
+"4 5 6 7 8 9 0 a b b 0 0 0 c d b e f g h i ",
+"j k l m n o ( p q r s s t u v w x y z A k ",
+"B C D E F G H H I I J K J L M N O P Q R S ",
+"T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.",
+",.'.).y !.~.{.].^./.(.(._.:.<.[.}.|.1.2.3.",
+";.4.5.6.7.8.9.9.9.0.a.a.9.b.c.d.e.f.1.2.g.",
+"h.i.'.j.k.l.m.m.n.o.p.q.q.r.s.t.u.v.w.2.g.",
+"h.x.1.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.U g.",
+"O.P.1.Q.R.S.T.U.E.V.W.X.Y.Z.`. +u..+++@+#+",
+"w.1.N.$+%+&+*+=+F.W.-+;+=+>+,+'+u.)+w.@+!+",
+"w.P.~+{+]+&+*+^+/+X.;+(+^+>+_+:+<+[+}+|+1+",
+"2+3+h.4+5+'+6+7+8+9+0+a+b+c+d+e+f+g+h+|+i+",
+"O.j+k+l+m+n+o+p+q+r+s+t+t+o+u+v+w+x+y+@+z+",
+"O.'.z+A+% B+C+D+D+E+F+F+F+G+H+I+J+K+L+@+i+",
+"O.'.M+N+O+P+Q++ R+Q+S+S+S+T+U+V+O+W+X+'.Y+",
+"O.L+Z+`+ @.@+@@@#@$@%@%@%@&@*@=@-@x.;@'.>@",
+",@'@)@T !@J+~@{@]@{@^@/@^@(@_@:@<@[@X+}@|@",
+"1@2@2@)@3@4@#+z `+5@z 6@z g.4@7@8@<@9@0@N.",
+"a@b@c@d@e@f@8@i.g@i.i.i.i.8@<@h@i@j@d@k@l@",
+"m@n@o@p@q@r@s@s@t@t@t@t@t@t@t@u@v@w@c@x@y@"};
diff --git a/gtk2_ardour/pixmaps/vslider00.xpm b/gtk2_ardour/pixmaps/vslider00.xpm
new file mode 100644
index 0000000000..2a3687b937
--- /dev/null
+++ b/gtk2_ardour/pixmaps/vslider00.xpm
@@ -0,0 +1,197 @@
+/* XPM */
+static char * vslider00_xpm[] = {
+"16 32 162 2",
+" c None",
+". c #7B7B7B",
+"+ c #6C6C6C",
+"@ c #626262",
+"# c #585858",
+"$ c #505050",
+"% c #4B4B4B",
+"& c #494949",
+"* c #8C8C8C",
+"= c #8E8E8E",
+"- c #858585",
+"; c #787878",
+"> c #6D6D6D",
+", c #666666",
+"' c #616161",
+") c #5C5C5C",
+"! c #5B5B5B",
+"~ c #595959",
+"{ c #555555",
+"] c #959595",
+"^ c #ACACAC",
+"/ c #A0A0A0",
+"( c #949494",
+"_ c #8D8D8D",
+": c #888888",
+"< c #848484",
+"[ c #7E7E7E",
+"} c #7C7C7C",
+"| c #7A7A7A",
+"1 c #797979",
+"2 c #757575",
+"3 c #676767",
+"4 c #474747",
+"5 c #9C9C9C",
+"6 c #C2C2C2",
+"7 c #BDBDBD",
+"8 c #B9B9B9",
+"9 c #B4B4B4",
+"0 c #B1B1B1",
+"a c #AEAEAE",
+"b c #ABABAB",
+"c c #A8A8A8",
+"d c #A6A6A6",
+"e c #A5A5A5",
+"f c #A4A4A4",
+"g c #9A9A9A",
+"h c #323232",
+"i c #9F9F9F",
+"j c #D6D6D6",
+"k c #D2D2D2",
+"l c #D3D3D3",
+"m c #D4D4D4",
+"n c #D5D5D5",
+"o c #D1D1D1",
+"p c #232323",
+"q c #DFDFDF",
+"r c #DBDBDB",
+"s c #E0E0E0",
+"t c #E4E4E4",
+"u c #E6E6E6",
+"v c #E2E2E2",
+"w c #DDDDDD",
+"x c #D8D8D8",
+"y c #AAAAAA",
+"z c #777777",
+"A c #1A1A1A",
+"B c #F3F3F3",
+"C c #D7D7D7",
+"D c #D9D9D9",
+"E c #CDCDCD",
+"F c #737373",
+"G c #151515",
+"H c #F2F2F2",
+"I c #DADADA",
+"J c #D0D0D0",
+"K c #CFCFCF",
+"L c #CBCBCB",
+"M c #C3C3C3",
+"N c #999999",
+"O c #131313",
+"P c #F1F1F1",
+"Q c #CACACA",
+"R c #C6C6C6",
+"S c #C1C1C1",
+"T c #BBBBBB",
+"U c #B8B8B8",
+"V c #B3B3B3",
+"W c #707070",
+"X c #111111",
+"Y c #F0F0F0",
+"Z c #BCBCBC",
+"` c #B6B6B6",
+" . c #AFAFAF",
+".. c #929292",
+"+. c #828282",
+"@. c #6B6B6B",
+"#. c #101010",
+"$. c #CECECE",
+"%. c #C8C8C8",
+"&. c #BEBEBE",
+"*. c #A3A3A3",
+"=. c #9B9B9B",
+"-. c #919191",
+";. c #7F7F7F",
+">. c #0F0F0F",
+",. c #EDEDED",
+"'. c #CCCCCC",
+"). c #C5C5C5",
+"!. c #C0C0C0",
+"~. c #BABABA",
+"{. c #A1A1A1",
+"]. c #B5B5B5",
+"^. c #A2A2A2",
+"/. c #9E9E9E",
+"(. c #979797",
+"_. c #C7C7C7",
+":. c #C4C4C4",
+"<. c #C9C9C9",
+"[. c #8A8A8A",
+"}. c #989898",
+"|. c #7D7D7D",
+"1. c #747474",
+"2. c #6F6F6F",
+"3. c #0B0B0B",
+"4. c #868686",
+"5. c #2C2C2C",
+"6. c #0E0E0E",
+"7. c #0D0D0D",
+"8. c #0C0C0C",
+"9. c #090909",
+"0. c #010101",
+"a. c #878787",
+"b. c #353535",
+"c. c #141414",
+"d. c #020202",
+"e. c #8F8F8F",
+"f. c #8B8B8B",
+"g. c #838383",
+"h. c #606060",
+"i. c #E3E3E3",
+"j. c #727272",
+"k. c #A7A7A7",
+"l. c #DEDEDE",
+"m. c #BFBFBF",
+"n. c #B0B0B0",
+"o. c #6A6A6A",
+"p. c #F4F4F4",
+"q. c #B7B7B7",
+"r. c #696969",
+"s. c #B2B2B2",
+"t. c #6E6E6E",
+"u. c #A9A9A9",
+"v. c #909090",
+"w. c #ADADAD",
+"x. c #646464",
+"y. c #656565",
+"z. c #5A5A5A",
+"A. c #545454",
+"B. c #484848",
+"C. c #404040",
+"D. c #3E3E3E",
+"E. c #0A0A0A",
+" . + @ # $ % % % % % % % % & ",
+"* = - ; > , ' ) ) ! ! ! ! ~ { ~ ",
+"] ^ / ( _ : < [ } . | | 1 2 3 4 ",
+"5 6 7 8 9 0 a b c d e e f g 2 h ",
+"i j k k l m n n n n m m o 9 } p ",
+"/ q r s t u u u v w r x m y z A ",
+"e B C j x x x x D D n o E / F G ",
+"e H j I r D j m k J K L M N F O ",
+"e P o o K Q R S 7 T U V d * W X ",
+"e Y K E Q R S Z ` .c / ..+.@.#.",
+"e P $.L %.M &.U 0 y *.=.-.;., >.",
+"f ,.'.).!.~.9 a c {.=.( * < W #.",
+"{.s E &.]. .y c e ^.i /.(.+.+ #.",
+"*.u L _.%.M :.:.R <._.S V [.@.#.",
+"}./.+.|.;.. | ; z z 1.2.3 # 4 3.",
+"4.5.#.#.#.>.>.>.6.6.6.7.8.3.9.0.",
+"a.b.c.c.c.c.c.c.c.c.c.c.c.c.6.d.",
+"}.*.e.e.e.e.= _ _ * f.[.: g.h.7.",
+"*.i._.)._._.:.6 S &.T ` y ] j.#.",
+"/ w %.].` ` ].9 9 V 0 .k._ @.#.",
+"/ l.K ).M 6 S !.!.m.&.~.n.= o.#.",
+"e P m J E E L Q Q <._.6 ` -.3 >.",
+"e p.D J '.'.L Q <.%.).6 q.] r.>.",
+"e B J T s.0 0 s.V s.s. .f - 3 >.",
+"e H l E %.R R %.<.<.%.S s._ @.#.",
+"e B C k K E '.L L '.'._.T =.t.>.",
+"e B %.` ]. .b u.c k.k.k.e v.r.>.",
+"e Y Q S ~.` s. .w.^ ^ b ^.- o.#.",
+"^.w ~.0 ^ k.^./.=.N }.}.e.2 x.>.",
+"( /.- 1 t.r.3 y.y.x.x.x.' # z.>.",
+"~ 3 A.B.C.D.D.D.D.D.D.D.D.D.% 7.",
+" c.8.E.9.9.9.9.9.9.9.9.9.9.3.d."};
diff --git a/gtk2_ardour/pixmaps/vslider01.xpm b/gtk2_ardour/pixmaps/vslider01.xpm
new file mode 100644
index 0000000000..4afc6d1605
--- /dev/null
+++ b/gtk2_ardour/pixmaps/vslider01.xpm
@@ -0,0 +1,206 @@
+/* XPM */
+static char * vslider01_xpm[] = {
+"3 200 3 1",
+" c None",
+". c #000000",
+"+ c #969393",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+",
+"..+"};
diff --git a/gtk2_ardour/playlist_selection.h b/gtk2_ardour/playlist_selection.h
new file mode 100644
index 0000000000..af0031fec9
--- /dev/null
+++ b/gtk2_ardour/playlist_selection.h
@@ -0,0 +1,12 @@
+#ifndef __ardour_gtk_playlist_selection_h__
+#define __ardour_gtk_playlist_selection_h__
+
+#include <list>
+
+namespace ARDOUR {
+ class Playlist;
+}
+
+struct PlaylistSelection : list<ARDOUR::Playlist*> {};
+
+#endif /* __ardour_gtk_playlist_selection_h__ */
diff --git a/gtk2_ardour/playlist_selector.cc b/gtk2_ardour/playlist_selector.cc
new file mode 100644
index 0000000000..d0796c0aa6
--- /dev/null
+++ b/gtk2_ardour/playlist_selector.cc
@@ -0,0 +1,249 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+
+*/
+
+#include <gtk--/button.h>
+#include <gtk--/ctree.h>
+
+#include <ardour/session_playlist.h>
+#include <ardour/diskstream.h>
+#include <ardour/playlist.h>
+#include <ardour/audio_track.h>
+#include <ardour/audioplaylist.h>
+#include <ardour/configuration.h>
+
+#include <gtkmmext/gtk_ui.h>
+
+#include "playlist_selector.h"
+#include "route_ui.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace SigC;
+using namespace Gtk;
+using namespace ARDOUR;
+
+static const gchar *tree_display_titles[] = {
+ N_("Playlists grouped by track"),
+ 0
+};
+
+PlaylistSelector::PlaylistSelector ()
+ : ArdourDialog ("playlist selector"),
+ tree (internationalize (tree_display_titles)),
+ close_button (_("close"))
+{
+ rui = 0;
+
+ set_position (GTK_WIN_POS_MOUSE);
+ set_name ("PlaylistSelectorWindow");
+ set_title (_("ardour: playlists"));
+ set_modal(true);
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+ set_usize (300, 200);
+
+ scroller.add_with_viewport (tree);
+ scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ close_button.clicked.connect (slot (*this, &PlaylistSelector::close_button_click));
+
+ vpacker.set_border_width (6);
+ vpacker.set_spacing (12);
+ vpacker.pack_start (scroller);
+ vpacker.pack_start (close_button, false, false);
+
+ add (vpacker);
+}
+
+PlaylistSelector::~PlaylistSelector ()
+{
+ clear_map ();
+}
+
+void
+PlaylistSelector::clear_map ()
+{
+ for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) {
+ delete x->second;
+ }
+ dspl_map.clear ();
+}
+
+void
+PlaylistSelector::show_for (RouteUI* ruix)
+{
+ using namespace CTree_Helpers;
+ vector<const char*> item;
+ RowList::iterator i;
+ RowList::iterator tmpi;
+ RowList::iterator others;
+ DiskStream* this_ds;
+ string str;
+
+ rui = ruix;
+
+ str = _("ardour: playlist for ");
+ str += rui->route().name();
+
+ set_title (str);
+
+ clear_map ();
+ select_connection.disconnect ();
+
+ /* ---------------------------------------- */
+ /* XXX MAKE ME A FUNCTION (no CTree::clear() in gtkmm 1.2) */
+ gtk_ctree_remove_node (tree.gtkobj(), NULL);
+ /* ---------------------------------------- */
+
+ session->foreach_playlist (this, &PlaylistSelector::add_playlist_to_map);
+
+ this_ds = rui->get_diskstream();
+
+ item.clear();
+ item.push_back (_("Other tracks"));
+ others = tree.rows().insert (tree.rows().begin(), Element (item));
+
+ for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) {
+
+ DiskStream* ds = session->diskstream_by_id (x->first);
+
+ if (ds == 0) {
+ continue;
+ }
+
+ /* add a node for the diskstream */
+
+ item.clear ();
+
+ if (ds->name().empty()) {
+ item.push_back (_("unassigned"));
+ } else {
+ item.push_back (ds->name().c_str());
+ }
+
+ if (ds == this_ds) {
+ i = tree.rows().insert (tree.rows().begin(),
+ Gtk::CTree_Helpers::Element (item));
+ } else {
+ i = others->subtree().insert (others->subtree().end(),
+ Gtk::CTree_Helpers::Element (item));
+ }
+
+ /* Now insert all the playlists for this diskstream/track in a subtree */
+
+ list<Playlist*> *pls = x->second;
+
+ for (list<Playlist*>::iterator p = pls->begin(); p != pls->end(); ++p) {
+
+ item.clear ();
+ item.push_back ((*p)->name().c_str());
+
+ tmpi = i->subtree().insert (i->subtree().end(), Element (item));
+
+ if (*p == this_ds->playlist()) {
+ (*tmpi).select ();
+ }
+
+ (*tmpi).set_data (*p);
+
+ }
+
+ if (ds == this_ds) {
+ i->expand ();
+ }
+ }
+
+ show_all ();
+ select_connection = tree.tree_select_row.connect (slot (*this, &PlaylistSelector::row_selected));
+}
+
+void
+PlaylistSelector::add_playlist_to_map (Playlist *pl)
+{
+ AudioPlaylist* apl;
+
+ if (pl->frozen()) {
+ return;
+ }
+
+ if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
+ return;
+ }
+
+ DSPL_Map::iterator x;
+
+ if ((x = dspl_map.find (apl->get_orig_diskstream_id())) == dspl_map.end()) {
+
+ pair<ARDOUR::id_t,list<Playlist*>*> newp (apl->get_orig_diskstream_id(), new list<Playlist*>);
+
+ x = dspl_map.insert (dspl_map.end(), newp);
+ }
+
+ x->second->push_back (pl);
+}
+
+void
+PlaylistSelector::set_session (Session* s)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &PlaylistSelector::set_session), s));
+
+ session = s;
+
+ if (session) {
+ session->going_away.connect (bind (slot (*this, &PlaylistSelector::set_session), static_cast<Session*> (0)));
+ }
+}
+
+void
+PlaylistSelector::close_button_click ()
+{
+ rui = 0;
+ hide ();
+}
+
+void
+PlaylistSelector::row_selected (Gtk::CTree::Row row, gint col)
+{
+ Playlist *playlist;
+
+ if ((playlist = (Playlist *) row.get_data()) != 0) {
+
+ AudioTrack* at;
+ AudioPlaylist* apl;
+
+ if ((at = dynamic_cast<AudioTrack*> (&rui->route())) == 0) {
+ /* eh? */
+ return;
+ }
+
+ if ((apl = dynamic_cast<AudioPlaylist*> (playlist)) == 0) {
+ /* eh? */
+ return;
+ }
+
+ at->disk_stream().use_playlist (apl);
+
+ hide ();
+ }
+
+}
+
diff --git a/gtk2_ardour/playlist_selector.h b/gtk2_ardour/playlist_selector.h
new file mode 100644
index 0000000000..5c36d6b0a3
--- /dev/null
+++ b/gtk2_ardour/playlist_selector.h
@@ -0,0 +1,65 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_playlist_selector_h__
+#define __ardour_playlist_selector_h__
+
+#include <gtk--.h>
+#include <gtk--/ctree.h>
+#include <gtkmmext/selector.h>
+
+#include <ardour_dialog.h>
+
+namespace ARDOUR {
+ class Session;
+ class PluginManager;
+ class Plugin;
+}
+
+class RouteUI;
+
+class PlaylistSelector : public ArdourDialog
+{
+ public:
+ PlaylistSelector ();
+ ~PlaylistSelector ();
+
+ void set_session (ARDOUR::Session*);
+ void show_for (RouteUI*);
+
+ private:
+ typedef std::map<ARDOUR::id_t,std::list<ARDOUR::Playlist*>*> DSPL_Map;
+
+ ARDOUR::Session* session;
+ Gtk::VBox vpacker;
+ Gtk::ScrolledWindow scroller;
+ Gtk::CTree tree;
+ Gtk::Button close_button;
+ DSPL_Map dspl_map;
+ RouteUI* rui;
+
+ SigC::Connection select_connection;
+
+ void add_playlist_to_map (ARDOUR::Playlist*);
+ void clear_map ();
+ void close_button_click ();
+ void row_selected (Gtk::CTree::Row, int32_t col);
+};
+
+#endif // __ardour_playlist_selector_h__
diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc
new file mode 100644
index 0000000000..1ba8062f89
--- /dev/null
+++ b/gtk2_ardour/plugin_selector.cc
@@ -0,0 +1,418 @@
+/*
+ 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 <cstdio>
+#include <lrdf.h>
+
+#include <gtk--/table.h>
+#include <gtk--/button.h>
+#include <gtk--/notebook.h>
+#include <gtk--/ctree.h>
+
+#include <ardour/plugin_manager.h>
+#include <ardour/plugin.h>
+#include <ardour/configuration.h>
+
+#include "ardour_ui.h"
+#include "plugin_selector.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+
+static const gchar *i_titles[] = {
+ N_("Available LADSPA plugins"),
+ N_("Type"),
+ N_("# Inputs"),
+ N_("# Outputs"),
+ 0
+};
+
+#ifdef VST_SUPPORT
+static const gchar *vst_titles[] = {
+ N_("Available VST plugins"),
+ N_("# Inputs"),
+ N_("# Outputs"),
+ 0
+};
+#endif
+
+static const gchar *o_titles[] = {
+ N_("To be added"),
+ 0
+};
+
+PluginSelector::PluginSelector (PluginManager *mgr)
+ : ArdourDialog ("plugin selector"),
+ ladspa_display (_input_refiller, this, internationalize (i_titles), false, true),
+#ifdef VST_SUPPORT
+ vst_display (_vst_refiller, this, internationalize (vst_titles), false, true),
+#endif
+ o_selector (_output_refiller, this, internationalize (o_titles), false, true)
+{
+ set_position (GTK_WIN_POS_MOUSE);
+ set_name ("PluginSelectorWindow");
+ set_title (_("ardour: plugins"));
+ set_modal(true);
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ manager = mgr;
+ session = 0;
+ o_selected_plug = -1;
+ i_selected_plug = 0;
+
+ Gtk::Button *btn_add = manage(new Gtk::Button(_("Add")));
+ ARDOUR_UI::instance()->tooltips().set_tip(*btn_add, _("Add a plugin to the effect list"));
+ Gtk::Button *btn_remove = manage(new Gtk::Button(_("Remove")));
+ ARDOUR_UI::instance()->tooltips().set_tip(*btn_remove, _("Remove a plugin from the effect list"));
+ Gtk::Button *btn_ok = manage(new Gtk::Button(_("OK")));
+ Gtk::Button *btn_cancel = manage(new Gtk::Button(_("Cancel")));
+
+ Gtk::Button *btn_update = manage(new Gtk::Button(_("Update")));
+ ARDOUR_UI::instance()->tooltips().set_tip(*btn_update, _("Update available plugins"));
+
+ btn_ok->set_name("PluginSelectorButton");
+ btn_cancel->set_name("PluginSelectorButton");
+ btn_add->set_name("PluginSelectorButton");
+ btn_remove->set_name("PluginSelectorButton");
+
+ Gtk::Table* table = manage(new Gtk::Table(7, 10));
+ table->set_usize(750, 500);
+ table->attach(notebook, 0, 7, 0, 5);
+
+ table->attach(*btn_add, 1, 2, 5, 6, GTK_FILL, 0, 5, 5);
+ table->attach(*btn_remove, 3, 4, 5, 6, GTK_FILL, 0, 5, 5);
+ table->attach(*btn_update, 5, 6, 5, 6, GTK_FILL, 0, 5, 5);
+
+ table->attach(o_selector, 0, 7, 7, 9);
+ table->attach(*btn_ok, 1, 3, 9, 10, GTK_FILL, 0, 5, 5);
+ table->attach(*btn_cancel, 3, 4, 9, 10, GTK_FILL, 0, 5, 5);
+ add (*table);
+
+ using namespace Gtk::Notebook_Helpers;
+ notebook.pages().push_back (TabElem (ladspa_display, _("LADSPA")));
+#ifdef VST_SUPPORT
+ if (Config->get_use_vst()) {
+ notebook.pages().push_back (TabElem (vst_display, _("VST")));
+ }
+#endif
+
+ table->set_name("PluginSelectorTable");
+ //ladspa_display.set_name("PluginSelectorDisplay");
+ ladspa_display.clist().set_name("PluginSelectorList");
+ o_selector.clist().set_name("PluginSelectorList");
+
+ ladspa_display.clist().column_titles_active();
+ ladspa_display.clist().column(0).set_auto_resize (false);
+ ladspa_display.clist().column(0).set_width(470);
+
+ ladspa_display.clist().column(1).set_auto_resize (true);
+ o_selector.clist().column(0).set_auto_resize (true);
+
+ ladspa_display.selection_made.connect (slot(*this, &PluginSelector::i_plugin_selected));
+ ladspa_display.choice_made.connect(slot(*this, &PluginSelector::i_plugin_chosen));
+ ladspa_display.clist().click_column.connect(bind (slot(*this, &PluginSelector::column_clicked), ladspa_display.clist().gtkobj()));
+#ifdef VST_SUPPORT
+ if (Config->get_use_vst()) {
+ vst_display.selection_made.connect (slot(*this, &PluginSelector::i_plugin_selected));
+ vst_display.choice_made.connect(slot(*this, &PluginSelector::i_plugin_chosen));
+ vst_display.clist().click_column.connect(bind (slot(*this, &PluginSelector::column_clicked), vst_display.clist().gtkobj()));
+ }
+#endif
+ o_selector.selection_made.connect(slot(*this, &PluginSelector::o_plugin_selected));
+ o_selector.choice_made.connect(slot(*this,&PluginSelector::o_plugin_chosen));
+ btn_update->clicked.connect (slot(*this, &PluginSelector::btn_update_clicked));
+ btn_add->clicked.connect(slot(*this, &PluginSelector::btn_add_clicked));
+ btn_remove->clicked.connect(slot(*this, &PluginSelector::btn_remove_clicked));
+ btn_ok->clicked.connect(slot(*this, &PluginSelector::btn_ok_clicked));
+ btn_cancel->clicked.connect(slot(*this,&PluginSelector::btn_cancel_clicked));
+ delete_event.connect (slot (*this, &PluginSelector::wm_close));
+
+}
+
+void
+PluginSelector::set_session (Session* s)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &PluginSelector::set_session), s));
+
+ session = s;
+
+ if (session) {
+ session->going_away.connect (bind (slot (*this, &PluginSelector::set_session), static_cast<Session*> (0)));
+ }
+}
+
+void
+PluginSelector::_input_refiller (Gtk::CList &list, void *arg)
+{
+ ((PluginSelector *) arg)->input_refiller (list);
+}
+
+void
+PluginSelector::_output_refiller (Gtk::CList &list, void *arg)
+{
+ ((PluginSelector *) arg)->output_refiller (list);
+}
+
+int compare(const void *left, const void *right)
+{
+ return strcmp(*((char**)left), *((char**)right));
+}
+
+void
+PluginSelector::input_refiller (Gtk::CList &clist)
+{
+ const gchar *rowdata[4];
+ guint row;
+ list<PluginInfo *> &plugs = manager->ladspa_plugin_info ();
+ list<PluginInfo *>::iterator i;
+ char ibuf[16], obuf[16];
+
+ // Insert into GTK list
+ for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) {
+ rowdata[0] = (*i)->name.c_str();
+ rowdata[1] = (*i)->category.c_str();
+
+ snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
+ snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);
+ rowdata[2] = ibuf;
+ rowdata[3] = obuf;
+
+ clist.insert_row (row, rowdata);
+ clist.rows().back().set_data (*i);
+ }
+
+ clist.set_sort_column (0);
+ clist.sort ();
+}
+
+#ifdef VST_SUPPORT
+
+void
+PluginSelector::_vst_refiller (Gtk::CList &list, void *arg)
+{
+ ((PluginSelector *) arg)->vst_refiller (list);
+}
+
+void
+PluginSelector::vst_refiller (Gtk::CList &clist)
+{
+ const gchar *rowdata[3];
+ guint row;
+ list<PluginInfo *> &plugs = manager->vst_plugin_info ();
+ list<PluginInfo *>::iterator i;
+ char ibuf[16], obuf[16];
+
+ if (!Config->get_use_vst()) {
+ return;
+ }
+
+ // Insert into GTK list
+
+ for (row = 0, i = plugs.begin(); i != plugs.end(); ++i, ++row) {
+ rowdata[0] = (*i)->name.c_str();
+
+ snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs);
+ snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs);
+ rowdata[1] = ibuf;
+ rowdata[2] = obuf;
+
+ clist.insert_row (row, rowdata);
+ clist.rows().back().set_data (*i);
+ }
+
+ clist.set_sort_column (0);
+ clist.sort ();
+}
+#endif
+
+void
+PluginSelector::output_refiller (Gtk::CList &clist)
+{
+ const gchar *rowdata[2];
+ guint row;
+ list<PluginInfo*>::iterator i;
+
+ // Insert into GTK list
+
+ for (row = 0, i = added_plugins.begin(); i != added_plugins.end(); ++i, ++row){
+ rowdata[0] = (*i)->name.c_str();
+ clist.insert_row (row, rowdata);
+ clist.rows().back().set_data (*i);
+ }
+}
+
+void
+PluginSelector::i_plugin_chosen (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *res)
+{
+ if (res) {
+ // get text for name column (0)
+ i_selected_plug = static_cast<PluginInfo*> (selector->clist().row(res->row).get_data());
+ //i_selected_plug = *res->text;
+ } else {
+ i_selected_plug = 0;
+ }
+}
+
+void
+PluginSelector::i_plugin_selected (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *res)
+{
+ if (res) {
+ added_plugins.push_back (static_cast<PluginInfo*> (selector->clist().row(res->row).get_data()));
+ //added_plugins.push_back(*(res->text));
+ o_selector.rescan();
+ }
+}
+
+void
+PluginSelector::o_plugin_chosen (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *res)
+{
+ if (res && res->text) {
+ o_selected_plug = res->row;
+ } else {
+ o_selected_plug = -1;
+ }
+
+}
+
+void
+PluginSelector::o_plugin_selected (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *res)
+{
+ if(res && res->text){
+ gint row = 0;
+ list<PluginInfo*>::iterator i = added_plugins.begin();
+ while (row < res->row){
+ i++;
+ row++;
+ }
+ added_plugins.erase(i);
+ o_selector.rescan();
+ o_selected_plug = -1;
+ }
+}
+
+void
+PluginSelector::use_plugin (PluginInfo* pi)
+{
+ list<PluginInfo *>::iterator i;
+
+ if (pi == 0 || session == 0) {
+ return;
+ }
+
+ Plugin *plugin = manager->load (*session, pi);
+
+ if (plugin) {
+ PluginCreated (plugin);
+ }
+}
+
+void
+PluginSelector::btn_add_clicked()
+{
+ if (i_selected_plug) {
+ added_plugins.push_back (i_selected_plug);
+ o_selector.rescan();
+ }
+}
+
+void
+PluginSelector::btn_remove_clicked()
+{
+ if (o_selected_plug > -1){
+ gint row = 0;
+ list<PluginInfo*>::iterator i = added_plugins.begin();
+ while(row < o_selected_plug){
+ i++;
+ row++;
+ }
+ added_plugins.erase(i);
+ o_selector.rescan();
+ o_selected_plug = -1;
+ }
+}
+
+// Adds a plugin, and closes the window.
+void
+PluginSelector::btn_ok_clicked()
+{
+ using namespace Gtk::CList_Helpers;
+
+ list<PluginInfo*>::iterator i;
+
+ for (i = added_plugins.begin(); i != added_plugins.end(); ++i){
+ use_plugin (*i);
+ }
+
+ hide();
+ added_plugins.clear();
+ o_selector.rescan();
+ i_selected_plug = 0;
+ o_selected_plug = -1;
+
+ SelectionList s_list = ladspa_display.clist().selection();
+ SelectionList::iterator s = s_list.begin();
+ if (s != s_list.end()) {
+ (*s).unselect();
+ }
+
+#ifdef VST_SUPPORT
+ SelectionList v_list = vst_display.clist().selection();
+ SelectionList::iterator v = v_list.begin();
+ if (v != v_list.end()) {
+ (*v).unselect();
+ }
+#endif
+}
+
+void
+PluginSelector::btn_cancel_clicked()
+{
+ hide();
+ added_plugins.clear();
+ o_selector.rescan();
+ i_selected_plug = 0;
+ o_selected_plug = -1;
+}
+
+void
+PluginSelector::btn_update_clicked()
+{
+ manager->refresh ();
+ ladspa_display.rescan ();
+}
+
+gint
+PluginSelector::wm_close(GdkEventAny* ev)
+{
+ btn_cancel_clicked();
+ return TRUE;
+}
+
+void
+PluginSelector::column_clicked (int column, GtkCList* clist)
+{
+ gtk_clist_set_sort_column (clist, column);
+ gtk_clist_sort (clist);
+}
diff --git a/gtk2_ardour/plugin_selector.h b/gtk2_ardour/plugin_selector.h
new file mode 100644
index 0000000000..d1d0a54747
--- /dev/null
+++ b/gtk2_ardour/plugin_selector.h
@@ -0,0 +1,92 @@
+/*
+ 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.
+
+*/
+
+#ifndef __ardour_plugin_selector_h__
+#define __ardour_plugin_selector_h__
+
+#include <gtk--.h>
+#include <gtk--/ctree.h>
+#include <gtkmmext/selector.h>
+
+#include <ardour_dialog.h>
+
+namespace ARDOUR {
+ class Session;
+ class PluginManager;
+ class Plugin;
+}
+
+class PluginSelector : public ArdourDialog
+{
+ public:
+ PluginSelector (ARDOUR::PluginManager *);
+ SigC::Signal1<void,ARDOUR::Plugin *> PluginCreated;
+
+ void set_session (ARDOUR::Session*);
+
+ private:
+ ARDOUR::Session* session;
+ Gtk::Notebook notebook;
+
+ // page 1
+ Gtkmmext::Selector ladspa_display;
+ void column_clicked (int column, GtkCList* clist);
+
+#ifdef VST_SUPPORT
+ // page 2
+ Gtkmmext::Selector vst_display;
+ static void _vst_refiller (Gtk::CList &, void *);
+ void vst_refiller (Gtk::CList &);
+#endif
+ Gtkmmext::Selector o_selector;
+
+ ARDOUR::PluginInfo* i_selected_plug;
+
+ // We need an integer for the output side because
+ // the name isn't promised to be unique.
+ gint o_selected_plug;
+
+ ARDOUR::PluginManager *manager;
+ list<ARDOUR::PluginInfo*> added_plugins;
+
+ static void _input_refiller (Gtk::CList &, void *);
+ static void _output_refiller (Gtk::CList &, void *);
+
+ void input_refiller (Gtk::CList &);
+ void output_refiller (Gtk::CList &);
+ void i_plugin_selected (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *res);
+ void i_plugin_chosen (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *res);
+ void o_plugin_selected (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *res);
+ void o_plugin_chosen (Gtkmmext::Selector *selector,
+ Gtkmmext::SelectionResult *res);
+
+ void btn_add_clicked();
+ void btn_remove_clicked();
+ void btn_ok_clicked();
+ void btn_update_clicked();
+ void btn_apply_clicked();
+ void btn_cancel_clicked();
+ void use_plugin (ARDOUR::PluginInfo*);
+ gint wm_close(GdkEventAny* ev);
+};
+
+#endif // __ardour_plugin_selector_h__
diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc
new file mode 100644
index 0000000000..3932541ebc
--- /dev/null
+++ b/gtk2_ardour/plugin_ui.cc
@@ -0,0 +1,933 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <climits>
+#include <cerrno>
+#include <cmath>
+#include <string>
+
+#include <pbd/stl_delete.h>
+#include <pbd/xml++.h>
+#include <pbd/failed_constructor.h>
+
+#include <gtkmmext/click_box.h>
+#include <gtkmmext/fastmeter.h>
+#include <gtkmmext/slider_controller.h>
+#include <gtkmmext/barcontroller.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/doi.h>
+
+#include <midi++/manager.h>
+
+#include <ardour/audioengine.h>
+#include <ardour/plugin.h>
+#include <ardour/insert.h>
+#include <ardour/ladspa_plugin.h>
+#ifdef VST_SUPPORT
+#include <ardour/vst_plugin.h>
+#endif
+
+#include <lrdf.h>
+
+#include "ardour_ui.h"
+#include "prompter.h"
+#include "plugin_ui.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace Gtkmmext;
+using namespace Gtk;
+using namespace SigC;
+
+PluginUIWindow::PluginUIWindow (AudioEngine &engine, PluginInsert& insert, bool scrollable)
+ : ArdourDialog ("plugin ui")
+{
+ if (insert.plugin().has_editor()) {
+
+#ifdef VST_SUPPORT
+
+ VSTPlugin* vp;
+
+ if ((vp = dynamic_cast<VSTPlugin*> (&insert.plugin())) != 0) {
+
+
+ VSTPluginUI* vpu = new VSTPluginUI (insert, *vp);
+
+ _pluginui = vpu;
+ add (*vpu);
+ vpu->package (*this);
+
+ } else {
+#endif
+ 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 {
+
+ PluginUI* pu = new PluginUI (engine, insert, scrollable);
+
+ _pluginui = pu;
+ add (*pu);
+
+ map_event.connect (slot (*pu, &PluginUI::start_updating));
+ unmap_event.connect (slot (*pu, &PluginUI::stop_updating));
+ }
+
+ set_position (GTK_WIN_POS_MOUSE);
+ set_name ("PluginEditor");
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ delete_event.connect (bind (slot (just_hide_it), reinterpret_cast<Window*> (this)));
+ insert.GoingAway.connect (slot (*this, &PluginUIWindow::plugin_going_away));
+
+ if (scrollable) {
+ gint h = _pluginui->get_preferred_height ();
+ if (h > 600) h = 600;
+ set_default_size (450, h);
+ }
+}
+
+PluginUIWindow::~PluginUIWindow ()
+{
+}
+
+PluginUI::PluginUI (AudioEngine &engine, PluginInsert& pi, bool scrollable)
+ : PlugUIBase (pi),
+ engine(engine),
+ button_table (initial_button_rows, initial_button_cols),
+ output_table (initial_output_rows, initial_output_cols),
+ 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);
+
+ smaller_hbox->pack_start (combo, false, false);
+ smaller_hbox->pack_start (save_button, false, false);
+
+ constraint_hbox->set_spacing (10);
+ constraint_hbox->pack_start (*smaller_hbox, true, false);
+ constraint_hbox->pack_end (bypass_button, false, false);
+
+// name_ebox.add (*text_hbox);
+// info_vbox.pack_start (name_ebox, false, false);
+// info_vbox.pack_start (makerinfo_label, false, false);
+// info_vbox.pack_start (paraminfo_label, false, false, 5);
+
+// settings_box.pack_start (info_vbox, false, false, 10);
+ 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);
+
+ // this is a hack to get the theme right
+ name_ebox.set_name ("PluginNameBox");
+ }
+
+ insert.active_changed.connect (slot (*this, &PluginUI::redirect_active_changed));
+ bypass_button.set_active (!insert.active());
+
+ build (engine);
+}
+
+PluginUI::~PluginUI ()
+{
+ if (output_controls.size() > 0) {
+ screen_update_connection.disconnect();
+ }
+}
+
+void
+PluginUI::build (AudioEngine &engine)
+
+{
+ guint32 i = 0;
+ guint32 x = 0;
+ Frame* frame;
+ Frame* bt_frame;
+ VBox* box;
+ char info[32];
+ int output_row, output_col;
+ int button_row, button_col;
+ int output_rows, output_cols;
+ int button_rows, button_cols;
+ guint32 n_ins=0, n_outs = 0;
+
+ 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);
+ frame = manage (new Frame);
+ frame->set_name ("BaseFrame");
+ frame->add (*box);
+ hpacker.pack_start(*frame, true, true);
+
+ box->set_border_width (5);
+ box->set_spacing (1);
+
+ /* 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)) {
+
+ 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 = 0;
+ }
+ }
+
+ /* Don't show latency control ports */
+
+ if (plugin.describe_parameter (i) == X_("latency")) {
+ continue;
+ }
+
+ if ((cui = build_control_ui (engine, i, plugin.get_nth_midi_control (i))) == 0) {
+ error << 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,
+ GTK_FILL|GTK_EXPAND, 0);
+ button_row++;
+
+ } else if (cui->display) {
+
+ 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,
+ GTK_FILL|GTK_EXPAND, 0);
+
+ 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;
+
+ }
+ }
+
+ n_ins = plugin.get_info().n_inputs;
+ n_outs = plugin.get_info().n_outputs;
+
+ 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 ();
+
+ string pname = plugin.name();
+
+ if (pname.length() > 24) {
+ pname = pname.substr (0, 24);
+ pname += "...";
+ ARDOUR_UI::instance()->tooltips().set_tip(name_ebox, plugin.name());
+ }
+
+
+ nameinfo_label.set_text (pname);
+ nameinfo_label.set_name ("PluginNameInfo");
+ nameinfo_label.set_alignment (0.0, 0.0);
+
+ string maker = plugin.maker();
+ string::size_type email_pos;
+
+ if ((email_pos = maker.find_first_of ('<')) != string::npos) {
+ maker = maker.substr (0, email_pos - 1);
+ }
+
+ if (maker.length() > 32) {
+ maker = maker.substr (0, 32);
+ maker += " ...";
+ }
+
+ makerinfo_label.set_text (maker);
+ makerinfo_label.set_name ("PluginMakerInfo");
+ makerinfo_label.set_alignment (0.0, 0.0);
+
+ snprintf (info, sizeof(info),"[ %u %s | %u %s ]",
+ n_ins, ngettext(_("in"), _("ins"), n_ins),
+ n_outs, ngettext(_("out"), _("outs"), n_outs));
+ paraminfo_label.set_text (info);
+ paraminfo_label.set_name ("PluginParameterInfo");
+ paraminfo_label.set_alignment (0.0, 0.0);
+
+ output_table.show_all ();
+ button_table.show_all ();
+}
+
+PluginUI::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"));
+
+ /* don't fix the height, it messes up the bar controllers */
+
+ set_usize_to_display_given_text (automate_button, X_("longenuff"), 2, -1);
+
+ ignore_change = 0;
+ display = 0;
+ button = 0;
+ control = 0;
+ clickbox = 0;
+ adjustment = 0;
+ meterinfo = 0;
+}
+
+PluginUI::ControlUI::~ControlUI()
+{
+ if (adjustment) {
+ delete adjustment;
+ }
+
+ if (meterinfo) {
+ delete meterinfo->meter;
+ delete meterinfo;
+ }
+}
+
+void
+PluginUI::automation_state_changed (ControlUI* cui)
+{
+ /* update button label */
+
+ switch (insert.get_port_automation_state (cui->port_index) & (Off|Play|Touch|Write)) {
+ case Off:
+ static_cast<Gtk::Label*>(cui->automate_button.get_child())->set_text (_("off"));
+ break;
+ case Play:
+ static_cast<Gtk::Label*>(cui->automate_button.get_child())->set_text (_("play"));
+ break;
+ case Write:
+ static_cast<Gtk::Label*>(cui->automate_button.get_child())->set_text (_("write"));
+ break;
+ case Touch:
+ static_cast<Gtk::Label*>(cui->automate_button.get_child())->set_text (_("touch"));
+ break;
+ default:
+ static_cast<Gtk::Label*>(cui->automate_button.get_child())->set_text (_("???"));
+ break;
+ }
+}
+
+
+static void integer_printer (char buf[32], Adjustment &adj, void *arg)
+{
+ snprintf (buf, 32, "%.0f", adj.get_value());
+}
+
+void
+PluginUI::print_parameter (char *buf, uint32_t len, uint32_t param)
+{
+ plugin.print_parameter (param, buf, len);
+}
+
+PluginUI::ControlUI*
+PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Controllable* mcontrol)
+
+{
+ ControlUI* control_ui;
+ Plugin::ParameterDescriptor desc;
+
+ plugin.get_parameter_descriptor (port_index, desc);
+
+ control_ui = manage (new ControlUI ());
+ control_ui->adjustment = 0;
+ control_ui->combo = 0;
+ control_ui->combo_map = 0;
+ control_ui->port_index = port_index;
+ 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);
+
+ if (plugin.parameter_is_input (port_index)) {
+
+ LadspaPlugin* lp;
+
+ if ((lp = dynamic_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::Combo;
+ control_ui->combo->set_value_in_list(true, false);
+ control_ui->combo->set_popdown_strings(setup_scale_values(port_index, control_ui));
+ control_ui->combo->get_popwin()->unmap_event.connect(bind (slot (*this, &PluginUI::control_combo_changed), control_ui));
+ plugin.ParameterChanged.connect (bind (slot (*this, &PluginUI::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_usize (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->clicked.connect (bind (slot (*this, &PluginUI::control_port_toggled), control_ui));
+
+ if(plugin.get_parameter (port_index) == 1){
+ control_ui->button->set_active(true);
+ }
+
+ return control_ui;
+ }
+
+ control_ui->adjustment = new Adjustment (0, 0, 0, 0, 0);
+
+ /* XXX this code is not right yet, because it doesn't handle
+ the absence of bounds in any sensible fashion.
+ */
+
+ control_ui->adjustment->set_lower (desc.lower);
+ control_ui->adjustment->set_upper (desc.upper);
+
+ control_ui->logarithmic = desc.logarithmic;
+ if (control_ui->logarithmic) {
+ if (control_ui->adjustment->get_lower() == 0.0) {
+ control_ui->adjustment->set_lower (control_ui->adjustment->get_upper()/10000);
+ }
+ control_ui->adjustment->set_upper (log(control_ui->adjustment->get_upper()));
+ control_ui->adjustment->set_lower (log(control_ui->adjustment->get_lower()));
+ }
+
+ float delta = desc.upper - desc.lower;
+
+ control_ui->adjustment->set_page_size (delta/100.0);
+ control_ui->adjustment->set_step_increment (desc.step);
+ control_ui->adjustment->set_page_increment (desc.largestep);
+
+ if (desc.integer_step) {
+ control_ui->clickbox = new ClickBox (control_ui->adjustment, "PluginUIClickBox");
+ Gtkmmext::set_usize_to_display_given_text (*control_ui->clickbox, "g9999999", 2, 2);
+ control_ui->clickbox->set_print_func (integer_printer, 0);
+ } else {
+// control_ui->control = new HSliderController (ARDOUR_UI::instance()->plugin_ui_slider_pix(),
+// control_ui->adjustment,
+// mcontrol);
+
+ SigC::Slot2<void,char*,uint32_t> pslot = SigC::bind (slot (*this, &PluginUI::print_parameter), (uint32_t) port_index);
+
+ control_ui->control = new BarController (*control_ui->adjustment, mcontrol, pslot);
+ control_ui->control->set_usize (200, 15);
+ control_ui->control->set_name (X_("PluginSlider"));
+ control_ui->control->set_style (BarController::LeftToRight);
+ control_ui->control->set_use_parent (true);
+
+ control_ui->control->get_spin_button().focus_in_event.connect (slot (*this, &PluginUI::entry_focus_event));
+ control_ui->control->get_spin_button().focus_out_event.connect (slot (*this, &PluginUI::entry_focus_event));
+
+ control_ui->control->StartGesture.connect (bind (slot (*this, &PluginUI::start_touch), control_ui));
+ control_ui->control->StopGesture.connect (bind (slot (*this, &PluginUI::stop_touch), control_ui));
+
+ }
+
+ if (control_ui->logarithmic) {
+ control_ui->adjustment->set_value(log(plugin.get_parameter(port_index)));
+ } else{
+ control_ui->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->control, false, false);
+ }
+
+ control_ui->pack_start (control_ui->automate_button, false, false);
+ control_ui->adjustment->value_changed.connect (bind (slot (*this, &PluginUI::control_adjustment_changed), control_ui));
+ control_ui->automate_button.clicked.connect (bind (slot (*this, &PluginUI::astate_clicked), control_ui, (uint32_t) port_index));
+
+ automation_state_changed (control_ui);
+
+ plugin.ParameterChanged.connect (bind (slot (*this, &PluginUI::parameter_changed), control_ui));
+ insert.automation_list (port_index).automation_state_changed.connect
+ (bind (slot (*this, &PluginUI::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);
+ Gtkmmext::set_usize_to_display_given_text (*control_ui->display, "g999999", 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 (100, 5, FastMeter::Horizontal);
+
+ 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->vbox->pack_start (control_ui->label, false, false);
+ control_ui->vbox->pack_start (*info->meter, false, false);
+
+ control_ui->pack_start (*control_ui->vbox, false, false);
+ control_ui->pack_start (*control_ui->display, false, false);
+
+ control_ui->meterinfo->meter->show_all();
+ control_ui->meterinfo->packed = true;
+
+ output_controls.push_back (control_ui);
+ }
+
+ plugin.ParameterChanged.connect (bind (slot (*this, &PluginUI::parameter_changed), control_ui));
+ return control_ui;
+}
+
+void
+PluginUI::start_touch (PluginUI::ControlUI* cui)
+{
+ insert.automation_list (cui->port_index).start_touch ();
+}
+
+void
+PluginUI::stop_touch (PluginUI::ControlUI* cui)
+{
+ insert.automation_list (cui->port_index).stop_touch ();
+}
+
+void
+PluginUI::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 (_("off"),
+ bind (slot (*this, &PluginUI::set_automation_state), (AutoState) Off, cui)));
+ items.push_back (MenuElem (_("play"),
+ bind (slot (*this, &PluginUI::set_automation_state), (AutoState) Play, cui)));
+ items.push_back (MenuElem (_("write"),
+ bind (slot (*this, &PluginUI::set_automation_state), (AutoState) Write, cui)));
+ items.push_back (MenuElem (_("touch"),
+ bind (slot (*this, &PluginUI::set_automation_state), (AutoState) Touch, cui)));
+
+ automation_menu->popup (1, 0);
+}
+
+void
+PluginUI::set_automation_state (AutoState state, ControlUI* cui)
+{
+ insert.set_port_automation_state (cui->port_index, state);
+}
+
+void
+PluginUI::control_adjustment_changed (ControlUI* cui)
+{
+ if (cui->ignore_change) {
+ return;
+ }
+
+ double value = cui->adjustment->get_value();
+
+ if (cui->logarithmic) {
+ value = exp(value);
+ }
+
+ insert.set_parameter (cui->port_index, (float) value);
+}
+
+void
+PluginUI::parameter_changed (uint32_t abs_port_id, float val, ControlUI* cui)
+{
+ if (cui->port_index == abs_port_id) {
+ if (!cui->update_pending) {
+ cui->update_pending = true;
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &PluginUI::update_control_display), cui));
+ }
+ }
+}
+
+void
+PluginUI::update_control_display (ControlUI* cui)
+{
+ /* XXX how do we handle logarithmic stuff here ? */
+
+ cui->update_pending = false;
+
+ float val = plugin.get_parameter (cui->port_index);
+
+ cui->ignore_change++;
+ if (cui->combo) {
+ map<string,float>::iterator it;
+ for (it = cui->combo_map->begin(); it != cui->combo_map->end(); ++it) {
+ if (it->second == val) {
+ cui->combo->get_entry()->set_text(it->first);
+ break;
+ }
+ }
+ } else if (cui->adjustment == 0) {
+
+ if (val > 0.5) {
+ cui->button->set_active (true);
+ } else {
+ cui->button->set_active (false);
+ }
+
+ } else {
+ if (cui->logarithmic) {
+ val = log(val);
+ }
+ if (val != cui->adjustment->get_value()) {
+ cui->adjustment->set_value (val);
+ }
+ }
+ cui->ignore_change--;
+}
+
+void
+PluginUI::control_port_toggled (ControlUI* cui)
+{
+ if (!cui->ignore_change) {
+ insert.set_parameter (cui->port_index, cui->button->get_active());
+ }
+}
+
+gint
+PluginUI::control_combo_changed (GdkEventAny* ignored, ControlUI* cui)
+{
+ if (!cui->ignore_change) {
+ string value = cui->combo->get_entry()->get_text();
+ map<string,float> mapping = *cui->combo_map;
+ insert.set_parameter (cui->port_index, mapping[value]);
+ }
+
+ return FALSE;
+}
+
+void
+PluginUIWindow::plugin_going_away (ARDOUR::Redirect* ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &PluginUIWindow::plugin_going_away), ignored));
+
+ _pluginui->stop_updating(0);
+ delete_when_idle (this);
+}
+
+gint
+PluginUI::entry_focus_event (GdkEventFocus* ev)
+{
+ if (ev->in) {
+ ARDOUR_UI::instance()->allow_focus (true);
+ } else {
+ ARDOUR_UI::instance()->allow_focus (false);
+ }
+ return TRUE;
+}
+
+void
+PluginUI::redirect_active_changed (Redirect* r, void* src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &PluginUI::redirect_active_changed), r, src));
+
+ bypass_button.set_active (!r->active());
+}
+
+gint
+PluginUI::start_updating (GdkEventAny *ev)
+{
+ if (output_controls.size() > 0 ) {
+ screen_update_connection.disconnect();
+ screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
+ (slot (*this, &PluginUI::output_update));
+ }
+ return FALSE;
+}
+
+gint
+PluginUI::stop_updating (GdkEventAny *ev)
+{
+ if (output_controls.size() > 0 ) {
+ screen_update_connection.disconnect();
+ }
+ return FALSE;
+}
+
+void
+PluginUI::output_update ()
+{
+ for (vector<ControlUI*>::iterator i = output_controls.begin(); i != output_controls.end(); ++i) {
+ float val = plugin.get_parameter ((*i)->port_index);
+ 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 );
+ }
+ }
+ }
+}
+
+list<string>
+PluginUI::setup_scale_values(guint32 port_index, ControlUI* cui)
+{
+ list<string> enums;
+ LadspaPlugin* lp = dynamic_cast<LadspaPlugin*> (&plugin);
+
+ cui->combo_map = new 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;
+}
+
+PlugUIBase::PlugUIBase (PluginInsert& pi)
+ : insert (pi),
+ plugin (insert.plugin()),
+ save_button(_("save")),
+ bypass_button (_("bypass"))
+{
+ combo.set_value_in_list(true,true);
+ combo.set_use_arrows(true);
+ combo.set_use_arrows_always(true);
+ combo.set_popdown_strings(plugin.get_presets());
+ combo.get_entry()->set_text("");
+ combo.get_popwin()->unmap_event.connect(slot (*this, &PlugUIBase::setting_selected));
+
+ save_button.set_name ("PluginSaveButton");
+ save_button.clicked.connect(slot (*this, &PlugUIBase::save_plugin_setting));
+
+ bypass_button.set_name ("PluginBypassButton");
+ bypass_button.toggled.connect (slot (*this, &PlugUIBase::bypass_toggled));
+}
+
+gint
+PlugUIBase::setting_selected(GdkEventAny* ignored)
+{
+ Entry* entry = combo.get_entry();
+ if (entry->get_text().length() > 0) {
+ if (!plugin.load_preset(entry->get_text())) {
+ warning << compose(_("Plugin preset %1 not found"), entry->get_text()) << endmsg;
+ }
+ }
+
+ return FALSE;
+}
+
+void
+PlugUIBase::save_plugin_setting ()
+{
+ ArdourPrompter prompter (true);
+ prompter.set_prompt(_("Name for plugin settings:"));
+
+ prompter.show_all();
+ prompter.done.connect(Main::quit.slot());
+
+ Main::run();
+
+ if (prompter.status == Gtkmmext::Prompter::entered) {
+ string name;
+
+ prompter.get_result(name);
+
+ if (name.length()) {
+ if(plugin.save_preset(name)){
+ combo.set_popdown_strings(plugin.get_presets());
+ combo.get_entry()->set_text(name);
+ }
+ }
+ }
+}
+
+void
+PlugUIBase::bypass_toggled ()
+{
+ bool x;
+
+ if ((x = bypass_button.get_active()) == insert.active()) {
+ insert.set_active (!x, this);
+ }
+}
+
diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h
new file mode 100644
index 0000000000..e46d7be9c0
--- /dev/null
+++ b/gtk2_ardour/plugin_ui.h
@@ -0,0 +1,230 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_plugin_ui_h__
+#define __ardour_plugin_ui_h__
+
+#include <vector>
+#include <map>
+#include <list>
+
+#include <sigc++/signal_system.h>
+
+#include <gtk--.h>
+#include <gtk--/socket.h>
+
+#include <ardour_dialog.h>
+#include <ardour/types.h>
+
+namespace ARDOUR {
+ class AudioEngine;
+ class PluginInsert;
+ class Plugin;
+ class VSTPlugin;
+ class Redirect;
+}
+
+namespace MIDI {
+ class Controllable;
+}
+
+namespace Gtkmmext {
+ class HSliderController;
+ class BarController;
+ class ClickBox;
+ class FastMeter;
+ class PixmapButton;
+}
+
+class PlugUIBase : public SigC::Object
+{
+ public:
+ PlugUIBase (ARDOUR::PluginInsert&);
+ virtual ~PlugUIBase() {}
+
+ virtual gint get_preferred_height () = 0;
+ virtual gint start_updating(GdkEventAny*) = 0;
+ virtual gint stop_updating(GdkEventAny*) = 0;
+
+ protected:
+ ARDOUR::PluginInsert& insert;
+ ARDOUR::Plugin& plugin;
+ Gtk::Combo combo;
+ Gtk::Button save_button;
+ Gtk::ToggleButton bypass_button;
+
+ gint setting_selected(GdkEventAny* ignored);
+ void save_plugin_setting (void);
+ void bypass_toggled();
+};
+
+class PluginUI : public PlugUIBase, public Gtk::VBox
+{
+ public:
+ PluginUI (ARDOUR::AudioEngine &, ARDOUR::PluginInsert& plug, bool scrollable=false);
+ ~PluginUI ();
+
+ gint get_preferred_height () { return prefheight; }
+
+ gint start_updating(GdkEventAny*);
+ gint stop_updating(GdkEventAny*);
+
+ private:
+ ARDOUR::AudioEngine &engine;
+ Gtk::HBox settings_box;
+ Gtk::HBox hpacker;
+ Gtk::VBox info_vbox;
+ Gtk::EventBox name_ebox;
+
+ Gtk::Table button_table;
+ Gtk::Table output_table;
+
+ Gtk::ScrolledWindow scroller;
+ Gtk::Viewport scroller_view;
+ Gtk::Label nameinfo_label;
+ Gtk::Label paraminfo_label;
+ Gtk::Label makerinfo_label;
+ Gtk::Menu* automation_menu;
+
+ bool setting_name_status;
+
+ gint prefheight;
+ bool is_scrollable;
+
+ struct MeterInfo {
+ Gtkmmext::FastMeter *meter;
+
+ float min;
+ float max;
+ bool min_unbound;
+ bool max_unbound;
+ bool packed;
+
+ MeterInfo(int i) {
+ meter = 0;
+ packed = false;
+ min = 1.0e10;
+ max = -1.0e10;
+ min_unbound = false;
+ max_unbound = false;
+ }
+ };
+
+ static const int32_t initial_button_rows = 6;
+ static const int32_t initial_button_cols = 1;
+ static const int32_t initial_output_rows = 8;
+ static const int32_t initial_output_cols = 1;
+
+ struct ControlUI : public Gtk::HBox {
+
+ uint32_t port_index;
+
+ /* input */
+
+ Gtk::Adjustment* adjustment;
+ Gtk::Combo* combo;
+ std::map<string, float>* combo_map;
+ Gtk::ToggleButton* button;
+ Gtkmmext::BarController* control;
+ Gtkmmext::ClickBox* clickbox;
+ Gtk::Label label;
+ bool logarithmic;
+ bool update_pending;
+ char ignore_change;
+ Gtk::Button automate_button;
+
+ /* output */
+
+ Gtk::EventBox *display;
+ Gtk::Label* display_label;
+
+ Gtk::VBox * vbox;
+ MeterInfo * meterinfo;
+
+ ControlUI ();
+ ~ControlUI();
+ };
+
+ std::vector<ControlUI*> output_controls;
+ SigC::Connection screen_update_connection;
+ void output_update();
+
+ void build (ARDOUR::AudioEngine &);
+ ControlUI* build_control_ui (ARDOUR::AudioEngine &, guint32 port_index, MIDI::Controllable *);
+ std::list<string> setup_scale_values(guint32 port_index, ControlUI* cui);
+ void control_adjustment_changed (ControlUI* cui);
+ void parameter_changed (uint32_t, float, ControlUI* cui);
+ void update_control_display (ControlUI* cui);
+ void control_port_toggled (ControlUI* cui);
+ gint control_combo_changed (GdkEventAny* ignored, ControlUI* cui);
+ gint entry_focus_event (GdkEventFocus* ev);
+
+ void redirect_active_changed (ARDOUR::Redirect*, void*);
+
+ void astate_clicked (ControlUI*, uint32_t parameter);
+ void automation_state_changed (ControlUI*);
+ void set_automation_state (ARDOUR::AutoState state, ControlUI* cui);
+ void start_touch (ControlUI*);
+ void stop_touch (ControlUI*);
+
+ void print_parameter (char *buf, uint32_t len, uint32_t param);
+};
+
+class PluginUIWindow : public ArdourDialog
+{
+ public:
+ PluginUIWindow (ARDOUR::AudioEngine &, ARDOUR::PluginInsert& insert, bool scrollable=false);
+ ~PluginUIWindow ();
+
+ PlugUIBase& pluginui() { return *_pluginui; }
+
+ void resize_preferred();
+
+ private:
+ PlugUIBase* _pluginui;
+ void plugin_going_away (ARDOUR::Redirect*);
+};
+
+
+#ifdef VST_SUPPORT
+class VSTPluginUI : public PlugUIBase, public Gtk::VBox
+{
+ public:
+ VSTPluginUI (ARDOUR::PluginInsert&, ARDOUR::VSTPlugin&);
+ ~VSTPluginUI ();
+
+ gint get_preferred_height ();
+ gint start_updating(GdkEventAny*) { return 0; }
+ gint stop_updating(GdkEventAny*) { return 0; }
+
+ int package (Gtk::Window&);
+
+ private:
+ ARDOUR::VSTPlugin& vst;
+ Gtk::Socket socket;
+ Gtk::HBox preset_box;
+ Gtk::VBox vpacker;
+
+ gboolean configure_handler (GdkEventConfigure*, GtkSocket*);
+ void save_plugin_setting ();
+};
+#endif
+
+#endif /* __ardour_plugin_ui_h__ */
diff --git a/gtk2_ardour/po/.cvsignore b/gtk2_ardour/po/.cvsignore
new file mode 100644
index 0000000000..3e8b787838
--- /dev/null
+++ b/gtk2_ardour/po/.cvsignore
@@ -0,0 +1,14 @@
+Makefile
+Makefile.in
+Makefile.in.in
+POTFILES
+Rules-quot
+boldquot.sed
+en@boldquot.header
+en@quot.header
+insert-header.sin
+quot.sed
+remove-potcdate.sin
+remove-potcdate.sed
+*.gmo
+gtk-ardour.pot
diff --git a/gtk2_ardour/po/de_DE.po b/gtk2_ardour/po/de_DE.po
new file mode 100644
index 0000000000..7e464a775d
--- /dev/null
+++ b/gtk2_ardour/po/de_DE.po
@@ -0,0 +1,5179 @@
+# German translations for gtk-ardour
+# Copyright (C) 2003 Paul Davis
+# This file is distributed under the same license as the gtk-ardour package.
+# Karsten Petersen <kapet@kapet.de>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gtk-ardour 0.347.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-09-19 18:09-0400\n"
+"PO-Revision-Date: 2003-05-11 17:36+0200\n"
+"Last-Translator: Karsten Petersen <kapet@kapet.de>\n"
+"Language-Team: Deutsch <de@li.org>\n"
+"MIME-Version: 1.0\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"
+
+#: gtk_ardour/about.cc:134
+msgid "Marcus Andersson"
+msgstr ""
+
+#: gtk_ardour/about.cc:135
+msgid "Jeremy Hall"
+msgstr ""
+
+#: gtk_ardour/about.cc:136
+msgid "Steve Harris"
+msgstr ""
+
+#: gtk_ardour/about.cc:137
+msgid "Tim Mayberry"
+msgstr ""
+
+#: gtk_ardour/about.cc:138
+msgid "Mark Stewart"
+msgstr ""
+
+#: gtk_ardour/about.cc:139
+msgid "Sam Chessman"
+msgstr ""
+
+#: gtk_ardour/about.cc:140
+msgid "Jack O'Quin"
+msgstr ""
+
+#: gtk_ardour/about.cc:141
+msgid "Matt Krai"
+msgstr ""
+
+#: gtk_ardour/about.cc:142
+msgid "Ben Bell"
+msgstr ""
+
+#: gtk_ardour/about.cc:143
+msgid "Gerard van Dongen"
+msgstr ""
+
+#: gtk_ardour/about.cc:144
+msgid "Thomas Charbonnel"
+msgstr ""
+
+#: gtk_ardour/about.cc:145
+msgid "Nick Mainsbridge"
+msgstr ""
+
+#: gtk_ardour/about.cc:146
+msgid "Colin Law"
+msgstr ""
+
+#: gtk_ardour/about.cc:147
+msgid "Sampo Savolainen"
+msgstr ""
+
+#: gtk_ardour/about.cc:148
+msgid "Joshua Leach"
+msgstr ""
+
+#: gtk_ardour/about.cc:149
+msgid "Rob Holland"
+msgstr ""
+
+#: gtk_ardour/about.cc:150
+msgid "Per Sigmond"
+msgstr ""
+
+#: gtk_ardour/about.cc:151
+msgid "Doug Mclain"
+msgstr ""
+
+#: gtk_ardour/about.cc:156
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+msgstr ""
+
+#: gtk_ardour/about.cc:157
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+msgstr ""
+
+#: gtk_ardour/about.cc:158
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+msgstr ""
+
+#: gtk_ardour/about.cc:159
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:160
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:162
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn@fastmail.fm>"
+msgstr ""
+
+#: gtk_ardour/about.cc:163
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop@nm.ru>"
+msgstr ""
+
+#: gtk_ardour/about.cc:181
+msgid ""
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n"
+msgstr ""
+
+#: gtk_ardour/about.cc:188
+msgid ""
+"Ardour: %1\n"
+"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+msgstr ""
+
+#: gtk_ardour/about.cc:206
+msgid ""
+"Primary author:\n"
+"\tPaul Davis\n"
+"\n"
+"Major developers:\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributors:\n"
+"\t"
+msgstr ""
+
+#: gtk_ardour/about.cc:243
+msgid "Authors"
+msgstr ""
+
+#: gtk_ardour/about.cc:244
+#, fuzzy
+msgid "Translators"
+msgstr "dreieckig"
+
+#: gtk_ardour/about.cc:361
+msgid "cannot open splash image file \"%1\""
+msgstr ""
+
+#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33
+#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81
+#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977
+#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85
+#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777
+#: gtk_ardour/redirect_box.cc:900
+msgid "OK"
+msgstr ""
+
+#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92
+#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046
+#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72
+#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982
+#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733
+#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000
+#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129
+#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785
+#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86
+#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072
+#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33
+#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94
+msgid "Tracks"
+msgstr "Spuren"
+
+#: gtk_ardour/add_route_dialog.cc:43
+msgid "Busses"
+msgstr ""
+
+#: gtk_ardour/add_route_dialog.cc:48
+#, fuzzy
+msgid "ardour: add track/bus"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: gtk_ardour/add_route_dialog.cc:86
+#, fuzzy
+msgid "Name (template)"
+msgstr "Name für Mixer-Voreinstellung"
+
+#: gtk_ardour/ardour_ui.cc:798
+msgid ""
+"pre\n"
+"roll"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:799
+msgid ""
+"post\n"
+"roll"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:807
+msgid "% "
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:808
+#, fuzzy
+msgid "spring"
+msgstr "Importieren"
+
+#: gtk_ardour/ardour_ui.cc:810
+msgid ""
+"punch\n"
+"in"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:811
+msgid ""
+"punch\n"
+"out"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:812
+msgid ""
+"auto\n"
+"return"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:813
+msgid ""
+"auto\n"
+"play"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:814
+#, fuzzy
+msgid ""
+"auto\n"
+"input"
+msgstr "Port hinzufügen"
+
+#: gtk_ardour/ardour_ui.cc:815
+msgid "click"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:816
+msgid ""
+"follow\n"
+"PH"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:817
+msgid "AUDITIONING"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:818
+msgid "SOLO"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:870
+#, fuzzy
+msgid "Percentage"
+msgstr "Zurücksetzen"
+
+#: gtk_ardour/ardour_ui.cc:872
+#, fuzzy
+msgid "Semitones"
+msgstr "Sitzung"
+
+#: gtk_ardour/ardour_ui.cc:875
+#, fuzzy
+msgid "Sprung"
+msgstr "Sortieren"
+
+#: gtk_ardour/ardour_ui.cc:877
+msgid "Wheel"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:902
+msgid ""
+"You cannot record-enable\n"
+"track %1\n"
+"because it has no input connections.\n"
+"You would be wasting space recording silence."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1073
+msgid "quit"
+msgstr "Verlassen"
+
+#: gtk_ardour/ardour_ui.cc:1082
+msgid ""
+"Ardour was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1107
+msgid "Save and %1"
+msgstr "Speichern und %1"
+
+#: gtk_ardour/ardour_ui.cc:1112
+msgid "Just %1"
+msgstr "Nur %1"
+
+#: gtk_ardour/ardour_ui.cc:1117
+msgid "Don't %1"
+msgstr "Ohne %1"
+
+#: gtk_ardour/ardour_ui.cc:1126
+#, fuzzy
+msgid "session"
+msgstr "Sitzung"
+
+#: gtk_ardour/ardour_ui.cc:1128
+#, fuzzy
+msgid "snapshot"
+msgstr "Schnappschuß"
+
+#: gtk_ardour/ardour_ui.cc:1130
+#, fuzzy
+msgid ""
+"The %1\n"
+"\"%2\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
+msgstr ""
+"Die Sitzung \"%1\"\n"
+"wurde nicht gespeichert.\n"
+"\n"
+"Alle Änderungen werden verloren\n"
+"gehen wenn Sie nicht speichern.\n"
+"\n"
+"Was wollen Sie machen?"
+
+#: gtk_ardour/ardour_ui.cc:1151
+msgid "Prompter"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1152
+msgid "ardour: save session?"
+msgstr "Ardour: Sitzung speichern?"
+
+#: gtk_ardour/ardour_ui.cc:1219
+#, fuzzy, c-format
+msgid "disconnected"
+msgstr "Trennen"
+
+#: gtk_ardour/ardour_ui.cc:1226
+#, c-format
+msgid "SR: %.1f kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1230
+#, c-format
+msgid "SR: %u kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1243
+#, fuzzy, c-format
+msgid "DSP Load: %.1f%%"
+msgstr "Auslastung der CPU: %.1f%%"
+
+#: gtk_ardour/ardour_ui.cc:1253
+#, c-format
+msgid "Disk r:%5.1f w:%5.1f MB/s"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1267
+#, c-format
+msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1294
+msgid "space: 24hrs+"
+msgstr "Platz: >24 Stunden"
+
+#: gtk_ardour/ardour_ui.cc:1324
+#, c-format
+msgid "space: %02dh:%02dm:%02ds"
+msgstr "Platz: %02dh:%02dm:%02ds"
+
+#: gtk_ardour/ardour_ui.cc:1575
+msgid "programming error: impossible control method"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1800
+msgid "cancel"
+msgstr "Abbrechen"
+
+#: gtk_ardour/ardour_ui.cc:1801
+msgid "rescan"
+msgstr "Auffrischen"
+
+#: gtk_ardour/ardour_ui.cc:1842
+#, fuzzy
+msgid "open session"
+msgstr "Sitzung"
+
+#: gtk_ardour/ardour_ui.cc:1897
+msgid "Patience is a virtue.\n"
+msgstr "Geduld ist eine Tugend.\n"
+
+#: gtk_ardour/ardour_ui.cc:1906
+msgid "You cannot add a track without a session already loaded."
+msgstr "Sie können erst eine Spur hinzufügen, wenn eine Sitzung geladen wurde."
+
+#: gtk_ardour/ardour_ui.cc:1913
+msgid "could not create new audio track"
+msgstr "Konnte neue Spur nicht erstellen."
+
+#: gtk_ardour/ardour_ui.cc:1917
+msgid "could not create new audio bus"
+msgstr "Konnte neuen Audiokanal nicht erstellen."
+
+#: gtk_ardour/ardour_ui.cc:1936
+msgid ""
+"There are insufficient JACK ports available\n"
+"to create a new track or bus.\n"
+"You should save Ardour, exit and\n"
+"restart JACK with more ports."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2071
+msgid ""
+"Please create 1 or more track\n"
+"before trying to record.\n"
+"Check the Session menu."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2312
+#, fuzzy
+msgid ""
+"JACK has either been shutdown or it\n"
+"disconnected Ardour because Ardour\n"
+"was not fast enough. You can save the\n"
+"session and/or try to reconnect to JACK ."
+msgstr ""
+"JACK wurde entweder beendet oder es\n"
+"hat Ardour abgekoppelt weil Ardour nicht\n"
+"schnell genug war. Sie sollten die Sitzung\n"
+"speichern und JACK sowie Ardour neu starten."
+
+#: gtk_ardour/ardour_ui.cc:2328
+msgid "Unable to create all required ports"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2336
+#, fuzzy
+msgid "Unable to start the session running"
+msgstr "An den Anfang der Sitzung springen"
+
+#: gtk_ardour/ardour_ui.cc:2472
+msgid "No Stream"
+msgstr "Kein Datenstrom"
+
+#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518
+msgid "none"
+msgstr "keine"
+
+#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527
+#: gtk_ardour/automation_time_axis.cc:189
+#: gtk_ardour/automation_time_axis.cc:218
+#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211
+#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947
+#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659
+msgid "off"
+msgstr "aus"
+
+#: gtk_ardour/ardour_ui.cc:2548
+msgid "Name for snapshot"
+msgstr "Name für Schnappschuß"
+
+#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294
+msgid "Name for mix template:"
+msgstr "Name für Mixer-Voreinstellung"
+
+#: gtk_ardour/ardour_ui.cc:2717
+#, fuzzy
+msgid "-template"
+msgstr "Voreinstellung"
+
+#: gtk_ardour/ardour_ui.cc:2760
+msgid "Session %1 already exists at %2"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2832
+msgid ""
+"You do not have write access to this session.\n"
+"This prevents the session from being loaded."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897
+#, fuzzy
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "Sitzung \"%1\" konnte nicht geladen werden."
+
+#: gtk_ardour/ardour_ui.cc:2966
+msgid ""
+"No audio files were ready for cleanup\n"
+"\n"
+"If this seems suprising, check for any existing\n"
+"snapshots. These may still include regions that\n"
+"require some unused files to continue to exist."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001
+msgid "files"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003
+msgid "file"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3026
+#, fuzzy
+msgid "ardour: cleanup"
+msgstr "Ardour: Uhr"
+
+#: gtk_ardour/ardour_ui.cc:3040
+msgid ""
+"Cleanup is a destructive operation.\n"
+"ALL undo/redo information will be lost if you cleanup.\n"
+"Unused audio files will be moved to a \"dead sounds\" location."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3045
+msgid "Proceed with cleanup"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3061
+#, fuzzy
+msgid "CleanupDialog"
+msgstr "leeren"
+
+#: gtk_ardour/ardour_ui.cc:3062
+#, fuzzy
+msgid "ardour cleanup"
+msgstr "Ardour: Uhr"
+
+#: gtk_ardour/ardour_ui.cc:3063
+#, fuzzy
+msgid "ardour_cleanup"
+msgstr "Ardour: Uhr"
+
+#: gtk_ardour/ardour_ui.cc:3086
+msgid "cleaned files"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3087
+msgid ""
+"The following %1 %2 were not in use.\n"
+"The next time you flush the wastebasket\n"
+"it will release an additional %3 %4bytes\n"
+"of disk space"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3110
+#, fuzzy
+msgid "deleted file"
+msgstr "entfernen"
+
+#: gtk_ardour/ardour_ui.cc:3111
+msgid ""
+"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3226
+msgid "Recording was stopped because your system could not keep up."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3248
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3266
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3291
+msgid "Recover from crash"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3292
+msgid "Ignore crash data"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3293
+msgid ""
+"This session appears to have been in\n"
+"middle of recording when ardour or\n"
+"the computer was shutdown.\n"
+"\n"
+"Ardour can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3338
+msgid "Could not disconnect from JACK"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3351
+msgid "Could not reconnect to JACK"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:60
+msgid "UI: cannot setup editor"
+msgstr "Der Editor konnte nicht initialisiert werden."
+
+#: gtk_ardour/ardour_ui2.cc:65
+msgid "UI: cannot setup mixer"
+msgstr "Der Mixer konnte nicht initialisiert werden."
+
+#: gtk_ardour/ardour_ui2.cc:70
+msgid "UI: cannot setup meter_bridge"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:98
+msgid "MMC + Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:99
+msgid "MMC"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:100
+msgid "Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:117
+msgid "MMC ID"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:215
+msgid "Play from playhead"
+msgstr "Wiedergabe ab Playhead"
+
+#: gtk_ardour/ardour_ui2.cc:216
+msgid "Stop playback"
+msgstr "Wiedergabe anhalten"
+
+#: gtk_ardour/ardour_ui2.cc:217
+#, fuzzy
+msgid "Play range/selection"
+msgstr "Auswahl wiedergeben"
+
+#: gtk_ardour/ardour_ui2.cc:218
+msgid "Go to start of session"
+msgstr "An den Anfang der Sitzung springen"
+
+#: gtk_ardour/ardour_ui2.cc:219
+msgid "Go to end of session"
+msgstr "Ans Ende der Sitzung springen"
+
+#: gtk_ardour/ardour_ui2.cc:220
+#, fuzzy
+msgid "Play loop range"
+msgstr "Bereich"
+
+#: gtk_ardour/ardour_ui2.cc:221
+msgid "Return to last playback start when stopped"
+msgstr "Bei Stopp zum Wiedergabeanfang springen"
+
+#: gtk_ardour/ardour_ui2.cc:222
+msgid "Start playback after any locate"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:223
+msgid "Be sensible about input monitoring"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:224
+msgid "Start recording at auto-punch start"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:225
+msgid "Stop recording at auto-punch end"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:226
+msgid "Enable/Disable audio click"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:227
+#, fuzzy
+msgid "Enable/Disable follow playhead"
+msgstr "Wiedergabeschleife an/abschalten"
+
+#: gtk_ardour/ardour_ui2.cc:228
+msgid "Shuttle speed control"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:229
+#, c-format
+msgid "Select semitones or %%-age for speed display"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:230
+msgid "Select sprung or wheel behaviour"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:231
+msgid "Current transport speed"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:312
+#, fuzzy
+msgid "Primary clock"
+msgstr "Ardour: Uhr"
+
+#: gtk_ardour/ardour_ui2.cc:313
+msgid "secondary clock"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751
+#: gtk_ardour/ardour_ui2.cc:770
+msgid "stopped"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:431
+msgid "ardour: clock"
+msgstr "Ardour: Uhr"
+
+#: gtk_ardour/ardour_ui2.cc:721
+#, fuzzy
+msgid "st"
+msgstr "bestmöglich"
+
+#: gtk_ardour/ardour_ui2.cc:731
+msgid "sprung"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:742
+msgid "wheel"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dependents.cc:74
+msgid "keyboard_target: error setting binding state: invalid node"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dialogs.cc:158
+#, fuzzy
+msgid "close session"
+msgstr "Bitte mittels des \"Sitzung\"-Menüs\n"
+
+#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895
+#, fuzzy
+msgid "New"
+msgstr "Neu..."
+
+#: gtk_ardour/ardour_ui_ed.cc:76
+#, fuzzy
+msgid "Open"
+msgstr "Öffnen..."
+
+#: gtk_ardour/ardour_ui_ed.cc:77
+#, fuzzy
+msgid "Recent"
+msgstr "Zurücksetzen"
+
+#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+msgid "Close"
+msgstr "Schließen"
+
+#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488
+#, fuzzy
+msgid "Add Track/Bus"
+msgstr "MIDI Spur(en) hinzufügen"
+
+#: gtk_ardour/ardour_ui_ed.cc:99
+#, fuzzy
+msgid "Connect"
+msgstr "Verbindungen"
+
+#: gtk_ardour/ardour_ui_ed.cc:100
+msgid "Image Compositor"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:114
+msgid "Save"
+msgstr "Speichern"
+
+#: gtk_ardour/ardour_ui_ed.cc:118
+msgid "Snapshot"
+msgstr "Schnappschuß"
+
+#: gtk_ardour/ardour_ui_ed.cc:126
+msgid "Save Template..."
+msgstr "Speichern als Voreinstellung..."
+
+#: gtk_ardour/ardour_ui_ed.cc:133
+msgid "Export session to audiofile..."
+msgstr "Export als Audio-Datei..."
+
+#: gtk_ardour/ardour_ui_ed.cc:134
+#, fuzzy
+msgid "Export range to audiofile..."
+msgstr "Export als Audio-Datei..."
+
+#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312
+#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118
+#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227
+msgid "Export"
+msgstr "Exportieren"
+
+#: gtk_ardour/ardour_ui_ed.cc:146
+msgid "Cleanup unused sources"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:147
+msgid "Flush wastebasket"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:149
+#, fuzzy
+msgid "Cleanup"
+msgstr "leeren"
+
+#: gtk_ardour/ardour_ui_ed.cc:154
+msgid "Quit"
+msgstr "Beenden"
+
+#: gtk_ardour/ardour_ui_ed.cc:156
+msgid "Session"
+msgstr "Sitzung"
+
+#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287
+#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499
+#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570
+#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572
+#: gtk_ardour/mixer_strip.cc:631
+msgid "Disconnect"
+msgstr "Trennen"
+
+#: gtk_ardour/ardour_ui_ed.cc:174
+#, fuzzy
+msgid "Reconnect"
+msgstr "Verbindungen"
+
+#: gtk_ardour/ardour_ui_ed.cc:192
+msgid "Latency"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:195
+msgid "JACK"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:205
+msgid "Editor"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:206
+msgid "Mixer"
+msgstr "Mixer"
+
+#: gtk_ardour/ardour_ui_ed.cc:212
+#, fuzzy
+msgid "Options Editor"
+msgstr "Geschwindigkeitseditor"
+
+#: gtk_ardour/ardour_ui_ed.cc:219
+#, fuzzy
+msgid "Audio Library"
+msgstr "Ardour: Audio Bibliothek"
+
+#: gtk_ardour/ardour_ui_ed.cc:225
+msgid "Track/Bus Inspector"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:232
+msgid "Connections"
+msgstr "Verbindungen"
+
+#: gtk_ardour/ardour_ui_ed.cc:240
+msgid "Meter Bridge"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:248
+msgid "Locations"
+msgstr "Stellen"
+
+#: gtk_ardour/ardour_ui_ed.cc:255
+msgid "Big Clock"
+msgstr "Große Uhr"
+
+#: gtk_ardour/ardour_ui_ed.cc:261
+msgid "About"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:264
+msgid "Windows"
+msgstr "Fenster"
+
+#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203
+msgid "SMPTE"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202
+#: gtk_ardour/editor_rulers.cc:359
+msgid "Bars:Beats"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1642
+msgid "Minutes:Seconds"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/audio_clock.cc:1643
+msgid "Audio Frames"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356
+#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713
+#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774
+#: gtk_ardour/option_editor.cc:794
+msgid "Off"
+msgstr "Aus"
+
+#: gtk_ardour/audio_clock.cc:1646
+msgid "Mode"
+msgstr "Modus"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523
+msgid "m"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524
+msgid "s"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104
+msgid "r"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:108
+msgid "g"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:109
+msgid "p"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44
+#: gtk_ardour/visual_time_axis.cc:90
+msgid "h"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:111
+msgid "a"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89
+msgid "v"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:185
+#, fuzzy
+msgid "Record"
+msgstr "Wiederherstellen"
+
+#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191
+#, fuzzy
+msgid "Solo"
+msgstr "solo"
+
+#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236
+#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433
+#, fuzzy
+msgid "Mute"
+msgstr "mute"
+
+#: gtk_ardour/audio_time_axis.cc:188
+#, fuzzy
+msgid "Edit Group"
+msgstr "Mix Gruppen"
+
+#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110
+#, fuzzy
+msgid "Display Height"
+msgstr "Anzeige"
+
+#: gtk_ardour/audio_time_axis.cc:190
+#, fuzzy
+msgid "Playlist"
+msgstr "Wiedergabe"
+
+#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752
+#, fuzzy
+msgid "Automation"
+msgstr "Stellen"
+
+#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111
+msgid "Visual options"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112
+msgid "Hide this track"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:349
+#, fuzzy
+msgid "No group"
+msgstr "keine Gruppe"
+
+#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447
+#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229
+#, fuzzy
+msgid "Height"
+msgstr "Rechts"
+
+#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266
+#: gtk_ardour/marker_time_axis.cc:230
+#, fuzzy
+msgid "Color"
+msgstr "solo"
+
+#: gtk_ardour/audio_time_axis.cc:720
+msgid "Hide all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:721
+msgid "Show all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:729
+#, fuzzy
+msgid "show all automation"
+msgstr "Stellen"
+
+#: gtk_ardour/audio_time_axis.cc:732
+#, fuzzy
+msgid "show existing automation"
+msgstr "Stellen"
+
+#: gtk_ardour/audio_time_axis.cc:735
+#, fuzzy
+msgid "hide all automation"
+msgstr "Stellen"
+
+#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204
+#: gtk_ardour/editor.cc:234
+msgid "gain"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244
+msgid "pan"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388
+msgid "Plugins"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95
+#, fuzzy
+msgid "Show waveforms"
+msgstr "Wellenform zeigen"
+
+#: gtk_ardour/audio_time_axis.cc:766
+msgid "Traditional"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:769
+msgid "Rectified"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:772
+#, fuzzy
+msgid "Waveform"
+msgstr "Wellenform zeigen"
+
+#: gtk_ardour/audio_time_axis.cc:782
+msgid "align with existing material"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:787
+msgid "align with capture time"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:793
+msgid "Alignment"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288
+msgid "Active"
+msgstr "Aktiv"
+
+#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386
+#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467
+#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269
+#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233
+#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83
+msgid "Remove"
+msgstr "Entfernen"
+
+#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880
+#: gtk_ardour/audio_time_axis.cc:911
+#, fuzzy
+msgid "Name for playlist"
+msgstr "Name für Schnappschuß"
+
+#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433
+msgid "a track already exists with that name"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001
+#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539
+msgid "programming error: "
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:1889
+msgid "Current: %1"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452
+#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226
+#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377
+msgid "Rename"
+msgstr "Umbenennen"
+
+#: gtk_ardour/audio_time_axis.cc:1896
+#, fuzzy
+msgid "New Copy"
+msgstr "Kopieren"
+
+#: gtk_ardour/audio_time_axis.cc:1898
+msgid "Clear Current"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472
+#: gtk_ardour/editor.cc:2557
+msgid "Select"
+msgstr "Auswahl"
+
+#: gtk_ardour/automation_line.cc:904
+#, fuzzy
+msgid "automation event move"
+msgstr "Stellen"
+
+#: gtk_ardour/automation_line.cc:906
+#, fuzzy
+msgid "automation range drag"
+msgstr "Stellen"
+
+#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64
+#, fuzzy
+msgid "remove control point"
+msgstr "Synchronisationspunkt entfernen"
+
+#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010
+msgid "clear"
+msgstr "leeren"
+
+#: gtk_ardour/automation_time_axis.cc:80
+msgid "track height"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:81
+#, fuzzy
+msgid "automation state"
+msgstr "Stellen"
+
+#: gtk_ardour/automation_time_axis.cc:82
+#, fuzzy
+msgid "clear track"
+msgstr "Verbindungen löschen"
+
+#: gtk_ardour/automation_time_axis.cc:83
+#, fuzzy
+msgid "hide track"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/automation_time_axis.cc:191
+#: gtk_ardour/automation_time_axis.cc:229
+#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213
+#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419
+#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50
+msgid "play"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:193
+#: gtk_ardour/automation_time_axis.cc:240
+#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215
+#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422
+#: gtk_ardour/plugin_ui.cc:663
+msgid "write"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:195
+#: gtk_ardour/automation_time_axis.cc:251
+#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217
+#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953
+#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665
+msgid "touch"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274
+#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428
+msgid "???"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:276
+#, fuzzy
+msgid "clear automation"
+msgstr "Verbindungen löschen"
+
+#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453
+#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398
+msgid "Hide"
+msgstr "Verbergen"
+
+#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52
+#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364
+msgid "Clear"
+msgstr "leeren"
+
+#: gtk_ardour/automation_time_axis.cc:474
+#, fuzzy
+msgid "State"
+msgstr "Anfang"
+
+#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49
+msgid "Input Connections"
+msgstr "Verbindungen der Eingänge"
+
+#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48
+msgid "Output Connections"
+msgstr "Verbindungen der Ausgänge"
+
+#: gtk_ardour/connection_editor.cc:49
+#, fuzzy
+msgid "New Input"
+msgstr "Neuer Eingang"
+
+#: gtk_ardour/connection_editor.cc:50
+#, fuzzy
+msgid "New Output"
+msgstr "Neuer Ausgang"
+
+#: gtk_ardour/connection_editor.cc:51
+#, fuzzy
+msgid "Delete"
+msgstr "entfernen"
+
+#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96
+#, fuzzy
+msgid "Add Port"
+msgstr "Port hinzufügen"
+
+#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105
+#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786
+#, fuzzy
+msgid "Rescan"
+msgstr "Auffrischen"
+
+#: gtk_ardour/connection_editor.cc:101
+#, fuzzy
+msgid "Available Ports"
+msgstr "Verfügbare Verbindungen"
+
+#: gtk_ardour/connection_editor.cc:183
+msgid "ardour: connections"
+msgstr "Ardour: Verbindungen"
+
+#: gtk_ardour/connection_editor.cc:513
+#, c-format
+msgid "in %d"
+msgstr ""
+
+#: gtk_ardour/connection_editor.cc:644
+msgid "Name for new connection:"
+msgstr "Name für neue Verbindung:"
+
+#: gtk_ardour/crossfade_edit.cc:71
+#, fuzzy
+msgid "crossfade editor"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449
+#, fuzzy
+msgid "Reset"
+msgstr "bestmöglich"
+
+#: gtk_ardour/crossfade_edit.cc:78
+msgid "Fade"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:79
+msgid "Out (dry)"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:80
+#, fuzzy
+msgid "Out"
+msgstr "Ausgänge"
+
+#: gtk_ardour/crossfade_edit.cc:81
+msgid "In (dry)"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:82
+msgid "In"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:84
+msgid "With Pre-roll"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:85
+msgid "With Post-roll"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:93
+msgid "Fade In"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:94
+msgid "Fade Out"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:98
+#, fuzzy
+msgid "ardour: x-fade edit"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311
+#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189
+msgid "Audition"
+msgstr ""
+
+#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804
+#, fuzzy
+msgid "Regions/name"
+msgstr "Regionen"
+
+#: gtk_ardour/editor.cc:108
+msgid "Chunks"
+msgstr "Stücke"
+
+#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079
+msgid "Slide"
+msgstr ""
+
+#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077
+msgid "Splice"
+msgstr ""
+
+#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136
+#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96
+#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977
+msgid "None"
+msgstr "Nichts"
+
+#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124
+msgid "CD Frames"
+msgstr ""
+
+#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126
+msgid "SMPTE Frames"
+msgstr ""
+
+#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128
+msgid "SMPTE Seconds"
+msgstr ""
+
+#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130
+msgid "SMPTE Minutes"
+msgstr ""
+
+#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132
+#, fuzzy
+msgid "Seconds"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134
+#, fuzzy
+msgid "Minutes"
+msgstr "mute"
+
+#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106
+msgid "Beats/32"
+msgstr ""
+
+#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104
+msgid "Beats/16"
+msgstr ""
+
+#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102
+msgid "Beats/8"
+msgstr ""
+
+#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100
+msgid "Beats/4"
+msgstr ""
+
+#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098
+msgid "Beats/3"
+msgstr ""
+
+#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108
+msgid "Beats"
+msgstr ""
+
+#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110
+msgid "Bars"
+msgstr ""
+
+#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112
+msgid "Marks"
+msgstr ""
+
+#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114
+#: gtk_ardour/editor.cc:4182
+msgid "Edit Cursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116
+#, fuzzy
+msgid "Region starts"
+msgstr "Regionen"
+
+#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118
+#, fuzzy
+msgid "Region ends"
+msgstr "Regionen"
+
+#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122
+#, fuzzy
+msgid "Region syncs"
+msgstr "Regionen"
+
+#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120
+#, fuzzy
+msgid "Region bounds"
+msgstr "Regionen"
+
+#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153
+#: gtk_ardour/time_axis_view.cc:449
+msgid "Normal"
+msgstr ""
+
+#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155
+#, fuzzy
+msgid "Magnetic"
+msgstr "generisch"
+
+#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174
+#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237
+msgid "Left"
+msgstr "Links"
+
+#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176
+#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238
+msgid "Right"
+msgstr "Rechts"
+
+#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178
+msgid "Center"
+msgstr "Mitte"
+
+#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180
+msgid "Playhead"
+msgstr ""
+
+#: gtk_ardour/editor.cc:201
+msgid "Mins:Secs"
+msgstr "Min:Sek"
+
+#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353
+msgid "Frames"
+msgstr ""
+
+#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373
+msgid "Tempo"
+msgstr ""
+
+#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367
+msgid "Meter"
+msgstr ""
+
+#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379
+#, fuzzy
+msgid "Location Markers"
+msgstr "Stellen"
+
+#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385
+msgid "Range Markers"
+msgstr ""
+
+#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391
+msgid "Loop/Punch Ranges"
+msgstr ""
+
+#: gtk_ardour/editor.cc:221
+#, fuzzy
+msgid ""
+"editor\n"
+"mixer"
+msgstr "Ardour: Mixer"
+
+#: gtk_ardour/editor.cc:232
+msgid "range"
+msgstr "Bereich"
+
+#: gtk_ardour/editor.cc:233
+msgid "object"
+msgstr "Objekt"
+
+#: gtk_ardour/editor.cc:235
+msgid "zoom"
+msgstr ""
+
+#: gtk_ardour/editor.cc:236
+msgid "timefx"
+msgstr ""
+
+#: gtk_ardour/editor.cc:237
+msgid "listen"
+msgstr ""
+
+#: gtk_ardour/editor.cc:239
+msgid "mode"
+msgstr "Modus"
+
+#: gtk_ardour/editor.cc:240
+msgid "automation"
+msgstr ""
+
+#: gtk_ardour/editor.cc:242
+msgid "Edit Mode"
+msgstr "Bearbeitungs Modus"
+
+#: gtk_ardour/editor.cc:243
+msgid "Snap To"
+msgstr ""
+
+#: gtk_ardour/editor.cc:244
+#, fuzzy
+msgid "Snap Mode"
+msgstr "Modus"
+
+#: gtk_ardour/editor.cc:245
+#, fuzzy
+msgid "Zoom Focus"
+msgstr "Verkleinern"
+
+#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364
+#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579
+msgid "Nudge"
+msgstr ""
+
+#: gtk_ardour/editor.cc:511
+msgid "Zoom in"
+msgstr "Vergrößern"
+
+#: gtk_ardour/editor.cc:512
+msgid "Zoom out"
+msgstr "Verkleinern"
+
+#: gtk_ardour/editor.cc:517
+#, fuzzy
+msgid "Zoom to session"
+msgstr "Vergrößern auf Auswahl"
+
+#: gtk_ardour/editor.cc:536
+#, fuzzy
+msgid "Zoom Span"
+msgstr "Vergrößern"
+
+#: gtk_ardour/editor.cc:566
+msgid "Edit Groups"
+msgstr ""
+
+#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142
+msgid "-all-"
+msgstr "-alle-"
+
+#: gtk_ardour/editor.cc:718
+msgid "Nudge region/selection forwards"
+msgstr ""
+
+#: gtk_ardour/editor.cc:719
+msgid "Nudge region/selection backwards"
+msgstr ""
+
+#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308
+msgid "ardour: editor"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/editor.cc:729
+#, fuzzy
+msgid "ardour_editor"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/editor.cc:846
+msgid "VerboseCanvasCursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1405
+msgid "FirstActionMessage"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1407
+#, fuzzy
+msgid "Start a new session\n"
+msgstr "Bitte mittels des \"Sitzung\"-Menüs\n"
+
+#: gtk_ardour/editor.cc:1408
+msgid "via Session menu"
+msgstr "eine Sitzung laden oder eine neue erstellen!"
+
+#: gtk_ardour/editor.cc:1703
+msgid "ardour: editor: "
+msgstr "Ardour: Editor: "
+
+#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796
+#: gtk_ardour/editor_markers.cc:797
+msgid "Loop"
+msgstr "Schleife"
+
+#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810
+#: gtk_ardour/editor_markers.cc:823
+msgid "Punch"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688
+msgid "programming error: fade in canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986
+#: gtk_ardour/redirect_box.cc:401
+#, fuzzy
+msgid "Deactivate"
+msgstr "Alles deaktivieren"
+
+#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988
+#: gtk_ardour/redirect_box.cc:398
+#, fuzzy
+msgid "Activate"
+msgstr "Aktiv"
+
+#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993
+msgid "Linear"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994
+#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734
+#: gtk_ardour/option_editor.cc:796
+#, fuzzy
+msgid "Slowest"
+msgstr "Alle zeigen"
+
+#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995
+#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735
+#: gtk_ardour/option_editor.cc:798
+#, fuzzy
+msgid "Slow"
+msgstr "solo"
+
+#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996
+#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737
+#: gtk_ardour/option_editor.cc:802
+#, fuzzy
+msgid "Fast"
+msgstr "Einfügen"
+
+#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997
+#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739
+#: gtk_ardour/option_editor.cc:806
+#, fuzzy
+msgid "Fastest"
+msgstr "schnellstmöglich"
+
+#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113
+msgid "Freeze"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2109
+msgid "Unfreeze"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328
+#, fuzzy
+msgid "Unmute"
+msgstr "mute"
+
+#: gtk_ardour/editor.cc:2247
+msgid "Convert to short"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2249
+msgid "Convert to full"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2260
+#, fuzzy
+msgid "Crossfade"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/editor.cc:2303
+msgid "Popup region editor"
+msgstr "Regionen Editor öffnen"
+
+#: gtk_ardour/editor.cc:2304
+#, fuzzy
+msgid "Raise to top layer"
+msgstr "Region ganz nach oben"
+
+#: gtk_ardour/editor.cc:2305
+#, fuzzy
+msgid "Lower to bottom layer"
+msgstr "Region ganz nach unten"
+
+#: gtk_ardour/editor.cc:2307
+msgid "Define sync point"
+msgstr "Synchronisationspunkt definieren"
+
+#: gtk_ardour/editor.cc:2308
+msgid "Remove sync point"
+msgstr "Synchronisationspunkt entfernen"
+
+#: gtk_ardour/editor.cc:2313
+#, fuzzy
+msgid "Bounce"
+msgstr "Bereich"
+
+#: gtk_ardour/editor.cc:2323
+#, fuzzy
+msgid "Lock"
+msgstr "OK"
+
+#: gtk_ardour/editor.cc:2324
+#, fuzzy
+msgid "Unlock"
+msgstr "Rückgängig"
+
+#: gtk_ardour/editor.cc:2334
+#, fuzzy
+msgid "Original position"
+msgstr "Regionen"
+
+#: gtk_ardour/editor.cc:2340
+msgid "Toggle envelope visibility"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2341
+msgid "Toggle envelope active"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2345
+#, fuzzy
+msgid "DeNormalize"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor.cc:2347
+#, fuzzy
+msgid "Normalize"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor.cc:2350
+#, fuzzy
+msgid "Reverse"
+msgstr "Entfernen"
+
+#: gtk_ardour/editor.cc:2359
+msgid "Nudge fwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2360
+msgid "Nudge bwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2361
+msgid "Nudge fwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2362
+msgid "Nudge bwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2371
+msgid "Start to edit cursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2372
+msgid "Edit cursor to end"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2374
+msgid "Trim"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2377
+msgid "Split"
+msgstr "Teilen"
+
+#: gtk_ardour/editor.cc:2380
+#, fuzzy
+msgid "Make mono regions"
+msgstr "Name für Region:"
+
+#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428
+msgid "Duplicate"
+msgstr "Duplizieren"
+
+#: gtk_ardour/editor.cc:2384
+#, fuzzy
+msgid "Fill Track"
+msgstr "Spur"
+
+#: gtk_ardour/editor.cc:2388
+msgid "Destroy"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2418
+#, fuzzy
+msgid "Play range"
+msgstr "Bereich"
+
+#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446
+#, fuzzy
+msgid "Loop range"
+msgstr "Bereich"
+
+#: gtk_ardour/editor.cc:2421
+#, fuzzy
+msgid "Create chunk from range"
+msgstr "Auswahl zu Abschnitt machen"
+
+#: gtk_ardour/editor.cc:2423
+msgid "Create Region"
+msgstr "Region erstellen"
+
+#: gtk_ardour/editor.cc:2424
+msgid "Separate Region"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2425
+#, fuzzy
+msgid "Crop Region to range"
+msgstr "Regionen Editor öffnen"
+
+#: gtk_ardour/editor.cc:2426
+#, fuzzy
+msgid "Bounce range"
+msgstr "Bereich"
+
+#: gtk_ardour/editor.cc:2432
+#, fuzzy
+msgid "Fill range w/Region"
+msgstr "Region erstellen"
+
+#: gtk_ardour/editor.cc:2434
+#, fuzzy
+msgid "Range"
+msgstr "Bereich"
+
+#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538
+#, fuzzy
+msgid "Play from edit cursor"
+msgstr "Wiedergabe ab Cursor"
+
+#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539
+msgid "Play from start"
+msgstr "Wiedergabe ab Anfang"
+
+#: gtk_ardour/editor.cc:2451
+#, fuzzy
+msgid "Play region"
+msgstr "Wiedergabe der Region"
+
+#: gtk_ardour/editor.cc:2453
+#, fuzzy
+msgid "Loop Region"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540
+#: gtk_ardour/library_ui.cc:972
+msgid "Play"
+msgstr "Wiedergabe"
+
+#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548
+#, fuzzy
+msgid "Select All in track"
+msgstr "Auswahl"
+
+#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549
+#, fuzzy
+msgid "Select All"
+msgstr "Auswahl"
+
+#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550
+#, fuzzy
+msgid "Invert in track"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551
+msgid "Invert"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553
+#, fuzzy
+msgid "Select loop range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554
+#, fuzzy
+msgid "Select punch range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565
+#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369
+msgid "Cut"
+msgstr "Ausschneiden"
+
+#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566
+#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371
+msgid "Copy"
+msgstr "Kopieren"
+
+#: gtk_ardour/editor.cc:2482
+#, fuzzy
+msgid "Paste at edit cursor"
+msgstr "Wiedergabe ab Cursor"
+
+#: gtk_ardour/editor.cc:2483
+msgid "Paste at mouse"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923
+msgid "Align"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925
+msgid "Align Relative"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2492
+msgid "Insert chunk"
+msgstr "Abschnitt einfügen"
+
+#: gtk_ardour/editor.cc:2496
+msgid "New Region from range"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2497
+#, fuzzy
+msgid "Separate Range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor.cc:2507
+msgid "Insert Region"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2508
+msgid "Insert external sndfile"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438
+msgid "Import"
+msgstr "Importieren"
+
+#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574
+msgid "Nudge entire track fwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575
+msgid "Nudge track after edit cursor fwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576
+msgid "Nudge entire track bwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577
+msgid "Nudge track after edit cursor bwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920
+#: gtk_ardour/redirect_box.cc:373
+msgid "Paste"
+msgstr "Einfügen"
+
+#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645
+#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799
+msgid "add marker"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3084
+msgid "select/move objects"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3085
+#, fuzzy
+msgid "select/move ranges"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor.cc:3086
+msgid "draw gain automation"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3087
+#, fuzzy
+msgid "select zoom range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor.cc:3088
+msgid "stretch/shrink regions"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3089
+#, fuzzy
+msgid "listen to specific regions"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor.cc:3213
+msgid "Start:"
+msgstr "Anfang:"
+
+#: gtk_ardour/editor.cc:3214
+msgid "End:"
+msgstr "Ende:"
+
+#: gtk_ardour/editor.cc:3215
+msgid "Edit:"
+msgstr "Bearbeiten:"
+
+#: gtk_ardour/editor.cc:3429
+msgid "incorrectly formatted URI list, ignored"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3611
+#, fuzzy
+msgid "set selected trackview"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/editor.cc:3647
+#, fuzzy
+msgid "set selected control point"
+msgstr "Synchronisationspunkt entfernen"
+
+#: gtk_ardour/editor.cc:3719
+#, fuzzy
+msgid "set selected regionview"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835
+#, fuzzy
+msgid "set selected regions"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor.cc:3891
+msgid "Undo"
+msgstr "Rückgängig"
+
+#: gtk_ardour/editor.cc:3893
+msgid "Undo (%1)"
+msgstr "Rückgängig (%1)"
+
+#: gtk_ardour/editor.cc:3903
+msgid "Redo"
+msgstr "Wiederherstellen"
+
+#: gtk_ardour/editor.cc:3905
+msgid "Redo (%1)"
+msgstr "Wiederherstellen (%1)"
+
+#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946
+msgid "... as new track"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947
+#, fuzzy
+msgid "... as new region"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452
+#, fuzzy
+msgid "Import audio (copy)"
+msgstr "Audio Importieren"
+
+#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457
+msgid "Embed audio (link)"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3953
+#, fuzzy
+msgid "Remove last capture"
+msgstr "Synchronisationspunkt entfernen"
+
+#: gtk_ardour/editor.cc:3974
+msgid "Duplicate how many times?"
+msgstr "Wie häufig duplizieren?"
+
+#: gtk_ardour/editor.cc:4550
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If left alone, no audio files used by it will be cleaned.\n"
+"If deleted, audio files used by it alone by will cleaned."
+msgstr ""
+
+#: gtk_ardour/editor.cc:4555
+#, fuzzy
+msgid "Delete playlist"
+msgstr "Name für Schnappschuß"
+
+#: gtk_ardour/editor.cc:4556
+#, fuzzy
+msgid "Keep playlist"
+msgstr "Name für Schnappschuß"
+
+#: gtk_ardour/editor.cc:4557
+#, fuzzy
+msgid "Cancel cleanup"
+msgstr "leeren"
+
+#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258
+#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290
+msgid ""
+"programming error: control point canvas item has no control point object "
+"pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:717
+msgid "programming error: line canvas item has no line object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:744
+#: gtk_ardour/editor_canvas_events.cc:784
+#: gtk_ardour/editor_canvas_events.cc:823
+msgid "programming error: no \"rect\" pointer associated with selection item"
+msgstr ""
+
+#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298
+#: gtk_ardour/mixer_ui.cc:670
+msgid "Show All"
+msgstr "Alles zeigen"
+
+#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299
+#: gtk_ardour/mixer_ui.cc:671
+msgid "Hide All"
+msgstr "Alle verstecken"
+
+#: gtk_ardour/editor_edit_groups.cc:98
+msgid "Name for new edit group"
+msgstr ""
+
+#: gtk_ardour/editor_export_audio.cc:60
+msgid ""
+"There is no range to export.\n"
+"\n"
+"Select a range using the range mouse mode"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707
+msgid "programming error: no ImageFrameView selected"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930
+msgid "programming error: no MarkerView selected"
+msgstr ""
+
+#: gtk_ardour/editor_keys.cc:187
+#, fuzzy
+msgid "keyboard selection"
+msgstr "Auswahl zu Abschnitt machen"
+
+#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376
+#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526
+#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584
+#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650
+#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700
+#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960
+#: gtk_ardour/editor_mouse.cc:4075
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681
+msgid "remove marker"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494
+#, fuzzy
+msgid "Locate to"
+msgstr "Stellen"
+
+#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495
+#, fuzzy
+msgid "Play from"
+msgstr "Wiedergabe ab Anfang"
+
+#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496
+#, fuzzy
+msgid "Set from playhead"
+msgstr "Wiedergabe ab Playhead"
+
+#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497
+#, fuzzy
+msgid "Set from range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor_markers.cc:479
+#, fuzzy
+msgid "Set Loop Range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor_markers.cc:480
+msgid "Set Punch Range"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:736
+#, fuzzy
+msgid "ardour: rename mark"
+msgstr "Ardour: Region umbenennen"
+
+#: gtk_ardour/editor_markers.cc:738
+#, fuzzy
+msgid "ardour: rename range"
+msgstr "Ardour: Region umbenennen"
+
+#: gtk_ardour/editor_markers.cc:792
+#, fuzzy
+msgid "set loop range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor_markers.cc:818
+#, fuzzy
+msgid "set punch range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor_mouse.cc:99
+msgid "Editor::event_frame() used on unhandled event type %1"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1555
+msgid "programming error: start_grab called without drag item"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1760
+msgid "change fade in length"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1778
+msgid "programming error: fade out canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1852
+#, fuzzy
+msgid "change fade out length"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/editor_mouse.cc:1871
+msgid "programming error: cursor canvas item has no cursor data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470
+msgid ""
+"programming error: meter marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2163
+msgid "move meter mark"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335
+#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439
+msgid ""
+"programming error: tempo marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340
+#: gtk_ardour/editor_tempodisplay.cc:425
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2245
+msgid "move tempo mark"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2388
+msgid "programming error: line canvas item has no line pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2497
+#, fuzzy
+msgid "move region(s)"
+msgstr "Name für Region:"
+
+#: gtk_ardour/editor_mouse.cc:2509
+msgid "Drag region copy"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2579
+#, fuzzy
+msgid "copy region(s)"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor_mouse.cc:2612
+#, fuzzy
+msgid "Drag region brush"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor_mouse.cc:3425
+#, fuzzy
+msgid "selection grab"
+msgstr "Auswahl"
+
+#: gtk_ardour/editor_mouse.cc:3571
+#, fuzzy
+msgid "range selection"
+msgstr "Auswahl wiedergeben"
+
+#: gtk_ardour/editor_mouse.cc:3587
+#, fuzzy
+msgid "trim selection start"
+msgstr "Auswahl zu Abschnitt machen"
+
+#: gtk_ardour/editor_mouse.cc:3603
+#, fuzzy
+msgid "trim selection end"
+msgstr "Auswahl zu Abschnitt machen"
+
+#: gtk_ardour/editor_mouse.cc:3620
+#, fuzzy
+msgid "move selection"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor_mouse.cc:3995
+msgid "Start point trim"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:4023
+msgid "End point trim"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:4062
+#, fuzzy
+msgid "trimmed region"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor_mouse.cc:4203
+#, fuzzy
+msgid "new range marker"
+msgstr "Ardour: Region umbenennen"
+
+#: gtk_ardour/editor_mouse.cc:4422
+#, fuzzy
+msgid "select regions"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor_mouse.cc:4451
+msgid "Name for region:"
+msgstr "Name für Region:"
+
+#: gtk_ardour/editor_mouse.cc:4517
+#, fuzzy
+msgid "timestretch"
+msgstr "Ardour: Mixer"
+
+#: gtk_ardour/editor_ops.cc:117
+#, fuzzy
+msgid "split"
+msgstr "Teilen"
+
+#: gtk_ardour/editor_ops.cc:153
+#, fuzzy
+msgid "remove region"
+msgstr "Name für Region:"
+
+#: gtk_ardour/editor_ops.cc:172
+msgid ""
+" This is destructive, will possibly delete audio files\n"
+"It cannot be undone\n"
+"Do you really want to destroy %1 ?"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "these regions"
+msgstr "Name für Region:"
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "this region"
+msgstr "Name für Region:"
+
+#: gtk_ardour/editor_ops.cc:179
+#, fuzzy
+msgid "Yes, destroy them."
+msgstr "Ja, entfernen."
+
+#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434
+#, fuzzy
+msgid "Yes, destroy it."
+msgstr "Ja, entfernen."
+
+#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435
+#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300
+msgid "No, do nothing."
+msgstr "Nein, nichts machen."
+
+#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307
+#, fuzzy
+msgid "extend selection"
+msgstr "Auswahl zu Abschnitt machen"
+
+#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357
+#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427
+msgid "nudge forward"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:491
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1305
+#, fuzzy
+msgid "set selection from range"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor_ops.cc:1421
+msgid "clear markers"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1433
+#, fuzzy
+msgid "clear ranges"
+msgstr "Verbindungen löschen"
+
+#: gtk_ardour/editor_ops.cc:1452
+#, fuzzy
+msgid "clear locations"
+msgstr "Verbindungen löschen"
+
+#: gtk_ardour/editor_ops.cc:1503
+#, fuzzy
+msgid "insert dragged region"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor_ops.cc:1538
+#, fuzzy
+msgid "insert region"
+msgstr "Name für Region:"
+
+#: gtk_ardour/editor_ops.cc:1744
+msgid "ardour: rename region"
+msgstr "Ardour: Region umbenennen"
+
+#: gtk_ardour/editor_ops.cc:1891
+msgid "You can't import an audiofile until you have a session loaded."
+msgstr ""
+"Sie können keine Audio-Daten importieren, solange keine Sitzung geladen ist."
+
+#: gtk_ardour/editor_ops.cc:1901
+#, fuzzy
+msgid "Import selected as tracks"
+msgstr "Auswahl importieren"
+
+#: gtk_ardour/editor_ops.cc:1904
+#, fuzzy
+msgid "Import selected to region list"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor_ops.cc:1933
+msgid "ardour: audio import in progress"
+msgstr "Ardour: Audio Import in Arbeit"
+
+#: gtk_ardour/editor_ops.cc:1937
+msgid "Cancel Import"
+msgstr "Importieren Abbrechen"
+
+#: gtk_ardour/editor_ops.cc:1944
+#, fuzzy
+msgid "ardour: importing %1"
+msgstr "Ardour: Exportieren"
+
+#: gtk_ardour/editor_ops.cc:1990
+msgid "%1 it anyway"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1996
+#, fuzzy
+msgid "Don't %1 it"
+msgstr "Ohne %1"
+
+#: gtk_ardour/editor_ops.cc:1997
+msgid "%1 all without questions"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1998
+#, fuzzy
+msgid "Cancel entire import"
+msgstr "Importieren Abbrechen"
+
+#: gtk_ardour/editor_ops.cc:2004
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2032
+#, fuzzy
+msgid "You can't embed an audiofile until you have a session loaded."
+msgstr ""
+"Sie können keine Audio-Daten importieren, solange keine Sitzung geladen ist."
+
+#: gtk_ardour/editor_ops.cc:2039
+#, fuzzy
+msgid "Add to External Region list"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210
+#: gtk_ardour/editor_ops.cc:2286
+msgid "Editor: cannot open file \"%1\" (%2)"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312
+msgid "could not open %1"
+msgstr "Konnte \"%s\" nicht öffnen."
+
+#: gtk_ardour/editor_ops.cc:2171
+#, fuzzy
+msgid "Insert selected as new tracks"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/editor_ops.cc:2186
+#, fuzzy
+msgid "Insert selected"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/editor_ops.cc:2327
+#, fuzzy
+msgid "insert sndfile"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/editor_ops.cc:2464
+#, fuzzy
+msgid "separate"
+msgstr "Ausgewählten Bereich wiedergeben"
+
+#: gtk_ardour/editor_ops.cc:2528
+#, fuzzy
+msgid "trim to selection"
+msgstr "Auswahl zu Abschnitt machen"
+
+#: gtk_ardour/editor_ops.cc:2568
+msgid "region fill"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2626
+#, fuzzy
+msgid "fill selection"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor_ops.cc:2650
+msgid "Place the edit cursor at the desired sync point"
+msgstr ""
+"Positionieren sie den Arbeits-Cursor am gewünschten Synchronisationspunkt"
+
+#: gtk_ardour/editor_ops.cc:2656
+#, fuzzy
+msgid "set sync from edit cursor"
+msgstr "Wiedergabe ab Cursor"
+
+#: gtk_ardour/editor_ops.cc:2668
+#, fuzzy
+msgid "remove sync"
+msgstr "Synchronisationspunkt entfernen"
+
+#: gtk_ardour/editor_ops.cc:2682
+#, fuzzy
+msgid "naturalize"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor_ops.cc:2746
+msgid "align selection (relative)"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2774
+#, fuzzy
+msgid "align selection"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor_ops.cc:2786
+#, fuzzy
+msgid "align region"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858
+msgid "trim to edit"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2909
+#, fuzzy
+msgid "ardour: freeze"
+msgstr "Ardour: "
+
+#: gtk_ardour/editor_ops.cc:2914
+#, fuzzy
+msgid "Cancel Freeze"
+msgstr "Abbrechen"
+
+#: gtk_ardour/editor_ops.cc:2951
+#, fuzzy
+msgid "bounce range"
+msgstr "Bereich"
+
+#: gtk_ardour/editor_ops.cc:3004
+#, fuzzy
+msgid "cut"
+msgstr "Ausschneiden"
+
+#: gtk_ardour/editor_ops.cc:3007
+#, fuzzy
+msgid "copy"
+msgstr "Kopieren"
+
+#: gtk_ardour/editor_ops.cc:3020
+#, fuzzy
+msgid " objects"
+msgstr "Objekt"
+
+#: gtk_ardour/editor_ops.cc:3046
+#, fuzzy
+msgid " range"
+msgstr "Bereich"
+
+#: gtk_ardour/editor_ops.cc:3201
+#, fuzzy
+msgid "paste"
+msgstr "Einfügen"
+
+#: gtk_ardour/editor_ops.cc:3236
+#, fuzzy
+msgid "paste chunk"
+msgstr "Abschnitt erzeugen:"
+
+#: gtk_ardour/editor_ops.cc:3276
+#, fuzzy
+msgid "duplicate region"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor_ops.cc:3309
+#, fuzzy
+msgid "duplicate selection"
+msgstr "Auswahl zu Schleife machen"
+
+#: gtk_ardour/editor_ops.cc:3349
+#, fuzzy
+msgid "clear playlist"
+msgstr "Name für Schnappschuß"
+
+#: gtk_ardour/editor_ops.cc:3378
+#, fuzzy
+msgid "nudge track"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/editor_ops.cc:3431
+#, fuzzy
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"Wollen Sie wirklich die Spur \"%1\" löschen?\n"
+"(Kann nicht rückgängig gemacht werden!)"
+
+#: gtk_ardour/editor_ops.cc:3463
+#, fuzzy
+msgid "normalize"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/editor_ops.cc:3510
+#, fuzzy
+msgid "reverse regions"
+msgstr "Name für Region:"
+
+#: gtk_ardour/editor_region_list.cc:223
+#, fuzzy
+msgid "hidden"
+msgstr "Verbergen"
+
+#: gtk_ardour/editor_region_list.cc:408
+msgid "Show all"
+msgstr "Alle zeigen"
+
+#: gtk_ardour/editor_region_list.cc:417
+msgid "Ascending"
+msgstr "aufsteigend"
+
+#: gtk_ardour/editor_region_list.cc:419
+msgid "Descending"
+msgstr "absteigend"
+
+#: gtk_ardour/editor_region_list.cc:423
+msgid "By Region Name"
+msgstr "nach Name der Region"
+
+#: gtk_ardour/editor_region_list.cc:425
+msgid "By Region Length"
+msgstr "nach Länge der Region"
+
+#: gtk_ardour/editor_region_list.cc:427
+#, fuzzy
+msgid "By Region Position"
+msgstr "nach Zeitstempel der Region"
+
+#: gtk_ardour/editor_region_list.cc:429
+msgid "By Region Timestamp"
+msgstr "nach Zeitstempel der Region"
+
+#: gtk_ardour/editor_region_list.cc:431
+msgid "By Region Start in File"
+msgstr "nach Anfang der Region in der Datei"
+
+#: gtk_ardour/editor_region_list.cc:433
+msgid "By Region End in File"
+msgstr "nach Ende der Region in der Datei"
+
+#: gtk_ardour/editor_region_list.cc:435
+msgid "By Source File Name"
+msgstr "nach Namen der Quelldatei"
+
+#: gtk_ardour/editor_region_list.cc:437
+msgid "By Source File Length"
+msgstr "nach Länge der Quelldatei"
+
+#: gtk_ardour/editor_region_list.cc:439
+msgid "By Source File Creation Date"
+msgstr "nach Erstellungsdatum der Quelldatei"
+
+#: gtk_ardour/editor_region_list.cc:441
+msgid "By Source Filesystem"
+msgstr "nach Dateisystem der Quelle"
+
+#: gtk_ardour/editor_region_list.cc:444
+msgid "Sorting"
+msgstr "Sortieren"
+
+#: gtk_ardour/editor_region_list.cc:808
+#, fuzzy
+msgid "Regions/length"
+msgstr "nach Länge der Region"
+
+#: gtk_ardour/editor_region_list.cc:812
+#, fuzzy
+msgid "Regions/position"
+msgstr "Regionen"
+
+#: gtk_ardour/editor_region_list.cc:816
+#, fuzzy
+msgid "Regions/creation"
+msgstr "Regionen"
+
+#: gtk_ardour/editor_region_list.cc:820
+#, fuzzy
+msgid "Regions/start"
+msgstr "Regionen"
+
+#: gtk_ardour/editor_region_list.cc:824
+#, fuzzy
+msgid "Regions/end"
+msgstr "Regionen"
+
+#: gtk_ardour/editor_region_list.cc:828
+#, fuzzy
+msgid "Regions/file name"
+msgstr "nach Name der Region"
+
+#: gtk_ardour/editor_region_list.cc:832
+msgid "Regions/file size"
+msgstr ""
+
+#: gtk_ardour/editor_region_list.cc:836
+msgid "Regions/file date"
+msgstr ""
+
+#: gtk_ardour/editor_region_list.cc:840
+msgid "Regions/file system"
+msgstr ""
+
+#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73
+#: gtk_ardour/editor_route_list.cc:231
+msgid "editor"
+msgstr ""
+
+#: gtk_ardour/editor_route_list.cc:300
+msgid "Show All AbstractTracks"
+msgstr ""
+
+#: gtk_ardour/editor_route_list.cc:301
+msgid "Hide All AbstractTracks"
+msgstr ""
+
+#: gtk_ardour/editor_route_list.cc:302
+msgid "Show All AudioBus"
+msgstr ""
+
+#: gtk_ardour/editor_route_list.cc:303
+msgid "Hide All AudioBus"
+msgstr ""
+
+#: gtk_ardour/editor_rulers.cc:311
+#, fuzzy
+msgid "New location marker"
+msgstr "Stellen"
+
+#: gtk_ardour/editor_rulers.cc:312
+#, fuzzy
+msgid "Clear all locations"
+msgstr "Verbindungen löschen"
+
+#: gtk_ardour/editor_rulers.cc:317
+#, fuzzy
+msgid "Clear all ranges"
+msgstr "Verbindungen löschen"
+
+#: gtk_ardour/editor_rulers.cc:326
+msgid "New Tempo"
+msgstr ""
+
+#: gtk_ardour/editor_rulers.cc:327
+#, fuzzy
+msgid "Clear tempo"
+msgstr "leeren"
+
+#: gtk_ardour/editor_rulers.cc:332
+msgid "New Meter"
+msgstr ""
+
+#: gtk_ardour/editor_rulers.cc:333
+#, fuzzy
+msgid "Clear meter"
+msgstr "leeren"
+
+#: gtk_ardour/editor_rulers.cc:341
+#, fuzzy
+msgid "Min:Secs"
+msgstr "Min:Sek"
+
+#: gtk_ardour/editor_selection_list.cc:117
+msgid "name for chunk:"
+msgstr "Name für Abschnitt:"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Create chunk"
+msgstr "Abschnitt erzeugen:"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Forget it"
+msgstr "Abbrechen"
+
+#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295
+#, fuzzy
+msgid "add"
+msgstr "Hinzufügen"
+
+#: gtk_ardour/editor_tempodisplay.cc:276
+#, fuzzy
+msgid "add tempo mark"
+msgstr "Ardour: Region umbenennen"
+
+#: gtk_ardour/editor_tempodisplay.cc:318
+#, fuzzy
+msgid "add meter mark"
+msgstr "Ardour: Region umbenennen"
+
+#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383
+#, fuzzy
+msgid "done"
+msgstr "keine"
+
+#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404
+msgid "replace tempo mark"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487
+#, fuzzy
+msgid "remove tempo mark"
+msgstr "Ja, entfernen."
+
+#: gtk_ardour/editor_timefx.cc:50
+msgid "Quick but Ugly"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:51
+msgid "Skip Anti-aliasing"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:53
+msgid "Stretch/Shrink it"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:57
+#, fuzzy
+msgid "ardour: timestretch"
+msgstr "Ardour: Mixer"
+
+#: gtk_ardour/editor_timefx.cc:58
+msgid "TimeStretchDialog"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83
+#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85
+msgid "TimeStretchButton"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:86
+msgid "TimeStretchProgress"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:151
+msgid "timestretch cannot be started - thread creation error"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410
+#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189
+msgid "22.05kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413
+#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949
+#: gtk_ardour/export_dialog.cc:1191
+msgid "44.1kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416
+#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193
+msgid "48kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419
+#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195
+msgid "88.2kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422
+#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197
+msgid "96kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425
+#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199
+msgid "192kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:73
+msgid "best"
+msgstr "bestmöglich"
+
+#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964
+msgid "fastest"
+msgstr "schnellstmöglich"
+
+#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966
+msgid "linear"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968
+msgid "better"
+msgstr "besser"
+
+#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970
+msgid "intermediate"
+msgstr "mittelmäßig"
+
+#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979
+msgid "Rectangular"
+msgstr "rechteckig"
+
+#: gtk_ardour/export_dialog.cc:84
+msgid "Shaped Noise"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981
+msgid "Triangular"
+msgstr "dreieckig"
+
+#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336
+msgid "stereo"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497
+#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219
+#: gtk_ardour/utils.cc:334
+msgid "mono"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:97
+msgid "CUE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:98
+msgid "TOC"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:106
+msgid "FORMAT"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:107
+msgid "SAMPLE RATE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:108
+msgid "CONVERSION QUALITY"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:109
+msgid "DITHER TYPE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:110
+msgid "CD MARKER FILE TYPE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:111
+msgid "CHANNELS"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:112
+msgid "FILE TYPE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:113
+msgid "SAMPLE FORMAT"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:114
+msgid "SAMPLE ENDIANNESS"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:115
+msgid "EXPORT CD MARKER FILE ONLY"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:116
+msgid "EXPORT TO FILE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118
+#: gtk_ardour/option_editor.cc:119
+msgid "Browse"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:119
+msgid "Specific tracks ..."
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:131
+msgid "ardour: export"
+msgstr "Ardour: Exportieren"
+
+#: gtk_ardour/export_dialog.cc:132
+#, fuzzy
+msgid "ardour_export"
+msgstr "Ardour: Exportieren"
+
+#: gtk_ardour/export_dialog.cc:156
+#, fuzzy
+msgid "Output"
+msgstr "Ausgänge"
+
+#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626
+msgid "Track"
+msgstr "Spur"
+
+#: gtk_ardour/export_dialog.cc:287
+msgid "slereg"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:658
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD toc file"
+msgstr ""
+"Editor: Kann \"%1\" nicht öffnen um CD Track Markierungen zu exportieren."
+
+#: gtk_ardour/export_dialog.cc:780
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD cue file"
+msgstr ""
+"Editor: Kann \"%1\" nicht öffnen um CD Track Markierungen zu exportieren."
+
+#: gtk_ardour/export_dialog.cc:799
+msgid "WAV"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:1051
+msgid "Stop Export"
+msgstr "Export Abbrechen"
+
+#: gtk_ardour/gain_automation_time_axis.cc:60
+#, fuzzy
+msgid "add gain automation event"
+msgstr "Stellen"
+
+#: gtk_ardour/gain_meter.cc:68
+msgid "Cannot create slider pixmaps"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:83
+msgid "dbFS"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134
+#: gtk_ardour/gain_meter.cc:728
+msgid "pre"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724
+#, fuzzy
+msgid "input"
+msgstr "%1 Eingang"
+
+#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732
+#, fuzzy
+msgid "post"
+msgstr "Anschluß"
+
+#: gtk_ardour/gain_meter.cc:146
+msgid "tupni"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470
+#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537
+msgid "-inf"
+msgstr ""
+
+#: gtk_ardour/imageframe_socket_handler.cc:127
+msgid "Image Compositor Socket has been shutdown/closed"
+msgstr ""
+
+#: gtk_ardour/imageframe_time_axis.cc:295
+#, fuzzy
+msgid "0.5 seconds"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259
+#, fuzzy
+msgid "1 seconds"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260
+#, fuzzy
+msgid "1.5 seconds"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261
+#, fuzzy
+msgid "2 seconds"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262
+#, fuzzy
+msgid "2.5 seconds"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263
+#, fuzzy
+msgid "3 seconds"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268
+#, fuzzy
+msgid "Duration (sec)"
+msgstr "Ardour: Region"
+
+#: gtk_ardour/imageframe_time_axis.cc:310
+#, fuzzy
+msgid "Remove Frame"
+msgstr "Feld entfernen"
+
+#: gtk_ardour/imageframe_time_axis.cc:313
+msgid "Image Frame"
+msgstr ""
+
+#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274
+#, fuzzy
+msgid "Rename Track"
+msgstr "Umbenennen"
+
+#: gtk_ardour/io_selector.cc:64
+msgid "%1 input"
+msgstr "%1 Eingang"
+
+#: gtk_ardour/io_selector.cc:66
+msgid "%1 output"
+msgstr "%1 Ausgang"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103
+#, fuzzy
+msgid "Inputs"
+msgstr "Eingänge"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104
+#, fuzzy
+msgid "Outputs"
+msgstr "Ausgänge"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Input"
+msgstr "Port hinzufügen"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Output"
+msgstr "%1 Ausgang"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Input"
+msgstr "Synchronisationspunkt entfernen"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Output"
+msgstr "Ausgänge"
+
+#: gtk_ardour/io_selector.cc:144
+#, fuzzy
+msgid "Disconnect All"
+msgstr "Trennen"
+
+#: gtk_ardour/io_selector.cc:158
+msgid "Available connections"
+msgstr "Verfügbare Verbindungen"
+
+#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636
+#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724
+msgid "port"
+msgstr "Anschluß"
+
+#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587
+msgid "There are no more JACK ports available."
+msgstr ""
+
+#: gtk_ardour/io_selector.cc:790
+msgid "ardour: "
+msgstr "Ardour: "
+
+#: gtk_ardour/keyboard.cc:419
+msgid "KeyboardTarget: keyname \"%1\" is unknown."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:645
+msgid ""
+"Your system is completely broken - NumLock uses \"%1\"as its modifier. This "
+"is madness - see the man page for xmodmap to find out how to fix this."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:653
+msgid ""
+"Your system generates \"%1\" when the NumLock key is pressed. This can cause "
+"problems when editing so Ardour will use %2 to mean Meta rather than %1"
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:714
+msgid "You have %1 keys bound to \"mod1\""
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:729
+msgid "You have %1 keys bound to \"mod2\""
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:744
+msgid "You have %1 keys bound to \"mod3\""
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:759
+msgid "You have %1 keys bound to \"mod4\""
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:774
+msgid "You have %1 keys bound to \"mod5\""
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:72
+msgid "KeyboardTarget: empty string passed to add_binding."
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:78
+msgid "KeyboardTarget: no translation found for \"%1\""
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:83
+msgid "KeyboardTarget: unknown action \"%1\""
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:248
+msgid "misformed binding node - ignored"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:62
+#, fuzzy
+msgid "Soundfile Library"
+msgstr "Ardour: Audio Bibliothek"
+
+#: gtk_ardour/library_ui.cc:63
+#, fuzzy
+msgid "Filesystem"
+msgstr "nach Dateisystem der Quelle"
+
+#: gtk_ardour/library_ui.cc:66
+msgid "Split Channels"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:69
+#, fuzzy
+msgid "ardour: soundfile selector"
+msgstr "Ardour: Farbe auswählen"
+
+#: gtk_ardour/library_ui.cc:430
+msgid "Add to Library..."
+msgstr "Zu Bibliothek hinzufügen..."
+
+#: gtk_ardour/library_ui.cc:431
+msgid "Remove..."
+msgstr "Entfernen..."
+
+#: gtk_ardour/library_ui.cc:432
+msgid "Find..."
+msgstr "Suchen..."
+
+#: gtk_ardour/library_ui.cc:433
+msgid "Add Folder"
+msgstr "Verzeichnis hinzufügen"
+
+#: gtk_ardour/library_ui.cc:434
+msgid "Add audio file or directory"
+msgstr "Audio-Datei oder -Verzeichnis hinzufügen"
+
+#: gtk_ardour/library_ui.cc:713
+#, fuzzy
+msgid "Importing"
+msgstr "Importieren"
+
+#: gtk_ardour/library_ui.cc:748
+msgid "%1 not added to database"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:767
+msgid "Folder name:"
+msgstr "Verzeichnisname:"
+
+#: gtk_ardour/library_ui.cc:838
+#, fuzzy
+msgid "Should not be reached"
+msgstr "Datei \"%1\" konnte nicht geöffnet werden."
+
+#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096
+msgid "file \"%1\" could not be opened"
+msgstr "Datei \"%1\" konnte nicht geöffnet werden."
+
+#: gtk_ardour/library_ui.cc:956
+msgid "Field"
+msgstr "Feld"
+
+#: gtk_ardour/library_ui.cc:957
+msgid "Value"
+msgstr "Wert"
+
+#: gtk_ardour/library_ui.cc:973
+#, fuzzy
+msgid "Stop"
+msgstr "Stop"
+
+#: gtk_ardour/library_ui.cc:974
+msgid "Add Field..."
+msgstr "Feld hinzufügen..."
+
+#: gtk_ardour/library_ui.cc:975
+msgid "Remove Field"
+msgstr "Feld entfernen"
+
+#: gtk_ardour/library_ui.cc:979
+msgid "Soundfile Info"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1106
+msgid "file \"%1\" appears not to be an audio file"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1159
+msgid "Could not read file: %1 (%2)."
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1177
+msgid "Could not access soundfile: "
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1222
+msgid "Field name:"
+msgstr "Feldname:"
+
+#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367
+msgid "Field value:"
+msgstr "Wert des Feldes:"
+
+#: gtk_ardour/library_ui.cc:1295
+msgid "Find"
+msgstr "Suchen"
+
+#: gtk_ardour/library_ui.cc:1296
+msgid "AND"
+msgstr "UND"
+
+#: gtk_ardour/library_ui.cc:1297
+msgid "OR"
+msgstr "ODER"
+
+#: gtk_ardour/library_ui.cc:1300
+msgid "ardour: locate soundfiles"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1426
+msgid "Results"
+msgstr "Ergebnisse"
+
+#: gtk_ardour/library_ui.cc:1427
+msgid "Uris"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1439
+msgid "Create multi-channel region"
+msgstr "Region mit mehreren Kanälen erstellen"
+
+#: gtk_ardour/library_ui.cc:1442
+msgid "Ardour: Search Results"
+msgstr "Ardour: Suchergebnisse"
+
+#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50
+#, fuzzy
+msgid "Set"
+msgstr "Auswahl"
+
+#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51
+msgid "Go"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:54
+msgid "CD"
+msgstr "CD"
+
+#: gtk_ardour/location_ui.cc:55
+#, fuzzy
+msgid "Hidden"
+msgstr "Verbergen"
+
+#: gtk_ardour/location_ui.cc:57
+msgid "SCMS"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:58
+msgid "Pre-Emphasis"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:592
+#, fuzzy
+msgid "Add New Location"
+msgstr "Stellen"
+
+#: gtk_ardour/location_ui.cc:593
+msgid "Add New Range"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:597
+msgid "ardour: locations"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:598
+#, fuzzy
+msgid "ardour_locations"
+msgstr "Ardour: Verbindungen"
+
+#: gtk_ardour/location_ui.cc:629
+#, fuzzy
+msgid "Location (CD Index) Markers"
+msgstr "Stellen"
+
+#: gtk_ardour/location_ui.cc:649
+msgid "Range (CD Track) Markers"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:814
+#, fuzzy
+msgid "add range marker"
+msgstr "Ardour: Region umbenennen"
+
+#: gtk_ardour/main.cc:76
+msgid "ardour is killing itself for a clean exit\n"
+msgstr ""
+
+#: gtk_ardour/main.cc:85
+msgid "stopping user interface\n"
+msgstr ""
+
+#: gtk_ardour/main.cc:104
+#, c-format
+msgid "%d(%d): received signal %d\n"
+msgstr ""
+
+#: gtk_ardour/main.cc:190
+msgid "cannot become new process group leader (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:217
+msgid "cannot setup signal handling for %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:228
+msgid "cannot set default signal mask (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:253
+msgid ""
+"Without a UI style file, ardour will look strange.\n"
+" Please set ARDOUR_UI_RC to point to a valid UI style file"
+msgstr ""
+
+#: gtk_ardour/main.cc:292
+msgid ""
+"Ardour could not connect to JACK.\n"
+"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 ""
+
+#: gtk_ardour/main.cc:305
+#, fuzzy
+msgid "ardour: unplugged"
+msgstr "Ardour: Plugins"
+
+#: gtk_ardour/main.cc:363
+msgid "Ardour/GTK "
+msgstr ""
+
+#: gtk_ardour/main.cc:365
+msgid ""
+"\n"
+" (built using "
+msgstr ""
+
+#: gtk_ardour/main.cc:369
+msgid " with libardour "
+msgstr ""
+
+#: gtk_ardour/main.cc:374
+msgid " and GCC version "
+msgstr ""
+
+#: gtk_ardour/main.cc:384
+msgid "Copyright (C) 1999-2005 Paul Davis"
+msgstr ""
+
+#: gtk_ardour/main.cc:385
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+msgstr ""
+
+#: gtk_ardour/main.cc:387
+msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
+msgstr "Achtung: Es gibt zu Ardour KEINERLEI Gewährleistung!"
+
+#: gtk_ardour/main.cc:388
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr ""
+
+#: gtk_ardour/main.cc:389
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr "Dies ist freie Software und Sie dürfen sie gerne weiterverbreiten,"
+
+#: gtk_ardour/main.cc:390
+#, fuzzy
+msgid "under certain conditions; see the source for copying conditions."
+msgstr "solange Sie sich an die Spielregeln aus der Datei COPYING halten."
+
+#: gtk_ardour/main.cc:399
+msgid "could not create ARDOUR GUI"
+msgstr ""
+
+#: gtk_ardour/main.cc:419
+msgid "Could not connect to JACK server as \"%1\""
+msgstr ""
+
+#: gtk_ardour/main.cc:424
+msgid "could not initialize Ardour."
+msgstr ""
+
+#: gtk_ardour/main.cc:435
+msgid "could not load command line session \"%1\""
+msgstr ""
+
+#: gtk_ardour/main.cc:455
+msgid ""
+"\n"
+"\n"
+"A session named \"%1\" already exists.\n"
+"To avoid this message, start ardour as \"ardour %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:466
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as \"ardour --new %1"
+msgstr ""
+
+#: gtk_ardour/marker.cc:354
+#, fuzzy
+msgid "MarkerText"
+msgstr "Schicht"
+
+#: gtk_ardour/marker_time_axis.cc:271
+#, fuzzy
+msgid "Remove Marker"
+msgstr "Feld entfernen"
+
+#: gtk_ardour/marker_time_axis.cc:273
+#, fuzzy
+msgid "Marker"
+msgstr "Schicht"
+
+#: gtk_ardour/meter_bridge.cc:74
+msgid "ardour: meter bridge"
+msgstr ""
+
+#: gtk_ardour/meter_bridge.cc:75
+msgid "ardour_meter_bridge"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93
+#, c-format
+msgid "# of %u-sample overs"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:219
+msgid "New name for meter:"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507
+#: gtk_ardour/region_editor.cc:45
+msgid "mute"
+msgstr "mute"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508
+msgid "solo"
+msgstr "solo"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506
+msgid "RECORD"
+msgstr "AUFNAHME"
+
+#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514
+msgid "polarity"
+msgstr "Polarität"
+
+#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509
+msgid "comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810
+msgid "INPUT"
+msgstr "EINGANG"
+
+#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831
+msgid "OUTPUT"
+msgstr "AUSGANG"
+
+#: gtk_ardour/mixer_strip.cc:173
+#, fuzzy
+msgid "Pan automation mode"
+msgstr "Stellen"
+
+#: gtk_ardour/mixer_strip.cc:174
+#, fuzzy
+msgid "Gain automation mode"
+msgstr "Stellen"
+
+#: gtk_ardour/mixer_strip.cc:176
+#, fuzzy
+msgid "Pan automation type"
+msgstr "Stellen"
+
+#: gtk_ardour/mixer_strip.cc:177
+#, fuzzy
+msgid "Gain automation type"
+msgstr "Stellen"
+
+#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232
+#: gtk_ardour/mixer_strip.cc:979
+#, fuzzy
+msgid "trim"
+msgstr "Streifen"
+
+#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233
+#: gtk_ardour/mixer_strip.cc:983
+msgid "abs"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:240
+#, fuzzy
+msgid "gain automation mode"
+msgstr "Stellen"
+
+#: gtk_ardour/mixer_strip.cc:241
+#, fuzzy
+msgid "pan automation mode"
+msgstr "Stellen"
+
+#: gtk_ardour/mixer_strip.cc:242
+#, fuzzy
+msgid "gain automation state"
+msgstr "Stellen"
+
+#: gtk_ardour/mixer_strip.cc:243
+#, fuzzy
+msgid "pan automation state"
+msgstr "Stellen"
+
+#: gtk_ardour/mixer_strip.cc:259
+msgid "varispeed"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174
+msgid "click to add/edit comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:463
+msgid "unknown strip width \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:522
+msgid "REC"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:525
+#, fuzzy
+msgid "cmt"
+msgstr "Ausschneiden"
+
+#: gtk_ardour/mixer_strip.cc:530
+msgid "pol"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620
+#: gtk_ardour/redirect_box.cc:1180
+msgid "Not connected to JACK - no I/O changes are possible"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667
+msgid "could not register new ports required for that connection"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:813
+msgid "IN"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:834
+msgid "OUT"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:950
+msgid "aplay"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:956
+msgid "awrite"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:1134
+#, fuzzy
+msgid ": comment editor"
+msgstr "Der Editor konnte nicht initialisiert werden."
+
+#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224
+msgid "no group"
+msgstr "keine Gruppe"
+
+#: gtk_ardour/mixer_strip.cc:1227
+msgid "~G"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:52
+msgid "Strips"
+msgstr "Streifen"
+
+#: gtk_ardour/mixer_ui.cc:56
+msgid "Snapshots"
+msgstr "Schnapschüsse"
+
+#: gtk_ardour/mixer_ui.cc:61
+msgid "***"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17
+#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144
+#: gtk_ardour/tempo_dialog.cc:162
+msgid "Bar"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:121
+msgid "Mix Groups"
+msgstr "Mix Gruppen"
+
+#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373
+msgid "ardour: mixer"
+msgstr "Ardour: Mixer"
+
+#: gtk_ardour/mixer_ui.cc:192
+#, fuzzy
+msgid "ardour_mixer"
+msgstr "Ardour: Mixer"
+
+#: gtk_ardour/mixer_ui.cc:342
+msgid "ardour: mixer: "
+msgstr "Ardour: Mixer: "
+
+#: gtk_ardour/mixer_ui.cc:641
+msgid "signal"
+msgstr "Signal"
+
+#: gtk_ardour/mixer_ui.cc:672
+msgid "Show All AudioTrack MixerStrips"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:673
+msgid "Hide All AudioTrack MixerStrips"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:674
+msgid "Show All AudioBus MixerStrips"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:675
+msgid "Hide All AudioBus MixerStrips"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:687
+msgid "track display list item for renamed strip not found!"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:700
+msgid "Name for new mix group"
+msgstr "Name für neue Mix Gruppe"
+
+#: gtk_ardour/new_session_dialog.cc:39
+#, fuzzy
+msgid "Session name:"
+msgstr "Name der Sitzung"
+
+#: gtk_ardour/new_session_dialog.cc:39
+#, fuzzy
+msgid "Create"
+msgstr "Abschnitt erzeugen:"
+
+#: gtk_ardour/new_session_dialog.cc:40
+msgid "use control outs"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:41
+msgid "use master outs"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:42
+msgid "automatically connect track inputs to physical ports"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:43
+msgid "automatically connect track outputs to master outs"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:44
+msgid "automatically connect track outputs to physical ports"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:45
+msgid "manually connect track outputs"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:50
+#, fuzzy
+msgid "Advanced..."
+msgstr "Feld hinzufügen..."
+
+#: gtk_ardour/new_session_dialog.cc:52
+#, fuzzy
+msgid "show again"
+msgstr "Stellen"
+
+#: gtk_ardour/new_session_dialog.cc:55
+msgid "Hardware Inputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:56
+msgid "Hardware Outputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:62
+#, fuzzy
+msgid "new session setup"
+msgstr "Name der Sitzung"
+
+#: gtk_ardour/new_session_dialog.cc:63
+#, fuzzy
+msgid "ardour_new_session"
+msgstr "Ardour: Neue Sitzung"
+
+#: gtk_ardour/new_session_dialog.cc:72
+msgid "This session will playback and record at %1 Hz"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:74
+msgid ""
+"This rate is set by JACK and cannot be changed.\n"
+"If you want to use a different sample rate\n"
+"please exit and restart JACK"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:155
+#, fuzzy
+msgid "Session template"
+msgstr "Name der Sitzung"
+
+#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20
+#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146
+#: gtk_ardour/tempo_dialog.cc:164
+#, fuzzy
+msgid "Location"
+msgstr "Stellen"
+
+#: gtk_ardour/new_session_dialog.cc:178
+msgid "Configuration"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:269
+msgid "blank"
+msgstr "leer"
+
+#: gtk_ardour/new_session_dialog.cc:328
+msgid "No template - create tracks/busses manually"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:337
+#, fuzzy
+msgid "No template"
+msgstr "Voreinstellung"
+
+#: gtk_ardour/option_editor.cc:48
+#, fuzzy
+msgid "Internal"
+msgstr "mittelmäßig"
+
+#: gtk_ardour/option_editor.cc:49
+#, fuzzy
+msgid "Slave to MTC"
+msgstr "MTC senden"
+
+#: gtk_ardour/option_editor.cc:50
+msgid "Sync with JACK"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:51
+msgid "never used but stops crashes"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:56
+#, fuzzy
+msgid "Later regions are higher"
+msgstr "Region eine Ebene nach unten"
+
+#: gtk_ardour/option_editor.cc:57
+msgid "Most recently added/moved/trimmed regions are higher"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:58
+#, fuzzy
+msgid "Most recently added regions are higher"
+msgstr "Region eine Ebene nach unten"
+
+#: gtk_ardour/option_editor.cc:63
+#, fuzzy
+msgid "Span entire region overlap"
+msgstr "Region eine Ebene nach oben"
+
+#: gtk_ardour/option_editor.cc:64
+msgid "Short fades at the start of the overlap"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:82
+msgid "Automatically create crossfades"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:83
+msgid "New full-overlap crossfades are unmuted"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:84
+#, fuzzy
+msgid "Region layering mode"
+msgstr "Regionen"
+
+#: gtk_ardour/option_editor.cc:85
+msgid "Crossfade model"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:90
+msgid "Latched solo"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:91
+msgid "Solo via bus"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:96
+#, fuzzy
+msgid "Show waveforms while recording"
+msgstr "Wellenform zeigen"
+
+#: gtk_ardour/option_editor.cc:97
+#, fuzzy
+msgid "Narrow mixer strips"
+msgstr "schmale Mixerstreifen"
+
+#: gtk_ardour/option_editor.cc:98
+msgid "Show measure lines"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:99
+#, fuzzy
+msgid "Follow playhead"
+msgstr "Wiedergabe ab Playhead"
+
+#: gtk_ardour/option_editor.cc:103
+msgid "Send MTC"
+msgstr "MTC senden"
+
+#: gtk_ardour/option_editor.cc:104
+msgid "Send MMC"
+msgstr "MMC senden"
+
+#: gtk_ardour/option_editor.cc:105
+msgid "JACK time master"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:107
+msgid "SMPTE offset is negative"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:111
+msgid "Send MIDI parameter feedback"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:112
+msgid "MIDI parameter control"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:113
+msgid "MMC control"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:131
+msgid "Auto-connect new track inputs to hardware"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:132
+msgid "Auto-connect new track outputs to hardware"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:133
+msgid "Auto-connect new track outputs to master bus"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:134
+msgid "Manually connect new track outputs"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:135
+msgid "Use Hardware Monitoring"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:136
+msgid "Use Software Monitoring"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:137
+msgid "Stop plugins with transport"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:138
+msgid "Run plugins while recording"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:139
+#, fuzzy
+msgid "Verify remove last capture"
+msgstr "Synchronisationspunkt entfernen"
+
+#: gtk_ardour/option_editor.cc:140
+msgid "Stop recording on xrun"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:141
+#, fuzzy
+msgid "Stop transport at end of session"
+msgstr "Ans Ende der Sitzung springen"
+
+#: gtk_ardour/option_editor.cc:142
+msgid "Debug keyboard events"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:143
+msgid "-12dB gain reduction for ffwd/rew"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:152
+#, fuzzy
+msgid "ardour: options editor"
+msgstr "Ardour: Einstellungen"
+
+#: gtk_ardour/option_editor.cc:153
+#, fuzzy
+msgid "ardour_option_editor"
+msgstr "Ardour: Einstellungen"
+
+#: gtk_ardour/option_editor.cc:183
+#, fuzzy
+msgid "Misc"
+msgstr "Min:Sek"
+
+#: gtk_ardour/option_editor.cc:184
+msgid "Sync"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:185
+msgid "Paths/Files"
+msgstr "Pfade- und Dateinamen"
+
+#: gtk_ardour/option_editor.cc:186
+msgid "Display"
+msgstr "Anzeige"
+
+#: gtk_ardour/option_editor.cc:187
+msgid "Kbd/Mouse"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:188
+msgid "Click"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:190
+msgid "Layers & Fades"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:195
+msgid "MIDI"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:268
+msgid "24 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:270
+msgid "25 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:272
+msgid "30 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:278
+msgid "30 FPS drop"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379
+#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736
+#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800
+msgid "Medium"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738
+#: gtk_ardour/option_editor.cc:804
+#, fuzzy
+msgid "Faster"
+msgstr "Einfügen"
+
+#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714
+#: gtk_ardour/option_editor.cc:776
+#, fuzzy
+msgid "Short"
+msgstr "Anschluß"
+
+#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716
+#: gtk_ardour/option_editor.cc:780
+msgid "Long"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:396
+msgid "Broadcast WAVE/floating point"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:397
+msgid "WAVE/floating point"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:417
+msgid "session RAID path"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:422
+msgid "Native Format"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460
+#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409
+#, fuzzy
+msgid "internal"
+msgstr "mittelmäßig"
+
+#: gtk_ardour/option_editor.cc:537
+msgid "Short crossfade length (msecs)"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:710
+msgid "Meter Peak Hold"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:730
+msgid "Meter Falloff"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:847
+msgid "Positional Sync"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:902
+msgid "SMPTE Frames/second"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:903
+msgid "SMPTE Offset"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013
+#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211
+#, fuzzy
+msgid "online"
+msgstr "Verbindungen"
+
+#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014
+#: gtk_ardour/option_editor.cc:1208
+msgid "offline"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1319
+msgid "Use as click"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1344
+msgid "Use as click emphasis"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1478
+msgid "--unknown--"
+msgstr "--unbekannt--"
+
+#: gtk_ardour/option_editor.cc:1595
+msgid "Click audio file"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1601
+msgid "Click emphasis audiofile"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1638
+msgid ""
+"The auditioner is a dedicated mixer strip used\n"
+"for listening to specific regions outside the context\n"
+"of the overall mix. It can be connected just like any\n"
+"other mixer strip."
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1887
+#, fuzzy
+msgid "Edit using"
+msgstr "Mix Gruppen"
+
+#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924
+msgid "+ button"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1917
+#, fuzzy
+msgid "Delete using"
+msgstr "Messungen"
+
+#: gtk_ardour/option_editor.cc:1947
+msgid "Ignore snap using"
+msgstr ""
+
+#: gtk_ardour/opts.cc:46
+msgid "Usage: "
+msgstr "Aufruf:"
+
+#: gtk_ardour/opts.cc:47
+msgid " -v, --version Show version information\n"
+msgstr " -v, --version Versionsinformation ausgeben\n"
+
+#: gtk_ardour/opts.cc:48
+msgid " -h, --help Print this message\n"
+msgstr " -h, --help Diese Hinweise\n"
+
+#: gtk_ardour/opts.cc:49
+msgid ""
+" -b, --bindings Print all possible keyboard binding "
+"names\n"
+msgstr ""
+" -b, --bindings Alle möglichen Tastenzuweisungsnamen "
+"ausgeben\n"
+
+#: gtk_ardour/opts.cc:50
+#, fuzzy
+msgid " -n, --show-splash Show splash screen\n"
+msgstr " -h, --help Diese Hinweise\n"
+
+#: gtk_ardour/opts.cc:51
+#, fuzzy
+msgid ""
+" -c, --name name Use a specific jack client name, default "
+"is ardour\n"
+msgstr " -U, --ui-rcfile=FILENAME Dateiname für UI Einstellungen\n"
+
+#: gtk_ardour/opts.cc:52
+#, fuzzy
+msgid ""
+" -N, --new session-name Create a new session from the command "
+"line\n"
+msgstr " [session-name] Name der zu ladenden Sitzung\n"
+
+#: gtk_ardour/opts.cc:53
+msgid ""
+" -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:55
+#, fuzzy
+msgid " -V, --novst Do not use VST support\n"
+msgstr " -h, --help Diese Hinweise\n"
+
+#: gtk_ardour/opts.cc:57
+msgid " [session-name] Name of session to load\n"
+msgstr " [session-name] Name der zu ladenden Sitzung\n"
+
+#: gtk_ardour/opts.cc:58
+msgid " -C, --curvetest filename Curve algorithm debugger\n"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:58
+msgid "You can't graphically edit panning of more than stream"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:78
+#, fuzzy
+msgid "add pan automation event"
+msgstr "Stellen"
+
+#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441
+msgid "Bypass"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222
+#, fuzzy
+msgid "link"
+msgstr "leer"
+
+#: gtk_ardour/panner_ui.cc:103
+msgid "panning link control"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:105
+msgid "panning link direction"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:232
+msgid "L"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:344
+#, c-format
+msgid "panner for channel %u"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:451
+#, fuzzy
+msgid "Reset all"
+msgstr "bestmöglich"
+
+#: gtk_ardour/playlist_selector.cc:46
+msgid "Playlists grouped by track"
+msgstr ""
+
+#: gtk_ardour/playlist_selector.cc:53
+#, fuzzy
+msgid "close"
+msgstr "Schließen"
+
+#: gtk_ardour/playlist_selector.cc:59
+#, fuzzy
+msgid "ardour: playlists"
+msgstr "Ardour: Plugins"
+
+#: gtk_ardour/playlist_selector.cc:104
+#, fuzzy
+msgid "ardour: playlist for "
+msgstr "Ardour: Editor: "
+
+#: gtk_ardour/playlist_selector.cc:122
+#, fuzzy
+msgid "Other tracks"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/playlist_selector.cc:138
+msgid "unassigned"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:41
+msgid "Available LADSPA plugins"
+msgstr "Verfügbare LADSPA Plugins"
+
+#: gtk_ardour/plugin_selector.cc:42
+msgid "Type"
+msgstr "Typ"
+
+#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51
+msgid "# Inputs"
+msgstr "Eingänge"
+
+#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52
+msgid "# Outputs"
+msgstr "Ausgänge"
+
+#: gtk_ardour/plugin_selector.cc:50
+#, fuzzy
+msgid "Available VST plugins"
+msgstr "Verfügbare LADSPA Plugins"
+
+#: gtk_ardour/plugin_selector.cc:58
+msgid "To be added"
+msgstr "hinzuzufügen"
+
+#: gtk_ardour/plugin_selector.cc:72
+msgid "ardour: plugins"
+msgstr "Ardour: Plugins"
+
+#: gtk_ardour/plugin_selector.cc:82
+msgid "Add a plugin to the effect list"
+msgstr "Plugin zur Effektliste hinzufügen"
+
+#: gtk_ardour/plugin_selector.cc:84
+msgid "Remove a plugin from the effect list"
+msgstr "Plugin aus der Effektliste entfernen"
+
+#: gtk_ardour/plugin_selector.cc:88
+msgid "Update"
+msgstr "Auffrischen"
+
+#: gtk_ardour/plugin_selector.cc:89
+msgid "Update available plugins"
+msgstr "Verfügbare Plugins auffrischen"
+
+#: gtk_ardour/plugin_selector.cc:110
+msgid "LADSPA"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:113
+msgid "VST"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:83
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this "
+"version of ardour)"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:269
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "in"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "ins"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "out"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "outs"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:382
+#, fuzzy
+msgid "automation control"
+msgstr "Stellen"
+
+#: gtk_ardour/plugin_ui.cc:869
+#, fuzzy
+msgid "save"
+msgstr "Speichern"
+
+#: gtk_ardour/plugin_ui.cc:870
+msgid "bypass"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:892
+msgid "Plugin preset %1 not found"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:903
+msgid "Name for plugin settings:"
+msgstr "Name für Plugineinstellungen:"
+
+#: gtk_ardour/redirect_automation_line.cc:53
+msgid "redirect automation created for non-plugin"
+msgstr ""
+
+#: gtk_ardour/redirect_automation_time_axis.cc:92
+#, fuzzy
+msgid "add automation event to "
+msgstr "Stellen"
+
+#: gtk_ardour/redirect_box.cc:213
+msgid "New send"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:214
+msgid "Show send controls"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:360
+msgid "New Plugin ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:361
+#, fuzzy
+msgid "New Insert"
+msgstr "Neuer Eingang"
+
+#: gtk_ardour/redirect_box.cc:362
+msgid "New Send ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:380
+#, fuzzy
+msgid "Select all"
+msgstr "Auswahl"
+
+#: gtk_ardour/redirect_box.cc:381
+#, fuzzy
+msgid "Deselect all"
+msgstr "Auswahl"
+
+#: gtk_ardour/redirect_box.cc:389
+#, fuzzy
+msgid "Inserts"
+msgstr "Stille einfügen"
+
+#: gtk_ardour/redirect_box.cc:390
+#, fuzzy
+msgid "Sends"
+msgstr "Minuten:Sekunden"
+
+#: gtk_ardour/redirect_box.cc:393
+#, fuzzy
+msgid "Select all ..."
+msgstr "Auswahl"
+
+#: gtk_ardour/redirect_box.cc:406
+#, fuzzy
+msgid "Activate All"
+msgstr "Aktiv"
+
+#: gtk_ardour/redirect_box.cc:407
+#, fuzzy
+msgid "Deactivate All"
+msgstr "Alles deaktivieren"
+
+#: gtk_ardour/redirect_box.cc:488
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:500
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:513
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:616
+msgid "Pre-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:619
+msgid "Post-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:781
+msgid ""
+"You cannot reorder this set of redirects\n"
+"in that way because the inputs and\n"
+"outputs do not work correctly."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:903
+#, fuzzy
+msgid "ardour: rename redirect"
+msgstr "Ardour: Region umbenennen"
+
+#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043
+msgid ""
+"Copying the set of redirects on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:1064
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this track?\n"
+"(this cannot be undone)"
+msgstr ""
+"Wollen Sie wirklich die Spur \"%1\" löschen?\n"
+"(Kann nicht rückgängig gemacht werden!)"
+
+#: gtk_ardour/redirect_box.cc:1067
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this bus?\n"
+"(this cannot be undone)"
+msgstr ""
+"Wollen Sie wirklich die Spur \"%1\" löschen?\n"
+"(Kann nicht rückgängig gemacht werden!)"
+
+#: gtk_ardour/redirect_box.cc:1071
+#, fuzzy
+msgid "Yes, remove them all"
+msgstr "Ja, entfernen."
+
+#: gtk_ardour/redirect_box.cc:1114
+#, fuzzy
+msgid "ardour: %1"
+msgstr "Ardour: "
+
+#: gtk_ardour/redirect_box.cc:1156
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "Ardour: "
+
+#: gtk_ardour/region_editor.cc:43
+msgid "NAME:"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:44
+msgid "lock"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:46
+msgid "opaque"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:49
+msgid "Layer"
+msgstr "Schicht"
+
+#: gtk_ardour/region_editor.cc:57
+msgid "ENVELOPE"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:108
+#, fuzzy
+msgid "mute this region"
+msgstr "Name für Region:"
+
+#: gtk_ardour/region_editor.cc:109
+msgid "regions underneath this one cannot be heard"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:110
+msgid "prevent any changes to this region"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:111
+msgid "use the gain envelope during playback"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:112
+msgid "show the gain envelope"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:113
+msgid "use fade in curve during playback"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:114
+msgid "use fade out curve during playback"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:115
+msgid "audition this region"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:148
+msgid "START:"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:150
+msgid "END:"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:152
+msgid "LENGTH:"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198
+#: gtk_ardour/region_editor.cc:234
+msgid "active"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:179
+msgid "visible"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:197
+msgid "FADE IN"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235
+msgid "msecs"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:233
+msgid "FADE OUT"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:276
+msgid "ardour: region "
+msgstr "Ardour: Region"
+
+#: gtk_ardour/region_editor.cc:410
+msgid "fade in edit"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:422
+#, fuzzy
+msgid "fade out edit"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/regionview.cc:1169
+#, fuzzy
+msgid "add gain control point"
+msgstr "Synchronisationspunkt entfernen"
+
+#: gtk_ardour/route_params_ui.cc:58
+msgid "Tracks/Buses"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:59
+msgid "Pre Redirects"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:60
+msgid "Post Redirects"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:105
+msgid "Pre-fader Redirects"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:106
+msgid "Post-fader Redirects"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:138
+#, fuzzy
+msgid "ardour: track/bus inspector"
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/route_params_ui.cc:139
+#, fuzzy
+msgid "ardour_route_parameters"
+msgstr "Ardour: Route"
+
+#: gtk_ardour/route_params_ui.cc:189
+msgid "route display list item for renamed route not found!"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:448
+msgid "NO TRACK"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:669
+#, fuzzy
+msgid "ardour: track/bus inspector: "
+msgstr "Ardour: Editor"
+
+#: gtk_ardour/route_params_ui.cc:673
+msgid "No Route Selected"
+msgstr "Keine Route ausgewählt"
+
+#: gtk_ardour/route_params_ui.cc:674
+#, fuzzy
+msgid "ardour: track/bus/inspector: no route selected"
+msgstr "Ardour: Route: keine Route ausgewählt"
+
+#: gtk_ardour/route_ui.cc:134
+#, fuzzy
+msgid "mute change"
+msgstr "Bereich"
+
+#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220
+#, fuzzy
+msgid "solo change"
+msgstr "Bereich"
+
+#: gtk_ardour/route_ui.cc:284
+msgid "rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:423
+#, fuzzy
+msgid "Solo-safe"
+msgstr "solo"
+
+#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474
+msgid "MIDI Bind"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:445
+msgid "Pre Fader"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:452
+msgid "Post Fader"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:459
+msgid "Control Outs"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:466
+msgid "Main Outs"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:503
+msgid "mix group solo change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:537
+msgid "mix group mute change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:553
+msgid "mix group rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258
+msgid "ardour: color selection"
+msgstr "Ardour: Farbe auswählen"
+
+#: gtk_ardour/route_ui.cc:652
+#, fuzzy
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"You may also lose the playlist used by this track.\n"
+"(cannot be undone)"
+msgstr ""
+"Wollen Sie wirklich die Spur \"%1\" löschen?\n"
+"(Kann nicht rückgängig gemacht werden!)"
+
+#: gtk_ardour/route_ui.cc:654
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299
+msgid "Yes, remove it."
+msgstr "Ja, entfernen."
+
+#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358
+msgid "new name: "
+msgstr "Neuer Name: "
+
+#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31
+msgid "Beats per minute"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35
+#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163
+msgid "Beat"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158
+msgid "Meter denominator"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159
+msgid "Beats per bar"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189
+msgid "whole (1)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191
+msgid "second (2)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193
+msgid "third (3)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195
+#: gtk_ardour/tempo_dialog.cc:203
+msgid "quarter (4)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197
+msgid "eighth (8)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199
+msgid "sixteenth (16)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201
+msgid "thirty-second (32)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:301
+msgid "garbaged note type entry (%1)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:311
+msgid "incomprehensible note type entry (%1)"
+msgstr ""
+
+#: gtk_ardour/time_axis_view.cc:95
+msgid "gTortnam"
+msgstr ""
+
+#: gtk_ardour/time_axis_view.cc:446
+msgid "Largest"
+msgstr ""
+
+#: gtk_ardour/time_axis_view.cc:447
+#, fuzzy
+msgid "Large"
+msgstr "Schicht"
+
+#: gtk_ardour/time_axis_view.cc:448
+#, fuzzy
+msgid "Larger"
+msgstr "Schicht"
+
+#: gtk_ardour/time_axis_view.cc:450
+msgid "Smaller"
+msgstr ""
+
+#: gtk_ardour/time_axis_view.cc:451
+#, fuzzy
+msgid "Small"
+msgstr "Alle zeigen"
+
+#: gtk_ardour/time_axis_view.cc:785
+msgid "unknown track height name \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:69
+msgid "TimeAxisViewItemName"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:258
+msgid "new duration %1 frames is out of bounds for %2"
+msgstr ""
+
+#: gtk_ardour/time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr ""
+
+#: gtk_ardour/utils.cc:57
+msgid ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+msgstr ""
+
+#: gtk_ardour/utils.cc:66
+msgid "aeiou"
+msgstr ""
+
+#: gtk_ardour/utils.cc:75
+msgid "AEIOU"
+msgstr ""
+
+#: gtk_ardour/utils.cc:84
+msgid "bcdfghjklmnpqrtvwxyz"
+msgstr ""
+
+#: gtk_ardour/utils.cc:93
+msgid "BCDFGHJKLMNPQRTVWXYZ"
+msgstr ""
+
+#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265
+msgid "bad XPM header %1"
+msgstr ""
+
+#: gtk_ardour/utils.cc:516
+msgid "missing RGBA style for \"%1\""
+msgstr ""
+
+#: gtk_ardour/visual_time_axis.cc:297
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Wollen Sie wirklich die Spur \"%1\" löschen?\n"
+"(Kann nicht rückgängig gemacht werden!)"
+
+#: gtk_ardour/visual_time_axis.cc:385
+msgid "A track already exists with that name"
+msgstr ""
+
+#, fuzzy
+#~ msgid "Seamless Looping"
+#~ msgstr "Ausgewählten Bereich wiedergeben"
+
+#~ msgid "Export to CD"
+#~ msgstr "Export nach CD"
+
+#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Keine Grafiken für Umschalter-Knöpfe gefunden!\n"
+#~ "(Gesuchter Dateiname: \"toggle-button[0-9]*.xpm$\")"
+
+#~ msgid ""
+#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Keine Grafiken für kleine Schaltknöpfe gefunden!\n"
+#~ "(Gesuchter Dateiname: \"small-round-button[0-9]*.xpm$\")"
+
+#~ msgid "ardour: tempo editor"
+#~ msgstr "Ardour: Tempo bearbeiten"
+
+#, fuzzy
+#~ msgid "ardour_add_track_bus"
+#~ msgstr "Ardour: Editor"
+
+#~ msgid "ok"
+#~ msgstr "OK"
+
+#, fuzzy
+#~ msgid "apply"
+#~ msgstr "Anwenden"
+
+#, fuzzy
+#~ msgid "Edit left"
+#~ msgstr "Bearbeitungs Modus"
+
+#, fuzzy
+#~ msgid "Edit right"
+#~ msgstr "Mix Gruppen"
+
+#, fuzzy
+#~ msgid "Edit fade"
+#~ msgstr "Bearbeitungs Modus"
+
+#, fuzzy
+#~ msgid "Export region"
+#~ msgstr "Name für Region:"
+
+#, fuzzy
+#~ msgid "Bounce region"
+#~ msgstr "Bereich"
+
+#~ msgid "Play selected region"
+#~ msgstr "Wiedergabe der ausgewählten Region"
+
+#~ msgid "clear connections"
+#~ msgstr "Verbindungen löschen"
diff --git a/gtk2_ardour/po/el_GR.po b/gtk2_ardour/po/el_GR.po
new file mode 100644
index 0000000000..f694761af3
--- /dev/null
+++ b/gtk2_ardour/po/el_GR.po
@@ -0,0 +1,5195 @@
+# Σχολιαστικός Τίτλος.
+# Πνευματικά Δικαιώματα (C) YEAR Paul Davis
+# Το παÏόν αÏχείο διανέμεται υπό της ιδίας αδείας με του PACKAGE πακέτου.
+# ΠΡΩΤΟΣ ΔΗΜΙΟΥΡΓΟΣ <muadib@in.gr>, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 0.99beta23\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-09-19 18:09-0400\n"
+"PO-Revision-Date: 2005-01-11\n"
+"Last-Translator: Muadibas <EMAIL@ADDRESS>\n"
+"Language-Team: Hellenic(Greek) <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gtk_ardour/about.cc:134
+msgid "Marcus Andersson"
+msgstr ""
+
+#: gtk_ardour/about.cc:135
+msgid "Jeremy Hall"
+msgstr ""
+
+#: gtk_ardour/about.cc:136
+msgid "Steve Harris"
+msgstr ""
+
+#: gtk_ardour/about.cc:137
+msgid "Tim Mayberry"
+msgstr ""
+
+#: gtk_ardour/about.cc:138
+msgid "Mark Stewart"
+msgstr ""
+
+#: gtk_ardour/about.cc:139
+msgid "Sam Chessman"
+msgstr ""
+
+#: gtk_ardour/about.cc:140
+msgid "Jack O'Quin"
+msgstr ""
+
+#: gtk_ardour/about.cc:141
+msgid "Matt Krai"
+msgstr ""
+
+#: gtk_ardour/about.cc:142
+msgid "Ben Bell"
+msgstr ""
+
+#: gtk_ardour/about.cc:143
+msgid "Gerard van Dongen"
+msgstr ""
+
+#: gtk_ardour/about.cc:144
+msgid "Thomas Charbonnel"
+msgstr ""
+
+#: gtk_ardour/about.cc:145
+msgid "Nick Mainsbridge"
+msgstr ""
+
+#: gtk_ardour/about.cc:146
+msgid "Colin Law"
+msgstr ""
+
+#: gtk_ardour/about.cc:147
+msgid "Sampo Savolainen"
+msgstr ""
+
+#: gtk_ardour/about.cc:148
+msgid "Joshua Leach"
+msgstr ""
+
+#: gtk_ardour/about.cc:149
+msgid "Rob Holland"
+msgstr ""
+
+#: gtk_ardour/about.cc:150
+msgid "Per Sigmond"
+msgstr ""
+
+#: gtk_ardour/about.cc:151
+msgid "Doug Mclain"
+msgstr ""
+
+#: gtk_ardour/about.cc:156
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+msgstr ""
+
+#: gtk_ardour/about.cc:157
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+msgstr ""
+
+#: gtk_ardour/about.cc:158
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+msgstr ""
+
+#: gtk_ardour/about.cc:159
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:160
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:162
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn@fastmail.fm>"
+msgstr ""
+
+#: gtk_ardour/about.cc:163
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop@nm.ru>"
+msgstr ""
+
+#: gtk_ardour/about.cc:181
+#, fuzzy
+msgid ""
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n"
+msgstr ""
+"Πνευματικά Δικαιώματα (C) 1999-2004 Paul Davis\n"
+"Το Ï€ÏόγÏαμμα Ardour διανέμεται δίχως ΑΠΟΛΥΤΩΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ\n"
+"Το παÏόν ειναι δωÏεάν λογισμικό, είστε ευπÏόσδεκτοι να το επαναδιανείμετε \n"
+"υπό ειδικοÏÏ‚ ÏŒÏους; διαβάστε το αÏχείο COPYING για λεπτομέÏειες.\n"
+
+#: gtk_ardour/about.cc:188
+#, fuzzy
+msgid ""
+"Ardour: %1\n"
+"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+msgstr ""
+"Ardour: %1\n"
+"(Κτισμένο με ardour/gtk %2 libardour: %3.%4.%5)"
+
+#: gtk_ardour/about.cc:206
+msgid ""
+"Primary author:\n"
+"\tPaul Davis\n"
+"\n"
+"Major developers:\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributors:\n"
+"\t"
+msgstr ""
+
+#: gtk_ardour/about.cc:243
+msgid "Authors"
+msgstr "ΔημιουÏγοί"
+
+#: gtk_ardour/about.cc:244
+msgid "Translators"
+msgstr "ΜεταφÏαστές"
+
+#: gtk_ardour/about.cc:361
+msgid "cannot open splash image file \"%1\""
+msgstr "Η εισαγωγική εικόνα δεν ανοίγει\"%1\""
+
+#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33
+#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81
+#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977
+#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85
+#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777
+#: gtk_ardour/redirect_box.cc:900
+msgid "OK"
+msgstr "OK"
+
+#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92
+#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046
+#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72
+#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982
+#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733
+#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000
+#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129
+#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785
+#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86
+#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072
+#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33
+#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161
+msgid "Cancel"
+msgstr "ΑκÏÏωση"
+
+#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94
+msgid "Tracks"
+msgstr "Κανάλια"
+
+#: gtk_ardour/add_route_dialog.cc:43
+msgid "Busses"
+msgstr "Δίαυλοι"
+
+#: gtk_ardour/add_route_dialog.cc:48
+msgid "ardour: add track/bus"
+msgstr "ardour: Εισαγωγή καναλιοÏ/διαÏλου"
+
+#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81
+msgid "Add"
+msgstr "ΠÏόσθεση"
+
+#: gtk_ardour/add_route_dialog.cc:86
+msgid "Name (template)"
+msgstr "Όνομα (Ï€Ïοσχέδιο)"
+
+#: gtk_ardour/ardour_ui.cc:798
+msgid ""
+"pre\n"
+"roll"
+msgstr ""
+"pre\n"
+"roll"
+
+#: gtk_ardour/ardour_ui.cc:799
+msgid ""
+"post\n"
+"roll"
+msgstr ""
+"post\n"
+"roll"
+
+#: gtk_ardour/ardour_ui.cc:807
+msgid "% "
+msgstr "% "
+
+#: gtk_ardour/ardour_ui.cc:808
+msgid "spring"
+msgstr "έλασμα"
+
+#: gtk_ardour/ardour_ui.cc:810
+msgid ""
+"punch\n"
+"in"
+msgstr ""
+"punch\n"
+"in"
+
+#: gtk_ardour/ardour_ui.cc:811
+msgid ""
+"punch\n"
+"out"
+msgstr ""
+"punch\n"
+"out"
+
+#: gtk_ardour/ardour_ui.cc:812
+msgid ""
+"auto\n"
+"return"
+msgstr ""
+"αυτόματη\n"
+"επιστÏοφή"
+
+#: gtk_ardour/ardour_ui.cc:813
+msgid ""
+"auto\n"
+"play"
+msgstr ""
+"αυτόματη\n"
+"αναπαÏ/γή"
+
+#: gtk_ardour/ardour_ui.cc:814
+msgid ""
+"auto\n"
+"input"
+msgstr ""
+"αυτόματο\n"
+"input"
+
+#: gtk_ardour/ardour_ui.cc:815
+msgid "click"
+msgstr "μετÏονόμος"
+
+#: gtk_ardour/ardour_ui.cc:816
+msgid ""
+"follow\n"
+"PH"
+msgstr ""
+"ακολουθία\n"
+"ΚεÏσ."
+
+#: gtk_ardour/ardour_ui.cc:817
+msgid "AUDITIONING"
+msgstr "ΑΚΡΟΑΣΗ"
+
+#: gtk_ardour/ardour_ui.cc:818
+msgid "SOLO"
+msgstr "ΣΟΛΟ"
+
+#: gtk_ardour/ardour_ui.cc:870
+msgid "Percentage"
+msgstr "Ποσοστό"
+
+#: gtk_ardour/ardour_ui.cc:872
+msgid "Semitones"
+msgstr "Ημιτόνια"
+
+#: gtk_ardour/ardour_ui.cc:875
+msgid "Sprung"
+msgstr "Έλασμα"
+
+#: gtk_ardour/ardour_ui.cc:877
+msgid "Wheel"
+msgstr "ΤÏοχός"
+
+#: gtk_ardour/ardour_ui.cc:902
+msgid ""
+"You cannot record-enable\n"
+"track %1\n"
+"because it has no input connections.\n"
+"You would be wasting space recording silence."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1073
+msgid "quit"
+msgstr "Έξοδος"
+
+#: gtk_ardour/ardour_ui.cc:1082
+msgid ""
+"Ardour was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1107
+msgid "Save and %1"
+msgstr "Αποθήκευση και %1"
+
+#: gtk_ardour/ardour_ui.cc:1112
+msgid "Just %1"
+msgstr "Απλά %1"
+
+#: gtk_ardour/ardour_ui.cc:1117
+msgid "Don't %1"
+msgstr "Μη %1"
+
+#: gtk_ardour/ardour_ui.cc:1126
+#, fuzzy
+msgid "session"
+msgstr "ΣυνεδÏία"
+
+#: gtk_ardour/ardour_ui.cc:1128
+#, fuzzy
+msgid "snapshot"
+msgstr "Στιγμιότυπο"
+
+#: gtk_ardour/ardour_ui.cc:1130
+#, fuzzy
+msgid ""
+"The %1\n"
+"\"%2\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
+msgstr ""
+"Το Ï„ÏαγοÏδι \"%1\"\n"
+"δεν έχει αποθηκευθεί.\n"
+"\n"
+"Εάν δεν το αποθήκευσετε\n"
+"οι αλλαγές που κάνατε θα χαθοÏν.\n"
+"\n"
+"τί θέλετε να κάνετε;"
+
+#: gtk_ardour/ardour_ui.cc:1151
+msgid "Prompter"
+msgstr "Υποβολέας"
+
+#: gtk_ardour/ardour_ui.cc:1152
+msgid "ardour: save session?"
+msgstr "ardour: αποθήκευση συνεδÏίας;"
+
+#: gtk_ardour/ardour_ui.cc:1219
+#, fuzzy, c-format
+msgid "disconnected"
+msgstr "ΑποσÏνδεση"
+
+#: gtk_ardour/ardour_ui.cc:1226
+#, fuzzy, c-format
+msgid "SR: %.1f kHz / %4.1f msecs"
+msgstr "SR: %.1f kHz"
+
+#: gtk_ardour/ardour_ui.cc:1230
+#, c-format
+msgid "SR: %u kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1243
+#, c-format
+msgid "DSP Load: %.1f%%"
+msgstr "ΦοÏτίο DSP: %.1f%%"
+
+#: gtk_ardour/ardour_ui.cc:1253
+#, c-format
+msgid "Disk r:%5.1f w:%5.1f MB/s"
+msgstr "Δίσκοι r:%5.1f w:%5.1f MB/s"
+
+#: gtk_ardour/ardour_ui.cc:1267
+#, fuzzy, c-format
+msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
+msgstr "Buffers p:%5.0f%% c:%5.0f%%"
+
+#: gtk_ardour/ardour_ui.cc:1294
+msgid "space: 24hrs+"
+msgstr "χώÏος : 24hrs+"
+
+#: gtk_ardour/ardour_ui.cc:1324
+#, c-format
+msgid "space: %02dh:%02dm:%02ds"
+msgstr "χώÏος: %02dh:%02dm:%02ds"
+
+#: gtk_ardour/ardour_ui.cc:1575
+msgid "programming error: impossible control method"
+msgstr "Σφάλμα Ï€ÏογÏαμματισμοÏ: Μη-πιθανή μέθοδος ελέγχου"
+
+#: gtk_ardour/ardour_ui.cc:1800
+msgid "cancel"
+msgstr "ΑκÏÏωση"
+
+#: gtk_ardour/ardour_ui.cc:1801
+msgid "rescan"
+msgstr "Επανα-ανίχνευση"
+
+#: gtk_ardour/ardour_ui.cc:1842
+msgid "open session"
+msgstr "Άνοιγμα συνεδÏίας"
+
+#: gtk_ardour/ardour_ui.cc:1897
+msgid "Patience is a virtue.\n"
+msgstr "Η Υπομονή ειναι ΧÏυσός.\n"
+
+#: gtk_ardour/ardour_ui.cc:1906
+msgid "You cannot add a track without a session already loaded."
+msgstr "Δεν γίνεται να Ï€Ïοστεθεί κανάλι χωÏίς ήδη φοÏτωμένη συνεδÏία."
+
+#: gtk_ardour/ardour_ui.cc:1913
+msgid "could not create new audio track"
+msgstr "Δεν γίνεται να δημιουÏγηθεί νέο ηχητικό κανάλι"
+
+#: gtk_ardour/ardour_ui.cc:1917
+msgid "could not create new audio bus"
+msgstr "Δεν γίνεται να δημιουÏγηθεί νέος ηχητικός δίαυλος"
+
+#: gtk_ardour/ardour_ui.cc:1936
+msgid ""
+"There are insufficient JACK ports available\n"
+"to create a new track or bus.\n"
+"You should save Ardour, exit and\n"
+"restart JACK with more ports."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2071
+msgid ""
+"Please create 1 or more track\n"
+"before trying to record.\n"
+"Check the Session menu."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2312
+#, fuzzy
+msgid ""
+"JACK has either been shutdown or it\n"
+"disconnected Ardour because Ardour\n"
+"was not fast enough. You can save the\n"
+"session and/or try to reconnect to JACK ."
+msgstr ""
+"Ή ο JACK απενεÏγοποιήθηκε ή αυτός\n"
+"αποσÏνδεσε το Ardour διότι το Ardour\n"
+"δεν ήταν αÏκετά γÏήγοÏο. ΚαλÏτεÏα να αποθηκεÏσετε τη\n"
+"συνεδÏία και να επανακινήσετε και τον JACK και το Ardour."
+
+#: gtk_ardour/ardour_ui.cc:2328
+msgid "Unable to create all required ports"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2336
+#, fuzzy
+msgid "Unable to start the session running"
+msgstr "ΑÏχή της συνεδÏίας"
+
+#: gtk_ardour/ardour_ui.cc:2472
+msgid "No Stream"
+msgstr "Δεν υπάÏχει Ïοή(No stream)"
+
+#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518
+msgid "none"
+msgstr "Κανένα"
+
+#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527
+#: gtk_ardour/automation_time_axis.cc:189
+#: gtk_ardour/automation_time_axis.cc:218
+#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211
+#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947
+#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659
+msgid "off"
+msgstr "εκτός"
+
+#: gtk_ardour/ardour_ui.cc:2548
+msgid "Name for snapshot"
+msgstr "Όνομα για στιγμιότυπο"
+
+#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294
+msgid "Name for mix template:"
+msgstr "Όνομα για Ï€Ïοσχεδίο μίξεως:"
+
+#: gtk_ardour/ardour_ui.cc:2717
+msgid "-template"
+msgstr "-Ï€Ïοσχέδιο"
+
+#: gtk_ardour/ardour_ui.cc:2760
+msgid "Session %1 already exists at %2"
+msgstr "Η ΣυνεδÏία %1 υπάÏχει ήδη στο %2"
+
+#: gtk_ardour/ardour_ui.cc:2832
+msgid ""
+"You do not have write access to this session.\n"
+"This prevents the session from being loaded."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "Η ΣυνεδÏία \"%1 (στιγμιότυπο %2)\" δεν φοÏτώθηκε επιτυχώς"
+
+#: gtk_ardour/ardour_ui.cc:2966
+msgid ""
+"No audio files were ready for cleanup\n"
+"\n"
+"If this seems suprising, check for any existing\n"
+"snapshots. These may still include regions that\n"
+"require some unused files to continue to exist."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001
+msgid "files"
+msgstr "αÏχεία"
+
+#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003
+msgid "file"
+msgstr "αÏχείο"
+
+#: gtk_ardour/ardour_ui.cc:3026
+msgid "ardour: cleanup"
+msgstr "ardour: εκκαθάÏιση"
+
+#: gtk_ardour/ardour_ui.cc:3040
+msgid ""
+"Cleanup is a destructive operation.\n"
+"ALL undo/redo information will be lost if you cleanup.\n"
+"Unused audio files will be moved to a \"dead sounds\" location."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3045
+msgid "Proceed with cleanup"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3061
+#, fuzzy
+msgid "CleanupDialog"
+msgstr "ΕκκαθάÏιση"
+
+#: gtk_ardour/ardour_ui.cc:3062
+#, fuzzy
+msgid "ardour cleanup"
+msgstr "ardour: εκκαθάÏιση"
+
+#: gtk_ardour/ardour_ui.cc:3063
+#, fuzzy
+msgid "ardour_cleanup"
+msgstr "ardour: εκκαθάÏιση"
+
+#: gtk_ardour/ardour_ui.cc:3086
+msgid "cleaned files"
+msgstr "καθαÏισμένα αÏχεία"
+
+#: gtk_ardour/ardour_ui.cc:3087
+msgid ""
+"The following %1 %2 were not in use.\n"
+"The next time you flush the wastebasket\n"
+"it will release an additional %3 %4bytes\n"
+"of disk space"
+msgstr ""
+"Τα ακόλουθα %1 %2 δεν χÏησιμοποιοÏνταν.\n"
+"Την επόμενη φοÏά που θα αδειάσετε τον κάδο\n"
+"θα ελευθεÏωθοÏν %3 %4bytes\n"
+"χώÏου στο δίσκο"
+
+#: gtk_ardour/ardour_ui.cc:3110
+msgid "deleted file"
+msgstr "διαγÏαμμένα αÏχεία"
+
+#: gtk_ardour/ardour_ui.cc:3111
+msgid ""
+"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"
+msgstr ""
+"Τα ακόλουθα %1 file%2 διεγÏάφησαν, ελευθεÏώνοντας %3 %4bytes χώÏου στο δίσκο"
+
+#: gtk_ardour/ardour_ui.cc:3226
+msgid "Recording was stopped because your system could not keep up."
+msgstr "η ΕγγÏαφή διεκόπη διότι το σÏστημά δεν μποÏοÏσε να ανταπεξέλθει."
+
+#: gtk_ardour/ardour_ui.cc:3248
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3266
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3291
+msgid "Recover from crash"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3292
+msgid "Ignore crash data"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3293
+msgid ""
+"This session appears to have been in\n"
+"middle of recording when ardour or\n"
+"the computer was shutdown.\n"
+"\n"
+"Ardour can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3338
+#, fuzzy
+msgid "Could not disconnect from JACK"
+msgstr "Δεν γινόταν να συνδεθώ στον JACK server σαν \"%1\""
+
+#: gtk_ardour/ardour_ui.cc:3351
+#, fuzzy
+msgid "Could not reconnect to JACK"
+msgstr "Δεν γινόταν να συνδεθώ στον JACK server σαν \"%1\""
+
+#: gtk_ardour/ardour_ui2.cc:60
+msgid "UI: cannot setup editor"
+msgstr "UI: Ο 'editor' δεν μποÏεί να εγεÏθεί"
+
+#: gtk_ardour/ardour_ui2.cc:65
+msgid "UI: cannot setup mixer"
+msgstr "UI: ο μίκτης δεν μποÏεί να εγεÏθεί"
+
+#: gtk_ardour/ardour_ui2.cc:70
+msgid "UI: cannot setup meter_bridge"
+msgstr "UI: η γέφυÏα μετÏήσεων δεν μποÏεί να εγεÏθεί"
+
+#: gtk_ardour/ardour_ui2.cc:98
+msgid "MMC + Local"
+msgstr "MMC + Τοπικό"
+
+#: gtk_ardour/ardour_ui2.cc:99
+msgid "MMC"
+msgstr "MMC"
+
+#: gtk_ardour/ardour_ui2.cc:100
+msgid "Local"
+msgstr "Τοπικό"
+
+#: gtk_ardour/ardour_ui2.cc:117
+msgid "MMC ID"
+msgstr "MMC ID"
+
+#: gtk_ardour/ardour_ui2.cc:215
+msgid "Play from playhead"
+msgstr "ΑναπαÏ/γή από τον ΑναπαÏαγωγέα"
+
+#: gtk_ardour/ardour_ui2.cc:216
+msgid "Stop playback"
+msgstr "Διακοπή ΑναπαÏ/γής"
+
+#: gtk_ardour/ardour_ui2.cc:217
+msgid "Play range/selection"
+msgstr "ΑναπαÏ/γή διαστήματος/επιλογής"
+
+#: gtk_ardour/ardour_ui2.cc:218
+msgid "Go to start of session"
+msgstr "ΑÏχή της συνεδÏίας"
+
+#: gtk_ardour/ardour_ui2.cc:219
+msgid "Go to end of session"
+msgstr "Τέλος του συνεδÏίας"
+
+#: gtk_ardour/ardour_ui2.cc:220
+msgid "Play loop range"
+msgstr "Επαναληπτική αναπαÏ/γή διαστήματος"
+
+#: gtk_ardour/ardour_ui2.cc:221
+msgid "Return to last playback start when stopped"
+msgstr "ΕπιστÏοφή στην τελευταία θεση μετα απο παÏση"
+
+#: gtk_ardour/ardour_ui2.cc:222
+msgid "Start playback after any locate"
+msgstr "ΑÏχή αναπαÏ/γής μετά από κάθε τοποθέτηση"
+
+#: gtk_ardour/ardour_ui2.cc:223
+msgid "Be sensible about input monitoring"
+msgstr "ΠÏοσοχή στο input monitoring"
+
+#: gtk_ardour/ardour_ui2.cc:224
+msgid "Start recording at auto-punch start"
+msgstr "ΈναÏξη εγγÏαφής στην αÏχή αυτο-εναπόθεσης"
+
+#: gtk_ardour/ardour_ui2.cc:225
+msgid "Stop recording at auto-punch end"
+msgstr "Λήξη εγγÏαφής στο τέλος αυτο-εναπόθεσης"
+
+#: gtk_ardour/ardour_ui2.cc:226
+msgid "Enable/Disable audio click"
+msgstr "ΆÏση/ΠαÏση μετÏονόμου"
+
+#: gtk_ardour/ardour_ui2.cc:227
+msgid "Enable/Disable follow playhead"
+msgstr "ΆÏση/ΠαÏση ακολουθίας αναπαÏαγωγέα"
+
+#: gtk_ardour/ardour_ui2.cc:228
+msgid "Shuttle speed control"
+msgstr "Έλεγχος ταχÏτητας Shuttle"
+
+#: gtk_ardour/ardour_ui2.cc:229
+#, fuzzy, c-format
+msgid "Select semitones or %%-age for speed display"
+msgstr "Επιλογή ημιτονίων ή %- για απεικόνιση ταχÏτητος"
+
+#: gtk_ardour/ardour_ui2.cc:230
+msgid "Select sprung or wheel behaviour"
+msgstr "Επιλογή συμπεÏιφοÏάς ελάσματος ή Ï„ÏοχοÏ"
+
+#: gtk_ardour/ardour_ui2.cc:231
+msgid "Current transport speed"
+msgstr "ΤÏέχουσα ταχÏτητα μεταφοÏάς"
+
+#: gtk_ardour/ardour_ui2.cc:312
+msgid "Primary clock"
+msgstr "ΠÏωτεÏον ωÏολόγιον"
+
+#: gtk_ardour/ardour_ui2.cc:313
+msgid "secondary clock"
+msgstr "ΔευτεÏέυον ωÏολόγιον"
+
+#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751
+#: gtk_ardour/ardour_ui2.cc:770
+msgid "stopped"
+msgstr "παÏση"
+
+#: gtk_ardour/ardour_ui2.cc:431
+msgid "ardour: clock"
+msgstr "ardour: ΩÏολόγιον"
+
+#: gtk_ardour/ardour_ui2.cc:721
+msgid "st"
+msgstr "st"
+
+#: gtk_ardour/ardour_ui2.cc:731
+msgid "sprung"
+msgstr "έλασμα"
+
+#: gtk_ardour/ardour_ui2.cc:742
+msgid "wheel"
+msgstr "Ï„Ïοχός"
+
+#: gtk_ardour/ardour_ui_dependents.cc:74
+msgid "keyboard_target: error setting binding state: invalid node"
+msgstr ""
+"keyboard_target: σφάλμα στη θέση καταστάσεως Î´ÎµÏƒÎ¼Î¿Ï Ï€Î»Î®ÎºÏ„Ïων: ανÏπαÏκτος "
+"κόμβος"
+
+#: gtk_ardour/ardour_ui_dialogs.cc:158
+msgid "close session"
+msgstr "κλείσιμο συνεδÏίας"
+
+#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895
+msgid "New"
+msgstr "Îέο"
+
+#: gtk_ardour/ardour_ui_ed.cc:76
+msgid "Open"
+msgstr "Άνοιγμα"
+
+#: gtk_ardour/ardour_ui_ed.cc:77
+msgid "Recent"
+msgstr "ΠÏόσφατο"
+
+#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+msgid "Close"
+msgstr "Κλείσιμο"
+
+#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488
+msgid "Add Track/Bus"
+msgstr "ΠÏόσθεση καναλιοÏ/διαÏλου"
+
+#: gtk_ardour/ardour_ui_ed.cc:99
+msgid "Connect"
+msgstr "ΣÏνδεση"
+
+#: gtk_ardour/ardour_ui_ed.cc:100
+msgid "Image Compositor"
+msgstr "ΣÏνθεση εικόνων"
+
+#: gtk_ardour/ardour_ui_ed.cc:114
+msgid "Save"
+msgstr "Αποθήκευση"
+
+#: gtk_ardour/ardour_ui_ed.cc:118
+msgid "Snapshot"
+msgstr "Στιγμιότυπο"
+
+#: gtk_ardour/ardour_ui_ed.cc:126
+msgid "Save Template..."
+msgstr "Αποθήκευση Ï€Ïοσχεδίου..."
+
+#: gtk_ardour/ardour_ui_ed.cc:133
+msgid "Export session to audiofile..."
+msgstr "Εξαγωγή συνεδÏίας σε αÏχείο..."
+
+#: gtk_ardour/ardour_ui_ed.cc:134
+msgid "Export range to audiofile..."
+msgstr "Εξαγωγή διαστήματος σε αÏχείο..."
+
+#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312
+#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118
+#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227
+msgid "Export"
+msgstr "Εξαγωγή"
+
+#: gtk_ardour/ardour_ui_ed.cc:146
+msgid "Cleanup unused sources"
+msgstr "ΕκκαθάÏιση αχÏήστων πηγών"
+
+#: gtk_ardour/ardour_ui_ed.cc:147
+msgid "Flush wastebasket"
+msgstr "Άδειασμα κάδου"
+
+#: gtk_ardour/ardour_ui_ed.cc:149
+msgid "Cleanup"
+msgstr "ΕκκαθάÏιση"
+
+#: gtk_ardour/ardour_ui_ed.cc:154
+msgid "Quit"
+msgstr "Έξοδος"
+
+#: gtk_ardour/ardour_ui_ed.cc:156
+msgid "Session"
+msgstr "ΣυνεδÏία"
+
+#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287
+#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499
+#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570
+#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412
+msgid "Edit"
+msgstr "ΕπεξεÏγασία"
+
+#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572
+#: gtk_ardour/mixer_strip.cc:631
+msgid "Disconnect"
+msgstr "ΑποσÏνδεση"
+
+#: gtk_ardour/ardour_ui_ed.cc:174
+#, fuzzy
+msgid "Reconnect"
+msgstr "ΣÏνδεση"
+
+#: gtk_ardour/ardour_ui_ed.cc:192
+msgid "Latency"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:195
+msgid "JACK"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:205
+msgid "Editor"
+msgstr "ΕπεξεÏγαστής"
+
+#: gtk_ardour/ardour_ui_ed.cc:206
+msgid "Mixer"
+msgstr "Μίκτης"
+
+#: gtk_ardour/ardour_ui_ed.cc:212
+msgid "Options Editor"
+msgstr "Επεξ/στης Ρυθμίσεων"
+
+#: gtk_ardour/ardour_ui_ed.cc:219
+msgid "Audio Library"
+msgstr "Ηχητική βιβλιοθήκη"
+
+#: gtk_ardour/ardour_ui_ed.cc:225
+#, fuzzy
+msgid "Track/Bus Inspector"
+msgstr "κανάλια/δίαυλοι"
+
+#: gtk_ardour/ardour_ui_ed.cc:232
+msgid "Connections"
+msgstr "Συνδέσεις"
+
+#: gtk_ardour/ardour_ui_ed.cc:240
+msgid "Meter Bridge"
+msgstr "ΓέφυÏα μετÏητή"
+
+#: gtk_ardour/ardour_ui_ed.cc:248
+msgid "Locations"
+msgstr "Τοποθεσίες"
+
+#: gtk_ardour/ardour_ui_ed.cc:255
+msgid "Big Clock"
+msgstr "Μεγάλο ωÏολόγιον"
+
+#: gtk_ardour/ardour_ui_ed.cc:261
+msgid "About"
+msgstr "ΠληÏοφοÏίες"
+
+#: gtk_ardour/ardour_ui_ed.cc:264
+msgid "Windows"
+msgstr "ΠαÏάθυÏα"
+
+#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203
+msgid "SMPTE"
+msgstr "SMPTE"
+
+#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202
+#: gtk_ardour/editor_rulers.cc:359
+msgid "Bars:Beats"
+msgstr "ΜπάÏες:ΚτÏποι"
+
+#: gtk_ardour/audio_clock.cc:1642
+msgid "Minutes:Seconds"
+msgstr "Λεπτά:ΔεÏτεÏα"
+
+#: gtk_ardour/audio_clock.cc:1643
+msgid "Audio Frames"
+msgstr "Ηχητικά frames"
+
+#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356
+#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713
+#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774
+#: gtk_ardour/option_editor.cc:794
+msgid "Off"
+msgstr "Εκτός"
+
+#: gtk_ardour/audio_clock.cc:1646
+msgid "Mode"
+msgstr "ΛειτουÏγία"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523
+msgid "m"
+msgstr "m"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524
+msgid "s"
+msgstr "s"
+
+#: gtk_ardour/audio_time_axis.cc:104
+msgid "r"
+msgstr "r"
+
+#: gtk_ardour/audio_time_axis.cc:108
+msgid "g"
+msgstr "g"
+
+#: gtk_ardour/audio_time_axis.cc:109
+msgid "p"
+msgstr "p"
+
+#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44
+#: gtk_ardour/visual_time_axis.cc:90
+msgid "h"
+msgstr "h"
+
+#: gtk_ardour/audio_time_axis.cc:111
+msgid "a"
+msgstr "a"
+
+#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89
+msgid "v"
+msgstr "v"
+
+#: gtk_ardour/audio_time_axis.cc:185
+msgid "Record"
+msgstr "ΕγγÏαφή"
+
+#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191
+msgid "Solo"
+msgstr "Σόλο"
+
+#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236
+#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433
+msgid "Mute"
+msgstr "Σιγή"
+
+#: gtk_ardour/audio_time_axis.cc:188
+msgid "Edit Group"
+msgstr "ΔιαμόÏφωση Ομάδας"
+
+#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110
+msgid "Display Height"
+msgstr "Απεικόνιση Ïψους"
+
+#: gtk_ardour/audio_time_axis.cc:190
+msgid "Playlist"
+msgstr "Playlist"
+
+#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752
+msgid "Automation"
+msgstr "Αυτοματισμός"
+
+#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111
+msgid "Visual options"
+msgstr "Επιλογές Εμφανίσεως"
+
+#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112
+msgid "Hide this track"
+msgstr "ΑπόκÏυψη παÏόντος καναλιοÏ"
+
+#: gtk_ardour/audio_time_axis.cc:349
+msgid "No group"
+msgstr "ΧωÏίς ομάδα"
+
+#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447
+#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229
+msgid "Height"
+msgstr "Ύψος"
+
+#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266
+#: gtk_ardour/marker_time_axis.cc:230
+msgid "Color"
+msgstr "ΧÏώμα"
+
+#: gtk_ardour/audio_time_axis.cc:720
+msgid "Hide all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:721
+msgid "Show all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:729
+msgid "show all automation"
+msgstr "Ανάδειξη όλων των αυτοματισμών"
+
+#: gtk_ardour/audio_time_axis.cc:732
+msgid "show existing automation"
+msgstr "Ανάδειξη υπαÏχόντων αυτοματισμών"
+
+#: gtk_ardour/audio_time_axis.cc:735
+msgid "hide all automation"
+msgstr "ΚÏÏψιμο όλων των αυτοματισμών"
+
+#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204
+#: gtk_ardour/editor.cc:234
+msgid "gain"
+msgstr "gain"
+
+#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244
+msgid "pan"
+msgstr "pan"
+
+#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388
+msgid "Plugins"
+msgstr "Plugins"
+
+#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95
+msgid "Show waveforms"
+msgstr "Ανάδειξη κυματομοÏφών"
+
+#: gtk_ardour/audio_time_axis.cc:766
+msgid "Traditional"
+msgstr "ΠαÏαδοσιακή"
+
+#: gtk_ardour/audio_time_axis.cc:769
+msgid "Rectified"
+msgstr "ΑνοÏθωμένή"
+
+#: gtk_ardour/audio_time_axis.cc:772
+msgid "Waveform"
+msgstr "ΚυματομοÏφή"
+
+#: gtk_ardour/audio_time_axis.cc:782
+#, fuzzy
+msgid "align with existing material"
+msgstr "ΥπάÏχον υλικό"
+
+#: gtk_ardour/audio_time_axis.cc:787
+#, fuzzy
+msgid "align with capture time"
+msgstr "ΧÏόνος Λήψεως"
+
+#: gtk_ardour/audio_time_axis.cc:793
+#, fuzzy
+msgid "Alignment"
+msgstr "ΕυθυγÏάμμιση"
+
+#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288
+msgid "Active"
+msgstr "ΕνεÏγό"
+
+#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386
+#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467
+#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269
+#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233
+#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83
+msgid "Remove"
+msgstr "Απαλοιφή"
+
+#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880
+#: gtk_ardour/audio_time_axis.cc:911
+msgid "Name for playlist"
+msgstr "Όνομα για playlist"
+
+#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433
+msgid "a track already exists with that name"
+msgstr "Κανάλι με αυτό το όνομα ήδη υπάÏχει"
+
+#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001
+#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539
+msgid "programming error: "
+msgstr "σφάλμα Ï€ÏογÏαμματισμοÏ: "
+
+#: gtk_ardour/audio_time_axis.cc:1889
+msgid "Current: %1"
+msgstr "ΤÏέχον: %1"
+
+#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452
+#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226
+#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377
+msgid "Rename"
+msgstr "Μετονομασία"
+
+#: gtk_ardour/audio_time_axis.cc:1896
+msgid "New Copy"
+msgstr "Îέο αντίγÏαφο"
+
+#: gtk_ardour/audio_time_axis.cc:1898
+msgid "Clear Current"
+msgstr "ΕκκαθάÏιση Ï„Ïέχοντος"
+
+#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472
+#: gtk_ardour/editor.cc:2557
+msgid "Select"
+msgstr "Επιλογή"
+
+#: gtk_ardour/automation_line.cc:904
+msgid "automation event move"
+msgstr "μετακίνηση συμβάντος αυτοματισμοÏ"
+
+#: gtk_ardour/automation_line.cc:906
+msgid "automation range drag"
+msgstr "έλξη διαστήματος αυτοματισμοÏ"
+
+#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64
+msgid "remove control point"
+msgstr "απαλοιφή σημείου ελέγχου"
+
+#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010
+msgid "clear"
+msgstr "εκκαθάÏιση"
+
+#: gtk_ardour/automation_time_axis.cc:80
+msgid "track height"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:81
+#, fuzzy
+msgid "automation state"
+msgstr "Κατάσταση Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï pan"
+
+#: gtk_ardour/automation_time_axis.cc:82
+#, fuzzy
+msgid "clear track"
+msgstr "διαγÏαφή διαστημάτων"
+
+#: gtk_ardour/automation_time_axis.cc:83
+#, fuzzy
+msgid "hide track"
+msgstr "νÏξη καναλιοÏ"
+
+#: gtk_ardour/automation_time_axis.cc:191
+#: gtk_ardour/automation_time_axis.cc:229
+#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213
+#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419
+#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50
+msgid "play"
+msgstr "αναπαÏαγωγή"
+
+#: gtk_ardour/automation_time_axis.cc:193
+#: gtk_ardour/automation_time_axis.cc:240
+#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215
+#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422
+#: gtk_ardour/plugin_ui.cc:663
+msgid "write"
+msgstr "εγγÏαφή"
+
+#: gtk_ardour/automation_time_axis.cc:195
+#: gtk_ardour/automation_time_axis.cc:251
+#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217
+#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953
+#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665
+msgid "touch"
+msgstr "άγγιγμα"
+
+#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274
+#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428
+msgid "???"
+msgstr "???"
+
+#: gtk_ardour/automation_time_axis.cc:276
+msgid "clear automation"
+msgstr "εκκαθάÏιση αυτοματισμοÏ"
+
+#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453
+#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398
+msgid "Hide"
+msgstr "ΚÏÏψιμο"
+
+#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52
+#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364
+msgid "Clear"
+msgstr "ΕκκαθάÏιση"
+
+#: gtk_ardour/automation_time_axis.cc:474
+#, fuzzy
+msgid "State"
+msgstr "ΑÏχή:"
+
+#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49
+msgid "Input Connections"
+msgstr "Συνδέσεις Εισόδου"
+
+#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48
+msgid "Output Connections"
+msgstr "Συνδέσεις Εξόδου"
+
+#: gtk_ardour/connection_editor.cc:49
+#, fuzzy
+msgid "New Input"
+msgstr "νέα είσοδος"
+
+#: gtk_ardour/connection_editor.cc:50
+#, fuzzy
+msgid "New Output"
+msgstr "νέα έξοδος"
+
+#: gtk_ardour/connection_editor.cc:51
+#, fuzzy
+msgid "Delete"
+msgstr "διαγÏαφή"
+
+#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96
+#, fuzzy
+msgid "Add Port"
+msgstr "Ï€Ïόσθεση θÏÏας"
+
+#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105
+#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786
+#, fuzzy
+msgid "Rescan"
+msgstr "Επανα-ανίχνευση"
+
+#: gtk_ardour/connection_editor.cc:101
+msgid "Available Ports"
+msgstr "Διαθέσιμες ΘÏÏες"
+
+#: gtk_ardour/connection_editor.cc:183
+msgid "ardour: connections"
+msgstr "ardour: συνδέσεις"
+
+#: gtk_ardour/connection_editor.cc:513
+#, c-format
+msgid "in %d"
+msgstr "σε %d"
+
+#: gtk_ardour/connection_editor.cc:644
+msgid "Name for new connection:"
+msgstr "Όνομα για νέα σÏνδεση:"
+
+#: gtk_ardour/crossfade_edit.cc:71
+#, fuzzy
+msgid "crossfade editor"
+msgstr "επεξεÏ/σία fade in"
+
+#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449
+#, fuzzy
+msgid "Reset"
+msgstr "reset"
+
+#: gtk_ardour/crossfade_edit.cc:78
+#, fuzzy
+msgid "Fade"
+msgstr "Fades"
+
+#: gtk_ardour/crossfade_edit.cc:79
+#, fuzzy
+msgid "Out (dry)"
+msgstr "out (dry)"
+
+#: gtk_ardour/crossfade_edit.cc:80
+#, fuzzy
+msgid "Out"
+msgstr "Έξοδοι"
+
+#: gtk_ardour/crossfade_edit.cc:81
+#, fuzzy
+msgid "In (dry)"
+msgstr "in (dry)"
+
+#: gtk_ardour/crossfade_edit.cc:82
+msgid "In"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:84
+#, fuzzy
+msgid "With Pre-roll"
+msgstr "με pre-roll"
+
+#: gtk_ardour/crossfade_edit.cc:85
+#, fuzzy
+msgid "With Post-roll"
+msgstr "με post-roll"
+
+#: gtk_ardour/crossfade_edit.cc:93
+msgid "Fade In"
+msgstr "Fade In"
+
+#: gtk_ardour/crossfade_edit.cc:94
+msgid "Fade Out"
+msgstr "Fade Out"
+
+#: gtk_ardour/crossfade_edit.cc:98
+msgid "ardour: x-fade edit"
+msgstr "ardour: επεξεÏγασία x-fade"
+
+#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311
+#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189
+msgid "Audition"
+msgstr "ΑκÏόαση"
+
+#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804
+msgid "Regions/name"
+msgstr "ΠεÏιοχες/όνομα"
+
+#: gtk_ardour/editor.cc:108
+msgid "Chunks"
+msgstr "Κομμάτια"
+
+#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079
+msgid "Slide"
+msgstr "Ολίσθηση"
+
+#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077
+msgid "Splice"
+msgstr "Splice"
+
+#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136
+#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96
+#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977
+msgid "None"
+msgstr "Ουδέν"
+
+#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124
+#, fuzzy
+msgid "CD Frames"
+msgstr "Frames"
+
+#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126
+msgid "SMPTE Frames"
+msgstr "SMPTE Frames"
+
+#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128
+msgid "SMPTE Seconds"
+msgstr "SMPTE ΔευτεÏόλεπτα"
+
+#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130
+msgid "SMPTE Minutes"
+msgstr "SMPTE Λεπτά"
+
+#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132
+msgid "Seconds"
+msgstr "ΔευτεÏόλεπτα"
+
+#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134
+msgid "Minutes"
+msgstr "Λεπτά"
+
+#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106
+msgid "Beats/32"
+msgstr "ΚτÏποι/32"
+
+#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104
+msgid "Beats/16"
+msgstr "ΚτÏποι/16"
+
+#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102
+msgid "Beats/8"
+msgstr "ΚτÏποι/8"
+
+#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100
+msgid "Beats/4"
+msgstr "ΚτÏποι/4"
+
+#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098
+msgid "Beats/3"
+msgstr "ΚτÏποι/3"
+
+#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108
+msgid "Beats"
+msgstr "ΚτÏποι"
+
+#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110
+msgid "Bars"
+msgstr "ΜπάÏες"
+
+#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112
+msgid "Marks"
+msgstr "Στίγματα"
+
+#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114
+#: gtk_ardour/editor.cc:4182
+msgid "Edit Cursor"
+msgstr "ΚέÏσοÏας επεξεÏγασίας"
+
+#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116
+msgid "Region starts"
+msgstr "ΑÏχές ΠεÏιοχών"
+
+#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118
+msgid "Region ends"
+msgstr "Τέλη ΠεÏιοχών"
+
+#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122
+msgid "Region syncs"
+msgstr "ΣυγχÏονισμός ΠεÏιοχών"
+
+#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120
+msgid "Region bounds"
+msgstr "ÎŒÏια πεÏιοχών"
+
+#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153
+#: gtk_ardour/time_axis_view.cc:449
+msgid "Normal"
+msgstr "Κανονικό"
+
+#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155
+msgid "Magnetic"
+msgstr "Μαγνητικό"
+
+#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174
+#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237
+msgid "Left"
+msgstr "ΑÏιστεÏÏŒ"
+
+#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176
+#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238
+msgid "Right"
+msgstr "Δεξιό"
+
+#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178
+msgid "Center"
+msgstr "ΚέντÏο"
+
+#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180
+msgid "Playhead"
+msgstr "ΑναπαÏαγωγέας"
+
+#: gtk_ardour/editor.cc:201
+msgid "Mins:Secs"
+msgstr "Λεπτά:ΔέυτεÏα"
+
+#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353
+msgid "Frames"
+msgstr "Frames"
+
+#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373
+msgid "Tempo"
+msgstr "ΧÏόνος"
+
+#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367
+msgid "Meter"
+msgstr "ΜετÏητής"
+
+#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379
+msgid "Location Markers"
+msgstr "Στίγματα Τοποθεσίας"
+
+#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385
+msgid "Range Markers"
+msgstr "Στίγματα διαστημάτων"
+
+#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391
+msgid "Loop/Punch Ranges"
+msgstr "Διαστήματα Loop/Punch"
+
+#: gtk_ardour/editor.cc:221
+msgid ""
+"editor\n"
+"mixer"
+msgstr ""
+"Μίκτης\n"
+"ΕπεξεÏγαστή"
+
+#: gtk_ardour/editor.cc:232
+msgid "range"
+msgstr "διάστημα"
+
+#: gtk_ardour/editor.cc:233
+msgid "object"
+msgstr "αντικείμενο"
+
+#: gtk_ardour/editor.cc:235
+msgid "zoom"
+msgstr "zoom"
+
+#: gtk_ardour/editor.cc:236
+msgid "timefx"
+msgstr "timefx"
+
+#: gtk_ardour/editor.cc:237
+#, fuzzy
+msgid "listen"
+msgstr "link"
+
+#: gtk_ardour/editor.cc:239
+msgid "mode"
+msgstr "λειτουÏγία"
+
+#: gtk_ardour/editor.cc:240
+msgid "automation"
+msgstr "αυτοματισμός"
+
+#: gtk_ardour/editor.cc:242
+msgid "Edit Mode"
+msgstr "ΛειτουÏγία Επεξ/σίας"
+
+#: gtk_ardour/editor.cc:243
+msgid "Snap To"
+msgstr "Έλξη σε"
+
+#: gtk_ardour/editor.cc:244
+msgid "Snap Mode"
+msgstr "ΛειτουÏγία Έλξεως"
+
+#: gtk_ardour/editor.cc:245
+msgid "Zoom Focus"
+msgstr "Εστίαση Zoom"
+
+#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364
+#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579
+msgid "Nudge"
+msgstr "ÎÏξη"
+
+#: gtk_ardour/editor.cc:511
+msgid "Zoom in"
+msgstr "Zoom in"
+
+#: gtk_ardour/editor.cc:512
+msgid "Zoom out"
+msgstr "Zoom out"
+
+#: gtk_ardour/editor.cc:517
+msgid "Zoom to session"
+msgstr "Zoom στη συνεδÏία"
+
+#: gtk_ardour/editor.cc:536
+msgid "Zoom Span"
+msgstr "ΕÏÏος Zoom"
+
+#: gtk_ardour/editor.cc:566
+msgid "Edit Groups"
+msgstr "ΠÏόσθεση Ομάδων"
+
+#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142
+msgid "-all-"
+msgstr "-όλα-"
+
+#: gtk_ardour/editor.cc:718
+msgid "Nudge region/selection forwards"
+msgstr "ÎÏξη πεÏιοχής/επιλογής εμπÏός"
+
+#: gtk_ardour/editor.cc:719
+msgid "Nudge region/selection backwards"
+msgstr "ÎÏξη πεÏιοχής/επιλογής πίσω"
+
+#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308
+msgid "ardour: editor"
+msgstr "ardour: επεξεÏγαστής"
+
+#: gtk_ardour/editor.cc:729
+msgid "ardour_editor"
+msgstr "ardour_επεξεÏγαστής"
+
+#: gtk_ardour/editor.cc:846
+msgid "VerboseCanvasCursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1405
+msgid "FirstActionMessage"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1407
+msgid "Start a new session\n"
+msgstr "ΑÏχή καινοÏÏιας συνεδÏίας\n"
+
+#: gtk_ardour/editor.cc:1408
+msgid "via Session menu"
+msgstr "μέσω του Î¼ÎµÎ½Î¿Ï Î£Ï…Î½ÎµÎ´Ïίας"
+
+#: gtk_ardour/editor.cc:1703
+msgid "ardour: editor: "
+msgstr "ardour: επεξεÏγαστής: "
+
+#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796
+#: gtk_ardour/editor_markers.cc:797
+msgid "Loop"
+msgstr "Loop"
+
+#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810
+#: gtk_ardour/editor_markers.cc:823
+msgid "Punch"
+msgstr "Punch"
+
+#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688
+msgid "programming error: fade in canvas item has no regionview data pointer!"
+msgstr ""
+"Σφάλμα Ï€ÏογÏαμματισμοÏ: το αντικείμενο 'fade in canvas' δεν διαθέτει δείκτη "
+"δεδομένων οπτικής πεÏιοχών!"
+
+#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986
+#: gtk_ardour/redirect_box.cc:401
+msgid "Deactivate"
+msgstr "ΑπενεÏγοποίηση"
+
+#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988
+#: gtk_ardour/redirect_box.cc:398
+msgid "Activate"
+msgstr "ΕνεÏγοποίηση"
+
+#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993
+msgid "Linear"
+msgstr "ΓÏαμμικό"
+
+#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994
+#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734
+#: gtk_ardour/option_editor.cc:796
+msgid "Slowest"
+msgstr "ΑÏγότατο"
+
+#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995
+#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735
+#: gtk_ardour/option_editor.cc:798
+msgid "Slow"
+msgstr "ΑÏγό"
+
+#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996
+#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737
+#: gtk_ardour/option_editor.cc:802
+msgid "Fast"
+msgstr "ΤαχÏ"
+
+#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997
+#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739
+#: gtk_ardour/option_editor.cc:806
+msgid "Fastest"
+msgstr "ΤαχÏτατο"
+
+#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113
+msgid "Freeze"
+msgstr "Πάγωμα"
+
+#: gtk_ardour/editor.cc:2109
+msgid "Unfreeze"
+msgstr "Ξεπάγωμα"
+
+#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328
+#, fuzzy
+msgid "Unmute"
+msgstr "σιγή"
+
+#: gtk_ardour/editor.cc:2247
+msgid "Convert to short"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2249
+msgid "Convert to full"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2260
+#, fuzzy
+msgid "Crossfade"
+msgstr "Crossfade"
+
+#: gtk_ardour/editor.cc:2303
+msgid "Popup region editor"
+msgstr "Εμφάνιση του Ïυθμιστή πεÏιοχής"
+
+#: gtk_ardour/editor.cc:2304
+#, fuzzy
+msgid "Raise to top layer"
+msgstr "ΑνόÏθωση πεÏιοχής στο ανώτατο στÏώμα"
+
+#: gtk_ardour/editor.cc:2305
+#, fuzzy
+msgid "Lower to bottom layer"
+msgstr "Υποβίβαση πεÏιοχής στο κατώτατο στÏώμα"
+
+#: gtk_ardour/editor.cc:2307
+msgid "Define sync point"
+msgstr "ΠÏοσδιοÏισμός σημείου συγχÏονισμοÏ"
+
+#: gtk_ardour/editor.cc:2308
+msgid "Remove sync point"
+msgstr "Απαλοιφή σημείου συγχÏονισμοÏ"
+
+#: gtk_ardour/editor.cc:2313
+#, fuzzy
+msgid "Bounce"
+msgstr "Αναπήδηση διαστήματος"
+
+#: gtk_ardour/editor.cc:2323
+msgid "Lock"
+msgstr "Κλείδωμα"
+
+#: gtk_ardour/editor.cc:2324
+msgid "Unlock"
+msgstr "Ξεκλείδωμα"
+
+#: gtk_ardour/editor.cc:2334
+msgid "Original position"
+msgstr "ΠÏωταÏχική θέση"
+
+#: gtk_ardour/editor.cc:2340
+msgid "Toggle envelope visibility"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2341
+#, fuzzy
+msgid "Toggle envelope active"
+msgstr "Διακόπτης ΕνεÏγοÏ"
+
+#: gtk_ardour/editor.cc:2345
+#, fuzzy
+msgid "DeNormalize"
+msgstr "Εξομάλυνση"
+
+#: gtk_ardour/editor.cc:2347
+msgid "Normalize"
+msgstr "Εξομάλυνση"
+
+#: gtk_ardour/editor.cc:2350
+msgid "Reverse"
+msgstr "ΑντιστÏοφή"
+
+#: gtk_ardour/editor.cc:2359
+#, fuzzy
+msgid "Nudge fwd"
+msgstr "νÏξη εμπÏός"
+
+#: gtk_ardour/editor.cc:2360
+#, fuzzy
+msgid "Nudge bwd"
+msgstr "ÎÏξη"
+
+#: gtk_ardour/editor.cc:2361
+msgid "Nudge fwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2362
+msgid "Nudge bwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2371
+msgid "Start to edit cursor"
+msgstr "Από αÏχή μέχÏι κέÏσοÏα επεξεÏγασίας"
+
+#: gtk_ardour/editor.cc:2372
+msgid "Edit cursor to end"
+msgstr "Από κέÏσοÏα επεξεÏγασίας μέχÏι τέλους"
+
+#: gtk_ardour/editor.cc:2374
+msgid "Trim"
+msgstr "Ισοστάθμιση"
+
+#: gtk_ardour/editor.cc:2377
+msgid "Split"
+msgstr "ΔιαχωÏισμός"
+
+#: gtk_ardour/editor.cc:2380
+msgid "Make mono regions"
+msgstr "ΔημιουÏγία mono πεÏιοχών"
+
+#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428
+msgid "Duplicate"
+msgstr "ΑντιγÏαφή"
+
+#: gtk_ardour/editor.cc:2384
+msgid "Fill Track"
+msgstr "Γόμωση καναλιοÏ"
+
+#: gtk_ardour/editor.cc:2388
+msgid "Destroy"
+msgstr "ΚαταστÏοφή"
+
+#: gtk_ardour/editor.cc:2418
+msgid "Play range"
+msgstr "ΑναπαÏ/γή διαστήματος"
+
+#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446
+msgid "Loop range"
+msgstr "Loop διαστήματος"
+
+#: gtk_ardour/editor.cc:2421
+msgid "Create chunk from range"
+msgstr "ΔημιουÏγία ÎºÎ¿Î¼Î¼Î±Ï„Î¹Î¿Ï Î±Ï€ÏŒ διάστημα"
+
+#: gtk_ardour/editor.cc:2423
+msgid "Create Region"
+msgstr "ΔημιουÏγία πεÏιοχής"
+
+#: gtk_ardour/editor.cc:2424
+msgid "Separate Region"
+msgstr "ΔιαχωÏισμός πεÏιοχής"
+
+#: gtk_ardour/editor.cc:2425
+msgid "Crop Region to range"
+msgstr "Κοπή ΠεÏιοχής στο διάστημα"
+
+#: gtk_ardour/editor.cc:2426
+msgid "Bounce range"
+msgstr "Αναπήδηση διαστήματος"
+
+#: gtk_ardour/editor.cc:2432
+msgid "Fill range w/Region"
+msgstr "Γέμισμα διαστήματος μ/ΠεÏιοχή"
+
+#: gtk_ardour/editor.cc:2434
+msgid "Range"
+msgstr "Διάστημα"
+
+#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538
+msgid "Play from edit cursor"
+msgstr "ΑναπαÏ/γή από ΚέÏσοÏα ΕπεξεÏγασίας"
+
+#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539
+msgid "Play from start"
+msgstr "ΑναπαÏ/γή από αÏχή"
+
+#: gtk_ardour/editor.cc:2451
+#, fuzzy
+msgid "Play region"
+msgstr "ΑναπαÏ/γή ΠεÏιοχής"
+
+#: gtk_ardour/editor.cc:2453
+msgid "Loop Region"
+msgstr "Loop ΠεÏιοχής"
+
+#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540
+#: gtk_ardour/library_ui.cc:972
+msgid "Play"
+msgstr "ΑναπαÏ/γή"
+
+#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548
+msgid "Select All in track"
+msgstr "Επιλογή όλων στο κανάλι"
+
+#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549
+msgid "Select All"
+msgstr "Επιλογή όλων"
+
+#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550
+msgid "Invert in track"
+msgstr "ΑντιστÏοφή στο κανάλι"
+
+#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551
+msgid "Invert"
+msgstr "ΑντιστÏοφή"
+
+#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553
+msgid "Select loop range"
+msgstr "Επιλογή διαστήματος loop"
+
+#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554
+msgid "Select punch range"
+msgstr "Επιλογή διαστήματος punch"
+
+#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565
+#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369
+msgid "Cut"
+msgstr "Κοπή"
+
+#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566
+#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371
+msgid "Copy"
+msgstr "ΑντιγÏαφή"
+
+#: gtk_ardour/editor.cc:2482
+#, fuzzy
+msgid "Paste at edit cursor"
+msgstr "Από αÏχή μέχÏι κέÏσοÏα επεξεÏγασίας"
+
+#: gtk_ardour/editor.cc:2483
+#, fuzzy
+msgid "Paste at mouse"
+msgstr "χÏήση των master outs"
+
+#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923
+msgid "Align"
+msgstr "ΕυθυγÏάμμιση"
+
+#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925
+msgid "Align Relative"
+msgstr "ΕυθυγÏάμμιση σχετικών"
+
+#: gtk_ardour/editor.cc:2492
+msgid "Insert chunk"
+msgstr "ΠÏοσθήκη κομματιοÏ"
+
+#: gtk_ardour/editor.cc:2496
+msgid "New Region from range"
+msgstr "Îέα πεÏιοχή από διάστημα"
+
+#: gtk_ardour/editor.cc:2497
+msgid "Separate Range"
+msgstr "ΞεχωÏιστό διάστημα"
+
+#: gtk_ardour/editor.cc:2507
+msgid "Insert Region"
+msgstr "ΠÏοσθήκη πεÏιοχής"
+
+#: gtk_ardour/editor.cc:2508
+msgid "Insert external sndfile"
+msgstr "ΠÏοσθήκη εξωτεÏÎ¹ÎºÎ¿Ï Î±Ïχείου ήχου"
+
+#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438
+msgid "Import"
+msgstr "Εισαγωγή"
+
+#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574
+msgid "Nudge entire track fwd"
+msgstr "ÎÏξη ολόκληÏου ÎºÎ±Î½Î±Î»Î¹Î¿Ï ÎµÎ¼Ï€Ïός"
+
+#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575
+msgid "Nudge track after edit cursor fwd"
+msgstr "ÎÏξη ÎºÎ±Î½Î±Î»Î¹Î¿Ï Î¼ÎµÏ„Î¬ του κέÏσοÏα επεξεÏγασίας εμπÏός"
+
+#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576
+msgid "Nudge entire track bwd"
+msgstr "ÎÏξη ολοκλήÏου ÎºÎ±Î½Î±Î»Î¹Î¿Ï Ï€Î¯ÏƒÏ‰"
+
+#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577
+msgid "Nudge track after edit cursor bwd"
+msgstr "ÎÏξη κανάλι μετά του κέÏσοÏα επεξεÏγασίας πίσω"
+
+#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920
+#: gtk_ardour/redirect_box.cc:373
+msgid "Paste"
+msgstr "Επικόλληση"
+
+#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645
+#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799
+msgid "add marker"
+msgstr "Ï€Ïόσθεση στίγματος"
+
+#: gtk_ardour/editor.cc:3084
+msgid "select/move objects"
+msgstr "επιλογή/μετακίνηση αντικειμένων"
+
+#: gtk_ardour/editor.cc:3085
+msgid "select/move ranges"
+msgstr "επιλογή/μετακίνηση διαστημάτων"
+
+#: gtk_ardour/editor.cc:3086
+msgid "draw gain automation"
+msgstr "σχεδιασμός Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Ï„Î¿Ï… gain"
+
+#: gtk_ardour/editor.cc:3087
+msgid "select zoom range"
+msgstr "επιλογή διαστήματος zoom"
+
+#: gtk_ardour/editor.cc:3088
+msgid "stretch/shrink regions"
+msgstr "μεγέθυνση/σμίκÏυνση πεÏιοχών"
+
+#: gtk_ardour/editor.cc:3089
+#, fuzzy
+msgid "listen to specific regions"
+msgstr "θέση επιλεγμένης οπτικής πεÏιοχής"
+
+#: gtk_ardour/editor.cc:3213
+msgid "Start:"
+msgstr "ΑÏχή:"
+
+#: gtk_ardour/editor.cc:3214
+msgid "End:"
+msgstr "Τέλος:"
+
+#: gtk_ardour/editor.cc:3215
+msgid "Edit:"
+msgstr "ΣÏνταξη:"
+
+#: gtk_ardour/editor.cc:3429
+msgid "incorrectly formatted URI list, ignored"
+msgstr "λανθασμένα φοÏμαÏισμένη URI λίστα, αγνοήθηκε"
+
+#: gtk_ardour/editor.cc:3611
+msgid "set selected trackview"
+msgstr "θέση επιλεγμένης οπτικής καναλιοÏ"
+
+#: gtk_ardour/editor.cc:3647
+#, fuzzy
+msgid "set selected control point"
+msgstr "απαλοιφή σημείου ελέγχου"
+
+#: gtk_ardour/editor.cc:3719
+msgid "set selected regionview"
+msgstr "θέση επιλεγμένης οπτικής πεÏιοχής"
+
+#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835
+#, fuzzy
+msgid "set selected regions"
+msgstr "θέση επιλεγμένης οπτικής πεÏιοχής"
+
+#: gtk_ardour/editor.cc:3891
+msgid "Undo"
+msgstr "Undo"
+
+#: gtk_ardour/editor.cc:3893
+msgid "Undo (%1)"
+msgstr "Undo (%1)"
+
+#: gtk_ardour/editor.cc:3903
+msgid "Redo"
+msgstr "Redo"
+
+#: gtk_ardour/editor.cc:3905
+msgid "Redo (%1)"
+msgstr "Redo (%1)"
+
+#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946
+msgid "... as new track"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947
+#, fuzzy
+msgid "... as new region"
+msgstr "ευθυγÏάμμιση πεÏιοχής"
+
+#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452
+msgid "Import audio (copy)"
+msgstr "Εισαγωγή ήχου (αντίγÏαφο)"
+
+#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457
+msgid "Embed audio (link)"
+msgstr "ΕμφÏτευση ήχου (link)"
+
+#: gtk_ardour/editor.cc:3953
+msgid "Remove last capture"
+msgstr "Απαλοιφή τελευταίας λήψης"
+
+#: gtk_ardour/editor.cc:3974
+msgid "Duplicate how many times?"
+msgstr "ΑντιγÏαφή πόσες φοÏές?"
+
+#: gtk_ardour/editor.cc:4550
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If left alone, no audio files used by it will be cleaned.\n"
+"If deleted, audio files used by it alone by will cleaned."
+msgstr ""
+"Η Λίστα ΑναπαÏ/γής %1 Ï€Ïος το παÏόν δε χÏησιμοποιείται.\n"
+"Εάν μείνει έτσι, κανένα ηχητικό αÏχείο που χÏησιμοποιείται απο αυτήν δεν θα "
+"διαγÏαφεί.\n"
+"Εάν διαγÏαφεί, τα ηχητικά αÏχεία που χÏησιμοποιοÏνται μόνο απ'αυτήν θα "
+"διαγÏαφοÏν."
+
+#: gtk_ardour/editor.cc:4555
+msgid "Delete playlist"
+msgstr "ΔιαγÏαφή λίστας αναπαÏ/γής"
+
+#: gtk_ardour/editor.cc:4556
+msgid "Keep playlist"
+msgstr "ΔιατήÏηση λίστας αναπαÏ/γής"
+
+#: gtk_ardour/editor.cc:4557
+msgid "Cancel cleanup"
+msgstr "ΑκÏÏωση εκκαθάÏισης"
+
+#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258
+#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290
+msgid ""
+"programming error: control point canvas item has no control point object "
+"pointer!"
+msgstr ""
+"Σφάλμα ΠÏογÏαμματισμοÏ: ο καμβάς του σημείου ελέγχου δεν έχει δείκτη "
+"αναφοÏάς!"
+
+#: gtk_ardour/editor_canvas_events.cc:717
+msgid "programming error: line canvas item has no line object pointer!"
+msgstr ""
+"Σφάλμα ΠÏογÏαμματισμοÏ: ο καμβάς της γÏαμμής δεν έχει δείκτη αναφοÏάς της "
+"γÏαμμής!"
+
+#: gtk_ardour/editor_canvas_events.cc:744
+#: gtk_ardour/editor_canvas_events.cc:784
+#: gtk_ardour/editor_canvas_events.cc:823
+msgid "programming error: no \"rect\" pointer associated with selection item"
+msgstr ""
+"Σφάλμα Ï€ÏογÏαμματισμοÏ: κανένας \"rect\" δείκτης δεν σχετίζεται με το "
+"επιλεγμένο αντικείμενο"
+
+#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298
+#: gtk_ardour/mixer_ui.cc:670
+msgid "Show All"
+msgstr "Εμφάνιση Όλων"
+
+#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299
+#: gtk_ardour/mixer_ui.cc:671
+msgid "Hide All"
+msgstr "ΑπόκÏυψη όλων"
+
+#: gtk_ardour/editor_edit_groups.cc:98
+msgid "Name for new edit group"
+msgstr "Όνομα για νέα ομάδα επεξεÏγασίας"
+
+#: gtk_ardour/editor_export_audio.cc:60
+msgid ""
+"There is no range to export.\n"
+"\n"
+"Select a range using the range mouse mode"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707
+msgid "programming error: no ImageFrameView selected"
+msgstr "Σφάλμα Ï€ÏογÏαμματισμοÏ: δεν επιλέχθηκε οπτική καÏέ εικόνας"
+
+#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930
+msgid "programming error: no MarkerView selected"
+msgstr "Σφάλμα Ï€ÏογÏαμματισμοÏ: δεν επιλέχθηκε οπτική στίγματος"
+
+#: gtk_ardour/editor_keys.cc:187
+#, fuzzy
+msgid "keyboard selection"
+msgstr "επέκταση επιλογής"
+
+#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376
+#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526
+#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584
+#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650
+#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700
+#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960
+#: gtk_ardour/editor_mouse.cc:4075
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr ""
+"Σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς στιγμάτων δεν έχει δείκτη αντικειμένου "
+"στιγμάτων!"
+
+#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681
+msgid "remove marker"
+msgstr "απαλοιφή στίγματος"
+
+#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494
+msgid "Locate to"
+msgstr "Τοποθέτηση στο"
+
+#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495
+msgid "Play from"
+msgstr "ΑναπαÏ/γή από"
+
+#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496
+msgid "Set from playhead"
+msgstr "Θέση από αναπαÏαγωγέα"
+
+#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497
+msgid "Set from range"
+msgstr "Θέση από διάστημα"
+
+#: gtk_ardour/editor_markers.cc:479
+msgid "Set Loop Range"
+msgstr "Θέση Loop Διαστήματος"
+
+#: gtk_ardour/editor_markers.cc:480
+msgid "Set Punch Range"
+msgstr "Θέση Punch Διαστήματος"
+
+#: gtk_ardour/editor_markers.cc:736
+msgid "ardour: rename mark"
+msgstr "ardour: μετονομασία στίγματος"
+
+#: gtk_ardour/editor_markers.cc:738
+#, fuzzy
+msgid "ardour: rename range"
+msgstr "ardour: μετονομασία πεÏιοχής"
+
+#: gtk_ardour/editor_markers.cc:792
+msgid "set loop range"
+msgstr "Θέση loop διαστήματος"
+
+#: gtk_ardour/editor_markers.cc:818
+msgid "set punch range"
+msgstr "θέση punch διαστήματος"
+
+#: gtk_ardour/editor_mouse.cc:99
+msgid "Editor::event_frame() used on unhandled event type %1"
+msgstr ""
+"ΕπαξεÏγαστής::event_frame() χÏησιμοποιήθηκε στο αδιαχείÏιστο συμβάν Ï„Ïπου %1"
+
+#: gtk_ardour/editor_mouse.cc:1555
+msgid "programming error: start_grab called without drag item"
+msgstr ""
+"σφάλμα Ï€ÏογÏαμματισμοÏ: η Ïουτίνα start_grab εκλήθη δίχως 'drag' αντικείμενο"
+
+#: gtk_ardour/editor_mouse.cc:1760
+msgid "change fade in length"
+msgstr "αλλαγή μήκους fade in"
+
+#: gtk_ardour/editor_mouse.cc:1778
+msgid "programming error: fade out canvas item has no regionview data pointer!"
+msgstr ""
+"σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς fade out δεν έχει δείκτη δεδομένων της "
+"οπτικής πεÏιοχών!"
+
+#: gtk_ardour/editor_mouse.cc:1852
+msgid "change fade out length"
+msgstr "αλλαγή μήκους fade out"
+
+#: gtk_ardour/editor_mouse.cc:1871
+msgid "programming error: cursor canvas item has no cursor data pointer!"
+msgstr ""
+"σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς του κέÏσοÏα δεν έχει δείκτη δεδομένων του "
+"κέÏσοÏα!"
+
+#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470
+msgid ""
+"programming error: meter marker canvas item has no marker object pointer!"
+msgstr ""
+"σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς του μετÏητή στιγμάτων δεν έχει δείκτη "
+"αντικειμένου στιγμάτων!"
+
+#: gtk_ardour/editor_mouse.cc:2163
+msgid "move meter mark"
+msgstr "μετακίνηση στίγματος μετÏητή"
+
+#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335
+#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439
+msgid ""
+"programming error: tempo marker canvas item has no marker object pointer!"
+msgstr ""
+"σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς στίξης του tempo δεν έχει δείκτη "
+"αντικειμένου στιγμάτων!"
+
+#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340
+#: gtk_ardour/editor_tempodisplay.cc:425
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr ""
+"σφάλμα Ï€ÏογÏαμματισμοÏ: το στίγμα για το tempo δεν είναι στιγμα για tempo!"
+
+#: gtk_ardour/editor_mouse.cc:2245
+msgid "move tempo mark"
+msgstr "μετακίνηση στίγματος tempo"
+
+#: gtk_ardour/editor_mouse.cc:2388
+msgid "programming error: line canvas item has no line pointer!"
+msgstr "σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς γÏαμμών δεν έχει δείκτη γÏαμμών!"
+
+#: gtk_ardour/editor_mouse.cc:2497
+#, fuzzy
+msgid "move region(s)"
+msgstr "απαλοιφή πεÏιοχής"
+
+#: gtk_ardour/editor_mouse.cc:2509
+msgid "Drag region copy"
+msgstr "Έλξη αντιγÏαφής πεÏιοχής"
+
+#: gtk_ardour/editor_mouse.cc:2579
+#, fuzzy
+msgid "copy region(s)"
+msgstr "Έλξη πεÏιοχής(ων)"
+
+#: gtk_ardour/editor_mouse.cc:2612
+#, fuzzy
+msgid "Drag region brush"
+msgstr "Έλξη πεÏιοχής(ων)"
+
+#: gtk_ardour/editor_mouse.cc:3425
+msgid "selection grab"
+msgstr "αÏπαγή επιλεγμένων"
+
+#: gtk_ardour/editor_mouse.cc:3571
+msgid "range selection"
+msgstr "επιλογή διαστήματος"
+
+#: gtk_ardour/editor_mouse.cc:3587
+msgid "trim selection start"
+msgstr "αÏχή επιλογής Ï€Ïος ισοστάθμιση"
+
+#: gtk_ardour/editor_mouse.cc:3603
+msgid "trim selection end"
+msgstr "τέλος επιλογής Ï€Ïος ισοστάθμιση"
+
+#: gtk_ardour/editor_mouse.cc:3620
+msgid "move selection"
+msgstr "μετακίνηση επιλογής"
+
+#: gtk_ardour/editor_mouse.cc:3995
+msgid "Start point trim"
+msgstr "ΑÏχή σημείου ισοσταθμίσεως"
+
+#: gtk_ardour/editor_mouse.cc:4023
+msgid "End point trim"
+msgstr "Τέλος σημείου ισοσταθμίσεως"
+
+#: gtk_ardour/editor_mouse.cc:4062
+msgid "trimmed region"
+msgstr "ισοσταθμισμένη πεÏιοχή"
+
+#: gtk_ardour/editor_mouse.cc:4203
+msgid "new range marker"
+msgstr "νέο στίγμα διαστήματος"
+
+#: gtk_ardour/editor_mouse.cc:4422
+msgid "select regions"
+msgstr "επιλογή πεÏιοχών"
+
+#: gtk_ardour/editor_mouse.cc:4451
+msgid "Name for region:"
+msgstr "Όνομα για πεÏιοχή:"
+
+#: gtk_ardour/editor_mouse.cc:4517
+msgid "timestretch"
+msgstr "κάμψη χÏόνου"
+
+#: gtk_ardour/editor_ops.cc:117
+msgid "split"
+msgstr "διαχωÏισμός"
+
+#: gtk_ardour/editor_ops.cc:153
+msgid "remove region"
+msgstr "απαλοιφή πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:172
+msgid ""
+" This is destructive, will possibly delete audio files\n"
+"It cannot be undone\n"
+"Do you really want to destroy %1 ?"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "these regions"
+msgstr "αντιστÏοφή πεÏιοχών"
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "this region"
+msgstr "σιγή παÏοÏσας πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:179
+#, fuzzy
+msgid "Yes, destroy them."
+msgstr "Îαι, να καταστÏαφεί."
+
+#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434
+msgid "Yes, destroy it."
+msgstr "Îαι, να καταστÏαφεί."
+
+#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435
+#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300
+msgid "No, do nothing."
+msgstr "Όχι, να μην γίνει τίποτα."
+
+#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307
+msgid "extend selection"
+msgstr "επέκταση επιλογής"
+
+#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357
+#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427
+msgid "nudge forward"
+msgstr "νÏξη εμπÏός"
+
+#: gtk_ardour/editor_ops.cc:491
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr "build_region_boundary_cache εκλήθη με snap_type = %1"
+
+#: gtk_ardour/editor_ops.cc:1305
+msgid "set selection from range"
+msgstr "θέση επιλογής από διάστημα"
+
+#: gtk_ardour/editor_ops.cc:1421
+msgid "clear markers"
+msgstr "εκκαθάÏιση στιγμάτων"
+
+#: gtk_ardour/editor_ops.cc:1433
+msgid "clear ranges"
+msgstr "διαγÏαφή διαστημάτων"
+
+#: gtk_ardour/editor_ops.cc:1452
+msgid "clear locations"
+msgstr "διαγÏαφή τοποθεσιών"
+
+#: gtk_ardour/editor_ops.cc:1503
+msgid "insert dragged region"
+msgstr "Ï€Ïοσθήκη ελκομένης πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:1538
+msgid "insert region"
+msgstr "Ï€Ïοσθήκη πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:1744
+msgid "ardour: rename region"
+msgstr "ardour: μετονομασία πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:1891
+msgid "You can't import an audiofile until you have a session loaded."
+msgstr "Δεν γίνεται να εισαχθεί ήχος χωÏίς να έχει φοÏτωθεί Ï€Ïώτα ΣυνεδÏία."
+
+#: gtk_ardour/editor_ops.cc:1901
+#, fuzzy
+msgid "Import selected as tracks"
+msgstr "Εισαγωγή επιλεγμένου(ων)"
+
+#: gtk_ardour/editor_ops.cc:1904
+#, fuzzy
+msgid "Import selected to region list"
+msgstr "θέση επιλεγμένης οπτικής πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:1933
+msgid "ardour: audio import in progress"
+msgstr "ardour: εισαγωγή ήχων εν εξελίξι"
+
+#: gtk_ardour/editor_ops.cc:1937
+msgid "Cancel Import"
+msgstr "ΑκÏÏωση Εισαγωγής"
+
+#: gtk_ardour/editor_ops.cc:1944
+msgid "ardour: importing %1"
+msgstr "ardour: εισαγωγή εν εξελίξι %1"
+
+#: gtk_ardour/editor_ops.cc:1990
+msgid "%1 it anyway"
+msgstr "%1 το οÏτως ή άλλως"
+
+#: gtk_ardour/editor_ops.cc:1996
+#, fuzzy
+msgid "Don't %1 it"
+msgstr "Μη %1"
+
+#: gtk_ardour/editor_ops.cc:1997
+msgid "%1 all without questions"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1998
+#, fuzzy
+msgid "Cancel entire import"
+msgstr "ΑκÏÏωση Εισαγωγής"
+
+#: gtk_ardour/editor_ops.cc:2004
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr ""
+"%1\n"
+"Ο Ïυθμός δειγματοληψίας Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… αÏχείου δεν ταιÏιάζει με αυτόν της "
+"συνεδÏίας!"
+
+#: gtk_ardour/editor_ops.cc:2032
+msgid "You can't embed an audiofile until you have a session loaded."
+msgstr ""
+"Δεν γίνεται να εμφυτεÏσετε ηχο-αÏχεία μέχÏι να φοÏτώσετε κάποια συνεδÏία."
+
+#: gtk_ardour/editor_ops.cc:2039
+msgid "Add to External Region list"
+msgstr "ΠÏόσθεση σε Λίστα ΕξωτεÏικής ΠεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210
+#: gtk_ardour/editor_ops.cc:2286
+msgid "Editor: cannot open file \"%1\" (%2)"
+msgstr "Editor: δεν γίνεται να ανοίξει το αÏχείο \"%1\" (%2)"
+
+#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312
+msgid "could not open %1"
+msgstr "δεν μπόÏεσα να ανοίξω το %1"
+
+#: gtk_ardour/editor_ops.cc:2171
+#, fuzzy
+msgid "Insert selected as new tracks"
+msgstr "θέση επιλεγμένης οπτικής καναλιοÏ"
+
+#: gtk_ardour/editor_ops.cc:2186
+msgid "Insert selected"
+msgstr "ΠÏοσθήκη επιλεγμένου(ων)"
+
+#: gtk_ardour/editor_ops.cc:2327
+msgid "insert sndfile"
+msgstr "Ï€Ïοσθήκη ηχο-αÏχείου"
+
+#: gtk_ardour/editor_ops.cc:2464
+msgid "separate"
+msgstr "διαχωÏισμός"
+
+#: gtk_ardour/editor_ops.cc:2528
+msgid "trim to selection"
+msgstr "ισοστάθμιση Ï€Ïος τα επιλεγμένα"
+
+#: gtk_ardour/editor_ops.cc:2568
+msgid "region fill"
+msgstr "γόμωση πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:2626
+msgid "fill selection"
+msgstr "γόμωση επιλογής"
+
+#: gtk_ardour/editor_ops.cc:2650
+msgid "Place the edit cursor at the desired sync point"
+msgstr "Τοποθετήστε τον κεÏσοÏα επεξεÏ/σίας στο επιθÏμητό σημείο συγχÏονισμοÏ"
+
+#: gtk_ardour/editor_ops.cc:2656
+msgid "set sync from edit cursor"
+msgstr "Θέση συγχÏονισμοÏ(sync) απο κέÏσοÏα επεξεÏ/σίας"
+
+#: gtk_ardour/editor_ops.cc:2668
+msgid "remove sync"
+msgstr "απαλοιφή συγχÏονισμοÏ(sync)"
+
+#: gtk_ardour/editor_ops.cc:2682
+msgid "naturalize"
+msgstr "φυσικοποίηση"
+
+#: gtk_ardour/editor_ops.cc:2746
+msgid "align selection (relative)"
+msgstr "ευθυγÏάμμιση επιλογής (σχετική)"
+
+#: gtk_ardour/editor_ops.cc:2774
+msgid "align selection"
+msgstr "ευθυγÏάμμιση επιλογής"
+
+#: gtk_ardour/editor_ops.cc:2786
+msgid "align region"
+msgstr "ευθυγÏάμμιση πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858
+msgid "trim to edit"
+msgstr "ισοστάθμιση Ï€Ïος σÏνταξη"
+
+#: gtk_ardour/editor_ops.cc:2909
+#, fuzzy
+msgid "ardour: freeze"
+msgstr "ardour: "
+
+#: gtk_ardour/editor_ops.cc:2914
+#, fuzzy
+msgid "Cancel Freeze"
+msgstr "ΑκÏÏωση"
+
+#: gtk_ardour/editor_ops.cc:2951
+msgid "bounce range"
+msgstr "αναπήδηση διαστήματο"
+
+#: gtk_ardour/editor_ops.cc:3004
+msgid "cut"
+msgstr "κοπή"
+
+#: gtk_ardour/editor_ops.cc:3007
+msgid "copy"
+msgstr "αντιγÏαφή"
+
+#: gtk_ardour/editor_ops.cc:3020
+msgid " objects"
+msgstr " αντικειμένων"
+
+#: gtk_ardour/editor_ops.cc:3046
+msgid " range"
+msgstr " διαστήματος"
+
+#: gtk_ardour/editor_ops.cc:3201
+msgid "paste"
+msgstr "επικόλληση"
+
+#: gtk_ardour/editor_ops.cc:3236
+msgid "paste chunk"
+msgstr "επικόλληση κομματιοÏ"
+
+#: gtk_ardour/editor_ops.cc:3276
+msgid "duplicate region"
+msgstr "αντιγÏαφή πεÏιοχής"
+
+#: gtk_ardour/editor_ops.cc:3309
+msgid "duplicate selection"
+msgstr "αντιγÏαφή επιλογής"
+
+#: gtk_ardour/editor_ops.cc:3349
+msgid "clear playlist"
+msgstr "εκκαθάÏιση playlist"
+
+#: gtk_ardour/editor_ops.cc:3378
+msgid "nudge track"
+msgstr "νÏξη καναλιοÏ"
+
+#: gtk_ardour/editor_ops.cc:3431
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"Στ'αλήθεια θέλετε να καταστÏέψετε την τελευταία λήψη?\n"
+"(Η Ï€Ïάξη είνα‎ι καταστÏεπτική και δεν γίνεται επαναφοÏά της)"
+
+#: gtk_ardour/editor_ops.cc:3463
+msgid "normalize"
+msgstr "εξομάλυνση"
+
+#: gtk_ardour/editor_ops.cc:3510
+msgid "reverse regions"
+msgstr "αντιστÏοφή πεÏιοχών"
+
+#: gtk_ardour/editor_region_list.cc:223
+#, fuzzy
+msgid "hidden"
+msgstr "ΚÏυμμένο"
+
+#: gtk_ardour/editor_region_list.cc:408
+msgid "Show all"
+msgstr "Ανάδειξη όλων"
+
+#: gtk_ardour/editor_region_list.cc:417
+msgid "Ascending"
+msgstr "ΑÏξουσα"
+
+#: gtk_ardour/editor_region_list.cc:419
+msgid "Descending"
+msgstr "Φθίνουσα"
+
+#: gtk_ardour/editor_region_list.cc:423
+msgid "By Region Name"
+msgstr "Με Όνομα ΠεÏιοχής"
+
+#: gtk_ardour/editor_region_list.cc:425
+msgid "By Region Length"
+msgstr "Με Μέγεθος ΠεÏιοχής"
+
+#: gtk_ardour/editor_region_list.cc:427
+msgid "By Region Position"
+msgstr "Με Θέση ΠεÏιοχής"
+
+#: gtk_ardour/editor_region_list.cc:429
+msgid "By Region Timestamp"
+msgstr "Με ΧÏονο-στάμπα ΠεÏιοχής"
+
+#: gtk_ardour/editor_region_list.cc:431
+msgid "By Region Start in File"
+msgstr "Με ΑÏχή-στο-αÏχείο της ΠεÏιοχής"
+
+#: gtk_ardour/editor_region_list.cc:433
+msgid "By Region End in File"
+msgstr "Με Τέλος-στο -αÏχείο της ΠεÏιοχής"
+
+#: gtk_ardour/editor_region_list.cc:435
+msgid "By Source File Name"
+msgstr "Με Όνομα ΑÏχείου Πηγής"
+
+#: gtk_ardour/editor_region_list.cc:437
+msgid "By Source File Length"
+msgstr "Με Μέγεθος ΑÏχείου Πηγής"
+
+#: gtk_ardour/editor_region_list.cc:439
+msgid "By Source File Creation Date"
+msgstr "Με Ημ/νία ΑÏχείου Πηγής"
+
+#: gtk_ardour/editor_region_list.cc:441
+msgid "By Source Filesystem"
+msgstr "Με Filesystem Πηγής"
+
+#: gtk_ardour/editor_region_list.cc:444
+msgid "Sorting"
+msgstr "Ταξινόμηση"
+
+#: gtk_ardour/editor_region_list.cc:808
+msgid "Regions/length"
+msgstr "ΠεÏιοχές/διάÏκεια"
+
+#: gtk_ardour/editor_region_list.cc:812
+msgid "Regions/position"
+msgstr "ΠεÏιοχές/θέση"
+
+#: gtk_ardour/editor_region_list.cc:816
+msgid "Regions/creation"
+msgstr "ΠεÏιοχές/δημιουÏγία"
+
+#: gtk_ardour/editor_region_list.cc:820
+msgid "Regions/start"
+msgstr "ΠεÏιοχές/αÏχή"
+
+#: gtk_ardour/editor_region_list.cc:824
+msgid "Regions/end"
+msgstr "ΠεÏιοχές/τέλος"
+
+#: gtk_ardour/editor_region_list.cc:828
+msgid "Regions/file name"
+msgstr "ΠεÏιοχές/όνομα αÏχείου"
+
+#: gtk_ardour/editor_region_list.cc:832
+msgid "Regions/file size"
+msgstr "ΠεÏιοχές/μέγεθος αÏχείου"
+
+#: gtk_ardour/editor_region_list.cc:836
+msgid "Regions/file date"
+msgstr "ΠεÏιοχές/ημ/νία αÏχείου"
+
+#: gtk_ardour/editor_region_list.cc:840
+msgid "Regions/file system"
+msgstr "ΠεÏιοχές/file system"
+
+#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73
+#: gtk_ardour/editor_route_list.cc:231
+msgid "editor"
+msgstr "επεξεÏγαστής"
+
+#: gtk_ardour/editor_route_list.cc:300
+msgid "Show All AbstractTracks"
+msgstr "Ανάδειξη όλων των Abstractκανάλιs"
+
+#: gtk_ardour/editor_route_list.cc:301
+msgid "Hide All AbstractTracks"
+msgstr "ΑπόκÏυψη όλων των Abstractκαναλιών"
+
+#: gtk_ardour/editor_route_list.cc:302
+msgid "Show All AudioBus"
+msgstr "Ανάδειξη όλων των ΗχοδιαÏλων"
+
+#: gtk_ardour/editor_route_list.cc:303
+msgid "Hide All AudioBus"
+msgstr "ΑπόκÏυψη όλων των ΗχοδιαÏλων"
+
+#: gtk_ardour/editor_rulers.cc:311
+msgid "New location marker"
+msgstr "Îέο στίγμα θέσεως"
+
+#: gtk_ardour/editor_rulers.cc:312
+msgid "Clear all locations"
+msgstr "ΕκκαθάÏιση όλων των θέσεων"
+
+#: gtk_ardour/editor_rulers.cc:317
+msgid "Clear all ranges"
+msgstr "ΕκκαθάÏιση όλων των διαστημάτων"
+
+#: gtk_ardour/editor_rulers.cc:326
+msgid "New Tempo"
+msgstr "Îέος ΧÏόνος"
+
+#: gtk_ardour/editor_rulers.cc:327
+msgid "Clear tempo"
+msgstr "ΕκκαθάÏιση ΧÏόνου"
+
+#: gtk_ardour/editor_rulers.cc:332
+msgid "New Meter"
+msgstr "Îέο μέτÏο"
+
+#: gtk_ardour/editor_rulers.cc:333
+msgid "Clear meter"
+msgstr "ΕκκαθάÏιση μέτÏου"
+
+#: gtk_ardour/editor_rulers.cc:341
+msgid "Min:Secs"
+msgstr "Λεπ:ΔεÏÏ„"
+
+#: gtk_ardour/editor_selection_list.cc:117
+msgid "name for chunk:"
+msgstr "όνομα για κομμάτι:"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Create chunk"
+msgstr "ΔημιουÏγία κομματιοÏ"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Forget it"
+msgstr "Ξέχασέ το"
+
+#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295
+msgid "add"
+msgstr "Ï€Ïόσθεση"
+
+#: gtk_ardour/editor_tempodisplay.cc:276
+msgid "add tempo mark"
+msgstr "Ï€Ïόσθεση στίγματος χÏόνου"
+
+#: gtk_ardour/editor_tempodisplay.cc:318
+msgid "add meter mark"
+msgstr "Ï€Ïόσθεση στίγματος μέτÏου"
+
+#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383
+msgid "done"
+msgstr "έγινε"
+
+#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404
+msgid "replace tempo mark"
+msgstr "αντικατάσταση στίγματος χÏόνου"
+
+#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr ""
+"Σφάλμα Ï€ÏογÏαμματισμοÏ: το στίγμα για το μέτÏο δεν είναι στίγμα μέτÏου!"
+
+#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487
+msgid "remove tempo mark"
+msgstr "απαλοιφή στίγματος χÏόνου"
+
+#: gtk_ardour/editor_timefx.cc:50
+msgid "Quick but Ugly"
+msgstr "ΓÏήγοÏο αλλά Άσχημο"
+
+#: gtk_ardour/editor_timefx.cc:51
+msgid "Skip Anti-aliasing"
+msgstr "ΠαÏάκαμψη Anti-aliasing"
+
+#: gtk_ardour/editor_timefx.cc:53
+msgid "Stretch/Shrink it"
+msgstr "Μεγέθυνέ/ΣμίκÏυνέ το"
+
+#: gtk_ardour/editor_timefx.cc:57
+msgid "ardour: timestretch"
+msgstr "ardour: χÏονοκάμψη"
+
+#: gtk_ardour/editor_timefx.cc:58
+msgid "TimeStretchDialog"
+msgstr "ΔιάλογοςΧÏονοκάμψης"
+
+#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83
+#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85
+msgid "TimeStretchButton"
+msgstr "ΚουμπίΧÏονοκάμψης"
+
+#: gtk_ardour/editor_timefx.cc:86
+msgid "TimeStretchProgress"
+msgstr "ΠÏόοδοςΧÏονοκάμψης"
+
+#: gtk_ardour/editor_timefx.cc:151
+msgid "timestretch cannot be started - thread creation error"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410
+#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189
+msgid "22.05kHz"
+msgstr "22.05kHz"
+
+#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413
+#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949
+#: gtk_ardour/export_dialog.cc:1191
+msgid "44.1kHz"
+msgstr "44.1kHz"
+
+#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416
+#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193
+msgid "48kHz"
+msgstr "48kHz"
+
+#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419
+#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195
+msgid "88.2kHz"
+msgstr "88.2kHz"
+
+#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422
+#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197
+msgid "96kHz"
+msgstr "96kHz"
+
+#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425
+#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199
+msgid "192kHz"
+msgstr "192kHz"
+
+#: gtk_ardour/export_dialog.cc:73
+msgid "best"
+msgstr "βέλτιστη"
+
+#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964
+msgid "fastest"
+msgstr "ταχÏτατη"
+
+#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966
+msgid "linear"
+msgstr "γÏαμμική"
+
+#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968
+msgid "better"
+msgstr "καλÏτεÏη"
+
+#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970
+msgid "intermediate"
+msgstr "ενδιάμεση"
+
+#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979
+msgid "Rectangular"
+msgstr "ΤετÏάγωνη"
+
+#: gtk_ardour/export_dialog.cc:84
+msgid "Shaped Noise"
+msgstr "ΜοÏφοποιημένος ΘόÏυβος"
+
+#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981
+msgid "Triangular"
+msgstr "ΤÏίγωνη"
+
+#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336
+msgid "stereo"
+msgstr "stereo"
+
+#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497
+#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219
+#: gtk_ardour/utils.cc:334
+msgid "mono"
+msgstr "mono"
+
+#: gtk_ardour/export_dialog.cc:97
+msgid "CUE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:98
+msgid "TOC"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:106
+msgid "FORMAT"
+msgstr "FORMAT"
+
+#: gtk_ardour/export_dialog.cc:107
+msgid "SAMPLE RATE"
+msgstr "ΡΥΘΜΟΣ ΔΕΙΓΜΑΤ/ΨΙΑΣ"
+
+#: gtk_ardour/export_dialog.cc:108
+msgid "CONVERSION QUALITY"
+msgstr "ΠΟΙΟΤΗΤΑ ΜΕΤΑΤΡΟΠΗΣ"
+
+#: gtk_ardour/export_dialog.cc:109
+msgid "DITHER TYPE"
+msgstr "ΤΥΠΟΣ DITHER"
+
+#: gtk_ardour/export_dialog.cc:110
+#, fuzzy
+msgid "CD MARKER FILE TYPE"
+msgstr "ΤΥΠΟΣ ΑΡΧΕΙΟΥ"
+
+#: gtk_ardour/export_dialog.cc:111
+msgid "CHANNELS"
+msgstr "ΚΑÎΑΛΙΑ"
+
+#: gtk_ardour/export_dialog.cc:112
+msgid "FILE TYPE"
+msgstr "ΤΥΠΟΣ ΑΡΧΕΙΟΥ"
+
+#: gtk_ardour/export_dialog.cc:113
+msgid "SAMPLE FORMAT"
+msgstr "FORMAT ΔΕΙΓΜΑΤΟΣ"
+
+#: gtk_ardour/export_dialog.cc:114
+msgid "SAMPLE ENDIANNESS"
+msgstr "SAMPLE ENDIANNESS"
+
+#: gtk_ardour/export_dialog.cc:115
+#, fuzzy
+msgid "EXPORT CD MARKER FILE ONLY"
+msgstr "ΤΥΠΟΣ ΑΡΧΕΙΟΥ"
+
+#: gtk_ardour/export_dialog.cc:116
+msgid "EXPORT TO FILE"
+msgstr "ΕΞΑΓΩΓΗ ΣΕ ΑΡΧΕΙΟ"
+
+#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118
+#: gtk_ardour/option_editor.cc:119
+msgid "Browse"
+msgstr "Αναζήτηση"
+
+#: gtk_ardour/export_dialog.cc:119
+msgid "Specific tracks ..."
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:131
+msgid "ardour: export"
+msgstr "ardour: εξαγωγή"
+
+#: gtk_ardour/export_dialog.cc:132
+msgid "ardour_export"
+msgstr "ardour_εξαγωγή"
+
+#: gtk_ardour/export_dialog.cc:156
+#, fuzzy
+msgid "Output"
+msgstr "Έξοδοι"
+
+#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626
+msgid "Track"
+msgstr "Κανάλι"
+
+#: gtk_ardour/export_dialog.cc:287
+msgid "slereg"
+msgstr "slereg"
+
+#: gtk_ardour/export_dialog.cc:658
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD toc file"
+msgstr ""
+"ΕπεξεÏγαστής: δεν γίνεται να ανοιχτεί το \"%1\" ως αÏχείο εξαγωγής για "
+"στίγματα ÎºÎ±Î½Î±Î»Î¹Î¿Ï CD"
+
+#: gtk_ardour/export_dialog.cc:780
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD cue file"
+msgstr ""
+"ΕπεξεÏγαστής: δεν γίνεται να ανοιχτεί το \"%1\" ως αÏχείο εξαγωγής για "
+"στίγματα ÎºÎ±Î½Î±Î»Î¹Î¿Ï CD"
+
+#: gtk_ardour/export_dialog.cc:799
+msgid "WAV"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:1051
+msgid "Stop Export"
+msgstr "ΠαÏση Εξαγωγής"
+
+#: gtk_ardour/gain_automation_time_axis.cc:60
+#, fuzzy
+msgid "add gain automation event"
+msgstr "Ï€Ïόσθεση συμβάντος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï ÏƒÎµ "
+
+#: gtk_ardour/gain_meter.cc:68
+msgid "Cannot create slider pixmaps"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:83
+msgid "dbFS"
+msgstr "dbFS"
+
+#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134
+#: gtk_ardour/gain_meter.cc:728
+msgid "pre"
+msgstr "Ï€Ïο"
+
+#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724
+#, fuzzy
+msgid "input"
+msgstr "%1 είσοδος"
+
+#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732
+#, fuzzy
+msgid "post"
+msgstr "θÏÏα"
+
+#: gtk_ardour/gain_meter.cc:146
+msgid "tupni"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470
+#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537
+msgid "-inf"
+msgstr "-inf"
+
+#: gtk_ardour/imageframe_socket_handler.cc:127
+msgid "Image Compositor Socket has been shutdown/closed"
+msgstr "Η Socket για τον Image Compositor έχει τεÏματιστεί/κλείσει"
+
+#: gtk_ardour/imageframe_time_axis.cc:295
+#, fuzzy
+msgid "0.5 seconds"
+msgstr "ΔευτεÏόλεπτα"
+
+#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259
+#, fuzzy
+msgid "1 seconds"
+msgstr "ΔευτεÏόλεπτα"
+
+#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260
+#, fuzzy
+msgid "1.5 seconds"
+msgstr "ΔευτεÏόλεπτα"
+
+#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261
+#, fuzzy
+msgid "2 seconds"
+msgstr "ΔευτεÏόλεπτα"
+
+#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262
+#, fuzzy
+msgid "2.5 seconds"
+msgstr "ΔευτεÏόλεπτα"
+
+#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263
+#, fuzzy
+msgid "3 seconds"
+msgstr "ΔευτεÏόλεπτα"
+
+#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268
+#, fuzzy
+msgid "Duration (sec)"
+msgstr "Έλξη πεÏιοχής(ων)"
+
+#: gtk_ardour/imageframe_time_axis.cc:310
+#, fuzzy
+msgid "Remove Frame"
+msgstr "Απαλοιφή Πεδίου"
+
+#: gtk_ardour/imageframe_time_axis.cc:313
+#, fuzzy
+msgid "Image Frame"
+msgstr "Frames"
+
+#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274
+#, fuzzy
+msgid "Rename Track"
+msgstr "Μετονομασία"
+
+#: gtk_ardour/io_selector.cc:64
+msgid "%1 input"
+msgstr "%1 είσοδος"
+
+#: gtk_ardour/io_selector.cc:66
+msgid "%1 output"
+msgstr "%1 έξοδος"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103
+msgid "Inputs"
+msgstr "Είσοδοι"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104
+msgid "Outputs"
+msgstr "Έξοδοι"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Input"
+msgstr "Ï€Ïόσθεση εισόδου"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Output"
+msgstr "Ï€Ïόσθεση εξόδου"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Input"
+msgstr "Απαλοιφή σημείου συγχÏονισμοÏ"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Output"
+msgstr "# Έξοδοι"
+
+#: gtk_ardour/io_selector.cc:144
+#, fuzzy
+msgid "Disconnect All"
+msgstr "ΑποσÏνδεση"
+
+#: gtk_ardour/io_selector.cc:158
+msgid "Available connections"
+msgstr "Διαθέσιμες Συνδέσεις"
+
+#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636
+#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724
+msgid "port"
+msgstr "θÏÏα"
+
+#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587
+msgid "There are no more JACK ports available."
+msgstr ""
+
+#: gtk_ardour/io_selector.cc:790
+msgid "ardour: "
+msgstr "ardour: "
+
+#: gtk_ardour/keyboard.cc:419
+msgid "KeyboardTarget: keyname \"%1\" is unknown."
+msgstr "KeyboardTarget: το Όνομα ΠλήκτÏου \"%1\" είναι άγνωστο."
+
+#: gtk_ardour/keyboard.cc:645
+msgid ""
+"Your system is completely broken - NumLock uses \"%1\"as its modifier. This "
+"is madness - see the man page for xmodmap to find out how to fix this."
+msgstr ""
+"Το ΣÏστημά σας έχει χαλάσει τελείως - Το NumLock χÏησιμοποιεί το \"%1\"σαν "
+"μεταβλητή του. Αυτό είναι Ï„Ïέλα - ανατÏέξτε στην man page του xmodmap για να "
+"βÏείτε πώς θα το φτιάξετε."
+
+#: gtk_ardour/keyboard.cc:653
+msgid ""
+"Your system generates \"%1\" when the NumLock key is pressed. This can cause "
+"problems when editing so Ardour will use %2 to mean Meta rather than %1"
+msgstr ""
+"Το ΣÏστημά σας δημιουÏγεί \"%1\" όταν το NumLock είναι εν ενεÏγεία. Αυτό "
+"μποÏεί να δημιουÏγήσει Ï€Ïοβλήματα στην επεξεÏγασία οπότε ο Ardour θα "
+"χÏησιμοποιήσει %2 για Meta αντί του %1"
+
+#: gtk_ardour/keyboard.cc:714
+msgid "You have %1 keys bound to \"mod1\""
+msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod1\""
+
+#: gtk_ardour/keyboard.cc:729
+msgid "You have %1 keys bound to \"mod2\""
+msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod2\""
+
+#: gtk_ardour/keyboard.cc:744
+msgid "You have %1 keys bound to \"mod3\""
+msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod3\""
+
+#: gtk_ardour/keyboard.cc:759
+msgid "You have %1 keys bound to \"mod4\""
+msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod4\""
+
+#: gtk_ardour/keyboard.cc:774
+msgid "You have %1 keys bound to \"mod5\""
+msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod5\""
+
+#: gtk_ardour/keyboard_target.cc:72
+msgid "KeyboardTarget: empty string passed to add_binding."
+msgstr "KeyboardTarget: κενή γÏαμμή στην Ï€Ïόσθεση_δεσμοÏ."
+
+#: gtk_ardour/keyboard_target.cc:78
+msgid "KeyboardTarget: no translation found for \"%1\""
+msgstr "KeyboardTarget: δεν ευÏέθη μετάφÏαση για \"%1\""
+
+#: gtk_ardour/keyboard_target.cc:83
+msgid "KeyboardTarget: unknown action \"%1\""
+msgstr "KeyboardTarget: άγνωστη ενέÏγεια \"%1\""
+
+#: gtk_ardour/keyboard_target.cc:248
+msgid "misformed binding node - ignored"
+msgstr "παÏαμοÏφωμένος πομπός Î´ÎµÏƒÎ¼Î¿Ï - αγνοήθηκε"
+
+#: gtk_ardour/library_ui.cc:62
+msgid "Soundfile Library"
+msgstr "Βιβλιοθήκη Soundfiles"
+
+#: gtk_ardour/library_ui.cc:63
+msgid "Filesystem"
+msgstr "Filesystem"
+
+#: gtk_ardour/library_ui.cc:66
+msgid "Split Channels"
+msgstr "ΔιαχωÏισμός Καναλιών"
+
+#: gtk_ardour/library_ui.cc:69
+msgid "ardour: soundfile selector"
+msgstr "ardour: επιλογέας Soundfiles"
+
+#: gtk_ardour/library_ui.cc:430
+msgid "Add to Library..."
+msgstr "ΠÏόσθεση στη Βιβλιοθήκη..."
+
+#: gtk_ardour/library_ui.cc:431
+msgid "Remove..."
+msgstr "Απαλοιφή..."
+
+#: gtk_ardour/library_ui.cc:432
+msgid "Find..."
+msgstr "ΕÏÏεση..."
+
+#: gtk_ardour/library_ui.cc:433
+msgid "Add Folder"
+msgstr "ΠÏόσθεση Φακέλου"
+
+#: gtk_ardour/library_ui.cc:434
+msgid "Add audio file or directory"
+msgstr "ΠÏόσθεση αÏχείου ήχου ή φακέλου"
+
+#: gtk_ardour/library_ui.cc:713
+msgid "Importing"
+msgstr "Εισαγωγή εν εξελίξι"
+
+#: gtk_ardour/library_ui.cc:748
+msgid "%1 not added to database"
+msgstr "%1 δεν Ï€Ïοστέθηκε στην database"
+
+#: gtk_ardour/library_ui.cc:767
+msgid "Folder name:"
+msgstr "Όνομα φακέλου:"
+
+#: gtk_ardour/library_ui.cc:838
+msgid "Should not be reached"
+msgstr "Δεν θα έπÏεπε να αγγιχτεί"
+
+#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096
+msgid "file \"%1\" could not be opened"
+msgstr "το αÏχείο \"%1\" δεν γινόταν να ανοιχτεί"
+
+#: gtk_ardour/library_ui.cc:956
+msgid "Field"
+msgstr "Πεδίο"
+
+#: gtk_ardour/library_ui.cc:957
+msgid "Value"
+msgstr "Αξία"
+
+#: gtk_ardour/library_ui.cc:973
+msgid "Stop"
+msgstr "ΠαÏση"
+
+#: gtk_ardour/library_ui.cc:974
+msgid "Add Field..."
+msgstr "ΠÏόσθεση Πεδίου..."
+
+#: gtk_ardour/library_ui.cc:975
+msgid "Remove Field"
+msgstr "Απαλοιφή Πεδίου"
+
+#: gtk_ardour/library_ui.cc:979
+msgid "Soundfile Info"
+msgstr "ΠληÏοφοÏίες για το Soundfile"
+
+#: gtk_ardour/library_ui.cc:1106
+msgid "file \"%1\" appears not to be an audio file"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1159
+msgid "Could not read file: %1 (%2)."
+msgstr "Δεν γινόταν να διαβαστεί το αÏχείο: %1 (%2)."
+
+#: gtk_ardour/library_ui.cc:1177
+msgid "Could not access soundfile: "
+msgstr "Δεν γινόταν να διαβαστεί το soundfile: "
+
+#: gtk_ardour/library_ui.cc:1222
+msgid "Field name:"
+msgstr "Όνομα Πεδίου:"
+
+#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367
+msgid "Field value:"
+msgstr "Αξία Πεδίου:"
+
+#: gtk_ardour/library_ui.cc:1295
+msgid "Find"
+msgstr "ΕÏÏεση"
+
+#: gtk_ardour/library_ui.cc:1296
+msgid "AND"
+msgstr "AND"
+
+#: gtk_ardour/library_ui.cc:1297
+msgid "OR"
+msgstr "OR"
+
+#: gtk_ardour/library_ui.cc:1300
+msgid "ardour: locate soundfiles"
+msgstr "ardour: εÏÏεση soundfiles"
+
+#: gtk_ardour/library_ui.cc:1426
+msgid "Results"
+msgstr "Αποτελέσματα"
+
+#: gtk_ardour/library_ui.cc:1427
+msgid "Uris"
+msgstr "Uris"
+
+#: gtk_ardour/library_ui.cc:1439
+msgid "Create multi-channel region"
+msgstr "ΔημιουÏγία πολυκάναλης πεÏιοχής"
+
+#: gtk_ardour/library_ui.cc:1442
+msgid "Ardour: Search Results"
+msgstr "Ardour: Αποτελέσματα Αναζητήσεως"
+
+#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50
+msgid "Set"
+msgstr "Θέση"
+
+#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51
+msgid "Go"
+msgstr "Πήγαινε"
+
+#: gtk_ardour/location_ui.cc:54
+msgid "CD"
+msgstr "CD"
+
+#: gtk_ardour/location_ui.cc:55
+msgid "Hidden"
+msgstr "ΚÏυμμένο"
+
+#: gtk_ardour/location_ui.cc:57
+msgid "SCMS"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:58
+msgid "Pre-Emphasis"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:592
+msgid "Add New Location"
+msgstr "ΠÏόσθεση νέας τοποθεσίας"
+
+#: gtk_ardour/location_ui.cc:593
+msgid "Add New Range"
+msgstr "ΠÏόσθεση νέου διαστήματος"
+
+#: gtk_ardour/location_ui.cc:597
+msgid "ardour: locations"
+msgstr "ardour: τοποθεσίες"
+
+#: gtk_ardour/location_ui.cc:598
+msgid "ardour_locations"
+msgstr "ardour_τοποθεσίες"
+
+#: gtk_ardour/location_ui.cc:629
+#, fuzzy
+msgid "Location (CD Index) Markers"
+msgstr "Στίγματα Τοποθεσίας"
+
+#: gtk_ardour/location_ui.cc:649
+#, fuzzy
+msgid "Range (CD Track) Markers"
+msgstr "Στίγματα διαστημάτων"
+
+#: gtk_ardour/location_ui.cc:814
+msgid "add range marker"
+msgstr "Ï€Ïόσθεση στίγματος διαστήματος"
+
+#: gtk_ardour/main.cc:76
+msgid "ardour is killing itself for a clean exit\n"
+msgstr "Ο ardour σκοτώνει τον εαυτό του για καθαÏή έξοδο\n"
+
+#: gtk_ardour/main.cc:85
+msgid "stopping user interface\n"
+msgstr "παÏση του user interface\n"
+
+#: gtk_ardour/main.cc:104
+#, fuzzy, c-format
+msgid "%d(%d): received signal %d\n"
+msgstr "%d: εδέχθη σήμα %d\n"
+
+#: gtk_ardour/main.cc:190
+msgid "cannot become new process group leader (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:217
+msgid "cannot setup signal handling for %1"
+msgstr "δεν γίνεται να διαμοÏφώθεί η διαχείÏηση σημάτων για %1"
+
+#: gtk_ardour/main.cc:228
+msgid "cannot set default signal mask (%1)"
+msgstr "δεν γίνεται να διαμοÏφώθεί η Ï€ÏοκαθοÏισμένη μάσκα σημάτων (%1)"
+
+#: gtk_ardour/main.cc:253
+#, fuzzy
+msgid ""
+"Without a UI style file, ardour will look strange.\n"
+" Please set ARDOUR_UI_RC to point to a valid UI style file"
+msgstr ""
+"Δίχως αÏχείο εμφάνισεως UI, ο ardour θα φαίνεται παÏάξενα.\n"
+"ΠαÏακαλώ θέστε το ARDOUR_UI_RC να δείχνει σε ενεÏγό αÏχείο εμφανίσεως UI"
+
+#: gtk_ardour/main.cc:292
+msgid ""
+"Ardour could not connect to JACK.\n"
+"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 ""
+"Ο Ardour δεν μπόÏεσε να συνδεθεί στον JACK.\n"
+"ΥπάÏχουν διάφοÏοι πιθανοί λόγοι:\n"
+"\n"
+"1) Ο JACK δεν Ï„Ïέχει.\n"
+"2) JACK Ï„Ïέχει σαν άλλος ΧÏήστης, ίσως σαν root.\n"
+"3) ΥπάÏχει ήδη άλλο Ï€ÏόγÏαμμα με το όνομα \"ardour\".\n"
+"\n"
+"ΠαÏακαλώ αναλογιστείτε τις πιθανότητες, και ίσως (ξανα)ξεκινήστε τον JACK."
+
+#: gtk_ardour/main.cc:305
+msgid "ardour: unplugged"
+msgstr "ardour: unplugged"
+
+#: gtk_ardour/main.cc:363
+msgid "Ardour/GTK "
+msgstr "Ardour/GTK "
+
+#: gtk_ardour/main.cc:365
+msgid ""
+"\n"
+" (built using "
+msgstr ""
+
+#: gtk_ardour/main.cc:369
+#, fuzzy
+msgid " with libardour "
+msgstr " Ï„Ïέχοντας με libardour "
+
+#: gtk_ardour/main.cc:374
+msgid " and GCC version "
+msgstr ""
+
+#: gtk_ardour/main.cc:384
+#, fuzzy
+msgid "Copyright (C) 1999-2005 Paul Davis"
+msgstr "Πνευματικα Δικαιώματα 1999-2004 Paul Davis"
+
+#: gtk_ardour/main.cc:385
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+msgstr ""
+
+#: gtk_ardour/main.cc:387
+msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
+msgstr "Ο Ardour έÏχεται με απολÏτως ΚΑΜΙΑ ΕΓΓΥΗΣΗ"
+
+#: gtk_ardour/main.cc:388
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr ""
+
+#: gtk_ardour/main.cc:389
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr ""
+"Το παÏόν είναι ελεÏθεÏο λογισμικό, είστε ελεÏθεÏοι να το επαναδιανείμετε "
+
+#: gtk_ardour/main.cc:390
+#, fuzzy
+msgid "under certain conditions; see the source for copying conditions."
+msgstr "υπό οÏισμένους ÏŒÏους, ανατÏέξτε στο αÏχείο COPYING για λεπτομέÏειες"
+
+#: gtk_ardour/main.cc:399
+msgid "could not create ARDOUR GUI"
+msgstr "δεν γινόταν να δημιουÏγηθεί ARDOUR GUI"
+
+#: gtk_ardour/main.cc:419
+msgid "Could not connect to JACK server as \"%1\""
+msgstr "Δεν γινόταν να συνδεθώ στον JACK server σαν \"%1\""
+
+#: gtk_ardour/main.cc:424
+msgid "could not initialize Ardour."
+msgstr "δεν γινόταν να εκκινηθεί ο Ardour."
+
+#: gtk_ardour/main.cc:435
+msgid "could not load command line session \"%1\""
+msgstr "δεν γινόταν να φοÏτωθεί η συνεδÏία γÏαμμής εντολών \"%1\""
+
+#: gtk_ardour/main.cc:455
+msgid ""
+"\n"
+"\n"
+"A session named \"%1\" already exists.\n"
+"To avoid this message, start ardour as \"ardour %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:466
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as \"ardour --new %1"
+msgstr ""
+
+#: gtk_ardour/marker.cc:354
+#, fuzzy
+msgid "MarkerText"
+msgstr "Στίγματα"
+
+#: gtk_ardour/marker_time_axis.cc:271
+#, fuzzy
+msgid "Remove Marker"
+msgstr "απαλοιφή στίγματος"
+
+#: gtk_ardour/marker_time_axis.cc:273
+#, fuzzy
+msgid "Marker"
+msgstr "Στίγματα"
+
+#: gtk_ardour/meter_bridge.cc:74
+msgid "ardour: meter bridge"
+msgstr "ardour: γέφυÏα μετÏήσεων"
+
+#: gtk_ardour/meter_bridge.cc:75
+msgid "ardour_meter_bridge"
+msgstr "ardour_γέφυÏα_μετÏήσεων"
+
+#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93
+#, c-format
+msgid "# of %u-sample overs"
+msgstr "# από %u-sample overs"
+
+#: gtk_ardour/meter_bridge_strip.cc:219
+msgid "New name for meter:"
+msgstr "Îέο όνομα για μετÏητή:"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507
+#: gtk_ardour/region_editor.cc:45
+msgid "mute"
+msgstr "σιγή"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508
+msgid "solo"
+msgstr "σόλο"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506
+msgid "RECORD"
+msgstr "ΕΓΓΡΑΦΗ"
+
+#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514
+msgid "polarity"
+msgstr "πολικότητα"
+
+#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509
+msgid "comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810
+msgid "INPUT"
+msgstr "ΕΙΣΟΔΟΣ"
+
+#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831
+msgid "OUTPUT"
+msgstr "ΕΞΟΔΟΣ"
+
+#: gtk_ardour/mixer_strip.cc:173
+msgid "Pan automation mode"
+msgstr "ΛειτουÏγία Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Pan"
+
+#: gtk_ardour/mixer_strip.cc:174
+msgid "Gain automation mode"
+msgstr "ΛειτουÏγία Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Gain"
+
+#: gtk_ardour/mixer_strip.cc:176
+msgid "Pan automation type"
+msgstr "ΤÏπος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Pan"
+
+#: gtk_ardour/mixer_strip.cc:177
+msgid "Gain automation type"
+msgstr "ΤÏπος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Gain"
+
+#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232
+#: gtk_ardour/mixer_strip.cc:979
+msgid "trim"
+msgstr "ισοστάθμιση"
+
+#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233
+#: gtk_ardour/mixer_strip.cc:983
+msgid "abs"
+msgstr "abs"
+
+#: gtk_ardour/mixer_strip.cc:240
+msgid "gain automation mode"
+msgstr "ΛειτουÏγία Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï gain"
+
+#: gtk_ardour/mixer_strip.cc:241
+msgid "pan automation mode"
+msgstr "ΛειτουÏγία Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï pan"
+
+#: gtk_ardour/mixer_strip.cc:242
+msgid "gain automation state"
+msgstr "Κατάσταση Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï gain"
+
+#: gtk_ardour/mixer_strip.cc:243
+msgid "pan automation state"
+msgstr "Κατάσταση Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï pan"
+
+#: gtk_ardour/mixer_strip.cc:259
+msgid "varispeed"
+msgstr "μεταβλητή ταχÏτητα"
+
+#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174
+msgid "click to add/edit comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:463
+msgid "unknown strip width \"%1\" in XML GUI information"
+msgstr "άγνωστο εÏÏος διαδÏόμου \"%1\" στις πληÏοφοÏίες του XML GUI"
+
+#: gtk_ardour/mixer_strip.cc:522
+msgid "REC"
+msgstr "REC"
+
+#: gtk_ardour/mixer_strip.cc:525
+#, fuzzy
+msgid "cmt"
+msgstr "κοπή"
+
+#: gtk_ardour/mixer_strip.cc:530
+msgid "pol"
+msgstr "πολ"
+
+#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620
+#: gtk_ardour/redirect_box.cc:1180
+msgid "Not connected to JACK - no I/O changes are possible"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667
+msgid "could not register new ports required for that connection"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:813
+msgid "IN"
+msgstr "IN"
+
+#: gtk_ardour/mixer_strip.cc:834
+msgid "OUT"
+msgstr "OUT"
+
+#: gtk_ardour/mixer_strip.cc:950
+msgid "aplay"
+msgstr "aplay"
+
+#: gtk_ardour/mixer_strip.cc:956
+msgid "awrite"
+msgstr "awrite"
+
+#: gtk_ardour/mixer_strip.cc:1134
+#, fuzzy
+msgid ": comment editor"
+msgstr "UI: Ο 'editor' δεν μποÏεί να εγεÏθεί"
+
+#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224
+msgid "no group"
+msgstr "καμία ομάδα"
+
+#: gtk_ardour/mixer_strip.cc:1227
+msgid "~G"
+msgstr "~G"
+
+#: gtk_ardour/mixer_ui.cc:52
+msgid "Strips"
+msgstr "ΔιάδÏομοι"
+
+#: gtk_ardour/mixer_ui.cc:56
+msgid "Snapshots"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:61
+msgid "***"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17
+#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144
+#: gtk_ardour/tempo_dialog.cc:162
+msgid "Bar"
+msgstr "ΜπάÏα"
+
+#: gtk_ardour/mixer_ui.cc:121
+msgid "Mix Groups"
+msgstr "Ανάμειξη ομάδων"
+
+#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373
+msgid "ardour: mixer"
+msgstr "ardour: μίκτης"
+
+#: gtk_ardour/mixer_ui.cc:192
+msgid "ardour_mixer"
+msgstr "ardour_μίκτης"
+
+#: gtk_ardour/mixer_ui.cc:342
+msgid "ardour: mixer: "
+msgstr "ardour: μίκτης: "
+
+#: gtk_ardour/mixer_ui.cc:641
+msgid "signal"
+msgstr "σήμα"
+
+#: gtk_ardour/mixer_ui.cc:672
+msgid "Show All AudioTrack MixerStrips"
+msgstr "Ανάδειξη όλων των ΔιαδÏόμωνΜίξεως των καναλιών"
+
+#: gtk_ardour/mixer_ui.cc:673
+msgid "Hide All AudioTrack MixerStrips"
+msgstr "ΑπόκÏυψη όλων των ΔιαδÏόμωνΜίξεως των καναλιών"
+
+#: gtk_ardour/mixer_ui.cc:674
+msgid "Show All AudioBus MixerStrips"
+msgstr "Ανάδειξη όλων των ΔιαδÏόμωνΜίξεως των διαÏλων"
+
+#: gtk_ardour/mixer_ui.cc:675
+msgid "Hide All AudioBus MixerStrips"
+msgstr "ΑπόκÏυψη όλων των ΔιαδÏόμωνΜίξεως των διαÏλων"
+
+#: gtk_ardour/mixer_ui.cc:687
+msgid "track display list item for renamed strip not found!"
+msgstr "Λίστα αναδείξεως καναλιών για μετονομασμένο διάδÏομο δεν ευÏέθη!"
+
+#: gtk_ardour/mixer_ui.cc:700
+msgid "Name for new mix group"
+msgstr "Όνομα για νέα ομάδα μίξεως"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Session name:"
+msgstr "Όνομα συνεδÏίας:"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Create"
+msgstr "ΔημιουÏγία"
+
+#: gtk_ardour/new_session_dialog.cc:40
+msgid "use control outs"
+msgstr "χÏήση των control outs"
+
+#: gtk_ardour/new_session_dialog.cc:41
+msgid "use master outs"
+msgstr "χÏήση των master outs"
+
+#: gtk_ardour/new_session_dialog.cc:42
+msgid "automatically connect track inputs to physical ports"
+msgstr "αυτόματη σÏνδεση inputs καναλιών σε φυσικές θÏÏες"
+
+#: gtk_ardour/new_session_dialog.cc:43
+msgid "automatically connect track outputs to master outs"
+msgstr "αυτόματη σÏνδεση outputs καναλιών σε master outs"
+
+#: gtk_ardour/new_session_dialog.cc:44
+msgid "automatically connect track outputs to physical ports"
+msgstr "αυτόματη σÏνδεση outputs καναλιών σε φυσικές θÏÏες"
+
+#: gtk_ardour/new_session_dialog.cc:45
+msgid "manually connect track outputs"
+msgstr "χειÏοκίνητη σÏνδεση των outputs των καναλιών"
+
+#: gtk_ardour/new_session_dialog.cc:50
+msgid "Advanced..."
+msgstr "ΠÏοχωÏημένα..."
+
+#: gtk_ardour/new_session_dialog.cc:52
+msgid "show again"
+msgstr "δείξε πάλι"
+
+#: gtk_ardour/new_session_dialog.cc:55
+msgid "Hardware Inputs: use"
+msgstr "Hardware Είσοδοι: χÏήση"
+
+#: gtk_ardour/new_session_dialog.cc:56
+msgid "Hardware Outputs: use"
+msgstr "Hardware Έξοδοι: χÏήση"
+
+#: gtk_ardour/new_session_dialog.cc:62
+msgid "new session setup"
+msgstr "νέα δαÏÏÏθμιση συνεδÏίας"
+
+#: gtk_ardour/new_session_dialog.cc:63
+msgid "ardour_new_session"
+msgstr "ardour_νέα_συνεδÏία"
+
+#: gtk_ardour/new_session_dialog.cc:72
+msgid "This session will playback and record at %1 Hz"
+msgstr "Αυτή η συνεδÏία θα αναπαÏάγει και θα εγγÏάφει στα %1 Hz"
+
+#: gtk_ardour/new_session_dialog.cc:74
+msgid ""
+"This rate is set by JACK and cannot be changed.\n"
+"If you want to use a different sample rate\n"
+"please exit and restart JACK"
+msgstr ""
+"Αυτος ο 'Ïυθμός'(sample rate) τίθεται από τον JACK και δεν μποÏεί να "
+"αλλάξει.\n"
+"Αν επιθυμείτε να θέσετε διαφοÏετικό 'Ïυθμό'\n"
+"παÏακαλώ βγείτε και επανεκκινήστε τον JACK"
+
+#: gtk_ardour/new_session_dialog.cc:155
+msgid "Session template"
+msgstr "ΠÏοσχέδιο συνεδÏίας"
+
+#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20
+#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146
+#: gtk_ardour/tempo_dialog.cc:164
+msgid "Location"
+msgstr "Τοποθεσία"
+
+#: gtk_ardour/new_session_dialog.cc:178
+msgid "Configuration"
+msgstr "Διάταξη"
+
+#: gtk_ardour/new_session_dialog.cc:269
+msgid "blank"
+msgstr "κενό"
+
+#: gtk_ardour/new_session_dialog.cc:328
+msgid "No template - create tracks/busses manually"
+msgstr "ΧωÏίς Ï€Ïοσχέδιο - δημιουÏγία καναλιών/διαÏλων χειÏοκίνητα"
+
+#: gtk_ardour/new_session_dialog.cc:337
+msgid "No template"
+msgstr "ΧωÏίς Ï€Ïοσχέδιο"
+
+#: gtk_ardour/option_editor.cc:48
+msgid "Internal"
+msgstr "ΕσωτεÏικό"
+
+#: gtk_ardour/option_editor.cc:49
+msgid "Slave to MTC"
+msgstr "Slave στον MTC"
+
+#: gtk_ardour/option_editor.cc:50
+msgid "Sync with JACK"
+msgstr "ΣÏγχÏονος με τον JACK"
+
+#: gtk_ardour/option_editor.cc:51
+msgid "never used but stops crashes"
+msgstr "αχÏησιμοποίητο αλλά σταματά τα crashes"
+
+#: gtk_ardour/option_editor.cc:56
+#, fuzzy
+msgid "Later regions are higher"
+msgstr "Υποβίβαση πεÏιοχής κατά ένα στÏώμα"
+
+#: gtk_ardour/option_editor.cc:57
+msgid "Most recently added/moved/trimmed regions are higher"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:58
+#, fuzzy
+msgid "Most recently added regions are higher"
+msgstr "Υποβίβαση πεÏιοχής κατά ένα στÏώμα"
+
+#: gtk_ardour/option_editor.cc:63
+#, fuzzy
+msgid "Span entire region overlap"
+msgstr "ΑνόÏθωση πεÏιοχής κατά ένα στÏώμα"
+
+#: gtk_ardour/option_editor.cc:64
+msgid "Short fades at the start of the overlap"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:82
+#, fuzzy
+msgid "Automatically create crossfades"
+msgstr "Αυτόματο crossfade στα overlap"
+
+#: gtk_ardour/option_editor.cc:83
+msgid "New full-overlap crossfades are unmuted"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:84
+#, fuzzy
+msgid "Region layering mode"
+msgstr "Τέλη ΠεÏιοχών"
+
+#: gtk_ardour/option_editor.cc:85
+#, fuzzy
+msgid "Crossfade model"
+msgstr "Crossfade"
+
+#: gtk_ardour/option_editor.cc:90
+msgid "Latched solo"
+msgstr "ΠÏοσκολλημένο σόλο"
+
+#: gtk_ardour/option_editor.cc:91
+msgid "Solo via bus"
+msgstr "Solo μέσω διαÏλου"
+
+#: gtk_ardour/option_editor.cc:96
+msgid "Show waveforms while recording"
+msgstr "Ανάδειξη κυματομοÏφών κατά την εγγÏαφή"
+
+#: gtk_ardour/option_editor.cc:97
+msgid "Narrow mixer strips"
+msgstr "Στενοί διάδÏομοι μείκτη"
+
+#: gtk_ardour/option_editor.cc:98
+msgid "Show measure lines"
+msgstr "Ανάδειξη γÏαμμών μετÏήσεων"
+
+#: gtk_ardour/option_editor.cc:99
+msgid "Follow playhead"
+msgstr "Ακολουθία ΑναπαÏαγωγέα"
+
+#: gtk_ardour/option_editor.cc:103
+msgid "Send MTC"
+msgstr "Αποστολή MTC"
+
+#: gtk_ardour/option_editor.cc:104
+msgid "Send MMC"
+msgstr "Αποστολή MMC"
+
+#: gtk_ardour/option_editor.cc:105
+msgid "JACK time master"
+msgstr "JACK master χÏόνου"
+
+#: gtk_ardour/option_editor.cc:107
+#, fuzzy
+msgid "SMPTE offset is negative"
+msgstr "SMPTE ΈναÏξη"
+
+#: gtk_ardour/option_editor.cc:111
+msgid "Send MIDI parameter feedback"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:112
+msgid "MIDI parameter control"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:113
+#, fuzzy
+msgid "MMC control"
+msgstr "MMC ΘÏÏα"
+
+#: gtk_ardour/option_editor.cc:131
+#, fuzzy
+msgid "Auto-connect new track inputs to hardware"
+msgstr "Αυτο-σÏνδεση νέων καναλιών"
+
+#: gtk_ardour/option_editor.cc:132
+#, fuzzy
+msgid "Auto-connect new track outputs to hardware"
+msgstr "Αυτο-σÏνδεση νέων καναλιών"
+
+#: gtk_ardour/option_editor.cc:133
+#, fuzzy
+msgid "Auto-connect new track outputs to master bus"
+msgstr "αυτόματη σÏνδεση outputs καναλιών σε master outs"
+
+#: gtk_ardour/option_editor.cc:134
+#, fuzzy
+msgid "Manually connect new track outputs"
+msgstr "χειÏοκίνητη σÏνδεση των outputs των καναλιών"
+
+#: gtk_ardour/option_editor.cc:135
+msgid "Use Hardware Monitoring"
+msgstr "ΧÏήση Hardware Monitoring"
+
+#: gtk_ardour/option_editor.cc:136
+msgid "Use Software Monitoring"
+msgstr "ΧÏήση Software Monitoring"
+
+#: gtk_ardour/option_editor.cc:137
+msgid "Stop plugins with transport"
+msgstr "Λήξη των plugins με την παÏση"
+
+#: gtk_ardour/option_editor.cc:138
+msgid "Run plugins while recording"
+msgstr "ΛειτουÏγία plugins κατα την εγγÏαφή"
+
+#: gtk_ardour/option_editor.cc:139
+#, fuzzy
+msgid "Verify remove last capture"
+msgstr "Απαλοιφή τελευταίας λήψης"
+
+#: gtk_ardour/option_editor.cc:140
+msgid "Stop recording on xrun"
+msgstr "ΠαÏση εγγÏαφής στα xrun"
+
+#: gtk_ardour/option_editor.cc:141
+msgid "Stop transport at end of session"
+msgstr "Στάση αναπαÏαγωγέα στο τέλος της συνεδÏίας"
+
+#: gtk_ardour/option_editor.cc:142
+msgid "Debug keyboard events"
+msgstr "Debug γεγονότα πληκτÏολογίου"
+
+#: gtk_ardour/option_editor.cc:143
+msgid "-12dB gain reduction for ffwd/rew"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:152
+msgid "ardour: options editor"
+msgstr "ardour: επεξεÏγαστής Ïυθμίσεων"
+
+#: gtk_ardour/option_editor.cc:153
+msgid "ardour_option_editor"
+msgstr "ardour_επεξεÏγαστής_Ïυθμίσεων"
+
+#: gtk_ardour/option_editor.cc:183
+msgid "Misc"
+msgstr "ΔιάφοÏα"
+
+#: gtk_ardour/option_editor.cc:184
+msgid "Sync"
+msgstr "Sync"
+
+#: gtk_ardour/option_editor.cc:185
+msgid "Paths/Files"
+msgstr "Paths/ΑÏχεία"
+
+#: gtk_ardour/option_editor.cc:186
+msgid "Display"
+msgstr "Απεικόνιση"
+
+#: gtk_ardour/option_editor.cc:187
+msgid "Kbd/Mouse"
+msgstr "ΠλκτÏ/Ποντίκι"
+
+#: gtk_ardour/option_editor.cc:188
+msgid "Click"
+msgstr "ΜετÏονόμος"
+
+#: gtk_ardour/option_editor.cc:190
+msgid "Layers & Fades"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:195
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gtk_ardour/option_editor.cc:268
+msgid "24 FPS"
+msgstr "24 FPS"
+
+#: gtk_ardour/option_editor.cc:270
+msgid "25 FPS"
+msgstr "25 FPS"
+
+#: gtk_ardour/option_editor.cc:272
+#, fuzzy
+msgid "30 FPS"
+msgstr "30 FPS drop"
+
+#: gtk_ardour/option_editor.cc:278
+msgid "30 FPS drop"
+msgstr "30 FPS drop"
+
+#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379
+#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736
+#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800
+msgid "Medium"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738
+#: gtk_ardour/option_editor.cc:804
+#, fuzzy
+msgid "Faster"
+msgstr "ΤαχÏ"
+
+#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714
+#: gtk_ardour/option_editor.cc:776
+#, fuzzy
+msgid "Short"
+msgstr "θÏÏα"
+
+#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716
+#: gtk_ardour/option_editor.cc:780
+msgid "Long"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:396
+msgid "Broadcast WAVE/floating point"
+msgstr "Broadcast WAVE/μεταβλητής υποδ/λής"
+
+#: gtk_ardour/option_editor.cc:397
+msgid "WAVE/floating point"
+msgstr "WAVE/μεταβλητής υποδ/λής"
+
+#: gtk_ardour/option_editor.cc:417
+msgid "session RAID path"
+msgstr "RAID path συνεδÏίας"
+
+#: gtk_ardour/option_editor.cc:422
+msgid "Native Format"
+msgstr "Εντόπιο Format"
+
+#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460
+#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409
+msgid "internal"
+msgstr "εσωτεÏικό"
+
+#: gtk_ardour/option_editor.cc:537
+msgid "Short crossfade length (msecs)"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:710
+msgid "Meter Peak Hold"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:730
+msgid "Meter Falloff"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:847
+msgid "Positional Sync"
+msgstr "Τοποθεσιακό Sync"
+
+#: gtk_ardour/option_editor.cc:902
+msgid "SMPTE Frames/second"
+msgstr "SMPTE ΚαÏέ/δεÏτεÏα"
+
+#: gtk_ardour/option_editor.cc:903
+msgid "SMPTE Offset"
+msgstr "SMPTE ΈναÏξη"
+
+#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013
+#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211
+#, fuzzy
+msgid "online"
+msgstr "γÏαμμική"
+
+#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014
+#: gtk_ardour/option_editor.cc:1208
+#, fuzzy
+msgid "offline"
+msgstr "γÏαμμική"
+
+#: gtk_ardour/option_editor.cc:1319
+msgid "Use as click"
+msgstr "ΧÏήση όπως στο μετÏονόμο"
+
+#: gtk_ardour/option_editor.cc:1344
+msgid "Use as click emphasis"
+msgstr "Έμφαση χÏήσεως όπως στο μετÏονόμο"
+
+#: gtk_ardour/option_editor.cc:1478
+msgid "--unknown--"
+msgstr "--άγνωστο--"
+
+#: gtk_ardour/option_editor.cc:1595
+msgid "Click audio file"
+msgstr "ΑÏχείο ήχου ΜετÏονόμου"
+
+#: gtk_ardour/option_editor.cc:1601
+msgid "Click emphasis audiofile"
+msgstr "ΑÏχείο ήχου εμφάσεως ΜετÏονόμου"
+
+#: gtk_ardour/option_editor.cc:1638
+msgid ""
+"The auditioner is a dedicated mixer strip used\n"
+"for listening to specific regions outside the context\n"
+"of the overall mix. It can be connected just like any\n"
+"other mixer strip."
+msgstr ""
+"Ο 'ακÏοατής' είναι ένας αφοσιωμένος διάδÏομος μίξεως που χÏησιμοποιείται\n"
+"για ακÏόαση συγκεκÏιμένων πεÏιοχών εκτός\n"
+"του Î³ÎµÎ½Î¹ÎºÎ¿Ï Î¼Î¹Î¾Î±Ïίσματος. ΜποÏεί να συνδεθεί σαν άλλος ένας\n"
+"διάδÏομος μίξεως ή κανάλι."
+
+#: gtk_ardour/option_editor.cc:1887
+msgid "Edit using"
+msgstr "ΕπεξεÏγασία με"
+
+#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924
+msgid "+ button"
+msgstr "+ κουμπί"
+
+#: gtk_ardour/option_editor.cc:1917
+msgid "Delete using"
+msgstr "ΔιαγÏαφή με"
+
+#: gtk_ardour/option_editor.cc:1947
+msgid "Ignore snap using"
+msgstr "Άγνοια έλξεως με"
+
+#: gtk_ardour/opts.cc:46
+msgid "Usage: "
+msgstr "ΧÏήση: "
+
+#: gtk_ardour/opts.cc:47
+msgid " -v, --version Show version information\n"
+msgstr " -v, --version ΠληÏοφοÏίες εκδόσεως\n"
+
+#: gtk_ardour/opts.cc:48
+msgid " -h, --help Print this message\n"
+msgstr " -h, --help ΠÏοβολή του παÏόντος\n"
+
+#: gtk_ardour/opts.cc:49
+msgid ""
+" -b, --bindings Print all possible keyboard binding "
+"names\n"
+msgstr ""
+" -b, --bindings ΠÏοβολή όλων των πιθανών δεσμών "
+"πληκτÏολογίου ονόματα\n"
+
+#: gtk_ardour/opts.cc:50
+#, fuzzy
+msgid " -n, --show-splash Show splash screen\n"
+msgstr " -n, --no-splash Μήν δείξεις την εισαγωγική εικόνα\n"
+
+#: gtk_ardour/opts.cc:51
+#, fuzzy
+msgid ""
+" -c, --name name Use a specific jack client name, default "
+"is ardour\n"
+msgstr ""
+" -c, --jack-client-name name ΧÏήση συγκεκÏιμένου ονόματος για τον "
+"jack, το Ï€ÏοκαθοÏισμένο είναι ardour\n"
+
+#: gtk_ardour/opts.cc:52
+#, fuzzy
+msgid ""
+" -N, --new session-name Create a new session from the command "
+"line\n"
+msgstr " [όνομα-συνεδÏίας] Όνομα συνεδÏίας Ï€Ïος φόÏτωση\n"
+
+#: gtk_ardour/opts.cc:53
+msgid ""
+" -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:55
+#, fuzzy
+msgid " -V, --novst Do not use VST support\n"
+msgstr " -n, --no-splash Μήν δείξεις την εισαγωγική εικόνα\n"
+
+#: gtk_ardour/opts.cc:57
+msgid " [session-name] Name of session to load\n"
+msgstr " [όνομα-συνεδÏίας] Όνομα συνεδÏίας Ï€Ïος φόÏτωση\n"
+
+#: gtk_ardour/opts.cc:58
+msgid " -C, --curvetest filename Curve algorithm debugger\n"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:58
+msgid "You can't graphically edit panning of more than stream"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:78
+#, fuzzy
+msgid "add pan automation event"
+msgstr "Ï€Ïόσθεση συμβάντος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï ÏƒÎµ "
+
+#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441
+#, fuzzy
+msgid "Bypass"
+msgstr "bypass"
+
+#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222
+#, fuzzy
+msgid "link"
+msgstr "in"
+
+#: gtk_ardour/panner_ui.cc:103
+msgid "panning link control"
+msgstr "έλεγχος panning link"
+
+#: gtk_ardour/panner_ui.cc:105
+msgid "panning link direction"
+msgstr "κατεÏθυνση panning link"
+
+#: gtk_ardour/panner_ui.cc:232
+msgid "L"
+msgstr "L"
+
+#: gtk_ardour/panner_ui.cc:344
+#, c-format
+msgid "panner for channel %u"
+msgstr "panner για το κανάλι %u"
+
+#: gtk_ardour/panner_ui.cc:451
+#, fuzzy
+msgid "Reset all"
+msgstr "Επιλογή όλων"
+
+#: gtk_ardour/playlist_selector.cc:46
+msgid "Playlists grouped by track"
+msgstr ""
+
+#: gtk_ardour/playlist_selector.cc:53
+#, fuzzy
+msgid "close"
+msgstr "Κλείσιμο"
+
+#: gtk_ardour/playlist_selector.cc:59
+#, fuzzy
+msgid "ardour: playlists"
+msgstr "ardour: plugins"
+
+#: gtk_ardour/playlist_selector.cc:104
+#, fuzzy
+msgid "ardour: playlist for "
+msgstr "ardour: επεξεÏγαστής: "
+
+#: gtk_ardour/playlist_selector.cc:122
+#, fuzzy
+msgid "Other tracks"
+msgstr "νÏξη καναλιοÏ"
+
+#: gtk_ardour/playlist_selector.cc:138
+msgid "unassigned"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:41
+msgid "Available LADSPA plugins"
+msgstr "Διαθέσιμα LADSPA plugins"
+
+#: gtk_ardour/plugin_selector.cc:42
+msgid "Type"
+msgstr "ΤÏπωση"
+
+#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51
+msgid "# Inputs"
+msgstr "# Είσοδοι"
+
+#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52
+msgid "# Outputs"
+msgstr "# Έξοδοι"
+
+#: gtk_ardour/plugin_selector.cc:50
+msgid "Available VST plugins"
+msgstr "Διαθέσιμα VST plugins"
+
+#: gtk_ardour/plugin_selector.cc:58
+msgid "To be added"
+msgstr "ΠÏόκειται να Ï€ÏοστεθοÏν"
+
+#: gtk_ardour/plugin_selector.cc:72
+msgid "ardour: plugins"
+msgstr "ardour: plugins"
+
+#: gtk_ardour/plugin_selector.cc:82
+msgid "Add a plugin to the effect list"
+msgstr "ΠÏόσθεση plugin στη λίστα των εφφέ"
+
+#: gtk_ardour/plugin_selector.cc:84
+msgid "Remove a plugin from the effect list"
+msgstr "Απαλοιφή plugin από τη λίστα των εφφέ"
+
+#: gtk_ardour/plugin_selector.cc:88
+msgid "Update"
+msgstr "Ανανέωση"
+
+#: gtk_ardour/plugin_selector.cc:89
+msgid "Update available plugins"
+msgstr "Ανανέωση διαθέσιμων plugins"
+
+#: gtk_ardour/plugin_selector.cc:110
+msgid "LADSPA"
+msgstr "LADSPA"
+
+#: gtk_ardour/plugin_selector.cc:113
+msgid "VST"
+msgstr "VST"
+
+#: gtk_ardour/plugin_ui.cc:83
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this "
+"version of ardour)"
+msgstr ""
+"άγνωστος Ï„Ïπος Ï€Ïομηθευμένου plugin για τον editor(σημείωση: δεν υπάÏχει "
+"υποστήÏιξη VST στην παÏοÏσα έκδοση του ardour)"
+
+#: gtk_ardour/plugin_ui.cc:269
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr ""
+"ΕπεξεÏγαστής Plugin: δεν μπόÏεσα να κτίσω στοιχείο ελέγχου για τη θÏÏα %1"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "in"
+msgstr "in"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "ins"
+msgstr "ins"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "out"
+msgstr "out"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "outs"
+msgstr "outs"
+
+#: gtk_ardour/plugin_ui.cc:382
+msgid "automation control"
+msgstr "έλεγχος αυτοματισμοÏ"
+
+#: gtk_ardour/plugin_ui.cc:869
+msgid "save"
+msgstr "αποθήκευση"
+
+#: gtk_ardour/plugin_ui.cc:870
+msgid "bypass"
+msgstr "bypass"
+
+#: gtk_ardour/plugin_ui.cc:892
+msgid "Plugin preset %1 not found"
+msgstr "ΠÏο-ÏÏθμιση plugin %1 δεν ευÏέθη"
+
+#: gtk_ardour/plugin_ui.cc:903
+msgid "Name for plugin settings:"
+msgstr "Όνομα για Ïυθμίσεις του plugin:"
+
+#: gtk_ardour/redirect_automation_line.cc:53
+msgid "redirect automation created for non-plugin"
+msgstr "Ï€Ïοώθηση Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Î´Î·Î¼Î¹Î¿Ï…Ïγημένου για non-plugin"
+
+#: gtk_ardour/redirect_automation_time_axis.cc:92
+msgid "add automation event to "
+msgstr "Ï€Ïόσθεση συμβάντος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï ÏƒÎµ "
+
+#: gtk_ardour/redirect_box.cc:213
+msgid "New send"
+msgstr "Nέο send"
+
+#: gtk_ardour/redirect_box.cc:214
+msgid "Show send controls"
+msgstr "Ανάδειξη Ïυθμίσεων send"
+
+#: gtk_ardour/redirect_box.cc:360
+msgid "New Plugin ..."
+msgstr "Îέο Plugin ..."
+
+#: gtk_ardour/redirect_box.cc:361
+msgid "New Insert"
+msgstr "Îέο ΠÏοσθήκη"
+
+#: gtk_ardour/redirect_box.cc:362
+msgid "New Send ..."
+msgstr "Îέο Send ..."
+
+#: gtk_ardour/redirect_box.cc:380
+msgid "Select all"
+msgstr "Επιλογή όλων"
+
+#: gtk_ardour/redirect_box.cc:381
+#, fuzzy
+msgid "Deselect all"
+msgstr "Επιλογή όλων"
+
+#: gtk_ardour/redirect_box.cc:389
+#, fuzzy
+msgid "Inserts"
+msgstr "ΑντιστÏοφή"
+
+#: gtk_ardour/redirect_box.cc:390
+#, fuzzy
+msgid "Sends"
+msgstr "ΔευτεÏόλεπτα"
+
+#: gtk_ardour/redirect_box.cc:393
+msgid "Select all ..."
+msgstr "Επιλογή όλων ..."
+
+#: gtk_ardour/redirect_box.cc:406
+msgid "Activate All"
+msgstr "ΕνεÏγοποίηση όλων"
+
+#: gtk_ardour/redirect_box.cc:407
+msgid "Deactivate All"
+msgstr "ΑπενεÏγοποίηση όλων"
+
+#: gtk_ardour/redirect_box.cc:488
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."
+msgstr ""
+"ΑποπειÏαθήκατε να Ï€Ïοσθέσετε ένα plug-in (%1).\n"
+"Το plugin έχει %2 inputs\n"
+"αλλά στο σημείο υποδοχής, υπάÏχουν\n"
+"%3 ενεÏγά σήματα.\n"
+"\n"
+"Δεν έχει νόημα - έτσι χαÏαμίζετε\n"
+"μέÏος του σήματος."
+
+#: gtk_ardour/redirect_box.cc:500
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."
+msgstr ""
+"ΑποπειÏαθήκατε να Ï€Ïοσθέσετε ένα plug-in (%1).\n"
+"Το plugin έχει %2 inputs\n"
+"αλλά στο σημείο υποδοχής, υπάÏχουν\n"
+"μόνο %3 ενεÏγά σήματα..\n"
+"\n"
+"Δεν έχει νόημα - εκτός αν το plug-in υποστηÏίζει\n"
+"επι μέÏους inputs. Μελλοντική έκδοση του Ardour θα\n"
+"υποστηÏίζει αυτον τον Ï„Ïπο διατάξεως."
+
+#: gtk_ardour/redirect_box.cc:513
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"
+msgstr ""
+"ΑποπειÏαθήκατε να Ï€Ïοσθέσετε ένα plug-in (%1).\n"
+"\n"
+"Η I/O διάταξη δεν έχει νόημα:\n"
+"\n"
+"Το plugin έχει %2 inputs και %3 outputs.\n"
+"Το κανάλι/δίαυλος έχει %4 inputs και %5 outputs.\n"
+"Το σημείο υποδοχής, έχει %6 ενεÏγά σήματα.\n"
+"\n"
+"Ο Ardour δεν γνωÏίζει τι να κάνει σε τέτοιες πεÏιπτώσεις.\n"
+
+#: gtk_ardour/redirect_box.cc:616
+msgid "Pre-fader inserts, sends & plugins:"
+msgstr "Pre-fader εισαγωγές, sends & plugins:"
+
+#: gtk_ardour/redirect_box.cc:619
+msgid "Post-fader inserts, sends & plugins:"
+msgstr "Post-fader εισαγωγές, sends & plugins:"
+
+#: gtk_ardour/redirect_box.cc:781
+msgid ""
+"You cannot reorder this set of redirects\n"
+"in that way because the inputs and\n"
+"outputs do not work correctly."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:903
+msgid "ardour: rename redirect"
+msgstr "ardour: μετονομασία redirect"
+
+#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043
+msgid ""
+"Copying the set of redirects on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:1064
+msgid ""
+"Do you really want to remove all redirects from this track?\n"
+"(this cannot be undone)"
+msgstr ""
+"Στ'αλήθεια θέλετε να απαλοίψετε όλα τα redirects από το κανάλι?\n"
+"(δεν μποÏεί να ανακληθεί)"
+
+#: gtk_ardour/redirect_box.cc:1067
+msgid ""
+"Do you really want to remove all redirects from this bus?\n"
+"(this cannot be undone)"
+msgstr ""
+"Στ'αλήθεια θέλετε να απαλοίψετε όλα τα redirects από το δίαυλο?\n"
+"(δεν μποÏεί να ανακληθεί)"
+
+#: gtk_ardour/redirect_box.cc:1071
+msgid "Yes, remove them all"
+msgstr "Îαι, απάλοιψέ τα όλα"
+
+#: gtk_ardour/redirect_box.cc:1114
+msgid "ardour: %1"
+msgstr "ardour: %1"
+
+#: gtk_ardour/redirect_box.cc:1156
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "ardour: %1: %2"
+
+#: gtk_ardour/region_editor.cc:43
+msgid "NAME:"
+msgstr "ÎŒÎΟΜΑ:"
+
+#: gtk_ardour/region_editor.cc:44
+msgid "lock"
+msgstr "κλείδωμα"
+
+#: gtk_ardour/region_editor.cc:46
+msgid "opaque"
+msgstr "αδιαφανής"
+
+#: gtk_ardour/region_editor.cc:49
+msgid "Layer"
+msgstr "ΣτÏώμα"
+
+#: gtk_ardour/region_editor.cc:57
+msgid "ENVELOPE"
+msgstr "ΧΡΟÎΟΔΙΑΓΡΑΜΜΑ"
+
+#: gtk_ardour/region_editor.cc:108
+msgid "mute this region"
+msgstr "σιγή παÏοÏσας πεÏιοχής"
+
+#: gtk_ardour/region_editor.cc:109
+msgid "regions underneath this one cannot be heard"
+msgstr "πεÏιοχές κάτωθι της παÏοÏσας δεν μποÏοÏν να ακουστοÏν"
+
+#: gtk_ardour/region_editor.cc:110
+msgid "prevent any changes to this region"
+msgstr "αποτÏοπή αλλαγών σε αυτή την πεÏιοχή"
+
+#: gtk_ardour/region_editor.cc:111
+msgid "use the gain envelope during playback"
+msgstr "χÏήση χÏονοδιαγÏάμματος του gain κατά την αναπαÏ/γή"
+
+#: gtk_ardour/region_editor.cc:112
+msgid "show the gain envelope"
+msgstr "ανάδειξη χÏονοδιαγÏάμματος του gain"
+
+#: gtk_ardour/region_editor.cc:113
+msgid "use fade in curve during playback"
+msgstr "χÏήση της καμπÏλης fade in κατά την αναπαÏ/γή"
+
+#: gtk_ardour/region_editor.cc:114
+msgid "use fade out curve during playback"
+msgstr "χÏήση της καμπÏλης fade out κατά την αναπαÏ/γή"
+
+#: gtk_ardour/region_editor.cc:115
+msgid "audition this region"
+msgstr "ακÏόαση της πεÏιοχής"
+
+#: gtk_ardour/region_editor.cc:148
+msgid "START:"
+msgstr "ΑΡΧΗ:"
+
+#: gtk_ardour/region_editor.cc:150
+msgid "END:"
+msgstr "ΛΗΞΗ:"
+
+#: gtk_ardour/region_editor.cc:152
+msgid "LENGTH:"
+msgstr "ΜΗΚΟΣ:"
+
+#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198
+#: gtk_ardour/region_editor.cc:234
+msgid "active"
+msgstr "ενεÏγό"
+
+#: gtk_ardour/region_editor.cc:179
+msgid "visible"
+msgstr "οÏατό"
+
+#: gtk_ardour/region_editor.cc:197
+msgid "FADE IN"
+msgstr "FADE IN"
+
+#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235
+msgid "msecs"
+msgstr "msecs"
+
+#: gtk_ardour/region_editor.cc:233
+msgid "FADE OUT"
+msgstr "FADE OUT"
+
+#: gtk_ardour/region_editor.cc:276
+msgid "ardour: region "
+msgstr "ardour: πεÏιοχή "
+
+#: gtk_ardour/region_editor.cc:410
+msgid "fade in edit"
+msgstr "επεξεÏ/σία fade in"
+
+#: gtk_ardour/region_editor.cc:422
+msgid "fade out edit"
+msgstr "επεξεÏ/σία fade out"
+
+#: gtk_ardour/regionview.cc:1169
+#, fuzzy
+msgid "add gain control point"
+msgstr "απαλοιφή σημείου ελέγχου"
+
+#: gtk_ardour/route_params_ui.cc:58
+msgid "Tracks/Buses"
+msgstr "κανάλια/δίαυλοι"
+
+#: gtk_ardour/route_params_ui.cc:59
+msgid "Pre Redirects"
+msgstr "ΠÏο-Redirects"
+
+#: gtk_ardour/route_params_ui.cc:60
+msgid "Post Redirects"
+msgstr "Μετα-Redirects"
+
+#: gtk_ardour/route_params_ui.cc:105
+#, fuzzy
+msgid "Pre-fader Redirects"
+msgstr "ΠÏο-Redirects"
+
+#: gtk_ardour/route_params_ui.cc:106
+#, fuzzy
+msgid "Post-fader Redirects"
+msgstr "Μετα-Redirects"
+
+#: gtk_ardour/route_params_ui.cc:138
+#, fuzzy
+msgid "ardour: track/bus inspector"
+msgstr "ardour: Εισαγωγή καναλιοÏ/διαÏλου"
+
+#: gtk_ardour/route_params_ui.cc:139
+msgid "ardour_route_parameters"
+msgstr "ardour_παÏάμετÏοι_διαδÏομών"
+
+#: gtk_ardour/route_params_ui.cc:189
+msgid "route display list item for renamed route not found!"
+msgstr "Η λίστα ανάδειξης διαδÏομών για μετονομασμένη διαδÏομή δεν ευÏέθη!"
+
+#: gtk_ardour/route_params_ui.cc:448
+msgid "NO TRACK"
+msgstr "Κανένα κανάλι"
+
+#: gtk_ardour/route_params_ui.cc:669
+#, fuzzy
+msgid "ardour: track/bus inspector: "
+msgstr "ardour: Εισαγωγή καναλιοÏ/διαÏλου"
+
+#: gtk_ardour/route_params_ui.cc:673
+msgid "No Route Selected"
+msgstr "Δεν επελέχθη διαδÏομή"
+
+#: gtk_ardour/route_params_ui.cc:674
+#, fuzzy
+msgid "ardour: track/bus/inspector: no route selected"
+msgstr "ardour: παÏάμετÏοι διαδÏομών: δεν επελέχθη διαδÏομή"
+
+#: gtk_ardour/route_ui.cc:134
+msgid "mute change"
+msgstr "αλλαγή σιγής"
+
+#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220
+msgid "solo change"
+msgstr "αλλαγή σόλο"
+
+#: gtk_ardour/route_ui.cc:284
+msgid "rec-enable change"
+msgstr "αλλαγή rec-enable"
+
+#: gtk_ardour/route_ui.cc:423
+#, fuzzy
+msgid "Solo-safe"
+msgstr "Σόλο"
+
+#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474
+#, fuzzy
+msgid "MIDI Bind"
+msgstr "MIDI"
+
+#: gtk_ardour/route_ui.cc:445
+msgid "Pre Fader"
+msgstr "ΠÏο Fader"
+
+#: gtk_ardour/route_ui.cc:452
+msgid "Post Fader"
+msgstr "Μετά Fader"
+
+#: gtk_ardour/route_ui.cc:459
+msgid "Control Outs"
+msgstr "Control Outs"
+
+#: gtk_ardour/route_ui.cc:466
+msgid "Main Outs"
+msgstr "Main Outs"
+
+#: gtk_ardour/route_ui.cc:503
+msgid "mix group solo change"
+msgstr "αλλαγή solo ομάδας μίξεως"
+
+#: gtk_ardour/route_ui.cc:537
+msgid "mix group mute change"
+msgstr "αλλαγή mute ομάδας μίξεως"
+
+#: gtk_ardour/route_ui.cc:553
+msgid "mix group rec-enable change"
+msgstr "αλλαγή rec-enable ομάδας μίξεως"
+
+#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258
+msgid "ardour: color selection"
+msgstr "ardour: επιλογή χÏωμάτων"
+
+#: gtk_ardour/route_ui.cc:652
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"You may also lose the playlist used by this track.\n"
+"(cannot be undone)"
+msgstr ""
+"Στ'αλήθεια θέλετε να απαλοίψετε το κανάλι \"%1\" ?\n"
+"Πιθανόν να χάσετε και τη λίστα που χÏησιμοποιείται από το κανάλι.\n"
+"(δεν μποÏεί να ανακληθεί)"
+
+#: gtk_ardour/route_ui.cc:654
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Στ'αλήθεια θέλετε να απαλοίψετε το κανάλι \"%1\" ?\n"
+"(δεν μποÏεί να ανακληθεί)"
+
+#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299
+msgid "Yes, remove it."
+msgstr "Îαι, απάλοιψε το."
+
+#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358
+msgid "new name: "
+msgstr "νέο όνομα: "
+
+#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31
+msgid "Beats per minute"
+msgstr "ΚτÏποι ανά λεπτό"
+
+#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35
+#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163
+msgid "Beat"
+msgstr "ΚτÏπος"
+
+#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158
+msgid "Meter denominator"
+msgstr "ΠαÏονομαστής ΜέτÏου"
+
+#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159
+msgid "Beats per bar"
+msgstr "ΚτÏποι ανά μπάÏα"
+
+#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189
+msgid "whole (1)"
+msgstr "ολόκληÏο (1)"
+
+#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191
+msgid "second (2)"
+msgstr "δεÏτεÏο (2)"
+
+#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193
+msgid "third (3)"
+msgstr "Ï„Ïίτο (3)"
+
+#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195
+#: gtk_ardour/tempo_dialog.cc:203
+msgid "quarter (4)"
+msgstr "τέταÏτο (4)"
+
+#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197
+msgid "eighth (8)"
+msgstr "όγδοο (8)"
+
+#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199
+msgid "sixteenth (16)"
+msgstr "δέκατο έκτο (16)"
+
+#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201
+msgid "thirty-second (32)"
+msgstr "Ï„Ïιακοστό-όγδοο (32)"
+
+#: gtk_ardour/tempo_dialog.cc:301
+msgid "garbaged note type entry (%1)"
+msgstr "είσοδος(type entry) άχÏηστης σημειώσεως (%1)"
+
+#: gtk_ardour/tempo_dialog.cc:311
+msgid "incomprehensible note type entry (%1)"
+msgstr "είσοδος(type entry) ακατανόητης σημειώσεως (%1)"
+
+#: gtk_ardour/time_axis_view.cc:95
+msgid "gTortnam"
+msgstr "gTortnam"
+
+#: gtk_ardour/time_axis_view.cc:446
+msgid "Largest"
+msgstr "Μέγιστο"
+
+#: gtk_ardour/time_axis_view.cc:447
+msgid "Large"
+msgstr "Μεγάλο"
+
+#: gtk_ardour/time_axis_view.cc:448
+msgid "Larger"
+msgstr "ΜεγαλÏτεÏο"
+
+#: gtk_ardour/time_axis_view.cc:450
+msgid "Smaller"
+msgstr "ΜικÏότεÏο"
+
+#: gtk_ardour/time_axis_view.cc:451
+msgid "Small"
+msgstr "ΜικÏÏŒ"
+
+#: gtk_ardour/time_axis_view.cc:785
+msgid "unknown track height name \"%1\" in XML GUI information"
+msgstr "Άγνωστο όνομα Ïψους καναλιοÏ\"%1\" στις XML GUI πληÏοφοÏίες"
+
+#: gtk_ardour/time_axis_view_item.cc:69
+msgid "TimeAxisViewItemName"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:258
+msgid "new duration %1 frames is out of bounds for %2"
+msgstr "νέα διάÏκεια %1 καÏέ είναι εκτός οÏίων για %2"
+
+#: gtk_ardour/time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr "Σφάλμα Ï€ÏογÏαμματισμοÏ: request για μη-υπάÏχον ηχητικό διάστημα (%1)!"
+
+#: gtk_ardour/utils.cc:57
+msgid ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+msgstr ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+
+#: gtk_ardour/utils.cc:66
+msgid "aeiou"
+msgstr "aeiou"
+
+#: gtk_ardour/utils.cc:75
+msgid "AEIOU"
+msgstr "AEIOU"
+
+#: gtk_ardour/utils.cc:84
+msgid "bcdfghjklmnpqrtvwxyz"
+msgstr "bcdfghjklmnpqrtvwxyz"
+
+#: gtk_ardour/utils.cc:93
+msgid "BCDFGHJKLMNPQRTVWXYZ"
+msgstr "BCDFGHJKLMNPQRTVWXYZ"
+
+#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265
+msgid "bad XPM header %1"
+msgstr "εσφαλμένος XPM header %1"
+
+#: gtk_ardour/utils.cc:516
+msgid "missing RGBA style for \"%1\""
+msgstr ""
+
+#: gtk_ardour/visual_time_axis.cc:297
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Στ'αλήθεια θέλετε να απαλοίψετε το κανάλι \"%1\" ?\n"
+"(δεν μποÏεί να ανακληθεί)"
+
+#: gtk_ardour/visual_time_axis.cc:385
+msgid "A track already exists with that name"
+msgstr "Κανάλι με αυτό το όνομα ήδη υπάÏχει"
+
+#~ msgid "Seamless Looping"
+#~ msgstr "Αδιάσπαστο Looping"
+
+#, fuzzy
+#~ msgid "Align recorded material with:"
+#~ msgstr "Στοίχιση ληφθέντος Ï…Î»Î¹ÎºÎ¿Ï Î¼Îµ"
+
+#~ msgid "Export to CD"
+#~ msgstr "Εξαγωγή σε CD"
+
+#~ msgid "programming error: location/marker map does not contain location!"
+#~ msgstr ""
+#~ "Σφάλμα Ï€ÏογÏαμματισμοÏ: ο χάÏτης τοποθεσίας/στίγματος δεν πεÏιέχει "
+#~ "τοποθεσίες!"
+
+#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Δεν ευÏέθησαν 'toggle button pixmaps' να ταιÏιάζουν στα toggle-button-[0-"
+#~ "9]*.xpm$"
+
+#~ msgid ""
+#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Δεν ευÏέθησαν 'small push button pixmaps' να ταιÏιάζουν στα small-round-"
+#~ "button-[0-9]*.xpm$"
+
+#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$"
+#~ msgstr "Δεν ευÏέθησαν 'pixmaps' να ταιÏιάζουν στα hslider[0-9]*.xpm$"
+
+#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$"
+#~ msgstr "Δεν ευÏέθησαν 'pixmaps' να ταιÏιάζουν vslider[0-9]*.xpm$"
+
+#~ msgid "Trace MIDI Input"
+#~ msgstr "Αναζήτηση MIDI Input"
+
+#~ msgid "Trace MIDI Output"
+#~ msgstr "Αναζήτηση MIDI Output"
+
+#~ msgid "30 FPS non-drop"
+#~ msgstr "30 FPS non-drop"
+
+#~ msgid "MTC Port"
+#~ msgstr "MTC ΘÏÏα"
+
+#~ msgid "attempt to timestretch a non-audio track!"
+#~ msgstr "απόπειÏα να χÏονοκαμφθεί ένα μη-ηχητικό κανάλι!"
+
+#~ msgid "cannot create timestretch thread - operation not carried out"
+#~ msgstr ""
+#~ "δεν δημιουÏγήθηκε σÏνδεσμος ΧÏονοκάμψης - η εÏγασία δεν ολοκληÏώθηκε"
+
+#, fuzzy
+#~ msgid "move region(s) between tracks"
+#~ msgstr "μετακίνηση πεÏιοχής Î¼ÎµÏ„Î±Î¾Ï ÎºÎ±Î½Î±Î»Î¹ÏŽÎ½"
+
+#, fuzzy
+#~ msgid "copy region(s) between tracks"
+#~ msgstr "αντιγÏαφή πεÏιοχής Î¼ÎµÏ„Î±Î¾Ï ÎºÎ±Î½Î±Î»Î¹ÏŽÎ½"
+
+#~ msgid "ardour: tempo editor"
+#~ msgstr "ardour: επεξεÏγαστής χÏόνου"
+
+#~ msgid "mouse brush"
+#~ msgstr "βοÏÏτσα ποντικιοÏ"
+
+#~ msgid "ardour_add_track_bus"
+#~ msgstr "ardour_εισαγωγή_καναλιοÏ_διαÏλου"
+
+#~ msgid "ok"
+#~ msgstr "Εν τάξει"
+
+#~ msgid "apply"
+#~ msgstr "ενεÏγοποίηση"
+
+#~ msgid "fade"
+#~ msgstr "fade"
+
+#~ msgid "Edit left"
+#~ msgstr "ΕπεξεÏγασία αÏιστεÏοÏ"
+
+#~ msgid "Edit right"
+#~ msgstr "ΕπεξεÏγασία δεξιοÏ"
+
+#~ msgid "Edit fade"
+#~ msgstr "ΕπεξεÏγασία fade"
+
+#~ msgid "Export region"
+#~ msgstr "Εξαγωγή πεÏιοχής"
+
+#~ msgid "Bounce region"
+#~ msgstr "Αναπήδηση πεÏιοχής"
+
+#~ msgid "Region"
+#~ msgstr "ΠεÏιοχή"
+
+#~ msgid "Play selected region"
+#~ msgstr "ΑναπαÏ/γή επιλεγμένης ΠεÏιοχής"
+
+#~ msgid "clear connections"
+#~ msgstr "εκκαθάÏιση συνδέσεων"
+
+#~ msgid "add comments/notes here"
+#~ msgstr "Ï€Ïόσθεση σχολίων/σημειώσεων εδώ"
+
+#~ msgid "Crossfades in use"
+#~ msgstr "Crossfades εν ενεÏγεία"
+
+#, fuzzy
+#~ msgid "outside this computer"
+#~ msgstr "ΑπόκÏυψη παÏόντος καναλιοÏ"
+
+#, fuzzy
+#~ msgid "inside this computer"
+#~ msgstr "ΑπόκÏυψη παÏόντος καναλιοÏ"
+
+#~ msgid "track %1 has no input connections [This Message To Be Expanded]"
+#~ msgstr "Το κανάλι %1 δεν εχει συνδέσεις λήψεως[Μήνυμα Ï€Ïος επέκταση]"
+
+#~ msgid "SR: %u kHz"
+#~ msgstr "SR: %u kHz"
+
+#~ msgid "Export CD track markers"
+#~ msgstr "Εξαγωγή σε CD από μαÏκάÏισμα καναλιοÏ"
+
+#~ msgid "Route Parameters"
+#~ msgstr "ΠαÏάμετÏοι διαδÏομών"
+
+#~ msgid "Use Other"
+#~ msgstr "ΧÏησιμοποίηση άλλου"
+
+#~ msgid "zoom to frame"
+#~ msgstr "zoom σε καÏέ"
+
+#~ msgid "Display Automatic Regions"
+#~ msgstr "Ανάδειξη Αυτομάτων ΠεÏιοχών"
+
+#~ msgid "Edit tempo"
+#~ msgstr "Επεξ/σία ΧÏόνου"
+
+#~ msgid "Ardour is done. Come again. Have a nice day. Etc.\n"
+#~ msgstr "Ο Ardour τελείωσε. Îα μας ξανάÏθετε. Καλή ημέÏα να έχετε. Κλπ.\n"
+
+#~ msgid "External MIDI Control"
+#~ msgstr "ΕξωτεÏικός Έλεγχος MIDI"
+
+#~ msgid " -U, --ui-rcfile path Use a specific UI style file\n"
+#~ msgstr ""
+#~ " -U, --ui-rcfile path ΧÏήση συγκεκÏιμένου αÏχείου για UI "
+#~ "στυλ\n"
+
+#~ msgid "INPUTs"
+#~ msgstr "Είσοδος(οι)"
+
+#~ msgid "OUTPUTs"
+#~ msgstr "'Εξοδος(οι)"
+
+#~ msgid "ardour: route parameters"
+#~ msgstr "ardour: παÏάμετÏοι διαδÏομών"
+
+#~ msgid "ardour: route parameters: "
+#~ msgstr "ardour: παÏάμετÏοι διαδÏομών: "
diff --git a/gtk2_ardour/po/es_ES.po b/gtk2_ardour/po/es_ES.po
new file mode 100644
index 0000000000..6b1c962f51
--- /dev/null
+++ b/gtk2_ardour/po/es_ES.po
@@ -0,0 +1,5194 @@
+# Ardour Spanish translation file
+# Copyright (C) 2003-2004 Paul Davis
+# This file is distributed under the same license as the Ardour package.
+# Author: Alex Krohn <alexkrohn@fastmail.fm>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ardour 0.688.4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-09-19 18:09-0400\n"
+"PO-Revision-Date: 2004-01-21 12:45+0100\n"
+"Last-Translator: Alex Krohn <alexkrohn@fastmail.fm>\n"
+"Language-Team: Spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gtk_ardour/about.cc:134
+msgid "Marcus Andersson"
+msgstr ""
+
+#: gtk_ardour/about.cc:135
+msgid "Jeremy Hall"
+msgstr ""
+
+#: gtk_ardour/about.cc:136
+msgid "Steve Harris"
+msgstr ""
+
+#: gtk_ardour/about.cc:137
+msgid "Tim Mayberry"
+msgstr ""
+
+#: gtk_ardour/about.cc:138
+msgid "Mark Stewart"
+msgstr ""
+
+#: gtk_ardour/about.cc:139
+msgid "Sam Chessman"
+msgstr ""
+
+#: gtk_ardour/about.cc:140
+msgid "Jack O'Quin"
+msgstr ""
+
+#: gtk_ardour/about.cc:141
+msgid "Matt Krai"
+msgstr ""
+
+#: gtk_ardour/about.cc:142
+msgid "Ben Bell"
+msgstr ""
+
+#: gtk_ardour/about.cc:143
+msgid "Gerard van Dongen"
+msgstr ""
+
+#: gtk_ardour/about.cc:144
+msgid "Thomas Charbonnel"
+msgstr ""
+
+#: gtk_ardour/about.cc:145
+msgid "Nick Mainsbridge"
+msgstr ""
+
+#: gtk_ardour/about.cc:146
+msgid "Colin Law"
+msgstr ""
+
+#: gtk_ardour/about.cc:147
+msgid "Sampo Savolainen"
+msgstr ""
+
+#: gtk_ardour/about.cc:148
+msgid "Joshua Leach"
+msgstr ""
+
+#: gtk_ardour/about.cc:149
+msgid "Rob Holland"
+msgstr ""
+
+#: gtk_ardour/about.cc:150
+msgid "Per Sigmond"
+msgstr ""
+
+#: gtk_ardour/about.cc:151
+msgid "Doug Mclain"
+msgstr ""
+
+#: gtk_ardour/about.cc:156
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+msgstr ""
+
+#: gtk_ardour/about.cc:157
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+msgstr ""
+
+#: gtk_ardour/about.cc:158
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+msgstr ""
+
+#: gtk_ardour/about.cc:159
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:160
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:162
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn@fastmail.fm>"
+msgstr ""
+
+#: gtk_ardour/about.cc:163
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop@nm.ru>"
+msgstr ""
+
+#: gtk_ardour/about.cc:181
+#, fuzzy
+msgid ""
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n"
+msgstr ""
+"Ardour no provee ningun tipo de garant�\n"
+"Este software es gratuito y usted lo puede redistribuir\n"
+"bajo ciertas condiciones;lea el archivo COPYING(en ingl�)\n"
+"para m� detalles\n"
+
+#: gtk_ardour/about.cc:188
+msgid ""
+"Ardour: %1\n"
+"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+msgstr ""
+
+#: gtk_ardour/about.cc:206
+msgid ""
+"Primary author:\n"
+"\tPaul Davis\n"
+"\n"
+"Major developers:\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributors:\n"
+"\t"
+msgstr ""
+
+#: gtk_ardour/about.cc:243
+msgid "Authors"
+msgstr "Autores"
+
+#: gtk_ardour/about.cc:244
+#, fuzzy
+msgid "Translators"
+msgstr "Traductores"
+
+#: gtk_ardour/about.cc:361
+msgid "cannot open splash image file \"%1\""
+msgstr "no se pudo mostrar el la imagen Acerca de \"%1\""
+
+#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33
+#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81
+#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977
+#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85
+#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777
+#: gtk_ardour/redirect_box.cc:900
+msgid "OK"
+msgstr "OK"
+
+#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92
+#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046
+#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72
+#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982
+#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733
+#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000
+#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129
+#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785
+#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86
+#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072
+#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33
+#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94
+msgid "Tracks"
+msgstr "Pistas"
+
+#: gtk_ardour/add_route_dialog.cc:43
+msgid "Busses"
+msgstr "Buses"
+
+#: gtk_ardour/add_route_dialog.cc:48
+msgid "ardour: add track/bus"
+msgstr "ardour: agregar Pistas/bus"
+
+#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81
+msgid "Add"
+msgstr "Agregar"
+
+#: gtk_ardour/add_route_dialog.cc:86
+msgid "Name (template)"
+msgstr "Nombre (esquema)"
+
+#: gtk_ardour/ardour_ui.cc:798
+msgid ""
+"pre\n"
+"roll"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:799
+msgid ""
+"post\n"
+"roll"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:807
+msgid "% "
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:808
+msgid "spring"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:810
+msgid ""
+"punch\n"
+"in"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:811
+msgid ""
+"punch\n"
+"out"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:812
+msgid ""
+"auto\n"
+"return"
+msgstr ""
+"retorno\n"
+"autom�ico"
+
+#: gtk_ardour/ardour_ui.cc:813
+msgid ""
+"auto\n"
+"play"
+msgstr ""
+"reproduccn\n"
+"autom�ica"
+
+#: gtk_ardour/ardour_ui.cc:814
+msgid ""
+"auto\n"
+"input"
+msgstr ""
+"auto\n"
+"monitoreo"
+
+#: gtk_ardour/ardour_ui.cc:815
+msgid "click"
+msgstr "metrnomo"
+
+#: gtk_ardour/ardour_ui.cc:816
+msgid ""
+"follow\n"
+"PH"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:817
+msgid "AUDITIONING"
+msgstr "AUDITANDO"
+
+#: gtk_ardour/ardour_ui.cc:818
+msgid "SOLO"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:870
+#, fuzzy
+msgid "Percentage"
+msgstr "Porcentage"
+
+#: gtk_ardour/ardour_ui.cc:872
+#, fuzzy
+msgid "Semitones"
+msgstr "Semitonos"
+
+#: gtk_ardour/ardour_ui.cc:875
+#, fuzzy
+msgid "Sprung"
+msgstr "Salto"
+
+#: gtk_ardour/ardour_ui.cc:877
+msgid "Wheel"
+msgstr "Rueda"
+
+#: gtk_ardour/ardour_ui.cc:902
+msgid ""
+"You cannot record-enable\n"
+"track %1\n"
+"because it has no input connections.\n"
+"You would be wasting space recording silence."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1073
+msgid "quit"
+msgstr "salir"
+
+#: gtk_ardour/ardour_ui.cc:1082
+msgid ""
+"Ardour was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1107
+msgid "Save and %1"
+msgstr "Guardar y %1"
+
+#: gtk_ardour/ardour_ui.cc:1112
+msgid "Just %1"
+msgstr "Slo %1"
+
+#: gtk_ardour/ardour_ui.cc:1117
+msgid "Don't %1"
+msgstr "No %1"
+
+#: gtk_ardour/ardour_ui.cc:1126
+#, fuzzy
+msgid "session"
+msgstr "Sesin"
+
+#: gtk_ardour/ardour_ui.cc:1128
+#, fuzzy
+msgid "snapshot"
+msgstr "Capturar instant�ea de sesin"
+
+#: gtk_ardour/ardour_ui.cc:1130
+#, fuzzy
+msgid ""
+"The %1\n"
+"\"%2\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
+msgstr ""
+"No ha guardado \"%1\"\n"
+"la sesin actual.\n"
+"\n"
+"Cualquier cambio que haya hecho\n"
+"se perder�si no selecciona guardar sesin.\n"
+"\n"
+"Qu�desea hacer?"
+
+#: gtk_ardour/ardour_ui.cc:1151
+msgid "Prompter"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1152
+msgid "ardour: save session?"
+msgstr "ardour: guardar sesin?"
+
+#: gtk_ardour/ardour_ui.cc:1219
+#, fuzzy, c-format
+msgid "disconnected"
+msgstr "Desconectar"
+
+#: gtk_ardour/ardour_ui.cc:1226
+#, fuzzy, c-format
+msgid "SR: %.1f kHz / %4.1f msecs"
+msgstr "SR: %.1f kHz"
+
+#: gtk_ardour/ardour_ui.cc:1230
+#, c-format
+msgid "SR: %u kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1243
+#, fuzzy, c-format
+msgid "DSP Load: %.1f%%"
+msgstr "CPU usada: %.1f%%"
+
+#: gtk_ardour/ardour_ui.cc:1253
+#, c-format
+msgid "Disk r:%5.1f w:%5.1f MB/s"
+msgstr "Disco r:%5.1f w:%5.1f MB/s"
+
+#: gtk_ardour/ardour_ui.cc:1267
+#, fuzzy, c-format
+msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
+msgstr "Buffers p:%5.0f%% c:%5.0f%%"
+
+#: gtk_ardour/ardour_ui.cc:1294
+msgid "space: 24hrs+"
+msgstr "disponible: 24hrs+"
+
+#: gtk_ardour/ardour_ui.cc:1324
+#, c-format
+msgid "space: %02dh:%02dm:%02ds"
+msgstr "disponible: %02dh:%02dm:%02ds"
+
+#: gtk_ardour/ardour_ui.cc:1575
+msgid "programming error: impossible control method"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1800
+msgid "cancel"
+msgstr "cancelar"
+
+#: gtk_ardour/ardour_ui.cc:1801
+msgid "rescan"
+msgstr "buscar de nuevo"
+
+#
+#: gtk_ardour/ardour_ui.cc:1842
+msgid "open session"
+msgstr "Abrir sesin"
+
+#: gtk_ardour/ardour_ui.cc:1897
+msgid "Patience is a virtue.\n"
+msgstr "La paciencia es una virtud.\n"
+
+#: gtk_ardour/ardour_ui.cc:1906
+msgid "You cannot add a track without a session already loaded."
+msgstr "No puede agregar pistas hasta que haya creado o abierto una sesin."
+
+#: gtk_ardour/ardour_ui.cc:1913
+msgid "could not create new audio track"
+msgstr "no se pudo crear la nueva pista"
+
+#: gtk_ardour/ardour_ui.cc:1917
+msgid "could not create new audio bus"
+msgstr "no se pudo crear el nuevo bus"
+
+#: gtk_ardour/ardour_ui.cc:1936
+msgid ""
+"There are insufficient JACK ports available\n"
+"to create a new track or bus.\n"
+"You should save Ardour, exit and\n"
+"restart JACK with more ports."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2071
+msgid ""
+"Please create 1 or more track\n"
+"before trying to record.\n"
+"Check the Session menu."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2312
+#, fuzzy
+msgid ""
+"JACK has either been shutdown or it\n"
+"disconnected Ardour because Ardour\n"
+"was not fast enough. You can save the\n"
+"session and/or try to reconnect to JACK ."
+msgstr ""
+"El programa Jackd fue detenido o �te \n"
+"desconect a Ardour por no ser \n"
+"suficientemente r�ido.\n"
+"Usted puede guardar su sesin ahora\n"
+"sin perder los cambios hechos.Luego,reinicie a Ardour y a Jackd."
+
+#: gtk_ardour/ardour_ui.cc:2328
+msgid "Unable to create all required ports"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2336
+#, fuzzy
+msgid "Unable to start the session running"
+msgstr "Ir al inicio de la sesin"
+
+#: gtk_ardour/ardour_ui.cc:2472
+msgid "No Stream"
+msgstr "Sin Flujo"
+
+#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518
+msgid "none"
+msgstr "ninguno"
+
+#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527
+#: gtk_ardour/automation_time_axis.cc:189
+#: gtk_ardour/automation_time_axis.cc:218
+#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211
+#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947
+#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659
+msgid "off"
+msgstr "off"
+
+#: gtk_ardour/ardour_ui.cc:2548
+msgid "Name for snapshot"
+msgstr "Nombre a captura de sesin"
+
+#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294
+msgid "Name for mix template:"
+msgstr "Nombre a esquema de mixer"
+
+#: gtk_ardour/ardour_ui.cc:2717
+msgid "-template"
+msgstr "-esquema"
+
+#: gtk_ardour/ardour_ui.cc:2760
+msgid "Session %1 already exists at %2"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2832
+msgid ""
+"You do not have write access to this session.\n"
+"This prevents the session from being loaded."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "No se puede cargar la sesin \"%1 (captura %2)\" "
+
+#: gtk_ardour/ardour_ui.cc:2966
+msgid ""
+"No audio files were ready for cleanup\n"
+"\n"
+"If this seems suprising, check for any existing\n"
+"snapshots. These may still include regions that\n"
+"require some unused files to continue to exist."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001
+msgid "files"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003
+msgid "file"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3026
+msgid "ardour: cleanup"
+msgstr "ardour: limpiar"
+
+#: gtk_ardour/ardour_ui.cc:3040
+msgid ""
+"Cleanup is a destructive operation.\n"
+"ALL undo/redo information will be lost if you cleanup.\n"
+"Unused audio files will be moved to a \"dead sounds\" location."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3045
+msgid "Proceed with cleanup"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3061
+#, fuzzy
+msgid "CleanupDialog"
+msgstr "Limpiar"
+
+#: gtk_ardour/ardour_ui.cc:3062
+#, fuzzy
+msgid "ardour cleanup"
+msgstr "ardour: limpiar"
+
+#: gtk_ardour/ardour_ui.cc:3063
+#, fuzzy
+msgid "ardour_cleanup"
+msgstr "ardour: limpiar"
+
+#: gtk_ardour/ardour_ui.cc:3086
+msgid "cleaned files"
+msgstr "archivos limpios"
+
+#: gtk_ardour/ardour_ui.cc:3087
+#, fuzzy
+msgid ""
+"The following %1 %2 were not in use.\n"
+"The next time you flush the wastebasket\n"
+"it will release an additional %3 %4bytes\n"
+"of disk space"
+msgstr ""
+"Los siguientes %1 archivos no estaban en uso \n"
+"Cuando vuelva a vaciar la papelera\n"
+"se liberar�%2 megabytes de espacio en disco \n"
+
+#: gtk_ardour/ardour_ui.cc:3110
+#, fuzzy
+msgid "deleted file"
+msgstr "archivos eliminados"
+
+#: gtk_ardour/ardour_ui.cc:3111
+#, fuzzy
+msgid ""
+"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"
+msgstr ""
+"Los siguientes %1 archivos fueron eliminados, liberando %2 megabytes de "
+"espacio"
+
+#: gtk_ardour/ardour_ui.cc:3226
+msgid "Recording was stopped because your system could not keep up."
+msgstr "Se detuvo la grabacin porque el sistema se sobrecarg"
+
+#: gtk_ardour/ardour_ui.cc:3248
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3266
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3291
+msgid "Recover from crash"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3292
+msgid "Ignore crash data"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3293
+msgid ""
+"This session appears to have been in\n"
+"middle of recording when ardour or\n"
+"the computer was shutdown.\n"
+"\n"
+"Ardour can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3338
+#, fuzzy
+msgid "Could not disconnect from JACK"
+msgstr "No se pudo conectar a JACK con el nombre \"%1\""
+
+#: gtk_ardour/ardour_ui.cc:3351
+#, fuzzy
+msgid "Could not reconnect to JACK"
+msgstr "No se pudo conectar a JACK con el nombre \"%1\""
+
+#: gtk_ardour/ardour_ui2.cc:60
+msgid "UI: cannot setup editor"
+msgstr "no se pudo iniciar el editor"
+
+#: gtk_ardour/ardour_ui2.cc:65
+msgid "UI: cannot setup mixer"
+msgstr "no se pudo iniciar el mixer"
+
+#: gtk_ardour/ardour_ui2.cc:70
+msgid "UI: cannot setup meter_bridge"
+msgstr "no se pudo iniciar el medidor volum�rico (VU)"
+
+#: gtk_ardour/ardour_ui2.cc:98
+msgid "MMC + Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:99
+msgid "MMC"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:100
+msgid "Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:117
+msgid "MMC ID"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:215
+msgid "Play from playhead"
+msgstr "Reproduzir a partir del in�io"
+
+#: gtk_ardour/ardour_ui2.cc:216
+msgid "Stop playback"
+msgstr "Detener la reproduccion"
+
+#: gtk_ardour/ardour_ui2.cc:217
+#, fuzzy
+msgid "Play range/selection"
+msgstr "Reproducir seleccin"
+
+#: gtk_ardour/ardour_ui2.cc:218
+msgid "Go to start of session"
+msgstr "Ir al inicio de la sesin"
+
+#: gtk_ardour/ardour_ui2.cc:219
+msgid "Go to end of session"
+msgstr "Ir al final de la sesin"
+
+#: gtk_ardour/ardour_ui2.cc:220
+#, fuzzy
+msgid "Play loop range"
+msgstr "Reproducir el intervalo cont�uamente"
+
+#: gtk_ardour/ardour_ui2.cc:221
+msgid "Return to last playback start when stopped"
+msgstr "Al detenerse, volver a donde inici la reproduccin"
+
+#: gtk_ardour/ardour_ui2.cc:222
+msgid "Start playback after any locate"
+msgstr ""
+"Reproducir inmedi�amente despu� de relocalizar la barra de reproduccin"
+
+#: gtk_ardour/ardour_ui2.cc:223
+msgid "Be sensible about input monitoring"
+msgstr "Monitorizacin sensible de entradas"
+
+#: gtk_ardour/ardour_ui2.cc:224
+msgid "Start recording at auto-punch start"
+msgstr "Iniciar grabacin en el punto auto-punch start(inicio)"
+
+#: gtk_ardour/ardour_ui2.cc:225
+msgid "Stop recording at auto-punch end"
+msgstr "Detener grabacin en el punto auto-punch end(final)"
+
+#: gtk_ardour/ardour_ui2.cc:226
+msgid "Enable/Disable audio click"
+msgstr "Habilitar/desabilitar metrnomo"
+
+#: gtk_ardour/ardour_ui2.cc:227
+#, fuzzy
+msgid "Enable/Disable follow playhead"
+msgstr "Habilitar/desbilitar reproduccin cont�ua"
+
+#: gtk_ardour/ardour_ui2.cc:228
+#, fuzzy
+msgid "Shuttle speed control"
+msgstr "Control de velocidad y sentido de reproduccin(pitch)"
+
+#: gtk_ardour/ardour_ui2.cc:229
+#, fuzzy, c-format
+msgid "Select semitones or %%-age for speed display"
+msgstr "Mostrar velocidad en semitonos o %-age"
+
+#: gtk_ardour/ardour_ui2.cc:230
+msgid "Select sprung or wheel behaviour"
+msgstr "Modo Salto(cambio constante) o Rueda deslizante(cambio moment�eo)"
+
+#: gtk_ardour/ardour_ui2.cc:231
+#, fuzzy
+msgid "Current transport speed"
+msgstr "Velocidad actual de transporte"
+
+#: gtk_ardour/ardour_ui2.cc:312
+msgid "Primary clock"
+msgstr "Reloj primario"
+
+#: gtk_ardour/ardour_ui2.cc:313
+msgid "secondary clock"
+msgstr "Reloj secundario"
+
+#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751
+#: gtk_ardour/ardour_ui2.cc:770
+msgid "stopped"
+msgstr "detenido"
+
+#: gtk_ardour/ardour_ui2.cc:431
+msgid "ardour: clock"
+msgstr "ardour: reloj"
+
+#: gtk_ardour/ardour_ui2.cc:721
+msgid "st"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:731
+#, fuzzy
+msgid "sprung"
+msgstr "Salto"
+
+#: gtk_ardour/ardour_ui2.cc:742
+#, fuzzy
+msgid "wheel"
+msgstr "Rueda"
+
+#: gtk_ardour/ardour_ui_dependents.cc:74
+msgid "keyboard_target: error setting binding state: invalid node"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dialogs.cc:158
+msgid "close session"
+msgstr "cerrar sesin"
+
+#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895
+msgid "New"
+msgstr "Nuevo"
+
+#: gtk_ardour/ardour_ui_ed.cc:76
+msgid "Open"
+msgstr "Abrir"
+
+#: gtk_ardour/ardour_ui_ed.cc:77
+msgid "Recent"
+msgstr "Reciente"
+
+#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+msgid "Close"
+msgstr "Cerrar"
+
+#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488
+msgid "Add Track/Bus"
+msgstr "Agregar Pista/Bus"
+
+#: gtk_ardour/ardour_ui_ed.cc:99
+msgid "Connect"
+msgstr "Conectar"
+
+#: gtk_ardour/ardour_ui_ed.cc:100
+msgid "Image Compositor"
+msgstr "Compositor de imagen"
+
+#: gtk_ardour/ardour_ui_ed.cc:114
+msgid "Save"
+msgstr "Guardar"
+
+#: gtk_ardour/ardour_ui_ed.cc:118
+msgid "Snapshot"
+msgstr "Capturar instant�ea de sesin"
+
+#: gtk_ardour/ardour_ui_ed.cc:126
+msgid "Save Template..."
+msgstr "Guardar esquema"
+
+#: gtk_ardour/ardour_ui_ed.cc:133
+msgid "Export session to audiofile..."
+msgstr "Exportar sesin a archivo de audio"
+
+#: gtk_ardour/ardour_ui_ed.cc:134
+#, fuzzy
+msgid "Export range to audiofile..."
+msgstr "Exportar sesin a archivo de audio"
+
+#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312
+#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118
+#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227
+msgid "Export"
+msgstr "Exportar"
+
+#: gtk_ardour/ardour_ui_ed.cc:146
+msgid "Cleanup unused sources"
+msgstr "Arrojar archivos no usados a papelera"
+
+#: gtk_ardour/ardour_ui_ed.cc:147
+msgid "Flush wastebasket"
+msgstr "Vaciar papelera"
+
+#: gtk_ardour/ardour_ui_ed.cc:149
+msgid "Cleanup"
+msgstr "Limpiar"
+
+#: gtk_ardour/ardour_ui_ed.cc:154
+msgid "Quit"
+msgstr "Salir"
+
+#: gtk_ardour/ardour_ui_ed.cc:156
+msgid "Session"
+msgstr "Sesin"
+
+#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287
+#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499
+#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570
+#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412
+msgid "Edit"
+msgstr "Editar"
+
+#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572
+#: gtk_ardour/mixer_strip.cc:631
+msgid "Disconnect"
+msgstr "Desconectar"
+
+#: gtk_ardour/ardour_ui_ed.cc:174
+#, fuzzy
+msgid "Reconnect"
+msgstr "Conectar"
+
+#: gtk_ardour/ardour_ui_ed.cc:192
+msgid "Latency"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:195
+msgid "JACK"
+msgstr "JACK"
+
+#: gtk_ardour/ardour_ui_ed.cc:205
+msgid "Editor"
+msgstr "Editor"
+
+#: gtk_ardour/ardour_ui_ed.cc:206
+msgid "Mixer"
+msgstr "Mixer"
+
+#: gtk_ardour/ardour_ui_ed.cc:212
+msgid "Options Editor"
+msgstr "Opciones Editor"
+
+#: gtk_ardour/ardour_ui_ed.cc:219
+msgid "Audio Library"
+msgstr "Biblioteca de Audio"
+
+#: gtk_ardour/ardour_ui_ed.cc:225
+#, fuzzy
+msgid "Track/Bus Inspector"
+msgstr "Pistas/Buses"
+
+#: gtk_ardour/ardour_ui_ed.cc:232
+msgid "Connections"
+msgstr "Conecciones"
+
+#: gtk_ardour/ardour_ui_ed.cc:240
+msgid "Meter Bridge"
+msgstr "V�ETRO"
+
+#: gtk_ardour/ardour_ui_ed.cc:248
+msgid "Locations"
+msgstr "Localizaciones"
+
+#: gtk_ardour/ardour_ui_ed.cc:255
+msgid "Big Clock"
+msgstr "Reloj Grande"
+
+#: gtk_ardour/ardour_ui_ed.cc:261
+msgid "About"
+msgstr "Acerca de"
+
+#: gtk_ardour/ardour_ui_ed.cc:264
+msgid "Windows"
+msgstr "Ventanas"
+
+#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203
+msgid "SMPTE"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202
+#: gtk_ardour/editor_rulers.cc:359
+msgid "Bars:Beats"
+msgstr "Compaces:Pulsos"
+
+#: gtk_ardour/audio_clock.cc:1642
+msgid "Minutes:Seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/audio_clock.cc:1643
+msgid "Audio Frames"
+msgstr "Cuadros de Audio"
+
+#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356
+#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713
+#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774
+#: gtk_ardour/option_editor.cc:794
+msgid "Off"
+msgstr "Deshabilitar"
+
+#: gtk_ardour/audio_clock.cc:1646
+msgid "Mode"
+msgstr "Modo"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523
+msgid "m"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524
+msgid "s"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104
+msgid "r"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:108
+msgid "g"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:109
+msgid "p"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44
+#: gtk_ardour/visual_time_axis.cc:90
+msgid "h"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:111
+msgid "a"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89
+msgid "v"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:185
+msgid "Record"
+msgstr "Grabar"
+
+#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191
+msgid "Solo"
+msgstr "Solo"
+
+#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236
+#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433
+msgid "Mute"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:188
+msgid "Edit Group"
+msgstr "Editar Grupo"
+
+#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110
+msgid "Display Height"
+msgstr "Tamao de pista"
+
+#: gtk_ardour/audio_time_axis.cc:190
+msgid "Playlist"
+msgstr "Lista de reproduccin"
+
+#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752
+msgid "Automation"
+msgstr "Automatizacin"
+
+#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111
+msgid "Visual options"
+msgstr "Opciones visuales"
+
+#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112
+msgid "Hide this track"
+msgstr "Ocultar esta pista"
+
+#: gtk_ardour/audio_time_axis.cc:349
+msgid "No group"
+msgstr "Sin grupo"
+
+#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447
+#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229
+msgid "Height"
+msgstr "Altura"
+
+#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266
+#: gtk_ardour/marker_time_axis.cc:230
+msgid "Color"
+msgstr "Color"
+
+#: gtk_ardour/audio_time_axis.cc:720
+msgid "Hide all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:721
+msgid "Show all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:729
+#, fuzzy
+msgid "show all automation"
+msgstr "Mostrar toda automatizacin"
+
+#: gtk_ardour/audio_time_axis.cc:732
+#, fuzzy
+msgid "show existing automation"
+msgstr "Mostrar toda automatizacin"
+
+#: gtk_ardour/audio_time_axis.cc:735
+#, fuzzy
+msgid "hide all automation"
+msgstr "ocultar toda automatizacin"
+
+#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204
+#: gtk_ardour/editor.cc:234
+msgid "gain"
+msgstr "volumen"
+
+#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244
+msgid "pan"
+msgstr "balance"
+
+#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388
+msgid "Plugins"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95
+msgid "Show waveforms"
+msgstr "Mostrar onda de audio"
+
+#: gtk_ardour/audio_time_axis.cc:766
+msgid "Traditional"
+msgstr "Tradicional"
+
+#: gtk_ardour/audio_time_axis.cc:769
+msgid "Rectified"
+msgstr "Corregido"
+
+#: gtk_ardour/audio_time_axis.cc:772
+msgid "Waveform"
+msgstr "Onda de audio"
+
+#: gtk_ardour/audio_time_axis.cc:782
+#, fuzzy
+msgid "align with existing material"
+msgstr "Material existente"
+
+#: gtk_ardour/audio_time_axis.cc:787
+#, fuzzy
+msgid "align with capture time"
+msgstr "Tiempo de captura"
+
+#: gtk_ardour/audio_time_axis.cc:793
+#, fuzzy
+msgid "Alignment"
+msgstr "Alinear"
+
+#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288
+msgid "Active"
+msgstr "Activar"
+
+#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386
+#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467
+#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269
+#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233
+#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83
+msgid "Remove"
+msgstr "Quitar"
+
+#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880
+#: gtk_ardour/audio_time_axis.cc:911
+#, fuzzy
+msgid "Name for playlist"
+msgstr "Nombre a captura de sesin"
+
+#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433
+msgid "a track already exists with that name"
+msgstr "ya existe una pista con este nombre"
+
+#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001
+#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539
+msgid "programming error: "
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:1889
+msgid "Current: %1"
+msgstr "Actual: %1"
+
+#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452
+#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226
+#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377
+msgid "Rename"
+msgstr "Renombrar"
+
+#: gtk_ardour/audio_time_axis.cc:1896
+msgid "New Copy"
+msgstr "Nueva Copia"
+
+#: gtk_ardour/audio_time_axis.cc:1898
+msgid "Clear Current"
+msgstr "Borrar actual"
+
+#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472
+#: gtk_ardour/editor.cc:2557
+msgid "Select"
+msgstr "Seleccionar"
+
+#: gtk_ardour/automation_line.cc:904
+#, fuzzy
+msgid "automation event move"
+msgstr "mover evento de automatizacin"
+
+#: gtk_ardour/automation_line.cc:906
+#, fuzzy
+msgid "automation range drag"
+msgstr "desplazar intervalo de automatizacin"
+
+#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64
+#, fuzzy
+msgid "remove control point"
+msgstr "Remover punto de sincron�"
+
+#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010
+msgid "clear"
+msgstr "borrar"
+
+#: gtk_ardour/automation_time_axis.cc:80
+msgid "track height"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:81
+#, fuzzy
+msgid "automation state"
+msgstr "estado de automatizacin de balance"
+
+#: gtk_ardour/automation_time_axis.cc:82
+#, fuzzy
+msgid "clear track"
+msgstr "borrar intervalos"
+
+#: gtk_ardour/automation_time_axis.cc:83
+#, fuzzy
+msgid "hide track"
+msgstr "Ocultar esta pista"
+
+#: gtk_ardour/automation_time_axis.cc:191
+#: gtk_ardour/automation_time_axis.cc:229
+#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213
+#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419
+#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50
+msgid "play"
+msgstr "reproducir"
+
+#: gtk_ardour/automation_time_axis.cc:193
+#: gtk_ardour/automation_time_axis.cc:240
+#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215
+#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422
+#: gtk_ardour/plugin_ui.cc:663
+msgid "write"
+msgstr "escritura"
+
+#: gtk_ardour/automation_time_axis.cc:195
+#: gtk_ardour/automation_time_axis.cc:251
+#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217
+#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953
+#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665
+#, fuzzy
+msgid "touch"
+msgstr "tocar"
+
+#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274
+#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428
+msgid "???"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:276
+#, fuzzy
+msgid "clear automation"
+msgstr "borrar localizaciones"
+
+#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453
+#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398
+msgid "Hide"
+msgstr "Ocultar"
+
+#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52
+#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364
+msgid "Clear"
+msgstr "Quitar todos"
+
+#: gtk_ardour/automation_time_axis.cc:474
+#, fuzzy
+msgid "State"
+msgstr "Inicio"
+
+#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49
+msgid "Input Connections"
+msgstr "Conecciones de entrada"
+
+#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48
+msgid "Output Connections"
+msgstr "Conecciones de salida"
+
+#: gtk_ardour/connection_editor.cc:49
+#, fuzzy
+msgid "New Input"
+msgstr "nueva entrada"
+
+#: gtk_ardour/connection_editor.cc:50
+#, fuzzy
+msgid "New Output"
+msgstr "nueva salida"
+
+#: gtk_ardour/connection_editor.cc:51
+#, fuzzy
+msgid "Delete"
+msgstr "quitar"
+
+#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96
+#, fuzzy
+msgid "Add Port"
+msgstr "agregar puerto"
+
+#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105
+#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786
+#, fuzzy
+msgid "Rescan"
+msgstr "buscar de nuevo"
+
+#: gtk_ardour/connection_editor.cc:101
+msgid "Available Ports"
+msgstr "Puertos Disponibles"
+
+#: gtk_ardour/connection_editor.cc:183
+msgid "ardour: connections"
+msgstr "ardour: conecciones"
+
+#: gtk_ardour/connection_editor.cc:513
+#, c-format
+msgid "in %d"
+msgstr "em %d"
+
+#: gtk_ardour/connection_editor.cc:644
+msgid "Name for new connection:"
+msgstr "Nombre para nueva coneccin:"
+
+#: gtk_ardour/crossfade_edit.cc:71
+#, fuzzy
+msgid "crossfade editor"
+msgstr "editar fade in"
+
+#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449
+#, fuzzy
+msgid "Reset"
+msgstr "resetear"
+
+#: gtk_ardour/crossfade_edit.cc:78
+#, fuzzy
+msgid "Fade"
+msgstr "Fades"
+
+#: gtk_ardour/crossfade_edit.cc:79
+msgid "Out (dry)"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:80
+#, fuzzy
+msgid "Out"
+msgstr "Salidas"
+
+#: gtk_ardour/crossfade_edit.cc:81
+msgid "In (dry)"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:82
+msgid "In"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:84
+msgid "With Pre-roll"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:85
+msgid "With Post-roll"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:93
+msgid "Fade In"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:94
+msgid "Fade Out"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:98
+msgid "ardour: x-fade edit"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311
+#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189
+msgid "Audition"
+msgstr "Audicionando"
+
+#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804
+msgid "Regions/name"
+msgstr "Regiones/nombre"
+
+#: gtk_ardour/editor.cc:108
+msgid "Chunks"
+msgstr "Trechos"
+
+#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079
+msgid "Slide"
+msgstr "Deslizar"
+
+#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077
+msgid "Splice"
+msgstr "Reunir"
+
+#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136
+#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96
+#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977
+msgid "None"
+msgstr "Ningn"
+
+#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124
+#, fuzzy
+msgid "CD Frames"
+msgstr "Cuadros"
+
+#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126
+#, fuzzy
+msgid "SMPTE Frames"
+msgstr "SMPTE Cuadros/segundo"
+
+#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128
+#, fuzzy
+msgid "SMPTE Seconds"
+msgstr "SMPTE Cuadros/segundo"
+
+#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130
+msgid "SMPTE Minutes"
+msgstr ""
+
+#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132
+#, fuzzy
+msgid "Seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134
+#, fuzzy
+msgid "Minutes"
+msgstr "Salidas Principales"
+
+#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106
+msgid "Beats/32"
+msgstr "Pulsos/32"
+
+#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104
+msgid "Beats/16"
+msgstr "Pulsos/16"
+
+#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102
+msgid "Beats/8"
+msgstr "Pulsos/8"
+
+#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100
+msgid "Beats/4"
+msgstr "Pulsos/4"
+
+#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098
+msgid "Beats/3"
+msgstr "Pulsos/3"
+
+#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108
+msgid "Beats"
+msgstr "Pulsos"
+
+#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110
+msgid "Bars"
+msgstr "Compaces"
+
+#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112
+msgid "Marks"
+msgstr "Marcas"
+
+#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114
+#: gtk_ardour/editor.cc:4182
+msgid "Edit Cursor"
+msgstr "Cursor de Edicin"
+
+#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116
+msgid "Region starts"
+msgstr "Comienzos de regin"
+
+#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118
+msgid "Region ends"
+msgstr "Fines de regin"
+
+#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122
+msgid "Region syncs"
+msgstr "Sincronizaciones de region"
+
+#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120
+msgid "Region bounds"
+msgstr "Bordes de regin"
+
+#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153
+#: gtk_ardour/time_axis_view.cc:449
+msgid "Normal"
+msgstr "Normal"
+
+#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155
+#, fuzzy
+msgid "Magnetic"
+msgstr "Magn�ico"
+
+#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174
+#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237
+msgid "Left"
+msgstr "Izquierdo"
+
+#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176
+#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238
+msgid "Right"
+msgstr "Derecho"
+
+#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178
+msgid "Center"
+msgstr "Centro"
+
+#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180
+msgid "Playhead"
+msgstr "Barra de reproduccin"
+
+#: gtk_ardour/editor.cc:201
+msgid "Mins:Secs"
+msgstr "Mins:Segs"
+
+#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353
+msgid "Frames"
+msgstr "Cuadros"
+
+#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373
+msgid "Tempo"
+msgstr "Tempo"
+
+#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367
+msgid "Meter"
+msgstr "Vmetro"
+
+#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379
+#, fuzzy
+msgid "Location Markers"
+msgstr "Marcadores de localizacin"
+
+#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385
+#, fuzzy
+msgid "Range Markers"
+msgstr "Marcadores de intervalo"
+
+#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391
+msgid "Loop/Punch Ranges"
+msgstr ""
+
+#: gtk_ardour/editor.cc:221
+msgid ""
+"editor\n"
+"mixer"
+msgstr ""
+
+#: gtk_ardour/editor.cc:232
+msgid "range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor.cc:233
+msgid "object"
+msgstr "objeto"
+
+#: gtk_ardour/editor.cc:235
+msgid "zoom"
+msgstr "zoom"
+
+#: gtk_ardour/editor.cc:236
+msgid "timefx"
+msgstr ""
+
+#: gtk_ardour/editor.cc:237
+msgid "listen"
+msgstr ""
+
+#: gtk_ardour/editor.cc:239
+msgid "mode"
+msgstr "modo"
+
+#: gtk_ardour/editor.cc:240
+msgid "automation"
+msgstr "automatizacin"
+
+#: gtk_ardour/editor.cc:242
+msgid "Edit Mode"
+msgstr "Modo de edicin"
+
+#: gtk_ardour/editor.cc:243
+msgid "Snap To"
+msgstr "Ajustar a"
+
+#: gtk_ardour/editor.cc:244
+#, fuzzy
+msgid "Snap Mode"
+msgstr "Modo de ajuste"
+
+#: gtk_ardour/editor.cc:245
+msgid "Zoom Focus"
+msgstr "Foco de Zoom"
+
+#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364
+#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579
+msgid "Nudge"
+msgstr "Retocar"
+
+#: gtk_ardour/editor.cc:511
+msgid "Zoom in"
+msgstr "Acercar"
+
+#: gtk_ardour/editor.cc:512
+msgid "Zoom out"
+msgstr "Alejar"
+
+#: gtk_ardour/editor.cc:517
+msgid "Zoom to session"
+msgstr "Mostrar toda la sesin"
+
+#: gtk_ardour/editor.cc:536
+msgid "Zoom Span"
+msgstr "Alcance de zoom"
+
+#: gtk_ardour/editor.cc:566
+msgid "Edit Groups"
+msgstr "Editar Grupos"
+
+#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142
+msgid "-all-"
+msgstr "-todo-"
+
+#: gtk_ardour/editor.cc:718
+msgid "Nudge region/selection forwards"
+msgstr "Retocar regin/selecin adelante"
+
+#: gtk_ardour/editor.cc:719
+msgid "Nudge region/selection backwards"
+msgstr "Retocar regin/selecin atr�"
+
+#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308
+msgid "ardour: editor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:729
+msgid "ardour_editor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:846
+msgid "VerboseCanvasCursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1405
+msgid "FirstActionMessage"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1407
+msgid "Start a new session\n"
+msgstr "Iniciar una nueva sesin\n"
+
+#: gtk_ardour/editor.cc:1408
+msgid "via Session menu"
+msgstr "via men de Sesin"
+
+#: gtk_ardour/editor.cc:1703
+msgid "ardour: editor: "
+msgstr ""
+
+#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796
+#: gtk_ardour/editor_markers.cc:797
+msgid "Loop"
+msgstr "c�lico"
+
+#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810
+#: gtk_ardour/editor_markers.cc:823
+msgid "Punch"
+msgstr "Insercin"
+
+#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688
+msgid "programming error: fade in canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986
+#: gtk_ardour/redirect_box.cc:401
+msgid "Deactivate"
+msgstr "Desactivar"
+
+#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988
+#: gtk_ardour/redirect_box.cc:398
+msgid "Activate"
+msgstr "Activar"
+
+#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993
+#, fuzzy
+msgid "Linear"
+msgstr "linear"
+
+#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994
+#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734
+#: gtk_ardour/option_editor.cc:796
+#, fuzzy
+msgid "Slowest"
+msgstr "Menor"
+
+#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995
+#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735
+#: gtk_ardour/option_editor.cc:798
+#, fuzzy
+msgid "Slow"
+msgstr "Solo"
+
+#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996
+#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737
+#: gtk_ardour/option_editor.cc:802
+#, fuzzy
+msgid "Fast"
+msgstr "Fades"
+
+#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997
+#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739
+#: gtk_ardour/option_editor.cc:806
+#, fuzzy
+msgid "Fastest"
+msgstr "r�ido"
+
+#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113
+msgid "Freeze"
+msgstr "Unir regiones"
+
+#: gtk_ardour/editor.cc:2109
+msgid "Unfreeze"
+msgstr "Separar regiones"
+
+#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328
+#, fuzzy
+msgid "Unmute"
+msgstr "mudo"
+
+#: gtk_ardour/editor.cc:2247
+msgid "Convert to short"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2249
+msgid "Convert to full"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2260
+#, fuzzy
+msgid "Crossfade"
+msgstr "editar fade in"
+
+#: gtk_ardour/editor.cc:2303
+msgid "Popup region editor"
+msgstr "Editor de regiones"
+
+#: gtk_ardour/editor.cc:2304
+#, fuzzy
+msgid "Raise to top layer"
+msgstr "Elevar regin a la capa m� alta"
+
+#: gtk_ardour/editor.cc:2305
+#, fuzzy
+msgid "Lower to bottom layer"
+msgstr "Enviar regin a capa m� baja"
+
+#: gtk_ardour/editor.cc:2307
+msgid "Define sync point"
+msgstr "Definir punto de sincron�"
+
+#: gtk_ardour/editor.cc:2308
+msgid "Remove sync point"
+msgstr "Remover punto de sincron�"
+
+#: gtk_ardour/editor.cc:2313
+#, fuzzy
+msgid "Bounce"
+msgstr "intervalo"
+
+#: gtk_ardour/editor.cc:2323
+#, fuzzy
+msgid "Lock"
+msgstr "bloquear"
+
+#: gtk_ardour/editor.cc:2324
+#, fuzzy
+msgid "Unlock"
+msgstr "Desbloquear"
+
+#: gtk_ardour/editor.cc:2334
+#, fuzzy
+msgid "Original position"
+msgstr "Posicin original"
+
+#: gtk_ardour/editor.cc:2340
+msgid "Toggle envelope visibility"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2341
+#, fuzzy
+msgid "Toggle envelope active"
+msgstr "activar"
+
+#: gtk_ardour/editor.cc:2345
+#, fuzzy
+msgid "DeNormalize"
+msgstr "Normalizar"
+
+#: gtk_ardour/editor.cc:2347
+#, fuzzy
+msgid "Normalize"
+msgstr "Normalizar"
+
+#: gtk_ardour/editor.cc:2350
+#, fuzzy
+msgid "Reverse"
+msgstr "Invertir"
+
+#: gtk_ardour/editor.cc:2359
+#, fuzzy
+msgid "Nudge fwd"
+msgstr "Retocar"
+
+#: gtk_ardour/editor.cc:2360
+#, fuzzy
+msgid "Nudge bwd"
+msgstr "Retocar"
+
+#: gtk_ardour/editor.cc:2361
+msgid "Nudge fwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2362
+msgid "Nudge bwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2371
+msgid "Start to edit cursor"
+msgstr "Desde principio hasta cursor de edicin"
+
+#: gtk_ardour/editor.cc:2372
+msgid "Edit cursor to end"
+msgstr "Desde cursor de edicin hasta final"
+
+#: gtk_ardour/editor.cc:2374
+msgid "Trim"
+msgstr "Cortar"
+
+#: gtk_ardour/editor.cc:2377
+msgid "Split"
+msgstr "Separar"
+
+#: gtk_ardour/editor.cc:2380
+msgid "Make mono regions"
+msgstr "Crear regiones mono"
+
+#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428
+msgid "Duplicate"
+msgstr "Duplicar"
+
+#: gtk_ardour/editor.cc:2384
+msgid "Fill Track"
+msgstr "Llenar Pista"
+
+#: gtk_ardour/editor.cc:2388
+#, fuzzy
+msgid "Destroy"
+msgstr "Destruir"
+
+#: gtk_ardour/editor.cc:2418
+#, fuzzy
+msgid "Play range"
+msgstr "Reproducir el intervalo cont�uamente"
+
+#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446
+#, fuzzy
+msgid "Loop range"
+msgstr "rango de reproduccin cont�ua"
+
+#: gtk_ardour/editor.cc:2421
+#, fuzzy
+msgid "Create chunk from range"
+msgstr "Crear trecho a partir de seleccin"
+
+#: gtk_ardour/editor.cc:2423
+msgid "Create Region"
+msgstr "Crear Regin"
+
+#: gtk_ardour/editor.cc:2424
+msgid "Separate Region"
+msgstr "Separar Regin"
+
+#: gtk_ardour/editor.cc:2425
+#, fuzzy
+msgid "Crop Region to range"
+msgstr "Acortar regin hasta la seleccin"
+
+#: gtk_ardour/editor.cc:2426
+#, fuzzy
+msgid "Bounce range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor.cc:2432
+#, fuzzy
+msgid "Fill range w/Region"
+msgstr "Crear Regin"
+
+#: gtk_ardour/editor.cc:2434
+#, fuzzy
+msgid "Range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538
+#, fuzzy
+msgid "Play from edit cursor"
+msgstr "Reproducir desde el cursor"
+
+#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539
+msgid "Play from start"
+msgstr "Reproducir desde el principio"
+
+#: gtk_ardour/editor.cc:2451
+#, fuzzy
+msgid "Play region"
+msgstr "Reproducir Regin"
+
+#: gtk_ardour/editor.cc:2453
+#, fuzzy
+msgid "Loop Region"
+msgstr "Reproducir regin cont�uamente"
+
+#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540
+#: gtk_ardour/library_ui.cc:972
+msgid "Play"
+msgstr "Reproducir"
+
+#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548
+#, fuzzy
+msgid "Select All in track"
+msgstr "Seleccionar todo dentro de pista"
+
+#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549
+#, fuzzy
+msgid "Select All"
+msgstr "Seleccionar todo"
+
+#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550
+msgid "Invert in track"
+msgstr "Invertir dentro de pista"
+
+#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551
+#, fuzzy
+msgid "Invert"
+msgstr "Invertir"
+
+#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553
+#, fuzzy
+msgid "Select loop range"
+msgstr "seleccionar rango de zoom"
+
+#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554
+#, fuzzy
+msgid "Select punch range"
+msgstr "Seleccionar intervalo actual"
+
+#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565
+#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369
+msgid "Cut"
+msgstr "Cortar"
+
+#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566
+#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371
+msgid "Copy"
+msgstr "Copiar"
+
+#: gtk_ardour/editor.cc:2482
+#, fuzzy
+msgid "Paste at edit cursor"
+msgstr "Desde principio hasta cursor de edicin"
+
+#: gtk_ardour/editor.cc:2483
+#, fuzzy
+msgid "Paste at mouse"
+msgstr "usar salidas Master"
+
+#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923
+msgid "Align"
+msgstr "Alinear"
+
+#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925
+msgid "Align Relative"
+msgstr "Alinear relativamente"
+
+#: gtk_ardour/editor.cc:2492
+msgid "Insert chunk"
+msgstr "Insertar trecho"
+
+#: gtk_ardour/editor.cc:2496
+#, fuzzy
+msgid "New Region from range"
+msgstr "Nueva region a partir de seleccin"
+
+#: gtk_ardour/editor.cc:2497
+#, fuzzy
+msgid "Separate Range"
+msgstr "Separar Regin"
+
+#: gtk_ardour/editor.cc:2507
+msgid "Insert Region"
+msgstr "Insertar Regin"
+
+#: gtk_ardour/editor.cc:2508
+msgid "Insert external sndfile"
+msgstr "Insertar archivo de audio externo"
+
+#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438
+msgid "Import"
+msgstr "Importar"
+
+#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574
+msgid "Nudge entire track fwd"
+msgstr "Retocar toda la pista adelante"
+
+#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575
+msgid "Nudge track after edit cursor fwd"
+msgstr "Retocar pista desde cursor de edicin adelante"
+
+#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576
+msgid "Nudge entire track bwd"
+msgstr "Retocar toda la pista atr�"
+
+#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577
+msgid "Nudge track after edit cursor bwd"
+msgstr "Retocar toda la pista, desde cursor de edicin atr�"
+
+#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920
+#: gtk_ardour/redirect_box.cc:373
+msgid "Paste"
+msgstr "Pegar"
+
+#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645
+#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799
+msgid "add marker"
+msgstr "agregar marcador"
+
+#: gtk_ardour/editor.cc:3084
+msgid "select/move objects"
+msgstr "selecionar/mover objetos"
+
+#: gtk_ardour/editor.cc:3085
+msgid "select/move ranges"
+msgstr "selecionar/mover intervalos"
+
+#: gtk_ardour/editor.cc:3086
+msgid "draw gain automation"
+msgstr "dibujar automatizacin de volumen"
+
+#: gtk_ardour/editor.cc:3087
+msgid "select zoom range"
+msgstr "seleccionar rango de zoom"
+
+#: gtk_ardour/editor.cc:3088
+msgid "stretch/shrink regions"
+msgstr "estirar/encoger regiones"
+
+#: gtk_ardour/editor.cc:3089
+#, fuzzy
+msgid "listen to specific regions"
+msgstr "Reproducir regin seleccionada cont�uamente"
+
+#: gtk_ardour/editor.cc:3213
+msgid "Start:"
+msgstr "Inicio:"
+
+#: gtk_ardour/editor.cc:3214
+msgid "End:"
+msgstr "Final:"
+
+#: gtk_ardour/editor.cc:3215
+msgid "Edit:"
+msgstr "Editar:"
+
+#: gtk_ardour/editor.cc:3429
+msgid "incorrectly formatted URI list, ignored"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3611
+#, fuzzy
+msgid "set selected trackview"
+msgstr "Insertar seleccin"
+
+#: gtk_ardour/editor.cc:3647
+#, fuzzy
+msgid "set selected control point"
+msgstr "Remover punto de sincron�"
+
+#: gtk_ardour/editor.cc:3719
+#, fuzzy
+msgid "set selected regionview"
+msgstr "Reproducir regin seleccionada cont�uamente"
+
+#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835
+#, fuzzy
+msgid "set selected regions"
+msgstr "Reproducir regin seleccionada cont�uamente"
+
+#: gtk_ardour/editor.cc:3891
+msgid "Undo"
+msgstr "Deshacer"
+
+#: gtk_ardour/editor.cc:3893
+msgid "Undo (%1)"
+msgstr "Deshacer (%1)"
+
+#: gtk_ardour/editor.cc:3903
+msgid "Redo"
+msgstr "Rehacer"
+
+#: gtk_ardour/editor.cc:3905
+msgid "Redo (%1)"
+msgstr "Rehacer (%1)"
+
+#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946
+msgid "... as new track"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947
+#, fuzzy
+msgid "... as new region"
+msgstr "normalizar regiones"
+
+#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452
+msgid "Import audio (copy)"
+msgstr "Importar audio (copiar)"
+
+#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457
+msgid "Embed audio (link)"
+msgstr "Linquear a a archivo"
+
+#: gtk_ardour/editor.cc:3953
+#, fuzzy
+msgid "Remove last capture"
+msgstr "Quitar ltima captura"
+
+#: gtk_ardour/editor.cc:3974
+msgid "Duplicate how many times?"
+msgstr "Duplicar cuantas veces?"
+
+#: gtk_ardour/editor.cc:4550
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If left alone, no audio files used by it will be cleaned.\n"
+"If deleted, audio files used by it alone by will cleaned."
+msgstr ""
+
+#: gtk_ardour/editor.cc:4555
+#, fuzzy
+msgid "Delete playlist"
+msgstr "Nombre a captura de sesin"
+
+#: gtk_ardour/editor.cc:4556
+#, fuzzy
+msgid "Keep playlist"
+msgstr "Nombre a captura de sesin"
+
+#: gtk_ardour/editor.cc:4557
+#, fuzzy
+msgid "Cancel cleanup"
+msgstr "Limpiar"
+
+#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258
+#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290
+msgid ""
+"programming error: control point canvas item has no control point object "
+"pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:717
+msgid "programming error: line canvas item has no line object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:744
+#: gtk_ardour/editor_canvas_events.cc:784
+#: gtk_ardour/editor_canvas_events.cc:823
+msgid "programming error: no \"rect\" pointer associated with selection item"
+msgstr ""
+
+#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298
+#: gtk_ardour/mixer_ui.cc:670
+msgid "Show All"
+msgstr "Mostrar Todo"
+
+#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299
+#: gtk_ardour/mixer_ui.cc:671
+msgid "Hide All"
+msgstr "Ocultar Todo"
+
+#: gtk_ardour/editor_edit_groups.cc:98
+msgid "Name for new edit group"
+msgstr "Nombre para nuevo grupo de edicin"
+
+#: gtk_ardour/editor_export_audio.cc:60
+msgid ""
+"There is no range to export.\n"
+"\n"
+"Select a range using the range mouse mode"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707
+msgid "programming error: no ImageFrameView selected"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930
+msgid "programming error: no MarkerView selected"
+msgstr ""
+
+#: gtk_ardour/editor_keys.cc:187
+#, fuzzy
+msgid "keyboard selection"
+msgstr "Separar Seleccin"
+
+#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376
+#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526
+#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584
+#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650
+#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700
+#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960
+#: gtk_ardour/editor_mouse.cc:4075
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681
+msgid "remove marker"
+msgstr "quitar marcador"
+
+#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494
+#, fuzzy
+msgid "Locate to"
+msgstr "Localizar a"
+
+#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495
+#, fuzzy
+msgid "Play from"
+msgstr "Reproducir desde"
+
+#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496
+#, fuzzy
+msgid "Set from playhead"
+msgstr "Ubicar desde barra de reproduccin"
+
+#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497
+#, fuzzy
+msgid "Set from range"
+msgstr "selecionar intervalo de reproduccin cont�ua"
+
+#: gtk_ardour/editor_markers.cc:479
+#, fuzzy
+msgid "Set Loop Range"
+msgstr "selecionar intervalo de reproduccin cont�ua"
+
+#: gtk_ardour/editor_markers.cc:480
+msgid "Set Punch Range"
+msgstr "Seleccionar intervalo de punch"
+
+#: gtk_ardour/editor_markers.cc:736
+msgid "ardour: rename mark"
+msgstr "ardour: renombrar marca"
+
+#: gtk_ardour/editor_markers.cc:738
+#, fuzzy
+msgid "ardour: rename range"
+msgstr "ardour: renombrar regin"
+
+#: gtk_ardour/editor_markers.cc:792
+#, fuzzy
+msgid "set loop range"
+msgstr "seleccionar rango de zoom"
+
+#: gtk_ardour/editor_markers.cc:818
+#, fuzzy
+msgid "set punch range"
+msgstr "Seleccionar intervalo actual"
+
+#: gtk_ardour/editor_mouse.cc:99
+msgid "Editor::event_frame() used on unhandled event type %1"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1555
+msgid "programming error: start_grab called without drag item"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1760
+#, fuzzy
+msgid "change fade in length"
+msgstr "editar fade in"
+
+#: gtk_ardour/editor_mouse.cc:1778
+msgid "programming error: fade out canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1852
+#, fuzzy
+msgid "change fade out length"
+msgstr "agregar salida"
+
+#: gtk_ardour/editor_mouse.cc:1871
+msgid "programming error: cursor canvas item has no cursor data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470
+msgid ""
+"programming error: meter marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2163
+#, fuzzy
+msgid "move meter mark"
+msgstr "quitar marcador"
+
+#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335
+#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439
+msgid ""
+"programming error: tempo marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340
+#: gtk_ardour/editor_tempodisplay.cc:425
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2245
+#, fuzzy
+msgid "move tempo mark"
+msgstr "quitar marcador"
+
+#: gtk_ardour/editor_mouse.cc:2388
+msgid "programming error: line canvas item has no line pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2497
+#, fuzzy
+msgid "move region(s)"
+msgstr "invertir regiones"
+
+#: gtk_ardour/editor_mouse.cc:2509
+msgid "Drag region copy"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2579
+#, fuzzy
+msgid "copy region(s)"
+msgstr "normalizar regiones"
+
+#: gtk_ardour/editor_mouse.cc:2612
+#, fuzzy
+msgid "Drag region brush"
+msgstr "normalizar regiones"
+
+#: gtk_ardour/editor_mouse.cc:3425
+#, fuzzy
+msgid "selection grab"
+msgstr "Seleccin"
+
+#: gtk_ardour/editor_mouse.cc:3571
+#, fuzzy
+msgid "range selection"
+msgstr "Reproducir seleccin"
+
+#: gtk_ardour/editor_mouse.cc:3587
+#, fuzzy
+msgid "trim selection start"
+msgstr "Desde locacin"
+
+#: gtk_ardour/editor_mouse.cc:3603
+#, fuzzy
+msgid "trim selection end"
+msgstr "Desde locacin"
+
+#: gtk_ardour/editor_mouse.cc:3620
+#, fuzzy
+msgid "move selection"
+msgstr "Grabar seleccin"
+
+#: gtk_ardour/editor_mouse.cc:3995
+#, fuzzy
+msgid "Start point trim"
+msgstr "Desde principio hasta cursor de edicin"
+
+#: gtk_ardour/editor_mouse.cc:4023
+msgid "End point trim"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:4062
+msgid "trimmed region"
+msgstr "regin acortada"
+
+#: gtk_ardour/editor_mouse.cc:4203
+#, fuzzy
+msgid "new range marker"
+msgstr "agregar un marcador de regin"
+
+#: gtk_ardour/editor_mouse.cc:4422
+#, fuzzy
+msgid "select regions"
+msgstr "Reproducir regin seleccionada cont�uamente"
+
+#: gtk_ardour/editor_mouse.cc:4451
+msgid "Name for region:"
+msgstr "Nombre para regin:"
+
+#: gtk_ardour/editor_mouse.cc:4517
+msgid "timestretch"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:117
+#, fuzzy
+msgid "split"
+msgstr "Separar"
+
+#: gtk_ardour/editor_ops.cc:153
+#, fuzzy
+msgid "remove region"
+msgstr "invertir regiones"
+
+#: gtk_ardour/editor_ops.cc:172
+msgid ""
+" This is destructive, will possibly delete audio files\n"
+"It cannot be undone\n"
+"Do you really want to destroy %1 ?"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "these regions"
+msgstr "invertir regiones"
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "this region"
+msgstr "enmudecer a esta regin"
+
+#: gtk_ardour/editor_ops.cc:179
+#, fuzzy
+msgid "Yes, destroy them."
+msgstr "Si, eliminar."
+
+#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434
+#, fuzzy
+msgid "Yes, destroy it."
+msgstr "Si, eliminar."
+
+#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435
+#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300
+#, fuzzy
+msgid "No, do nothing."
+msgstr "No, no hacer nada."
+
+#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307
+#, fuzzy
+msgid "extend selection"
+msgstr "Separar Seleccin"
+
+#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357
+#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427
+msgid "nudge forward"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:491
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1305
+#, fuzzy
+msgid "set selection from range"
+msgstr "Nueva region a partir de seleccin"
+
+#: gtk_ardour/editor_ops.cc:1421
+msgid "clear markers"
+msgstr "borrar marcadores"
+
+#: gtk_ardour/editor_ops.cc:1433
+msgid "clear ranges"
+msgstr "borrar intervalos"
+
+#: gtk_ardour/editor_ops.cc:1452
+msgid "clear locations"
+msgstr "borrar localizaciones"
+
+#: gtk_ardour/editor_ops.cc:1503
+#, fuzzy
+msgid "insert dragged region"
+msgstr "Insertar Regin"
+
+#: gtk_ardour/editor_ops.cc:1538
+#, fuzzy
+msgid "insert region"
+msgstr "Insertar Regin"
+
+#: gtk_ardour/editor_ops.cc:1744
+msgid "ardour: rename region"
+msgstr "ardour: renombrar regin"
+
+#: gtk_ardour/editor_ops.cc:1891
+msgid "You can't import an audiofile until you have a session loaded."
+msgstr "No puede importar un archivo a menos que abra o cree una sesin"
+
+#: gtk_ardour/editor_ops.cc:1901
+#, fuzzy
+msgid "Import selected as tracks"
+msgstr "Importar seleccin"
+
+#: gtk_ardour/editor_ops.cc:1904
+#, fuzzy
+msgid "Import selected to region list"
+msgstr "Reproducir regin seleccionada cont�uamente"
+
+#: gtk_ardour/editor_ops.cc:1933
+msgid "ardour: audio import in progress"
+msgstr "ardour: importando archivo de audio"
+
+#: gtk_ardour/editor_ops.cc:1937
+msgid "Cancel Import"
+msgstr "Cancelar importacin"
+
+#: gtk_ardour/editor_ops.cc:1944
+#, fuzzy
+msgid "ardour: importing %1"
+msgstr "ardour: exportar"
+
+#: gtk_ardour/editor_ops.cc:1990
+#, fuzzy
+msgid "%1 it anyway"
+msgstr "Linquear de todas formas"
+
+#: gtk_ardour/editor_ops.cc:1996
+#, fuzzy
+msgid "Don't %1 it"
+msgstr "No %1"
+
+#: gtk_ardour/editor_ops.cc:1997
+msgid "%1 all without questions"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1998
+#, fuzzy
+msgid "Cancel entire import"
+msgstr "Cancelar importacin"
+
+#: gtk_ardour/editor_ops.cc:2004
+#, fuzzy
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr "La frecuencia de muestreo de este archivo difiere de la de la sesin!"
+
+#: gtk_ardour/editor_ops.cc:2032
+#, fuzzy
+msgid "You can't embed an audiofile until you have a session loaded."
+msgstr "No puede linquear a un archivo a menos que abra o cree una sesin"
+
+#: gtk_ardour/editor_ops.cc:2039
+msgid "Add to External Region list"
+msgstr "Agregar a lista externa de regiones"
+
+#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210
+#: gtk_ardour/editor_ops.cc:2286
+msgid "Editor: cannot open file \"%1\" (%2)"
+msgstr "Editor: no se pudo abrir el archivo \"%1\" (%2)"
+
+#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312
+msgid "could not open %1"
+msgstr "no se pudo abrir %1"
+
+#: gtk_ardour/editor_ops.cc:2171
+#, fuzzy
+msgid "Insert selected as new tracks"
+msgstr "Insertar seleccin"
+
+#: gtk_ardour/editor_ops.cc:2186
+msgid "Insert selected"
+msgstr "Insertar seleccin"
+
+#: gtk_ardour/editor_ops.cc:2327
+#, fuzzy
+msgid "insert sndfile"
+msgstr "Insertar archivo de audio externo"
+
+#: gtk_ardour/editor_ops.cc:2464
+#, fuzzy
+msgid "separate"
+msgstr "Separar Regin"
+
+#: gtk_ardour/editor_ops.cc:2528
+#, fuzzy
+msgid "trim to selection"
+msgstr "Desde locacin"
+
+#: gtk_ardour/editor_ops.cc:2568
+msgid "region fill"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2626
+#, fuzzy
+msgid "fill selection"
+msgstr "Reproducir seleccin cont�uamente"
+
+#: gtk_ardour/editor_ops.cc:2650
+msgid "Place the edit cursor at the desired sync point"
+msgstr "Coloque el cursor de edicin en el punto de sincron� deseado"
+
+#: gtk_ardour/editor_ops.cc:2656
+#, fuzzy
+msgid "set sync from edit cursor"
+msgstr "Reproducir desde el cursor"
+
+#: gtk_ardour/editor_ops.cc:2668
+#, fuzzy
+msgid "remove sync"
+msgstr "Remover punto de sincron�"
+
+#: gtk_ardour/editor_ops.cc:2682
+#, fuzzy
+msgid "naturalize"
+msgstr "Normalizar"
+
+#: gtk_ardour/editor_ops.cc:2746
+#, fuzzy
+msgid "align selection (relative)"
+msgstr "Alinear relativamente"
+
+#: gtk_ardour/editor_ops.cc:2774
+#, fuzzy
+msgid "align selection"
+msgstr "Grabar seleccin"
+
+#: gtk_ardour/editor_ops.cc:2786
+#, fuzzy
+msgid "align region"
+msgstr "normalizar regiones"
+
+#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858
+#, fuzzy
+msgid "trim to edit"
+msgstr "Desde principio hasta cursor de edicin"
+
+#: gtk_ardour/editor_ops.cc:2909
+#, fuzzy
+msgid "ardour: freeze"
+msgstr "ardour: renombrar regin"
+
+#: gtk_ardour/editor_ops.cc:2914
+#, fuzzy
+msgid "Cancel Freeze"
+msgstr "Cancelar"
+
+#: gtk_ardour/editor_ops.cc:2951
+#, fuzzy
+msgid "bounce range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor_ops.cc:3004
+#, fuzzy
+msgid "cut"
+msgstr "cortar"
+
+#: gtk_ardour/editor_ops.cc:3007
+#, fuzzy
+msgid "copy"
+msgstr "copiar"
+
+#: gtk_ardour/editor_ops.cc:3020
+#, fuzzy
+msgid " objects"
+msgstr "objetos"
+
+#: gtk_ardour/editor_ops.cc:3046
+#, fuzzy
+msgid " range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor_ops.cc:3201
+#, fuzzy
+msgid "paste"
+msgstr "Pegar"
+
+#: gtk_ardour/editor_ops.cc:3236
+#, fuzzy
+msgid "paste chunk"
+msgstr "Crear trecho"
+
+#: gtk_ardour/editor_ops.cc:3276
+#, fuzzy
+msgid "duplicate region"
+msgstr "Reproducir regin seleccionada cont�uamente"
+
+#: gtk_ardour/editor_ops.cc:3309
+#, fuzzy
+msgid "duplicate selection"
+msgstr "Grabar seleccin"
+
+#: gtk_ardour/editor_ops.cc:3349
+#, fuzzy
+msgid "clear playlist"
+msgstr "Nombre a captura de sesin"
+
+#: gtk_ardour/editor_ops.cc:3378
+#, fuzzy
+msgid "nudge track"
+msgstr "Ocultar esta pista"
+
+#: gtk_ardour/editor_ops.cc:3431
+#, fuzzy
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"Realmente desea quitar el bus \"%1\" ?\n"
+"(no podr�deshacer este cambio)"
+
+#: gtk_ardour/editor_ops.cc:3463
+#, fuzzy
+msgid "normalize"
+msgstr "Normalizar"
+
+#: gtk_ardour/editor_ops.cc:3510
+#, fuzzy
+msgid "reverse regions"
+msgstr "invertir regiones"
+
+#: gtk_ardour/editor_region_list.cc:223
+#, fuzzy
+msgid "hidden"
+msgstr "Oculto"
+
+#: gtk_ardour/editor_region_list.cc:408
+msgid "Show all"
+msgstr "Mostrar todo"
+
+#: gtk_ardour/editor_region_list.cc:417
+msgid "Ascending"
+msgstr "Ascendente"
+
+#: gtk_ardour/editor_region_list.cc:419
+msgid "Descending"
+msgstr "Descendente"
+
+#: gtk_ardour/editor_region_list.cc:423
+msgid "By Region Name"
+msgstr "Por Nombre de Regin"
+
+#: gtk_ardour/editor_region_list.cc:425
+msgid "By Region Length"
+msgstr "Por Tamao de Regin"
+
+#: gtk_ardour/editor_region_list.cc:427
+msgid "By Region Position"
+msgstr "Por Posicin de regin"
+
+#: gtk_ardour/editor_region_list.cc:429
+msgid "By Region Timestamp"
+msgstr "Por fecha de Regin"
+
+#: gtk_ardour/editor_region_list.cc:431
+msgid "By Region Start in File"
+msgstr "Por inicio de regin en archivo"
+
+#: gtk_ardour/editor_region_list.cc:433
+msgid "By Region End in File"
+msgstr "Por fin de regin en archivo"
+
+#: gtk_ardour/editor_region_list.cc:435
+msgid "By Source File Name"
+msgstr "Por nombre de archivo"
+
+#: gtk_ardour/editor_region_list.cc:437
+msgid "By Source File Length"
+msgstr "Por tamao de archivo"
+
+#: gtk_ardour/editor_region_list.cc:439
+msgid "By Source File Creation Date"
+msgstr "Por fecha de creacin"
+
+#: gtk_ardour/editor_region_list.cc:441
+msgid "By Source Filesystem"
+msgstr "Por sistema de archivos"
+
+#: gtk_ardour/editor_region_list.cc:444
+msgid "Sorting"
+msgstr "Orden"
+
+#: gtk_ardour/editor_region_list.cc:808
+msgid "Regions/length"
+msgstr "Regiones/tamao"
+
+#: gtk_ardour/editor_region_list.cc:812
+msgid "Regions/position"
+msgstr "Regiones/posicin"
+
+#: gtk_ardour/editor_region_list.cc:816
+msgid "Regions/creation"
+msgstr "Regiones/creacin"
+
+#: gtk_ardour/editor_region_list.cc:820
+msgid "Regions/start"
+msgstr "Regiones/in�io"
+
+#: gtk_ardour/editor_region_list.cc:824
+msgid "Regions/end"
+msgstr "Regiones/final"
+
+#: gtk_ardour/editor_region_list.cc:828
+msgid "Regions/file name"
+msgstr "Regiones/nombre del archivo"
+
+#: gtk_ardour/editor_region_list.cc:832
+msgid "Regions/file size"
+msgstr "Regiones/tamao del archivo"
+
+#: gtk_ardour/editor_region_list.cc:836
+msgid "Regions/file date"
+msgstr "Regiones/fecha del archivo"
+
+#: gtk_ardour/editor_region_list.cc:840
+msgid "Regions/file system"
+msgstr "Regiones/sistema de archivos"
+
+#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73
+#: gtk_ardour/editor_route_list.cc:231
+msgid "editor"
+msgstr "editor"
+
+#: gtk_ardour/editor_route_list.cc:300
+msgid "Show All AbstractTracks"
+msgstr "Mostrar todas las pistas de Audio"
+
+#: gtk_ardour/editor_route_list.cc:301
+msgid "Hide All AbstractTracks"
+msgstr "Ocultar todas las pistas de Audio"
+
+#: gtk_ardour/editor_route_list.cc:302
+msgid "Show All AudioBus"
+msgstr "Mostrar todos los Buses"
+
+#: gtk_ardour/editor_route_list.cc:303
+msgid "Hide All AudioBus"
+msgstr "Ocultar todos los Buses"
+
+#: gtk_ardour/editor_rulers.cc:311
+#, fuzzy
+msgid "New location marker"
+msgstr "Nuevo marcador de localizacin"
+
+#: gtk_ardour/editor_rulers.cc:312
+#, fuzzy
+msgid "Clear all locations"
+msgstr "Quitar todas las localizaciones"
+
+#: gtk_ardour/editor_rulers.cc:317
+#, fuzzy
+msgid "Clear all ranges"
+msgstr "Quitar todas las selecciones"
+
+#: gtk_ardour/editor_rulers.cc:326
+#, fuzzy
+msgid "New Tempo"
+msgstr "Nuevo tempo"
+
+#: gtk_ardour/editor_rulers.cc:327
+#, fuzzy
+msgid "Clear tempo"
+msgstr "Resetear tempo"
+
+#: gtk_ardour/editor_rulers.cc:332
+#, fuzzy
+msgid "New Meter"
+msgstr "Nuevo Medidor"
+
+#: gtk_ardour/editor_rulers.cc:333
+#, fuzzy
+msgid "Clear meter"
+msgstr "Resetear Medidor"
+
+#: gtk_ardour/editor_rulers.cc:341
+#, fuzzy
+msgid "Min:Secs"
+msgstr "Mins:Segs"
+
+#: gtk_ardour/editor_selection_list.cc:117
+msgid "name for chunk:"
+msgstr "nombre para trecho"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Create chunk"
+msgstr "Crear trecho"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Forget it"
+msgstr "Olvidarlo"
+
+#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295
+msgid "add"
+msgstr "agregar"
+
+#: gtk_ardour/editor_tempodisplay.cc:276
+#, fuzzy
+msgid "add tempo mark"
+msgstr "agregar un marcador de regin"
+
+#: gtk_ardour/editor_tempodisplay.cc:318
+#, fuzzy
+msgid "add meter mark"
+msgstr "agregar un marcador de regin"
+
+#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383
+msgid "done"
+msgstr "listo"
+
+#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404
+msgid "replace tempo mark"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487
+#, fuzzy
+msgid "remove tempo mark"
+msgstr "quitar marcador"
+
+#: gtk_ardour/editor_timefx.cc:50
+msgid "Quick but Ugly"
+msgstr "R�ido pero pobre"
+
+#: gtk_ardour/editor_timefx.cc:51
+msgid "Skip Anti-aliasing"
+msgstr "No usar Anti-aliasing"
+
+#: gtk_ardour/editor_timefx.cc:53
+msgid "Stretch/Shrink it"
+msgstr "Estirar/Encoger esto"
+
+#: gtk_ardour/editor_timefx.cc:57
+msgid "ardour: timestretch"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:58
+msgid "TimeStretchDialog"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83
+#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85
+msgid "TimeStretchButton"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:86
+msgid "TimeStretchProgress"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:151
+msgid "timestretch cannot be started - thread creation error"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410
+#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189
+msgid "22.05kHz"
+msgstr "22.05kHz"
+
+#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413
+#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949
+#: gtk_ardour/export_dialog.cc:1191
+msgid "44.1kHz"
+msgstr "44.1kHz"
+
+#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416
+#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193
+msgid "48kHz"
+msgstr "48kHz"
+
+#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419
+#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195
+msgid "88.2kHz"
+msgstr "88.2kHz"
+
+#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422
+#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197
+msgid "96kHz"
+msgstr "96kHz"
+
+#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425
+#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199
+msgid "192kHz"
+msgstr "192kHz"
+
+#: gtk_ardour/export_dialog.cc:73
+msgid "best"
+msgstr "excelente"
+
+#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964
+msgid "fastest"
+msgstr "r�ido"
+
+#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966
+msgid "linear"
+msgstr "linear"
+
+#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968
+msgid "better"
+msgstr "bueno"
+
+#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970
+msgid "intermediate"
+msgstr "intermedio"
+
+#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979
+msgid "Rectangular"
+msgstr "Rectangular"
+
+#: gtk_ardour/export_dialog.cc:84
+msgid "Shaped Noise"
+msgstr "Perfil de Ru�o"
+
+#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981
+msgid "Triangular"
+msgstr "Triangular"
+
+#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336
+msgid "stereo"
+msgstr "est�eo"
+
+#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497
+#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219
+#: gtk_ardour/utils.cc:334
+msgid "mono"
+msgstr "mono"
+
+#: gtk_ardour/export_dialog.cc:97
+msgid "CUE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:98
+msgid "TOC"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:106
+msgid "FORMAT"
+msgstr "FORMATO"
+
+#: gtk_ardour/export_dialog.cc:107
+msgid "SAMPLE RATE"
+msgstr "FRECUENCIA DE MUESTREO"
+
+#: gtk_ardour/export_dialog.cc:108
+msgid "CONVERSION QUALITY"
+msgstr "CALIDAD DE CONVERSI�"
+
+#: gtk_ardour/export_dialog.cc:109
+msgid "DITHER TYPE"
+msgstr "TIPO DE DITHER"
+
+#: gtk_ardour/export_dialog.cc:110
+#, fuzzy
+msgid "CD MARKER FILE TYPE"
+msgstr "TIPO DE ARCHIVO"
+
+#: gtk_ardour/export_dialog.cc:111
+msgid "CHANNELS"
+msgstr "CANALES"
+
+#: gtk_ardour/export_dialog.cc:112
+msgid "FILE TYPE"
+msgstr "TIPO DE ARCHIVO"
+
+#: gtk_ardour/export_dialog.cc:113
+msgid "SAMPLE FORMAT"
+msgstr "FORMATO"
+
+#: gtk_ardour/export_dialog.cc:114
+msgid "SAMPLE ENDIANNESS"
+msgstr "TIPO DE ENDIAN"
+
+#: gtk_ardour/export_dialog.cc:115
+#, fuzzy
+msgid "EXPORT CD MARKER FILE ONLY"
+msgstr "TIPO DE ARCHIVO"
+
+#: gtk_ardour/export_dialog.cc:116
+msgid "EXPORT TO FILE"
+msgstr "EXPORTAR A ARCHIVO"
+
+#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118
+#: gtk_ardour/option_editor.cc:119
+msgid "Browse"
+msgstr "Seleccionar"
+
+#: gtk_ardour/export_dialog.cc:119
+msgid "Specific tracks ..."
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:131
+msgid "ardour: export"
+msgstr "ardour: exportar"
+
+#: gtk_ardour/export_dialog.cc:132
+msgid "ardour_export"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:156
+#, fuzzy
+msgid "Output"
+msgstr "Salidas"
+
+#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626
+msgid "Track"
+msgstr "Pista"
+
+#: gtk_ardour/export_dialog.cc:287
+msgid "slereg"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:658
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD toc file"
+msgstr ""
+"Editor: no se puede abrir \"%1\" como archivo de exportacin de marcadores de "
+"CD"
+
+#: gtk_ardour/export_dialog.cc:780
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD cue file"
+msgstr ""
+"Editor: no se puede abrir \"%1\" como archivo de exportacin de marcadores de "
+"CD"
+
+#: gtk_ardour/export_dialog.cc:799
+msgid "WAV"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:1051
+msgid "Stop Export"
+msgstr "Cancelar Exportacin"
+
+#: gtk_ardour/gain_automation_time_axis.cc:60
+#, fuzzy
+msgid "add gain automation event"
+msgstr "agregar evento de automatizacin a "
+
+#: gtk_ardour/gain_meter.cc:68
+msgid "Cannot create slider pixmaps"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:83
+msgid "dbFS"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134
+#: gtk_ardour/gain_meter.cc:728
+msgid "pre"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724
+#, fuzzy
+msgid "input"
+msgstr "%1 entrada"
+
+#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732
+#, fuzzy
+msgid "post"
+msgstr "conector"
+
+#: gtk_ardour/gain_meter.cc:146
+msgid "tupni"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470
+#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537
+#, fuzzy
+msgid "-inf"
+msgstr "entrada"
+
+#: gtk_ardour/imageframe_socket_handler.cc:127
+msgid "Image Compositor Socket has been shutdown/closed"
+msgstr "Se desconect al Compositor de Imagen"
+
+#: gtk_ardour/imageframe_time_axis.cc:295
+#, fuzzy
+msgid "0.5 seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259
+#, fuzzy
+msgid "1 seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260
+#, fuzzy
+msgid "1.5 seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261
+#, fuzzy
+msgid "2 seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262
+#, fuzzy
+msgid "2.5 seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263
+#, fuzzy
+msgid "3 seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268
+#, fuzzy
+msgid "Duration (sec)"
+msgstr "normalizar regiones"
+
+#: gtk_ardour/imageframe_time_axis.cc:310
+#, fuzzy
+msgid "Remove Frame"
+msgstr "Quitar Campo"
+
+#: gtk_ardour/imageframe_time_axis.cc:313
+#, fuzzy
+msgid "Image Frame"
+msgstr "Cuadros"
+
+#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274
+#, fuzzy
+msgid "Rename Track"
+msgstr "Renombrar"
+
+#: gtk_ardour/io_selector.cc:64
+msgid "%1 input"
+msgstr "%1 entrada"
+
+#: gtk_ardour/io_selector.cc:66
+msgid "%1 output"
+msgstr "%1 salida"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103
+msgid "Inputs"
+msgstr "Entradas"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104
+msgid "Outputs"
+msgstr "Salidas"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Input"
+msgstr "agregar entrada"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Output"
+msgstr "agregar salida"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Input"
+msgstr "Remover punto de sincron�"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Output"
+msgstr "# Salidas"
+
+#: gtk_ardour/io_selector.cc:144
+#, fuzzy
+msgid "Disconnect All"
+msgstr "Desconectar"
+
+#: gtk_ardour/io_selector.cc:158
+msgid "Available connections"
+msgstr "Conecciones disponibles"
+
+#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636
+#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724
+msgid "port"
+msgstr "conector"
+
+#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587
+msgid "There are no more JACK ports available."
+msgstr ""
+
+#: gtk_ardour/io_selector.cc:790
+msgid "ardour: "
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:419
+msgid "KeyboardTarget: keyname \"%1\" is unknown."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:645
+msgid ""
+"Your system is completely broken - NumLock uses \"%1\"as its modifier. This "
+"is madness - see the man page for xmodmap to find out how to fix this."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:653
+msgid ""
+"Your system generates \"%1\" when the NumLock key is pressed. This can cause "
+"problems when editing so Ardour will use %2 to mean Meta rather than %1"
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:714
+msgid "You have %1 keys bound to \"mod1\""
+msgstr "Tiene %1 teclas asignadas a \"mod1\""
+
+#: gtk_ardour/keyboard.cc:729
+msgid "You have %1 keys bound to \"mod2\""
+msgstr "Tiene %1 teclas asignadas a \"mod2\""
+
+#: gtk_ardour/keyboard.cc:744
+msgid "You have %1 keys bound to \"mod3\""
+msgstr "Tiene %1 teclas asignadas a \"mod3\""
+
+#: gtk_ardour/keyboard.cc:759
+msgid "You have %1 keys bound to \"mod4\""
+msgstr "Tiene %1 teclas asignadas a \"mod4\""
+
+#: gtk_ardour/keyboard.cc:774
+msgid "You have %1 keys bound to \"mod5\""
+msgstr "Tiene %1 teclas asignadas a \"mod5\""
+
+#: gtk_ardour/keyboard_target.cc:72
+msgid "KeyboardTarget: empty string passed to add_binding."
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:78
+msgid "KeyboardTarget: no translation found for \"%1\""
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:83
+msgid "KeyboardTarget: unknown action \"%1\""
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:248
+msgid "misformed binding node - ignored"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:62
+msgid "Soundfile Library"
+msgstr "Biblioteca de audio"
+
+#: gtk_ardour/library_ui.cc:63
+msgid "Filesystem"
+msgstr "Explorador de archivos"
+
+#: gtk_ardour/library_ui.cc:66
+msgid "Split Channels"
+msgstr "Separar canales"
+
+#: gtk_ardour/library_ui.cc:69
+msgid "ardour: soundfile selector"
+msgstr "ardour: seleccin de color"
+
+#: gtk_ardour/library_ui.cc:430
+msgid "Add to Library..."
+msgstr "Agregar a Biblioteca..."
+
+#: gtk_ardour/library_ui.cc:431
+msgid "Remove..."
+msgstr "Quitar..."
+
+#: gtk_ardour/library_ui.cc:432
+msgid "Find..."
+msgstr "Buscar..."
+
+#: gtk_ardour/library_ui.cc:433
+msgid "Add Folder"
+msgstr "Agregar Carpeta"
+
+#: gtk_ardour/library_ui.cc:434
+msgid "Add audio file or directory"
+msgstr "Agregar archivo o carpeta"
+
+#: gtk_ardour/library_ui.cc:713
+msgid "Importing"
+msgstr "Importando"
+
+#: gtk_ardour/library_ui.cc:748
+msgid "%1 not added to database"
+msgstr "%1 se agreg a banco de dados"
+
+#: gtk_ardour/library_ui.cc:767
+msgid "Folder name:"
+msgstr "Nombre de carpeta:"
+
+#: gtk_ardour/library_ui.cc:838
+msgid "Should not be reached"
+msgstr "No deber� alcanzarse"
+
+#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096
+msgid "file \"%1\" could not be opened"
+msgstr "el archivo \"%1\" no se pudo abrir"
+
+#: gtk_ardour/library_ui.cc:956
+msgid "Field"
+msgstr "Campo"
+
+#: gtk_ardour/library_ui.cc:957
+msgid "Value"
+msgstr "Valor"
+
+#: gtk_ardour/library_ui.cc:973
+msgid "Stop"
+msgstr "Detener"
+
+#: gtk_ardour/library_ui.cc:974
+msgid "Add Field..."
+msgstr "Agregar Campo..."
+
+#: gtk_ardour/library_ui.cc:975
+msgid "Remove Field"
+msgstr "Quitar Campo"
+
+#: gtk_ardour/library_ui.cc:979
+msgid "Soundfile Info"
+msgstr "Informacin de archivo"
+
+#: gtk_ardour/library_ui.cc:1106
+msgid "file \"%1\" appears not to be an audio file"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1159
+#, fuzzy
+msgid "Could not read file: %1 (%2)."
+msgstr "No se pudo abrir el archivo \"%1\" (%2)"
+
+#: gtk_ardour/library_ui.cc:1177
+msgid "Could not access soundfile: "
+msgstr "No se pudo acceder a archivo de audio"
+
+#: gtk_ardour/library_ui.cc:1222
+msgid "Field name:"
+msgstr "Nombre del campo:"
+
+#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367
+msgid "Field value:"
+msgstr "Valor del campo:"
+
+#: gtk_ardour/library_ui.cc:1295
+msgid "Find"
+msgstr "Buscar"
+
+#: gtk_ardour/library_ui.cc:1296
+msgid "AND"
+msgstr "Y"
+
+#: gtk_ardour/library_ui.cc:1297
+msgid "OR"
+msgstr "O"
+
+#: gtk_ardour/library_ui.cc:1300
+msgid "ardour: locate soundfiles"
+msgstr "ardour: localizar archivos de audio"
+
+#: gtk_ardour/library_ui.cc:1426
+msgid "Results"
+msgstr "Resultados"
+
+#: gtk_ardour/library_ui.cc:1427
+msgid "Uris"
+msgstr "URIs"
+
+#: gtk_ardour/library_ui.cc:1439
+msgid "Create multi-channel region"
+msgstr "Crear regin multi canal"
+
+#: gtk_ardour/library_ui.cc:1442
+msgid "Ardour: Search Results"
+msgstr "Ardour: Resultado de Bsqueda"
+
+#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50
+#, fuzzy
+msgid "Set"
+msgstr "Selecionar"
+
+#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51
+msgid "Go"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:54
+msgid "CD"
+msgstr "CD"
+
+#: gtk_ardour/location_ui.cc:55
+#, fuzzy
+msgid "Hidden"
+msgstr "Oculto"
+
+#: gtk_ardour/location_ui.cc:57
+msgid "SCMS"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:58
+msgid "Pre-Emphasis"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:592
+#, fuzzy
+msgid "Add New Location"
+msgstr "Agregar nueva localizacin"
+
+#: gtk_ardour/location_ui.cc:593
+msgid "Add New Range"
+msgstr "Agregar nueva regin"
+
+#: gtk_ardour/location_ui.cc:597
+msgid "ardour: locations"
+msgstr "ardour: localizaciones"
+
+#: gtk_ardour/location_ui.cc:598
+msgid "ardour_locations"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:629
+#, fuzzy
+msgid "Location (CD Index) Markers"
+msgstr "Marcadores de localizacin"
+
+#: gtk_ardour/location_ui.cc:649
+#, fuzzy
+msgid "Range (CD Track) Markers"
+msgstr "Marcadores de intervalo"
+
+#: gtk_ardour/location_ui.cc:814
+#, fuzzy
+msgid "add range marker"
+msgstr "agregar un marcador de regin"
+
+#: gtk_ardour/main.cc:76
+msgid "ardour is killing itself for a clean exit\n"
+msgstr "ardour se est�cerrando limpiamente\n"
+
+#: gtk_ardour/main.cc:85
+msgid "stopping user interface\n"
+msgstr "deteniendo interfase visual\n"
+
+#: gtk_ardour/main.cc:104
+#, c-format
+msgid "%d(%d): received signal %d\n"
+msgstr ""
+
+#: gtk_ardour/main.cc:190
+msgid "cannot become new process group leader (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:217
+msgid "cannot setup signal handling for %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:228
+msgid "cannot set default signal mask (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:253
+#, fuzzy
+msgid ""
+"Without a UI style file, ardour will look strange.\n"
+" Please set ARDOUR_UI_RC to point to a valid UI style file"
+msgstr ""
+"Sin un archivo de interfase visual, Ardour no se \n"
+"ver�correctamente. Apunte ARDOUR_UI_RC a un archivo v�ido"
+
+#: gtk_ardour/main.cc:292
+#, fuzzy
+msgid ""
+"Ardour could not connect to JACK.\n"
+"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 ""
+"Ardour no pudo conectarse a JACK.\n"
+"Hay varias razones posibles:\n"
+"\n"
+"1) JACK no est�corriendo.\n"
+"2) JACK est�corriendo bajo otro nombre de usuario,tal vez root.\n"
+"3) Ya hay otro cliente JACK corriendo con el nombre \"ardour\".\n"
+"\n"
+"Considere estas posibilidades y o reinicie a JACK.\n"
+
+#: gtk_ardour/main.cc:305
+#, fuzzy
+msgid "ardour: unplugged"
+msgstr "ardour: desconectado"
+
+#: gtk_ardour/main.cc:363
+msgid "Ardour/GTK "
+msgstr ""
+
+#: gtk_ardour/main.cc:365
+msgid ""
+"\n"
+" (built using "
+msgstr ""
+
+#: gtk_ardour/main.cc:369
+#, fuzzy
+msgid " with libardour "
+msgstr " corriendo con libardour "
+
+#: gtk_ardour/main.cc:374
+msgid " and GCC version "
+msgstr ""
+
+#: gtk_ardour/main.cc:384
+msgid "Copyright (C) 1999-2005 Paul Davis"
+msgstr ""
+
+#: gtk_ardour/main.cc:385
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+msgstr ""
+
+#: gtk_ardour/main.cc:387
+msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
+msgstr "Ardour no ofrece ningn tipo de garant�"
+
+#: gtk_ardour/main.cc:388
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr ""
+
+#: gtk_ardour/main.cc:389
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr "Este software es gratuito.Usted puede distribuirlo "
+
+#: gtk_ardour/main.cc:390
+#, fuzzy
+msgid "under certain conditions; see the source for copying conditions."
+msgstr "bajo ciertas condiciones; lea el archivo COPYING para m� detalles"
+
+#: gtk_ardour/main.cc:399
+msgid "could not create ARDOUR GUI"
+msgstr "no se pudo crear la interfase visual de Ardour"
+
+#: gtk_ardour/main.cc:419
+msgid "Could not connect to JACK server as \"%1\""
+msgstr "No se pudo conectar a JACK con el nombre \"%1\""
+
+#: gtk_ardour/main.cc:424
+msgid "could not initialize Ardour."
+msgstr "no se pudo iniciar a Ardour."
+
+#: gtk_ardour/main.cc:435
+msgid "could not load command line session \"%1\""
+msgstr "no se pudo cargar desde l�ea de comando a la sesin \"%1\""
+
+#: gtk_ardour/main.cc:455
+msgid ""
+"\n"
+"\n"
+"A session named \"%1\" already exists.\n"
+"To avoid this message, start ardour as \"ardour %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:466
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as \"ardour --new %1"
+msgstr ""
+
+#: gtk_ardour/marker.cc:354
+#, fuzzy
+msgid "MarkerText"
+msgstr "Marcas"
+
+#: gtk_ardour/marker_time_axis.cc:271
+#, fuzzy
+msgid "Remove Marker"
+msgstr "quitar marcador"
+
+#: gtk_ardour/marker_time_axis.cc:273
+#, fuzzy
+msgid "Marker"
+msgstr "Marcas"
+
+#: gtk_ardour/meter_bridge.cc:74
+msgid "ardour: meter bridge"
+msgstr "ardour: vmetro"
+
+#: gtk_ardour/meter_bridge.cc:75
+msgid "ardour_meter_bridge"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93
+#, c-format
+msgid "# of %u-sample overs"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:219
+msgid "New name for meter:"
+msgstr "Nuevo nombre para vmetro"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507
+#: gtk_ardour/region_editor.cc:45
+msgid "mute"
+msgstr "mudo"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508
+msgid "solo"
+msgstr "solo"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506
+msgid "RECORD"
+msgstr "GRABAR"
+
+#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514
+msgid "polarity"
+msgstr "polaridad"
+
+#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509
+msgid "comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810
+msgid "INPUT"
+msgstr "ENTRADA"
+
+#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831
+msgid "OUTPUT"
+msgstr "SALIDA"
+
+#: gtk_ardour/mixer_strip.cc:173
+#, fuzzy
+msgid "Pan automation mode"
+msgstr "modo de automatizacin de balance"
+
+#: gtk_ardour/mixer_strip.cc:174
+#, fuzzy
+msgid "Gain automation mode"
+msgstr "modo de automatizacin de volumen"
+
+#: gtk_ardour/mixer_strip.cc:176
+#, fuzzy
+msgid "Pan automation type"
+msgstr "estado de automatizacin de balance"
+
+#: gtk_ardour/mixer_strip.cc:177
+#, fuzzy
+msgid "Gain automation type"
+msgstr "estado de automatizacin de volumen"
+
+#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232
+#: gtk_ardour/mixer_strip.cc:979
+#, fuzzy
+msgid "trim"
+msgstr "cortar"
+
+#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233
+#: gtk_ardour/mixer_strip.cc:983
+msgid "abs"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:240
+#, fuzzy
+msgid "gain automation mode"
+msgstr "modo de automatizacin de volumen"
+
+#: gtk_ardour/mixer_strip.cc:241
+#, fuzzy
+msgid "pan automation mode"
+msgstr "modo de automatizacin de balance"
+
+#: gtk_ardour/mixer_strip.cc:242
+#, fuzzy
+msgid "gain automation state"
+msgstr "estado de automatizacin de volumen"
+
+#: gtk_ardour/mixer_strip.cc:243
+#, fuzzy
+msgid "pan automation state"
+msgstr "estado de automatizacin de balance"
+
+#: gtk_ardour/mixer_strip.cc:259
+msgid "varispeed"
+msgstr "velocidad"
+
+#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174
+msgid "click to add/edit comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:463
+msgid "unknown strip width \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:522
+msgid "REC"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:525
+#, fuzzy
+msgid "cmt"
+msgstr "cortar"
+
+#: gtk_ardour/mixer_strip.cc:530
+msgid "pol"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620
+#: gtk_ardour/redirect_box.cc:1180
+msgid "Not connected to JACK - no I/O changes are possible"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667
+msgid "could not register new ports required for that connection"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:813
+msgid "IN"
+msgstr "ENTRADA"
+
+#: gtk_ardour/mixer_strip.cc:834
+msgid "OUT"
+msgstr "SALIDA"
+
+#: gtk_ardour/mixer_strip.cc:950
+msgid "aplay"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:956
+msgid "awrite"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:1134
+#, fuzzy
+msgid ": comment editor"
+msgstr "no se pudo iniciar el editor"
+
+#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224
+msgid "no group"
+msgstr "sin grupo"
+
+#: gtk_ardour/mixer_strip.cc:1227
+msgid "~G"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:52
+msgid "Strips"
+msgstr "Pistas"
+
+#: gtk_ardour/mixer_ui.cc:56
+msgid "Snapshots"
+msgstr "Capturas"
+
+#: gtk_ardour/mixer_ui.cc:61
+msgid "***"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17
+#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144
+#: gtk_ardour/tempo_dialog.cc:162
+msgid "Bar"
+msgstr "Comp�"
+
+#: gtk_ardour/mixer_ui.cc:121
+msgid "Mix Groups"
+msgstr "Grupos de Mixer"
+
+#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373
+msgid "ardour: mixer"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:192
+msgid "ardour_mixer"
+msgstr "ardour_mixer"
+
+#: gtk_ardour/mixer_ui.cc:342
+msgid "ardour: mixer: "
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:641
+msgid "signal"
+msgstr "seal"
+
+#: gtk_ardour/mixer_ui.cc:672
+msgid "Show All AudioTrack MixerStrips"
+msgstr "Mostrar todas las pistas de Audio en el Mixer"
+
+#: gtk_ardour/mixer_ui.cc:673
+msgid "Hide All AudioTrack MixerStrips"
+msgstr "Ocultar todas las pistas de Audio en el Mixer"
+
+#: gtk_ardour/mixer_ui.cc:674
+msgid "Show All AudioBus MixerStrips"
+msgstr "Mostrar todos los Buses en el Mixer"
+
+#: gtk_ardour/mixer_ui.cc:675
+msgid "Hide All AudioBus MixerStrips"
+msgstr "Ocultar todos los Buses en el Mixer"
+
+#: gtk_ardour/mixer_ui.cc:687
+msgid "track display list item for renamed strip not found!"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:700
+msgid "Name for new mix group"
+msgstr "Nombre para nuevo grupo del mixer"
+
+#
+#: gtk_ardour/new_session_dialog.cc:39
+#, fuzzy
+msgid "Session name:"
+msgstr "Nombre de sesin:"
+
+#: gtk_ardour/new_session_dialog.cc:39
+#, fuzzy
+msgid "Create"
+msgstr "Crear"
+
+#: gtk_ardour/new_session_dialog.cc:40
+#, fuzzy
+msgid "use control outs"
+msgstr "Usar salidas de Control"
+
+#: gtk_ardour/new_session_dialog.cc:41
+#, fuzzy
+msgid "use master outs"
+msgstr "usar salidas Master"
+
+#: gtk_ardour/new_session_dialog.cc:42
+#, fuzzy
+msgid "automatically connect track inputs to physical ports"
+msgstr "conectar autom�icamente entradas de pistas a entradas f�icas"
+
+#: gtk_ardour/new_session_dialog.cc:43
+#, fuzzy
+msgid "automatically connect track outputs to master outs"
+msgstr "conectar autom�icamente salidas de pistas a salidas Master"
+
+#: gtk_ardour/new_session_dialog.cc:44
+#, fuzzy
+msgid "automatically connect track outputs to physical ports"
+msgstr "conectar autom�icamente salidas de pistas a salidas f�icas"
+
+#: gtk_ardour/new_session_dialog.cc:45
+msgid "manually connect track outputs"
+msgstr "conectar pistas manualmente"
+
+#: gtk_ardour/new_session_dialog.cc:50
+#, fuzzy
+msgid "Advanced..."
+msgstr "Avanzado..."
+
+#: gtk_ardour/new_session_dialog.cc:52
+#, fuzzy
+msgid "show again"
+msgstr "Mostrar toda automatizacin"
+
+#: gtk_ardour/new_session_dialog.cc:55
+msgid "Hardware Inputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:56
+msgid "Hardware Outputs: use"
+msgstr ""
+
+#
+#: gtk_ardour/new_session_dialog.cc:62
+#, fuzzy
+msgid "new session setup"
+msgstr "Configuracin para nueva sesin"
+
+#: gtk_ardour/new_session_dialog.cc:63
+msgid "ardour_new_session"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:72
+msgid "This session will playback and record at %1 Hz"
+msgstr "Esta sesin reproducir�y grabar�a %1 Hz"
+
+#: gtk_ardour/new_session_dialog.cc:74
+#, fuzzy
+msgid ""
+"This rate is set by JACK and cannot be changed.\n"
+"If you want to use a different sample rate\n"
+"please exit and restart JACK"
+msgstr ""
+"Esta frecuencia de muestreo es configurada por JACK\n"
+"y no puede ser modificada desde Ardour.Si desea una\n"
+"frecuencia de muestreo distinta, cierre Ardour,reinice\n"
+"JACK y vuelva a ejecutar Ardour\n"
+
+#: gtk_ardour/new_session_dialog.cc:155
+#, fuzzy
+msgid "Session template"
+msgstr "usar esquema existente"
+
+#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20
+#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146
+#: gtk_ardour/tempo_dialog.cc:164
+msgid "Location"
+msgstr "Localizacin"
+
+#: gtk_ardour/new_session_dialog.cc:178
+msgid "Configuration"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:269
+msgid "blank"
+msgstr "en blanco"
+
+#: gtk_ardour/new_session_dialog.cc:328
+msgid "No template - create tracks/busses manually"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:337
+#, fuzzy
+msgid "No template"
+msgstr "-esquema"
+
+#: gtk_ardour/option_editor.cc:48
+#, fuzzy
+msgid "Internal"
+msgstr "interno"
+
+#: gtk_ardour/option_editor.cc:49
+#, fuzzy
+msgid "Slave to MTC"
+msgstr "Enviar MTC"
+
+#: gtk_ardour/option_editor.cc:50
+msgid "Sync with JACK"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:51
+msgid "never used but stops crashes"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:56
+#, fuzzy
+msgid "Later regions are higher"
+msgstr "Bajar regin una capa"
+
+#: gtk_ardour/option_editor.cc:57
+msgid "Most recently added/moved/trimmed regions are higher"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:58
+#, fuzzy
+msgid "Most recently added regions are higher"
+msgstr "Bajar regin una capa"
+
+#: gtk_ardour/option_editor.cc:63
+#, fuzzy
+msgid "Span entire region overlap"
+msgstr "Elevar regin una capa"
+
+#: gtk_ardour/option_editor.cc:64
+msgid "Short fades at the start of the overlap"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:82
+#, fuzzy
+msgid "Automatically create crossfades"
+msgstr "Crosfade autom�ico si dos regiones se superponen"
+
+#: gtk_ardour/option_editor.cc:83
+msgid "New full-overlap crossfades are unmuted"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:84
+#, fuzzy
+msgid "Region layering mode"
+msgstr "Fines de regin"
+
+#: gtk_ardour/option_editor.cc:85
+#, fuzzy
+msgid "Crossfade model"
+msgstr "editar fade in"
+
+#: gtk_ardour/option_editor.cc:90
+msgid "Latched solo"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:91
+msgid "Solo via bus"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:96
+#, fuzzy
+msgid "Show waveforms while recording"
+msgstr "Mostrar onda de audio"
+
+#: gtk_ardour/option_editor.cc:97
+msgid "Narrow mixer strips"
+msgstr "Estrechar pistas del mixer"
+
+#: gtk_ardour/option_editor.cc:98
+msgid "Show measure lines"
+msgstr "Mostrar l�eas de medida"
+
+#: gtk_ardour/option_editor.cc:99
+msgid "Follow playhead"
+msgstr "Seguir a la barra de reproduccin"
+
+#: gtk_ardour/option_editor.cc:103
+msgid "Send MTC"
+msgstr "Enviar MTC"
+
+#: gtk_ardour/option_editor.cc:104
+msgid "Send MMC"
+msgstr "Enviar MMC"
+
+#: gtk_ardour/option_editor.cc:105
+msgid "JACK time master"
+msgstr "M�ter de tiempo JACK"
+
+#: gtk_ardour/option_editor.cc:107
+msgid "SMPTE offset is negative"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:111
+msgid "Send MIDI parameter feedback"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:112
+msgid "MIDI parameter control"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:113
+#, fuzzy
+msgid "MMC control"
+msgstr "Puerto MMC"
+
+#: gtk_ardour/option_editor.cc:131
+#, fuzzy
+msgid "Auto-connect new track inputs to hardware"
+msgstr "Conectar nuevas pistas autom�icamente"
+
+#: gtk_ardour/option_editor.cc:132
+#, fuzzy
+msgid "Auto-connect new track outputs to hardware"
+msgstr "Conectar nuevas pistas autom�icamente"
+
+#: gtk_ardour/option_editor.cc:133
+#, fuzzy
+msgid "Auto-connect new track outputs to master bus"
+msgstr "conectar autom�icamente salidas de pistas a salidas Master"
+
+#: gtk_ardour/option_editor.cc:134
+#, fuzzy
+msgid "Manually connect new track outputs"
+msgstr "conectar pistas manualmente"
+
+#: gtk_ardour/option_editor.cc:135
+msgid "Use Hardware Monitoring"
+msgstr "Monitorizacin por Hardware"
+
+#: gtk_ardour/option_editor.cc:136
+msgid "Use Software Monitoring"
+msgstr "Monitorizacin por Software"
+
+#: gtk_ardour/option_editor.cc:137
+msgid "Stop plugins with transport"
+msgstr "No procesar plugins durante transporte"
+
+#: gtk_ardour/option_editor.cc:138
+msgid "Run plugins while recording"
+msgstr "Procesar plugins durante la grabacin"
+
+#: gtk_ardour/option_editor.cc:139
+#, fuzzy
+msgid "Verify remove last capture"
+msgstr "Quitar ltima captura"
+
+#: gtk_ardour/option_editor.cc:140
+msgid "Stop recording on xrun"
+msgstr "Detener grabacin al detectar un XRUN"
+
+#: gtk_ardour/option_editor.cc:141
+msgid "Stop transport at end of session"
+msgstr "Detener el transporte al llegar al final de la sesin"
+
+#: gtk_ardour/option_editor.cc:142
+msgid "Debug keyboard events"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:143
+msgid "-12dB gain reduction for ffwd/rew"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:152
+msgid "ardour: options editor"
+msgstr "ardour: opciones editor"
+
+#: gtk_ardour/option_editor.cc:153
+msgid "ardour_option_editor"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:183
+msgid "Misc"
+msgstr "Miscel�ea"
+
+#: gtk_ardour/option_editor.cc:184
+msgid "Sync"
+msgstr "Sincronizacin"
+
+#: gtk_ardour/option_editor.cc:185
+msgid "Paths/Files"
+msgstr "Carpetas/Archivos"
+
+#: gtk_ardour/option_editor.cc:186
+msgid "Display"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:187
+msgid "Kbd/Mouse"
+msgstr "Teclado/Mouse"
+
+#: gtk_ardour/option_editor.cc:188
+msgid "Click"
+msgstr "Metrnomo"
+
+#: gtk_ardour/option_editor.cc:190
+msgid "Layers & Fades"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:195
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gtk_ardour/option_editor.cc:268
+msgid "24 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:270
+msgid "25 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:272
+msgid "30 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:278
+msgid "30 FPS drop"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379
+#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736
+#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800
+msgid "Medium"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738
+#: gtk_ardour/option_editor.cc:804
+#, fuzzy
+msgid "Faster"
+msgstr "Fades"
+
+#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714
+#: gtk_ardour/option_editor.cc:776
+#, fuzzy
+msgid "Short"
+msgstr "conector"
+
+#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716
+#: gtk_ardour/option_editor.cc:780
+msgid "Long"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:396
+msgid "Broadcast WAVE/floating point"
+msgstr "Broadcast WAVE/punto flotante"
+
+#: gtk_ardour/option_editor.cc:397
+msgid "WAVE/floating point"
+msgstr "WAVE/punto flotante"
+
+#: gtk_ardour/option_editor.cc:417
+msgid "session RAID path"
+msgstr "ubicacin de archivos de sesin"
+
+#: gtk_ardour/option_editor.cc:422
+msgid "Native Format"
+msgstr "Formato Nativo"
+
+#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460
+#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409
+msgid "internal"
+msgstr "interno"
+
+#: gtk_ardour/option_editor.cc:537
+msgid "Short crossfade length (msecs)"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:710
+msgid "Meter Peak Hold"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:730
+msgid "Meter Falloff"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:847
+msgid "Positional Sync"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:902
+msgid "SMPTE Frames/second"
+msgstr "SMPTE Cuadros/segundo"
+
+#: gtk_ardour/option_editor.cc:903
+msgid "SMPTE Offset"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013
+#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211
+#, fuzzy
+msgid "online"
+msgstr "linear"
+
+#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014
+#: gtk_ardour/option_editor.cc:1208
+#, fuzzy
+msgid "offline"
+msgstr "linear"
+
+#: gtk_ardour/option_editor.cc:1319
+msgid "Use as click"
+msgstr "Usar como metrnomo"
+
+#: gtk_ardour/option_editor.cc:1344
+msgid "Use as click emphasis"
+msgstr "Usar como �fasis de metrnomo"
+
+#: gtk_ardour/option_editor.cc:1478
+msgid "--unknown--"
+msgstr "--desconocido--"
+
+#: gtk_ardour/option_editor.cc:1595
+msgid "Click audio file"
+msgstr "Archivo de sonido para metrnomo"
+
+#: gtk_ardour/option_editor.cc:1601
+msgid "Click emphasis audiofile"
+msgstr "Archivo de sonido de �fasis de metrnomo"
+
+#: gtk_ardour/option_editor.cc:1638
+msgid ""
+"The auditioner is a dedicated mixer strip used\n"
+"for listening to specific regions outside the context\n"
+"of the overall mix. It can be connected just like any\n"
+"other mixer strip."
+msgstr ""
+"El audicionador es una salida de sonido dedicada empleada\n"
+"para o� regiones espec�icas de la sesin o para\n"
+"escuchar archivos de sonido en el men Biblioteca de Audio\n"
+"Se puede configurar sus conecciones como a cualquier.otra del mixer"
+
+#: gtk_ardour/option_editor.cc:1887
+msgid "Edit using"
+msgstr "Editar con"
+
+#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924
+msgid "+ button"
+msgstr "botn +"
+
+#: gtk_ardour/option_editor.cc:1917
+msgid "Delete using"
+msgstr "Eliminar con"
+
+#: gtk_ardour/option_editor.cc:1947
+msgid "Ignore snap using"
+msgstr "Ignorar trabar con"
+
+#: gtk_ardour/opts.cc:46
+msgid "Usage: "
+msgstr "Uso: "
+
+#: gtk_ardour/opts.cc:47
+msgid " -v, --version Show version information\n"
+msgstr ""
+" -v, --version Mostra informacin acerca de la versin\n"
+
+#: gtk_ardour/opts.cc:48
+msgid " -h, --help Print this message\n"
+msgstr " -h, --help Muestra este mensage\n"
+
+#: gtk_ardour/opts.cc:49
+msgid ""
+" -b, --bindings Print all possible keyboard binding "
+"names\n"
+msgstr ""
+" -b, --bindings Muestra todos los comandos asignables a "
+"botones del teclado(shortcuts)\n"
+
+#: gtk_ardour/opts.cc:50
+#, fuzzy
+msgid " -n, --show-splash Show splash screen\n"
+msgstr " -n, --no-splash No mostrar recuadro inicial\n"
+
+#: gtk_ardour/opts.cc:51
+#, fuzzy
+msgid ""
+" -c, --name name Use a specific jack client name, default "
+"is ardour\n"
+msgstr ""
+" -c, --jack-client-name nombre Nombre de cliente jack para Ardour. Si "
+"no selecciona ninguno, el nombre ser�ardour\n"
+
+#: gtk_ardour/opts.cc:52
+#, fuzzy
+msgid ""
+" -N, --new session-name Create a new session from the command "
+"line\n"
+msgstr " [nombre-sesin] Nombre de sesin a cargar\n"
+
+#: gtk_ardour/opts.cc:53
+msgid ""
+" -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:55
+#, fuzzy
+msgid " -V, --novst Do not use VST support\n"
+msgstr " -n, --no-splash No mostrar recuadro inicial\n"
+
+#: gtk_ardour/opts.cc:57
+msgid " [session-name] Name of session to load\n"
+msgstr " [nombre-sesin] Nombre de sesin a cargar\n"
+
+#: gtk_ardour/opts.cc:58
+msgid " -C, --curvetest filename Curve algorithm debugger\n"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:58
+msgid "You can't graphically edit panning of more than stream"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:78
+#, fuzzy
+msgid "add pan automation event"
+msgstr "agregar evento de automatizacin a "
+
+#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441
+#, fuzzy
+msgid "Bypass"
+msgstr "no procesar"
+
+#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222
+#, fuzzy
+msgid "link"
+msgstr "entrada"
+
+#: gtk_ardour/panner_ui.cc:103
+msgid "panning link control"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:105
+msgid "panning link direction"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:232
+msgid "L"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:344
+#, c-format
+msgid "panner for channel %u"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:451
+#, fuzzy
+msgid "Reset all"
+msgstr "resetear"
+
+#: gtk_ardour/playlist_selector.cc:46
+msgid "Playlists grouped by track"
+msgstr ""
+
+#: gtk_ardour/playlist_selector.cc:53
+#, fuzzy
+msgid "close"
+msgstr "Cerrar"
+
+#: gtk_ardour/playlist_selector.cc:59
+#, fuzzy
+msgid "ardour: playlists"
+msgstr "ardour: plugins"
+
+#: gtk_ardour/playlist_selector.cc:104
+#, fuzzy
+msgid "ardour: playlist for "
+msgstr "ardour: plugins"
+
+#: gtk_ardour/playlist_selector.cc:122
+#, fuzzy
+msgid "Other tracks"
+msgstr "Ocultar esta pista"
+
+#: gtk_ardour/playlist_selector.cc:138
+msgid "unassigned"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:41
+msgid "Available LADSPA plugins"
+msgstr "Plugins LADSPA dispon�les"
+
+#: gtk_ardour/plugin_selector.cc:42
+msgid "Type"
+msgstr "Tipo"
+
+#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51
+msgid "# Inputs"
+msgstr "# Entradas"
+
+#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52
+msgid "# Outputs"
+msgstr "# Salidas"
+
+#: gtk_ardour/plugin_selector.cc:50
+#, fuzzy
+msgid "Available VST plugins"
+msgstr "Plugins LADSPA dispon�les"
+
+#: gtk_ardour/plugin_selector.cc:58
+msgid "To be added"
+msgstr "Plugins que se agregar�"
+
+#: gtk_ardour/plugin_selector.cc:72
+msgid "ardour: plugins"
+msgstr "ardour: plugins"
+
+#: gtk_ardour/plugin_selector.cc:82
+msgid "Add a plugin to the effect list"
+msgstr "Agregar plugin a lista de efectos"
+
+#: gtk_ardour/plugin_selector.cc:84
+msgid "Remove a plugin from the effect list"
+msgstr "Quitar plugin de lista de efectos"
+
+#: gtk_ardour/plugin_selector.cc:88
+msgid "Update"
+msgstr "Actualizar"
+
+#: gtk_ardour/plugin_selector.cc:89
+msgid "Update available plugins"
+msgstr "Actualizar plugins dispon�les"
+
+#: gtk_ardour/plugin_selector.cc:110
+msgid "LADSPA"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:113
+msgid "VST"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:83
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this "
+"version of ardour)"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:269
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "in"
+msgstr "entrada"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "ins"
+msgstr "entradas"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "out"
+msgstr "salida"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "outs"
+msgstr "salidas"
+
+#: gtk_ardour/plugin_ui.cc:382
+#, fuzzy
+msgid "automation control"
+msgstr "mover evento de automatizacin"
+
+#: gtk_ardour/plugin_ui.cc:869
+#, fuzzy
+msgid "save"
+msgstr "Guardar"
+
+#: gtk_ardour/plugin_ui.cc:870
+msgid "bypass"
+msgstr "no procesar"
+
+#: gtk_ardour/plugin_ui.cc:892
+msgid "Plugin preset %1 not found"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:903
+msgid "Name for plugin settings:"
+msgstr "Nombre para configuracin de plugin"
+
+#: gtk_ardour/redirect_automation_line.cc:53
+msgid "redirect automation created for non-plugin"
+msgstr "automatizacin creada para un redireccionamiento no-plugin"
+
+#: gtk_ardour/redirect_automation_time_axis.cc:92
+#, fuzzy
+msgid "add automation event to "
+msgstr "agregar evento de automatizacin a "
+
+#: gtk_ardour/redirect_box.cc:213
+msgid "New send"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:214
+#, fuzzy
+msgid "Show send controls"
+msgstr "Control de velocidad y sentido de reproduccin(pitch)"
+
+#: gtk_ardour/redirect_box.cc:360
+msgid "New Plugin ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:361
+#, fuzzy
+msgid "New Insert"
+msgstr "nueva entrada"
+
+#: gtk_ardour/redirect_box.cc:362
+msgid "New Send ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:380
+#, fuzzy
+msgid "Select all"
+msgstr "Seleccionar todo"
+
+#: gtk_ardour/redirect_box.cc:381
+#, fuzzy
+msgid "Deselect all"
+msgstr "Seleccionar todo"
+
+#: gtk_ardour/redirect_box.cc:389
+#, fuzzy
+msgid "Inserts"
+msgstr "Invertir"
+
+#: gtk_ardour/redirect_box.cc:390
+#, fuzzy
+msgid "Sends"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/redirect_box.cc:393
+#, fuzzy
+msgid "Select all ..."
+msgstr "Seleccionar todo"
+
+#: gtk_ardour/redirect_box.cc:406
+#, fuzzy
+msgid "Activate All"
+msgstr "Activar"
+
+#: gtk_ardour/redirect_box.cc:407
+#, fuzzy
+msgid "Deactivate All"
+msgstr "Desactivar"
+
+#: gtk_ardour/redirect_box.cc:488
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:500
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:513
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:616
+msgid "Pre-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:619
+msgid "Post-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:781
+msgid ""
+"You cannot reorder this set of redirects\n"
+"in that way because the inputs and\n"
+"outputs do not work correctly."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:903
+#, fuzzy
+msgid "ardour: rename redirect"
+msgstr "ardour: renombrar regin"
+
+#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043
+msgid ""
+"Copying the set of redirects on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:1064
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this track?\n"
+"(this cannot be undone)"
+msgstr ""
+"Realmente desea quitar la pista \"%1\" ?\n"
+"(no podr�deshacer esto)"
+
+#: gtk_ardour/redirect_box.cc:1067
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this bus?\n"
+"(this cannot be undone)"
+msgstr ""
+"Realmente desea quitar la pista \"%1\" ?\n"
+"(no podr�deshacer esto)"
+
+#: gtk_ardour/redirect_box.cc:1071
+#, fuzzy
+msgid "Yes, remove them all"
+msgstr "Si, eliminar esto."
+
+#: gtk_ardour/redirect_box.cc:1114
+#, fuzzy
+msgid "ardour: %1"
+msgstr "ardour: reloj"
+
+#: gtk_ardour/redirect_box.cc:1156
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "ardour: regin"
+
+#: gtk_ardour/region_editor.cc:43
+msgid "NAME:"
+msgstr "NOMBRE:"
+
+#: gtk_ardour/region_editor.cc:44
+msgid "lock"
+msgstr "bloquear"
+
+#: gtk_ardour/region_editor.cc:46
+msgid "opaque"
+msgstr "opaco"
+
+#: gtk_ardour/region_editor.cc:49
+msgid "Layer"
+msgstr "Capa"
+
+#: gtk_ardour/region_editor.cc:57
+msgid "ENVELOPE"
+msgstr "ENVELOPE"
+
+#: gtk_ardour/region_editor.cc:108
+msgid "mute this region"
+msgstr "enmudecer a esta regin"
+
+#: gtk_ardour/region_editor.cc:109
+msgid "regions underneath this one cannot be heard"
+msgstr "no se oir� a las regiones que est� bajo �ta"
+
+#: gtk_ardour/region_editor.cc:110
+msgid "prevent any changes to this region"
+msgstr "bloquear contra cambios a esta regin"
+
+#: gtk_ardour/region_editor.cc:111
+msgid "use the gain envelope during playback"
+msgstr "usar envelope de volumen durante la reproduccin"
+
+#: gtk_ardour/region_editor.cc:112
+msgid "show the gain envelope"
+msgstr "mostrar envelope de volumen"
+
+#: gtk_ardour/region_editor.cc:113
+msgid "use fade in curve during playback"
+msgstr "usar fade-in durante reproduccin"
+
+#: gtk_ardour/region_editor.cc:114
+msgid "use fade out curve during playback"
+msgstr "usar fade-out durante reproduccin"
+
+#: gtk_ardour/region_editor.cc:115
+msgid "audition this region"
+msgstr "audicionar esta regin"
+
+#: gtk_ardour/region_editor.cc:148
+msgid "START:"
+msgstr "INICIO"
+
+#: gtk_ardour/region_editor.cc:150
+msgid "END:"
+msgstr "FINAL:"
+
+#: gtk_ardour/region_editor.cc:152
+msgid "LENGTH:"
+msgstr "DURACI�:"
+
+#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198
+#: gtk_ardour/region_editor.cc:234
+msgid "active"
+msgstr "activo"
+
+#: gtk_ardour/region_editor.cc:179
+msgid "visible"
+msgstr "visible"
+
+#: gtk_ardour/region_editor.cc:197
+msgid "FADE IN"
+msgstr "FADE IN"
+
+#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235
+msgid "msecs"
+msgstr "milisecs."
+
+#: gtk_ardour/region_editor.cc:233
+msgid "FADE OUT"
+msgstr "FADE OUT"
+
+#: gtk_ardour/region_editor.cc:276
+msgid "ardour: region "
+msgstr "ardour: regin"
+
+#: gtk_ardour/region_editor.cc:410
+msgid "fade in edit"
+msgstr "editar fade in"
+
+#: gtk_ardour/region_editor.cc:422
+#, fuzzy
+msgid "fade out edit"
+msgstr "agregar salida"
+
+#: gtk_ardour/regionview.cc:1169
+#, fuzzy
+msgid "add gain control point"
+msgstr "Remover punto de sincron�"
+
+#: gtk_ardour/route_params_ui.cc:58
+msgid "Tracks/Buses"
+msgstr "Pistas/Buses"
+
+#: gtk_ardour/route_params_ui.cc:59
+msgid "Pre Redirects"
+msgstr "Pre Redireccionamentos"
+
+#: gtk_ardour/route_params_ui.cc:60
+msgid "Post Redirects"
+msgstr "Pst Redireccionamentos"
+
+#: gtk_ardour/route_params_ui.cc:105
+#, fuzzy
+msgid "Pre-fader Redirects"
+msgstr "Pre Redireccionamentos"
+
+#: gtk_ardour/route_params_ui.cc:106
+#, fuzzy
+msgid "Post-fader Redirects"
+msgstr "Pst Redireccionamentos"
+
+#: gtk_ardour/route_params_ui.cc:138
+#, fuzzy
+msgid "ardour: track/bus inspector"
+msgstr "ardour: agregar Pistas/bus"
+
+#: gtk_ardour/route_params_ui.cc:139
+msgid "ardour_route_parameters"
+msgstr "ardour_route_parameters"
+
+#: gtk_ardour/route_params_ui.cc:189
+msgid "route display list item for renamed route not found!"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:448
+msgid "NO TRACK"
+msgstr "NINGUNA PISTA"
+
+#: gtk_ardour/route_params_ui.cc:669
+#, fuzzy
+msgid "ardour: track/bus inspector: "
+msgstr "ardour: agregar Pistas/bus"
+
+#: gtk_ardour/route_params_ui.cc:673
+msgid "No Route Selected"
+msgstr "No seleccion ninguna Ruta"
+
+#: gtk_ardour/route_params_ui.cc:674
+#, fuzzy
+msgid "ardour: track/bus/inspector: no route selected"
+msgstr "ardour: par�etros de ruteo: no seleccion ninguna ruta"
+
+#: gtk_ardour/route_ui.cc:134
+#, fuzzy
+msgid "mute change"
+msgstr "Seleccionar intervalo de punch"
+
+#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220
+#, fuzzy
+msgid "solo change"
+msgstr "rango de reproduccin cont�ua"
+
+#: gtk_ardour/route_ui.cc:284
+msgid "rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:423
+#, fuzzy
+msgid "Solo-safe"
+msgstr "Solo"
+
+#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474
+#, fuzzy
+msgid "MIDI Bind"
+msgstr "MIDI"
+
+#: gtk_ardour/route_ui.cc:445
+msgid "Pre Fader"
+msgstr "Pre-Fader"
+
+#: gtk_ardour/route_ui.cc:452
+msgid "Post Fader"
+msgstr "Pst-Fader"
+
+#: gtk_ardour/route_ui.cc:459
+msgid "Control Outs"
+msgstr "Control de Salidas"
+
+#: gtk_ardour/route_ui.cc:466
+msgid "Main Outs"
+msgstr "Salidas Principales"
+
+#: gtk_ardour/route_ui.cc:503
+msgid "mix group solo change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:537
+msgid "mix group mute change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:553
+msgid "mix group rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258
+msgid "ardour: color selection"
+msgstr "ardour: seleccin de color"
+
+#: gtk_ardour/route_ui.cc:652
+#, fuzzy
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"You may also lose the playlist used by this track.\n"
+"(cannot be undone)"
+msgstr ""
+"Realmente desea quitar la pista \"%1\" ?\n"
+"(no podr�deshacer esto)"
+
+#: gtk_ardour/route_ui.cc:654
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Realmente desea quitar el bus \"%1\" ?\n"
+"(no podr�deshacer esto)"
+
+#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299
+msgid "Yes, remove it."
+msgstr "Si, eliminar esto."
+
+#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358
+msgid "new name: "
+msgstr "nuevo nombre: "
+
+#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31
+msgid "Beats per minute"
+msgstr "Pulsos por minuto"
+
+#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35
+#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163
+msgid "Beat"
+msgstr "Pulsos"
+
+#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158
+msgid "Meter denominator"
+msgstr "Denominador m�rico"
+
+#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159
+msgid "Beats per bar"
+msgstr "Pulsos por compaces"
+
+#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189
+msgid "whole (1)"
+msgstr "toda (1)"
+
+#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191
+msgid "second (2)"
+msgstr "segunda (2)"
+
+#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193
+msgid "third (3)"
+msgstr "tercera (3)"
+
+#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195
+#: gtk_ardour/tempo_dialog.cc:203
+msgid "quarter (4)"
+msgstr "cuarta (4)"
+
+#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197
+msgid "eighth (8)"
+msgstr "octava (8)"
+
+#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199
+msgid "sixteenth (16)"
+msgstr "d�ima sexta (16)"
+
+#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201
+msgid "thirty-second (32)"
+msgstr "trig�ima segunda (32)"
+
+#: gtk_ardour/tempo_dialog.cc:301
+msgid "garbaged note type entry (%1)"
+msgstr "se descart el texto (%1)"
+
+#: gtk_ardour/tempo_dialog.cc:311
+msgid "incomprehensible note type entry (%1)"
+msgstr "El formato de este texto es incomprensible(%1)"
+
+#: gtk_ardour/time_axis_view.cc:95
+msgid "gTortnam"
+msgstr "gTortnam"
+
+#: gtk_ardour/time_axis_view.cc:446
+msgid "Largest"
+msgstr "Enorme"
+
+#: gtk_ardour/time_axis_view.cc:447
+msgid "Large"
+msgstr "Grande"
+
+#: gtk_ardour/time_axis_view.cc:448
+msgid "Larger"
+msgstr "Mayor"
+
+#: gtk_ardour/time_axis_view.cc:450
+msgid "Smaller"
+msgstr "Menor"
+
+#: gtk_ardour/time_axis_view.cc:451
+msgid "Small"
+msgstr "Chico"
+
+#: gtk_ardour/time_axis_view.cc:785
+msgid "unknown track height name \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:69
+msgid "TimeAxisViewItemName"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:258
+msgid "new duration %1 frames is out of bounds for %2"
+msgstr ""
+
+#: gtk_ardour/time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr ""
+
+#: gtk_ardour/utils.cc:57
+msgid ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+msgstr ""
+
+#: gtk_ardour/utils.cc:66
+msgid "aeiou"
+msgstr ""
+
+#: gtk_ardour/utils.cc:75
+msgid "AEIOU"
+msgstr ""
+
+#: gtk_ardour/utils.cc:84
+msgid "bcdfghjklmnpqrtvwxyz"
+msgstr ""
+
+#: gtk_ardour/utils.cc:93
+msgid "BCDFGHJKLMNPQRTVWXYZ"
+msgstr ""
+
+#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265
+msgid "bad XPM header %1"
+msgstr ""
+
+#: gtk_ardour/utils.cc:516
+msgid "missing RGBA style for \"%1\""
+msgstr ""
+
+#: gtk_ardour/visual_time_axis.cc:297
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Realmente desea quitar la pista \"%1\" ?\n"
+"(no podr�deshacer esto)"
+
+#: gtk_ardour/visual_time_axis.cc:385
+msgid "A track already exists with that name"
+msgstr "Ya existe una pista con este nombre"
+
+#~ msgid "Export to CD"
+#~ msgstr "Exportar a CD"
+
+#, fuzzy
+#~ msgid "Trace MIDI Input"
+#~ msgstr "Vigilar Entrada de MIDI"
+
+#, fuzzy
+#~ msgid "Trace MIDI Output"
+#~ msgstr "Vigilar Salida de MIDI"
+
+#~ msgid "MTC Port"
+#~ msgstr "Puerto MTC"
+
+#~ msgid "attempt to timestretch a non-audio track!"
+#~ msgstr "se intent hacer estiramiento a una pista que no es de audio!"
+
+#~ msgid "ardour: tempo editor"
+#~ msgstr "ardour: editor de tempo"
+
+#~ msgid "ok"
+#~ msgstr "ok"
+
+#, fuzzy
+#~ msgid "apply"
+#~ msgstr "aplicar"
+
+#, fuzzy
+#~ msgid "Edit left"
+#~ msgstr "Modo de edicin"
+
+#, fuzzy
+#~ msgid "Edit right"
+#~ msgstr "Editar con"
+
+#, fuzzy
+#~ msgid "Edit fade"
+#~ msgstr "Modo de edicin"
+
+#, fuzzy
+#~ msgid "Export region"
+#~ msgstr "Exportar regin"
+
+#, fuzzy
+#~ msgid "Bounce region"
+#~ msgstr "Grabar seleccin"
+
+#~ msgid "Region"
+#~ msgstr "Regin"
+
+#~ msgid "Play selected region"
+#~ msgstr "Reproducir regin selecionada"
+
+#~ msgid "clear connections"
+#~ msgstr "Quitar conecciones"
+
+#, fuzzy
+#~ msgid "outside this computer"
+#~ msgstr "Ocultar esta pista"
+
+#, fuzzy
+#~ msgid "inside this computer"
+#~ msgstr "Ocultar esta pista"
diff --git a/gtk2_ardour/po/fr_FR.po b/gtk2_ardour/po/fr_FR.po
new file mode 100644
index 0000000000..479382a52a
--- /dev/null
+++ b/gtk2_ardour/po/fr_FR.po
@@ -0,0 +1,5198 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) 2004 Paul Davis
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gtk-ardour 0.334.5\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-09-19 18:09-0400\n"
+"PO-Revision-Date: 2005-02-14 11:19-0500\n"
+"Last-Translator: Alain Fréhel <alain.frehel@free.fr>\n"
+"Language-Team: French <ardour-dev@lists.sourceforge.net>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gtk_ardour/about.cc:134
+msgid "Marcus Andersson"
+msgstr ""
+
+#: gtk_ardour/about.cc:135
+msgid "Jeremy Hall"
+msgstr ""
+
+#: gtk_ardour/about.cc:136
+msgid "Steve Harris"
+msgstr ""
+
+#: gtk_ardour/about.cc:137
+msgid "Tim Mayberry"
+msgstr ""
+
+#: gtk_ardour/about.cc:138
+msgid "Mark Stewart"
+msgstr ""
+
+#: gtk_ardour/about.cc:139
+msgid "Sam Chessman"
+msgstr ""
+
+#: gtk_ardour/about.cc:140
+msgid "Jack O'Quin"
+msgstr ""
+
+#: gtk_ardour/about.cc:141
+msgid "Matt Krai"
+msgstr ""
+
+#: gtk_ardour/about.cc:142
+msgid "Ben Bell"
+msgstr ""
+
+#: gtk_ardour/about.cc:143
+msgid "Gerard van Dongen"
+msgstr ""
+
+#: gtk_ardour/about.cc:144
+msgid "Thomas Charbonnel"
+msgstr ""
+
+#: gtk_ardour/about.cc:145
+msgid "Nick Mainsbridge"
+msgstr ""
+
+#: gtk_ardour/about.cc:146
+msgid "Colin Law"
+msgstr ""
+
+#: gtk_ardour/about.cc:147
+msgid "Sampo Savolainen"
+msgstr ""
+
+#: gtk_ardour/about.cc:148
+msgid "Joshua Leach"
+msgstr ""
+
+#: gtk_ardour/about.cc:149
+msgid "Rob Holland"
+msgstr ""
+
+#: gtk_ardour/about.cc:150
+msgid "Per Sigmond"
+msgstr ""
+
+#: gtk_ardour/about.cc:151
+msgid "Doug Mclain"
+msgstr ""
+
+#: gtk_ardour/about.cc:156
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+msgstr ""
+"Français :\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+
+#: gtk_ardour/about.cc:157
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+msgstr ""
+"Allemand :\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+
+#: gtk_ardour/about.cc:158
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+msgstr ""
+"Italien :\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+
+#: gtk_ardour/about.cc:159
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+msgstr ""
+"Portugais :\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+
+#: gtk_ardour/about.cc:160
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+msgstr ""
+"Portugais du Brésil :\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+
+#: gtk_ardour/about.cc:162
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn@fastmail.fm>"
+msgstr ""
+"Espagnol :\n"
+"\tAlex Krohn <alexkrohn@fastmail.fm>"
+
+#: gtk_ardour/about.cc:163
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop@nm.ru>"
+msgstr ""
+"Russe :\n"
+"\tIgor Blinov <pitstop@nm.ru>"
+
+#: gtk_ardour/about.cc:181
+#, fuzzy
+msgid ""
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n"
+msgstr ""
+"Copyright (C) 1999-2004 Paul Davis\n"
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour est distribué SANS AUCUNE GARANTIE\n"
+"Ceci est un logiciel libre, et vous êtes encouragés à le distribuer\n"
+"sous certaines conditions ; voir le fichier COPYING pour les détails.\n"
+
+#: gtk_ardour/about.cc:188
+#, fuzzy
+msgid ""
+"Ardour: %1\n"
+"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+msgstr ""
+"Ardour: %1\n"
+"(fonctionnant avec ardour/gtk %2 libardour: %3.%4.%5)"
+
+#: gtk_ardour/about.cc:206
+msgid ""
+"Primary author:\n"
+"\tPaul Davis\n"
+"\n"
+"Major developers:\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributors:\n"
+"\t"
+msgstr ""
+"Auteur principal :\n"
+"\tPaul Davis\n"
+"\n"
+"Développeurs principaux :\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributeurs :\n"
+"\t"
+
+#: gtk_ardour/about.cc:243
+msgid "Authors"
+msgstr "Auteurs"
+
+#: gtk_ardour/about.cc:244
+msgid "Translators"
+msgstr "Traducteurs"
+
+#: gtk_ardour/about.cc:361
+msgid "cannot open splash image file \"%1\""
+msgstr "impossible d'ouvrir l'image de l'écran de démarrage \"%1\""
+
+#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33
+#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81
+#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977
+#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85
+#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777
+#: gtk_ardour/redirect_box.cc:900
+msgid "OK"
+msgstr "OK"
+
+#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92
+#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046
+#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72
+#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982
+#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733
+#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000
+#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129
+#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785
+#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86
+#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072
+#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33
+#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161
+msgid "Cancel"
+msgstr "Annuler"
+
+#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94
+msgid "Tracks"
+msgstr "Pistes"
+
+#: gtk_ardour/add_route_dialog.cc:43
+msgid "Busses"
+msgstr "Bus"
+
+#: gtk_ardour/add_route_dialog.cc:48
+msgid "ardour: add track/bus"
+msgstr "ardour : ajouter piste/bus"
+
+#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81
+msgid "Add"
+msgstr "Ajouter"
+
+#: gtk_ardour/add_route_dialog.cc:86
+msgid "Name (template)"
+msgstr "Nom (modèle)"
+
+#: gtk_ardour/ardour_ui.cc:798
+msgid ""
+"pre\n"
+"roll"
+msgstr ""
+"pré\n"
+"roll"
+
+#: gtk_ardour/ardour_ui.cc:799
+msgid ""
+"post\n"
+"roll"
+msgstr ""
+"post\n"
+"roll"
+
+#: gtk_ardour/ardour_ui.cc:807
+msgid "% "
+msgstr "% "
+
+#: gtk_ardour/ardour_ui.cc:808
+#, fuzzy
+msgid "spring"
+msgstr "spring"
+
+#: gtk_ardour/ardour_ui.cc:810
+#, fuzzy
+msgid ""
+"punch\n"
+"in"
+msgstr ""
+"punch\n"
+"in"
+
+#: gtk_ardour/ardour_ui.cc:811
+msgid ""
+"punch\n"
+"out"
+msgstr ""
+"punch\n"
+"out"
+
+#: gtk_ardour/ardour_ui.cc:812
+msgid ""
+"auto\n"
+"return"
+msgstr ""
+"retour\n"
+"auto"
+
+#: gtk_ardour/ardour_ui.cc:813
+msgid ""
+"auto\n"
+"play"
+msgstr ""
+"lecture\n"
+"auto."
+
+#: gtk_ardour/ardour_ui.cc:814
+msgid ""
+"auto\n"
+"input"
+msgstr ""
+"entrée\n"
+"auto."
+
+#: gtk_ardour/ardour_ui.cc:815
+msgid "click"
+msgstr "clic"
+
+#: gtk_ardour/ardour_ui.cc:816
+msgid ""
+"follow\n"
+"PH"
+msgstr ""
+"suivre\n"
+"TL"
+
+#: gtk_ardour/ardour_ui.cc:817
+msgid "AUDITIONING"
+msgstr "ECOUTE"
+
+#: gtk_ardour/ardour_ui.cc:818
+msgid "SOLO"
+msgstr "SOLO"
+
+#: gtk_ardour/ardour_ui.cc:870
+msgid "Percentage"
+msgstr "Pourcentage"
+
+#: gtk_ardour/ardour_ui.cc:872
+msgid "Semitones"
+msgstr "Demi-tons"
+
+#: gtk_ardour/ardour_ui.cc:875
+msgid "Sprung"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:877
+msgid "Wheel"
+msgstr "Roulette"
+
+#: gtk_ardour/ardour_ui.cc:902
+msgid ""
+"You cannot record-enable\n"
+"track %1\n"
+"because it has no input connections.\n"
+"You would be wasting space recording silence."
+msgstr ""
+"Vous ne pouvez activer\n"
+"l'enregistrement de la piste %1\n"
+"car elle n'a pas de connections en entrée.\n"
+"Vous gacheriez de l'espace en enregistrant du silence."
+
+#: gtk_ardour/ardour_ui.cc:1073
+msgid "quit"
+msgstr "quitter"
+
+#: gtk_ardour/ardour_ui.cc:1082
+msgid ""
+"Ardour was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1107
+msgid "Save and %1"
+msgstr "Enregistrer et %1"
+
+#: gtk_ardour/ardour_ui.cc:1112
+msgid "Just %1"
+msgstr "Juste %1"
+
+#: gtk_ardour/ardour_ui.cc:1117
+msgid "Don't %1"
+msgstr "Ne pas %1"
+
+#: gtk_ardour/ardour_ui.cc:1126
+msgid "session"
+msgstr "session"
+
+#: gtk_ardour/ardour_ui.cc:1128
+msgid "snapshot"
+msgstr "Instantané"
+
+#: gtk_ardour/ardour_ui.cc:1130
+msgid ""
+"The %1\n"
+"\"%2\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
+msgstr ""
+"La session \"%1\"\n"
+"n'a pas été enregistrée.\n"
+"\n"
+"Les changements effectués cette fois-ci\n"
+"seront perdus à moins que vous ne les enregistriez.\n"
+"\n"
+"Que voulez-vous faire ?"
+
+#: gtk_ardour/ardour_ui.cc:1151
+msgid "Prompter"
+msgstr "Prompter"
+
+#: gtk_ardour/ardour_ui.cc:1152
+msgid "ardour: save session?"
+msgstr "ardour : enregistrer la session ?"
+
+#: gtk_ardour/ardour_ui.cc:1219
+#, c-format
+msgid "disconnected"
+msgstr "déconnecté"
+
+#: gtk_ardour/ardour_ui.cc:1226
+#, c-format
+msgid "SR: %.1f kHz / %4.1f msecs"
+msgstr "F.E. : %.1f kHz / %4.1f ms"
+
+#: gtk_ardour/ardour_ui.cc:1230
+#, c-format
+msgid "SR: %u kHz / %4.1f msecs"
+msgstr "F.E. : %u kHz / %4.1f ms"
+
+#: gtk_ardour/ardour_ui.cc:1243
+#, c-format
+msgid "DSP Load: %.1f%%"
+msgstr "Charge DSP : %.1f%%"
+
+#: gtk_ardour/ardour_ui.cc:1253
+#, c-format
+msgid "Disk r:%5.1f w:%5.1f MB/s"
+msgstr "Disque l:%5.1f e:%5.1f Mo/s"
+
+#: gtk_ardour/ardour_ui.cc:1267
+#, c-format
+msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
+msgstr "Tampons p:%<PRIu32>%% c:%<PRIu32>%%"
+
+#: gtk_ardour/ardour_ui.cc:1294
+msgid "space: 24hrs+"
+msgstr "espace : 24hrs+"
+
+#: gtk_ardour/ardour_ui.cc:1324
+#, c-format
+msgid "space: %02dh:%02dm:%02ds"
+msgstr "espace: %02dh:%02dm:%02ds"
+
+#: gtk_ardour/ardour_ui.cc:1575
+msgid "programming error: impossible control method"
+msgstr "erreur de programmation : méthode de contrôle impossible"
+
+#: gtk_ardour/ardour_ui.cc:1800
+msgid "cancel"
+msgstr "annuler"
+
+#: gtk_ardour/ardour_ui.cc:1801
+msgid "rescan"
+msgstr "rafraîchir"
+
+#: gtk_ardour/ardour_ui.cc:1842
+msgid "open session"
+msgstr "ouvrir session"
+
+#: gtk_ardour/ardour_ui.cc:1897
+msgid "Patience is a virtue.\n"
+msgstr "La patience est une vertue.\n"
+
+#: gtk_ardour/ardour_ui.cc:1906
+msgid "You cannot add a track without a session already loaded."
+msgstr ""
+"Vous ne pouvez pas ajouter une piste sans qu'une session ait été chargée."
+
+#: gtk_ardour/ardour_ui.cc:1913
+msgid "could not create new audio track"
+msgstr "impossible de créer une nouvelle piste audio"
+
+#: gtk_ardour/ardour_ui.cc:1917
+msgid "could not create new audio bus"
+msgstr "impossible de créer un nouveau bus audio"
+
+#: gtk_ardour/ardour_ui.cc:1936
+msgid ""
+"There are insufficient JACK ports available\n"
+"to create a new track or bus.\n"
+"You should save Ardour, exit and\n"
+"restart JACK with more ports."
+msgstr ""
+"Il n'y a pas assez de ports JACK disponibles\n"
+"pour créer une nouvelle piste ou bus.\n"
+"Vous devriez enregistrer, quitter, puis\n"
+"redémarrer JACK avec plus de ports."
+
+#: gtk_ardour/ardour_ui.cc:2071
+msgid ""
+"Please create 1 or more track\n"
+"before trying to record.\n"
+"Check the Session menu."
+msgstr ""
+"Veuillez créer une ou plusieurs pistes supplémentaires\n"
+"avant d'essayer d'enregistrer.\n"
+"Regardez dans le menu Session."
+
+#: gtk_ardour/ardour_ui.cc:2312
+msgid ""
+"JACK has either been shutdown or it\n"
+"disconnected Ardour because Ardour\n"
+"was not fast enough. You can save the\n"
+"session and/or try to reconnect to JACK ."
+msgstr ""
+"Soit JACK a été arrêté, soit il a déconnecté\n"
+"Ardour parce que celui-ci n'était pas assez rapide.\n"
+"Vous devriez enregistrer la session\n"
+"et/ou essayer de le reconnecter à JACK."
+
+#: gtk_ardour/ardour_ui.cc:2328
+msgid "Unable to create all required ports"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2336
+msgid "Unable to start the session running"
+msgstr "Impossible de lancer la session"
+
+#: gtk_ardour/ardour_ui.cc:2472
+msgid "No Stream"
+msgstr "Pas de flux"
+
+#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518
+msgid "none"
+msgstr "aucun"
+
+#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527
+#: gtk_ardour/automation_time_axis.cc:189
+#: gtk_ardour/automation_time_axis.cc:218
+#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211
+#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947
+#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659
+msgid "off"
+msgstr "arrêt"
+
+#: gtk_ardour/ardour_ui.cc:2548
+msgid "Name for snapshot"
+msgstr "Nom de l'instantané"
+
+#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294
+msgid "Name for mix template:"
+msgstr "Nom du modèle de mélange : "
+
+#: gtk_ardour/ardour_ui.cc:2717
+msgid "-template"
+msgstr "-modèle"
+
+#: gtk_ardour/ardour_ui.cc:2760
+msgid "Session %1 already exists at %2"
+msgstr "La session %1 existe déjà en %2"
+
+#: gtk_ardour/ardour_ui.cc:2832
+msgid ""
+"You do not have write access to this session.\n"
+"This prevents the session from being loaded."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "La session \"%1 (instantané %2)\" ne s'est pas chargée correctement"
+
+#: gtk_ardour/ardour_ui.cc:2966
+msgid ""
+"No audio files were ready for cleanup\n"
+"\n"
+"If this seems suprising, check for any existing\n"
+"snapshots. These may still include regions that\n"
+"require some unused files to continue to exist."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001
+msgid "files"
+msgstr "fichiers"
+
+#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003
+msgid "file"
+msgstr "fichier"
+
+#: gtk_ardour/ardour_ui.cc:3026
+msgid "ardour: cleanup"
+msgstr "ardour : nettoyage"
+
+#: gtk_ardour/ardour_ui.cc:3040
+msgid ""
+"Cleanup is a destructive operation.\n"
+"ALL undo/redo information will be lost if you cleanup.\n"
+"Unused audio files will be moved to a \"dead sounds\" location."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3045
+msgid "Proceed with cleanup"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3061
+#, fuzzy
+msgid "CleanupDialog"
+msgstr "Nettoyer"
+
+#: gtk_ardour/ardour_ui.cc:3062
+#, fuzzy
+msgid "ardour cleanup"
+msgstr "ardour : nettoyage"
+
+#: gtk_ardour/ardour_ui.cc:3063
+#, fuzzy
+msgid "ardour_cleanup"
+msgstr "ardour : nettoyage"
+
+#: gtk_ardour/ardour_ui.cc:3086
+msgid "cleaned files"
+msgstr "fichiers nettoyés"
+
+#: gtk_ardour/ardour_ui.cc:3087
+msgid ""
+"The following %1 %2 were not in use.\n"
+"The next time you flush the wastebasket\n"
+"it will release an additional %3 %4bytes\n"
+"of disk space"
+msgstr ""
+"Les %1 %2 fichiers suivants n'étaient pas utilisés.\n"
+"La prochaine fois que vous viderez la corbeille,\n"
+"%3 %4-octets d'espace disque supplémentaires seront\n"
+"libérés"
+
+#: gtk_ardour/ardour_ui.cc:3110
+msgid "deleted file"
+msgstr "fichiers effacés"
+
+#: gtk_ardour/ardour_ui.cc:3111
+#, fuzzy
+msgid ""
+"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"
+msgstr ""
+"Les %1 fichier%2 suivant%2 seront effacé%2, libérant %3 %4-octets d'espace "
+"disque"
+
+#: gtk_ardour/ardour_ui.cc:3226
+msgid "Recording was stopped because your system could not keep up."
+msgstr ""
+"L'enregistrement a été stoppé parce que votre système ne peut pas suivre."
+
+#: gtk_ardour/ardour_ui.cc:3248
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
+msgstr ""
+"Le disque dur n'arrive pas\n"
+"à suivre Ardour.\n"
+"\n"
+"Plus précisement, il a été incapable d'écrire les données\n"
+"sur le disque assez rapidement pour suivre l'enregistrement.\n"
+
+#: gtk_ardour/ardour_ui.cc:3266
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
+msgstr ""
+"Le disque dur n'arrive pas\n"
+"à suivre Ardour.\n"
+"\n"
+"Plus précisement, il a été incapable de lire les données\n"
+"sur le disque assez rapidement pour suivre la lecture.\n"
+
+#: gtk_ardour/ardour_ui.cc:3291
+msgid "Recover from crash"
+msgstr "Récupérer après un plantage"
+
+#: gtk_ardour/ardour_ui.cc:3292
+msgid "Ignore crash data"
+msgstr "Ignorer les données du plantage"
+
+#: gtk_ardour/ardour_ui.cc:3293
+msgid ""
+"This session appears to have been in\n"
+"middle of recording when ardour or\n"
+"the computer was shutdown.\n"
+"\n"
+"Ardour can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
+msgstr ""
+"Cette session semble avoir été interrompue\n"
+"au milieu d'un enregistrement lorsque ardour ou\n"
+"l'ordinateur s'est arrêté.\n"
+"\n"
+"Ardour peut récupérer pour vous tout ce qui a été enregistré,\n"
+"ou vous pouvez l'ignorer. Veuillez décider\n"
+"sur ce que vous voulez faire.\n"
+
+#: gtk_ardour/ardour_ui.cc:3338
+msgid "Could not disconnect from JACK"
+msgstr "Impossible de se déconnecter de JACK"
+
+#: gtk_ardour/ardour_ui.cc:3351
+msgid "Could not reconnect to JACK"
+msgstr "Impossible de se reconnecter à JACK"
+
+#: gtk_ardour/ardour_ui2.cc:60
+msgid "UI: cannot setup editor"
+msgstr "IHM : impossible d'initialiser l'éditeur"
+
+#: gtk_ardour/ardour_ui2.cc:65
+msgid "UI: cannot setup mixer"
+msgstr "IHM : impossible d'initialiser la console de mixage"
+
+#: gtk_ardour/ardour_ui2.cc:70
+#, fuzzy
+msgid "UI: cannot setup meter_bridge"
+msgstr "IHM : impossible d'initialiser le bandeau_vu-mètre"
+
+#: gtk_ardour/ardour_ui2.cc:98
+msgid "MMC + Local"
+msgstr "MMC + Local"
+
+#: gtk_ardour/ardour_ui2.cc:99
+msgid "MMC"
+msgstr "MMC"
+
+#: gtk_ardour/ardour_ui2.cc:100
+msgid "Local"
+msgstr "Local"
+
+#: gtk_ardour/ardour_ui2.cc:117
+msgid "MMC ID"
+msgstr "ID MMC"
+
+#: gtk_ardour/ardour_ui2.cc:215
+msgid "Play from playhead"
+msgstr "Jouer depuis la tête de lecture"
+
+#: gtk_ardour/ardour_ui2.cc:216
+msgid "Stop playback"
+msgstr "Arrêter la lecture"
+
+#: gtk_ardour/ardour_ui2.cc:217
+msgid "Play range/selection"
+msgstr "Jouer l'intervalle/la sélection"
+
+#: gtk_ardour/ardour_ui2.cc:218
+msgid "Go to start of session"
+msgstr "Aller au début de la session"
+
+#: gtk_ardour/ardour_ui2.cc:219
+msgid "Go to end of session"
+msgstr "Aller à la fin de la session"
+
+#: gtk_ardour/ardour_ui2.cc:220
+msgid "Play loop range"
+msgstr "Jouer l'intervalle de boucle"
+
+#: gtk_ardour/ardour_ui2.cc:221
+msgid "Return to last playback start when stopped"
+msgstr "Revenir au dernier départ de lecture lors de l'arrêt"
+
+#: gtk_ardour/ardour_ui2.cc:222
+msgid "Start playback after any locate"
+msgstr "Démarrer la lecture aprés chaque locate"
+
+#: gtk_ardour/ardour_ui2.cc:223
+msgid "Be sensible about input monitoring"
+msgstr "Être raisonnable avec la pré-écoute des entrées"
+
+#: gtk_ardour/ardour_ui2.cc:224
+msgid "Start recording at auto-punch start"
+msgstr "Démarrer l'enregistrement en début d'auto-punch"
+
+#: gtk_ardour/ardour_ui2.cc:225
+msgid "Stop recording at auto-punch end"
+msgstr "Arrêter l'enregistrement en fin d'auto-punch"
+
+#: gtk_ardour/ardour_ui2.cc:226
+msgid "Enable/Disable audio click"
+msgstr "Activer/Désactiver le clic sonore"
+
+#: gtk_ardour/ardour_ui2.cc:227
+msgid "Enable/Disable follow playhead"
+msgstr "Activer/Désactiver la poursuite de la tête de lecture"
+
+#: gtk_ardour/ardour_ui2.cc:228
+#, fuzzy
+msgid "Shuttle speed control"
+msgstr "Contrôle de la vitesse avec molette"
+
+#: gtk_ardour/ardour_ui2.cc:229
+#, fuzzy, c-format
+msgid "Select semitones or %%-age for speed display"
+msgstr "Sélectionner les demi-tons ou le %-age pour l'affichage de la vitesse"
+
+#: gtk_ardour/ardour_ui2.cc:230
+#, fuzzy
+msgid "Select sprung or wheel behaviour"
+msgstr "Sélectionner le comportement du ressort ou de la roulette"
+
+#: gtk_ardour/ardour_ui2.cc:231
+msgid "Current transport speed"
+msgstr "Vitesse de transport courante"
+
+#: gtk_ardour/ardour_ui2.cc:312
+msgid "Primary clock"
+msgstr "Horloge principale"
+
+#: gtk_ardour/ardour_ui2.cc:313
+msgid "secondary clock"
+msgstr "Horloge secondaire"
+
+#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751
+#: gtk_ardour/ardour_ui2.cc:770
+msgid "stopped"
+msgstr "arrêté"
+
+#: gtk_ardour/ardour_ui2.cc:431
+msgid "ardour: clock"
+msgstr "ardour : horloge"
+
+#: gtk_ardour/ardour_ui2.cc:721
+msgid "st"
+msgstr "er"
+
+#: gtk_ardour/ardour_ui2.cc:731
+msgid "sprung"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:742
+msgid "wheel"
+msgstr "roulette"
+
+#: gtk_ardour/ardour_ui_dependents.cc:74
+#, fuzzy
+msgid "keyboard_target: error setting binding state: invalid node"
+msgstr "keyboard_target: error setting binding state: noeud invalide"
+
+#: gtk_ardour/ardour_ui_dialogs.cc:158
+msgid "close session"
+msgstr "fermer la session"
+
+#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895
+msgid "New"
+msgstr "Nouveau"
+
+#: gtk_ardour/ardour_ui_ed.cc:76
+msgid "Open"
+msgstr "Ouvrir"
+
+#: gtk_ardour/ardour_ui_ed.cc:77
+msgid "Recent"
+msgstr "Récent"
+
+#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+msgid "Close"
+msgstr "Fermer"
+
+#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488
+msgid "Add Track/Bus"
+msgstr "Ajouter piste/bus"
+
+#: gtk_ardour/ardour_ui_ed.cc:99
+msgid "Connect"
+msgstr "Connecter"
+
+#: gtk_ardour/ardour_ui_ed.cc:100
+msgid "Image Compositor"
+msgstr "Compositeur d'image"
+
+#: gtk_ardour/ardour_ui_ed.cc:114
+msgid "Save"
+msgstr "Enregistrer"
+
+#: gtk_ardour/ardour_ui_ed.cc:118
+msgid "Snapshot"
+msgstr "Instantané"
+
+#: gtk_ardour/ardour_ui_ed.cc:126
+msgid "Save Template..."
+msgstr "Enregistrer le modèle..."
+
+#: gtk_ardour/ardour_ui_ed.cc:133
+msgid "Export session to audiofile..."
+msgstr "Exporter la session dans un fichier audio..."
+
+#: gtk_ardour/ardour_ui_ed.cc:134
+#, fuzzy
+msgid "Export range to audiofile..."
+msgstr "Exporter la range dans un fichier audio..."
+
+#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312
+#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118
+#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227
+msgid "Export"
+msgstr "Exporter"
+
+#: gtk_ardour/ardour_ui_ed.cc:146
+msgid "Cleanup unused sources"
+msgstr "Nettoyer les sources inutilisées"
+
+#: gtk_ardour/ardour_ui_ed.cc:147
+msgid "Flush wastebasket"
+msgstr "Vider la corbeille"
+
+#: gtk_ardour/ardour_ui_ed.cc:149
+msgid "Cleanup"
+msgstr "Nettoyer"
+
+#: gtk_ardour/ardour_ui_ed.cc:154
+msgid "Quit"
+msgstr "Quitter"
+
+#: gtk_ardour/ardour_ui_ed.cc:156
+msgid "Session"
+msgstr "Session"
+
+#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287
+#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499
+#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570
+#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412
+msgid "Edit"
+msgstr "Édition"
+
+#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572
+#: gtk_ardour/mixer_strip.cc:631
+msgid "Disconnect"
+msgstr "Déconnecter"
+
+#: gtk_ardour/ardour_ui_ed.cc:174
+msgid "Reconnect"
+msgstr "Reconnecter"
+
+#: gtk_ardour/ardour_ui_ed.cc:192
+msgid "Latency"
+msgstr "Latence"
+
+#: gtk_ardour/ardour_ui_ed.cc:195
+msgid "JACK"
+msgstr "JACK"
+
+#: gtk_ardour/ardour_ui_ed.cc:205
+msgid "Editor"
+msgstr "Éditeur"
+
+#: gtk_ardour/ardour_ui_ed.cc:206
+msgid "Mixer"
+msgstr "Console de mixage"
+
+#: gtk_ardour/ardour_ui_ed.cc:212
+msgid "Options Editor"
+msgstr "Éditeur d'options"
+
+#: gtk_ardour/ardour_ui_ed.cc:219
+msgid "Audio Library"
+msgstr "Bibliothèque audio"
+
+#: gtk_ardour/ardour_ui_ed.cc:225
+msgid "Track/Bus Inspector"
+msgstr "Inspecteur de pistes/bus"
+
+#: gtk_ardour/ardour_ui_ed.cc:232
+msgid "Connections"
+msgstr "Connexions"
+
+#: gtk_ardour/ardour_ui_ed.cc:240
+msgid "Meter Bridge"
+msgstr "Bandeau de vu-mètre"
+
+#: gtk_ardour/ardour_ui_ed.cc:248
+msgid "Locations"
+msgstr "Emplacements"
+
+#: gtk_ardour/ardour_ui_ed.cc:255
+msgid "Big Clock"
+msgstr "Grande horloge"
+
+#: gtk_ardour/ardour_ui_ed.cc:261
+msgid "About"
+msgstr "À propos"
+
+#: gtk_ardour/ardour_ui_ed.cc:264
+msgid "Windows"
+msgstr "Fenêtres"
+
+#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203
+msgid "SMPTE"
+msgstr "SMPTE"
+
+#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202
+#: gtk_ardour/editor_rulers.cc:359
+msgid "Bars:Beats"
+msgstr "Mesures:Temps"
+
+#: gtk_ardour/audio_clock.cc:1642
+msgid "Minutes:Seconds"
+msgstr "Minutes:Secondes"
+
+#: gtk_ardour/audio_clock.cc:1643
+msgid "Audio Frames"
+msgstr "Trames audio"
+
+#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356
+#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713
+#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774
+#: gtk_ardour/option_editor.cc:794
+msgid "Off"
+msgstr "Arrêt"
+
+#: gtk_ardour/audio_clock.cc:1646
+msgid "Mode"
+msgstr "Mode"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523
+msgid "m"
+msgstr "m"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524
+msgid "s"
+msgstr "s"
+
+#: gtk_ardour/audio_time_axis.cc:104
+msgid "r"
+msgstr "r"
+
+#: gtk_ardour/audio_time_axis.cc:108
+msgid "g"
+msgstr "g"
+
+#: gtk_ardour/audio_time_axis.cc:109
+msgid "p"
+msgstr "p"
+
+#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44
+#: gtk_ardour/visual_time_axis.cc:90
+msgid "h"
+msgstr "h"
+
+#: gtk_ardour/audio_time_axis.cc:111
+msgid "a"
+msgstr "a"
+
+#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89
+msgid "v"
+msgstr "v"
+
+#: gtk_ardour/audio_time_axis.cc:185
+msgid "Record"
+msgstr "Enregistrer"
+
+#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191
+msgid "Solo"
+msgstr "Solo"
+
+#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236
+#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433
+msgid "Mute"
+msgstr "Muet"
+
+#: gtk_ardour/audio_time_axis.cc:188
+msgid "Edit Group"
+msgstr "Groupe d'édition"
+
+#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110
+msgid "Display Height"
+msgstr "Hauteur de l'affichage"
+
+#: gtk_ardour/audio_time_axis.cc:190
+msgid "Playlist"
+msgstr "Liste de lecture"
+
+#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752
+msgid "Automation"
+msgstr "Automatisation"
+
+#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111
+msgid "Visual options"
+msgstr "Options d'affichage"
+
+#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112
+msgid "Hide this track"
+msgstr "Cacher cette piste"
+
+#: gtk_ardour/audio_time_axis.cc:349
+msgid "No group"
+msgstr "Pas de groupe"
+
+#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447
+#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229
+msgid "Height"
+msgstr "Hauteur"
+
+#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266
+#: gtk_ardour/marker_time_axis.cc:230
+msgid "Color"
+msgstr "Couleur"
+
+#: gtk_ardour/audio_time_axis.cc:720
+#, fuzzy
+msgid "Hide all crossfades"
+msgstr "Cacher tous les fondus enchaînés"
+
+#: gtk_ardour/audio_time_axis.cc:721
+#, fuzzy
+msgid "Show all crossfades"
+msgstr "Montrer tous les fondus enchaînés"
+
+#: gtk_ardour/audio_time_axis.cc:729
+msgid "show all automation"
+msgstr "montrer toute l'automatisation"
+
+#: gtk_ardour/audio_time_axis.cc:732
+msgid "show existing automation"
+msgstr "montrer l'automatisation existante"
+
+#: gtk_ardour/audio_time_axis.cc:735
+msgid "hide all automation"
+msgstr "cacher toute l'automatisation"
+
+#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204
+#: gtk_ardour/editor.cc:234
+msgid "gain"
+msgstr "gain"
+
+#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244
+msgid "pan"
+msgstr "panoramique"
+
+#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388
+msgid "Plugins"
+msgstr "Greffons"
+
+#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95
+msgid "Show waveforms"
+msgstr "Montrer les formes d'onde"
+
+#: gtk_ardour/audio_time_axis.cc:766
+msgid "Traditional"
+msgstr "Traditionnel"
+
+#: gtk_ardour/audio_time_axis.cc:769
+msgid "Rectified"
+msgstr "Rectifié"
+
+#: gtk_ardour/audio_time_axis.cc:772
+msgid "Waveform"
+msgstr "Forme d'onde"
+
+#: gtk_ardour/audio_time_axis.cc:782
+msgid "align with existing material"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:787
+msgid "align with capture time"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:793
+#, fuzzy
+msgid "Alignment"
+msgstr "Aligner"
+
+#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288
+msgid "Active"
+msgstr "Actif"
+
+#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386
+#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467
+#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269
+#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233
+#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83
+msgid "Remove"
+msgstr "Enlever"
+
+#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880
+#: gtk_ardour/audio_time_axis.cc:911
+msgid "Name for playlist"
+msgstr "Nom de la liste de lecture"
+
+#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433
+msgid "a track already exists with that name"
+msgstr "une piste avec le même nom existe déjà"
+
+#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001
+#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539
+msgid "programming error: "
+msgstr "erreur de programmation : "
+
+#: gtk_ardour/audio_time_axis.cc:1889
+msgid "Current: %1"
+msgstr "Courant : %1"
+
+#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452
+#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226
+#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377
+msgid "Rename"
+msgstr "Renommer"
+
+#: gtk_ardour/audio_time_axis.cc:1896
+msgid "New Copy"
+msgstr "Nouvelle copie"
+
+#: gtk_ardour/audio_time_axis.cc:1898
+#, fuzzy
+msgid "Clear Current"
+msgstr "Effacer courante"
+
+#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472
+#: gtk_ardour/editor.cc:2557
+msgid "Select"
+msgstr "Sélectionner"
+
+#: gtk_ardour/automation_line.cc:904
+#, fuzzy
+msgid "automation event move"
+msgstr "déplacement d'évenement d'automatisation"
+
+#: gtk_ardour/automation_line.cc:906
+#, fuzzy
+msgid "automation range drag"
+msgstr "déplacement d'intervalle d'automatisation"
+
+#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64
+#, fuzzy
+msgid "remove control point"
+msgstr "Enlever le point de contrôle"
+
+#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010
+msgid "clear"
+msgstr "effacer"
+
+#: gtk_ardour/automation_time_axis.cc:80
+msgid "track height"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:81
+#, fuzzy
+msgid "automation state"
+msgstr "état de l'automatisation de panoramique"
+
+#: gtk_ardour/automation_time_axis.cc:82
+#, fuzzy
+msgid "clear track"
+msgstr "effacer les intervalles"
+
+#: gtk_ardour/automation_time_axis.cc:83
+#, fuzzy
+msgid "hide track"
+msgstr "décaler la piste"
+
+#: gtk_ardour/automation_time_axis.cc:191
+#: gtk_ardour/automation_time_axis.cc:229
+#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213
+#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419
+#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50
+msgid "play"
+msgstr "jouer"
+
+#: gtk_ardour/automation_time_axis.cc:193
+#: gtk_ardour/automation_time_axis.cc:240
+#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215
+#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422
+#: gtk_ardour/plugin_ui.cc:663
+msgid "write"
+msgstr "écrire"
+
+#: gtk_ardour/automation_time_axis.cc:195
+#: gtk_ardour/automation_time_axis.cc:251
+#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217
+#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953
+#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665
+#, fuzzy
+msgid "touch"
+msgstr "toucher"
+
+#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274
+#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428
+msgid "???"
+msgstr "???"
+
+#: gtk_ardour/automation_time_axis.cc:276
+#, fuzzy
+msgid "clear automation"
+msgstr "effacer l'automatisation"
+
+#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453
+#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398
+msgid "Hide"
+msgstr "Cacher"
+
+#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52
+#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364
+msgid "Clear"
+msgstr "Effacer"
+
+#: gtk_ardour/automation_time_axis.cc:474
+msgid "State"
+msgstr "État"
+
+#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49
+msgid "Input Connections"
+msgstr "Connexions en entrée"
+
+#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48
+msgid "Output Connections"
+msgstr "Connexions en sortie"
+
+#: gtk_ardour/connection_editor.cc:49
+msgid "New Input"
+msgstr "Nouvelle entrée"
+
+#: gtk_ardour/connection_editor.cc:50
+msgid "New Output"
+msgstr "Nouvelle sortie"
+
+#: gtk_ardour/connection_editor.cc:51
+msgid "Delete"
+msgstr "Supprimer"
+
+#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96
+msgid "Add Port"
+msgstr "Ajouter un port"
+
+#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105
+#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786
+msgid "Rescan"
+msgstr "Rafraîchir"
+
+#: gtk_ardour/connection_editor.cc:101
+msgid "Available Ports"
+msgstr "Ports disponibles"
+
+#: gtk_ardour/connection_editor.cc:183
+msgid "ardour: connections"
+msgstr "ardour : connexions"
+
+#: gtk_ardour/connection_editor.cc:513
+#, c-format
+msgid "in %d"
+msgstr "en %d"
+
+#: gtk_ardour/connection_editor.cc:644
+msgid "Name for new connection:"
+msgstr "Nom de la nouvelle connexion :"
+
+#: gtk_ardour/crossfade_edit.cc:71
+msgid "crossfade editor"
+msgstr "éditeur de fondu enchaîné"
+
+#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449
+msgid "Reset"
+msgstr "Réinitialiser"
+
+#: gtk_ardour/crossfade_edit.cc:78
+msgid "Fade"
+msgstr "Fondu"
+
+#: gtk_ardour/crossfade_edit.cc:79
+#, fuzzy
+msgid "Out (dry)"
+msgstr "Sortie (sec)"
+
+#: gtk_ardour/crossfade_edit.cc:80
+#, fuzzy
+msgid "Out"
+msgstr "Sortie"
+
+#: gtk_ardour/crossfade_edit.cc:81
+#, fuzzy
+msgid "In (dry)"
+msgstr "Entrée (sec)"
+
+#: gtk_ardour/crossfade_edit.cc:82
+msgid "In"
+msgstr "Entrée"
+
+#: gtk_ardour/crossfade_edit.cc:84
+#, fuzzy
+msgid "With Pre-roll"
+msgstr "Avec pré-roll"
+
+#: gtk_ardour/crossfade_edit.cc:85
+#, fuzzy
+msgid "With Post-roll"
+msgstr "Avec post-roll"
+
+#: gtk_ardour/crossfade_edit.cc:93
+msgid "Fade In"
+msgstr "Fondu d'ouverture"
+
+#: gtk_ardour/crossfade_edit.cc:94
+msgid "Fade Out"
+msgstr "Fondu de fermeture"
+
+#: gtk_ardour/crossfade_edit.cc:98
+msgid "ardour: x-fade edit"
+msgstr "ardour : édition fondu enchaîné"
+
+#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311
+#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189
+msgid "Audition"
+msgstr "Audition"
+
+#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804
+msgid "Regions/name"
+msgstr "Régions/nom"
+
+#: gtk_ardour/editor.cc:108
+msgid "Chunks"
+msgstr "Fragments"
+
+#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079
+msgid "Slide"
+msgstr "Curseur"
+
+#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077
+msgid "Splice"
+msgstr "Réunion"
+
+#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136
+#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96
+#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977
+msgid "None"
+msgstr "Aucun"
+
+#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124
+#, fuzzy
+msgid "CD Frames"
+msgstr "Trames CD"
+
+#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126
+#, fuzzy
+msgid "SMPTE Frames"
+msgstr "Trames SMPTE"
+
+#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128
+msgid "SMPTE Seconds"
+msgstr "Secondes SMPTE"
+
+#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130
+msgid "SMPTE Minutes"
+msgstr "Minutes SMPTE"
+
+#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132
+msgid "Seconds"
+msgstr "Secondes"
+
+#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134
+msgid "Minutes"
+msgstr "Minutes"
+
+#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106
+msgid "Beats/32"
+msgstr "Temps/32"
+
+#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104
+msgid "Beats/16"
+msgstr "Temps/16"
+
+#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102
+msgid "Beats/8"
+msgstr "Temps/8"
+
+#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100
+msgid "Beats/4"
+msgstr "Temps/4"
+
+#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098
+msgid "Beats/3"
+msgstr "Temps/3"
+
+#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108
+msgid "Beats"
+msgstr "Temps"
+
+#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110
+msgid "Bars"
+msgstr "Mesures"
+
+#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112
+msgid "Marks"
+msgstr "Marques"
+
+#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114
+#: gtk_ardour/editor.cc:4182
+msgid "Edit Cursor"
+msgstr "Curseur d'édition"
+
+#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116
+#, fuzzy
+msgid "Region starts"
+msgstr "Débuts de régions"
+
+#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118
+#, fuzzy
+msgid "Region ends"
+msgstr "Fins de régions"
+
+#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122
+#, fuzzy
+msgid "Region syncs"
+msgstr "Syncro. de régions"
+
+#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120
+#, fuzzy
+msgid "Region bounds"
+msgstr "Limites de régions"
+
+#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153
+#: gtk_ardour/time_axis_view.cc:449
+msgid "Normal"
+msgstr "Normal"
+
+#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155
+msgid "Magnetic"
+msgstr "Magnétique"
+
+#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174
+#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237
+msgid "Left"
+msgstr "Gauche"
+
+#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176
+#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238
+msgid "Right"
+msgstr "Droite"
+
+#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178
+msgid "Center"
+msgstr "Centre"
+
+#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180
+msgid "Playhead"
+msgstr "Tête de lecture"
+
+#: gtk_ardour/editor.cc:201
+msgid "Mins:Secs"
+msgstr "Mins:Secs"
+
+#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353
+msgid "Frames"
+msgstr "Trames"
+
+#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373
+msgid "Tempo"
+msgstr "Tempo"
+
+#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367
+msgid "Meter"
+msgstr "Vu-mètre"
+
+#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379
+msgid "Location Markers"
+msgstr "Marqueurs d'emplacements"
+
+#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385
+msgid "Range Markers"
+msgstr "Marqueurs d'intervalle"
+
+#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391
+msgid "Loop/Punch Ranges"
+msgstr "Intervalles de boucle/punch"
+
+#: gtk_ardour/editor.cc:221
+msgid ""
+"editor\n"
+"mixer"
+msgstr ""
+"éditeur\n"
+"console de mixage"
+
+#: gtk_ardour/editor.cc:232
+msgid "range"
+msgstr "intervalle"
+
+#: gtk_ardour/editor.cc:233
+msgid "object"
+msgstr "objet"
+
+#: gtk_ardour/editor.cc:235
+msgid "zoom"
+msgstr "zoom"
+
+#: gtk_ardour/editor.cc:236
+#, fuzzy
+msgid "timefx"
+msgstr "Effet temporel"
+
+#: gtk_ardour/editor.cc:237
+msgid "listen"
+msgstr "écouter"
+
+#: gtk_ardour/editor.cc:239
+msgid "mode"
+msgstr "mode"
+
+#: gtk_ardour/editor.cc:240
+msgid "automation"
+msgstr "automatisation"
+
+#: gtk_ardour/editor.cc:242
+msgid "Edit Mode"
+msgstr "Mode d'édition"
+
+#: gtk_ardour/editor.cc:243
+#, fuzzy
+msgid "Snap To"
+msgstr "Snap to"
+
+#: gtk_ardour/editor.cc:244
+#, fuzzy
+msgid "Snap Mode"
+msgstr "Snap mode"
+
+#: gtk_ardour/editor.cc:245
+msgid "Zoom Focus"
+msgstr "Focus du zoom"
+
+#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364
+#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579
+msgid "Nudge"
+msgstr "Décaler"
+
+#: gtk_ardour/editor.cc:511
+msgid "Zoom in"
+msgstr "Zoom avant"
+
+#: gtk_ardour/editor.cc:512
+msgid "Zoom out"
+msgstr "Zoom arrière"
+
+#: gtk_ardour/editor.cc:517
+msgid "Zoom to session"
+msgstr "Zoomer vers la session"
+
+#: gtk_ardour/editor.cc:536
+#, fuzzy
+msgid "Zoom Span"
+msgstr "Largeur du zoom"
+
+#: gtk_ardour/editor.cc:566
+msgid "Edit Groups"
+msgstr "Groupes d'édition"
+
+#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142
+msgid "-all-"
+msgstr "-tout-"
+
+#: gtk_ardour/editor.cc:718
+msgid "Nudge region/selection forwards"
+msgstr "Décaller région/sélection vers l'avant"
+
+#: gtk_ardour/editor.cc:719
+msgid "Nudge region/selection backwards"
+msgstr "Décaller région/sélection vers l'arrière"
+
+#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308
+msgid "ardour: editor"
+msgstr "ardour : éditeur"
+
+#: gtk_ardour/editor.cc:729
+msgid "ardour_editor"
+msgstr "ardour_éditeur"
+
+#: gtk_ardour/editor.cc:846
+msgid "VerboseCanvasCursor"
+msgstr "VerboseCanvasCursor"
+
+#: gtk_ardour/editor.cc:1405
+msgid "FirstActionMessage"
+msgstr "FirstActionCursor"
+
+#: gtk_ardour/editor.cc:1407
+msgid "Start a new session\n"
+msgstr "Commencer une nouvelle session\n"
+
+#: gtk_ardour/editor.cc:1408
+msgid "via Session menu"
+msgstr "via le menu Session"
+
+#: gtk_ardour/editor.cc:1703
+msgid "ardour: editor: "
+msgstr "ardour : éditeur : "
+
+#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796
+#: gtk_ardour/editor_markers.cc:797
+msgid "Loop"
+msgstr "Boucle"
+
+#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810
+#: gtk_ardour/editor_markers.cc:823
+msgid "Punch"
+msgstr "Insérer"
+
+#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688
+msgid "programming error: fade in canvas item has no regionview data pointer!"
+msgstr "programming error: fade in canvas item has no regionview data pointer!"
+
+#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986
+#: gtk_ardour/redirect_box.cc:401
+msgid "Deactivate"
+msgstr "Désactiver"
+
+#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988
+#: gtk_ardour/redirect_box.cc:398
+msgid "Activate"
+msgstr "Activer"
+
+#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993
+msgid "Linear"
+msgstr "Linéaire"
+
+#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994
+#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734
+#: gtk_ardour/option_editor.cc:796
+msgid "Slowest"
+msgstr "Plus lent"
+
+#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995
+#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735
+#: gtk_ardour/option_editor.cc:798
+msgid "Slow"
+msgstr "Lent"
+
+#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996
+#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737
+#: gtk_ardour/option_editor.cc:802
+msgid "Fast"
+msgstr "Rapide"
+
+#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997
+#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739
+#: gtk_ardour/option_editor.cc:806
+msgid "Fastest"
+msgstr "Plus rapide"
+
+#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113
+msgid "Freeze"
+msgstr "Bloquer"
+
+#: gtk_ardour/editor.cc:2109
+msgid "Unfreeze"
+msgstr "Débloquer"
+
+#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328
+#, fuzzy
+msgid "Unmute"
+msgstr "Non muet"
+
+#: gtk_ardour/editor.cc:2247
+msgid "Convert to short"
+msgstr "Convertir en court"
+
+#: gtk_ardour/editor.cc:2249
+msgid "Convert to full"
+msgstr "Convertir en complet"
+
+#: gtk_ardour/editor.cc:2260
+#, fuzzy
+msgid "Crossfade"
+msgstr "Modèle de fondu enchaîné"
+
+#: gtk_ardour/editor.cc:2303
+msgid "Popup region editor"
+msgstr "Ouvrir l'éditeur de région"
+
+#: gtk_ardour/editor.cc:2304
+msgid "Raise to top layer"
+msgstr "Monter vers la couche du haut"
+
+#: gtk_ardour/editor.cc:2305
+msgid "Lower to bottom layer"
+msgstr "Descendre vers la couche du bas"
+
+#: gtk_ardour/editor.cc:2307
+msgid "Define sync point"
+msgstr "Définir le point de synchronisation"
+
+#: gtk_ardour/editor.cc:2308
+msgid "Remove sync point"
+msgstr "Enlever le point de synchronisation"
+
+#: gtk_ardour/editor.cc:2313
+msgid "Bounce"
+msgstr "Bounce"
+
+#: gtk_ardour/editor.cc:2323
+msgid "Lock"
+msgstr "Verrouiller"
+
+#: gtk_ardour/editor.cc:2324
+msgid "Unlock"
+msgstr "Déverrouiller"
+
+#: gtk_ardour/editor.cc:2334
+msgid "Original position"
+msgstr "Position d'origine"
+
+#: gtk_ardour/editor.cc:2340
+msgid "Toggle envelope visibility"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2341
+#, fuzzy
+msgid "Toggle envelope active"
+msgstr "Activer"
+
+#: gtk_ardour/editor.cc:2345
+msgid "DeNormalize"
+msgstr "Dénormaliser"
+
+#: gtk_ardour/editor.cc:2347
+msgid "Normalize"
+msgstr "Normaliser"
+
+#: gtk_ardour/editor.cc:2350
+#, fuzzy
+msgid "Reverse"
+msgstr "Retourner"
+
+#: gtk_ardour/editor.cc:2359
+msgid "Nudge fwd"
+msgstr "Décaler vers l'avant"
+
+#: gtk_ardour/editor.cc:2360
+#, fuzzy
+msgid "Nudge bwd"
+msgstr "Décaler vers l'arrière"
+
+#: gtk_ardour/editor.cc:2361
+msgid "Nudge fwd by capture offset"
+msgstr "Décaler vers l'avant du décalage de la capture"
+
+#: gtk_ardour/editor.cc:2362
+msgid "Nudge bwd by capture offset"
+msgstr "Décaler vers l'arrière du décallage de la capture"
+
+#: gtk_ardour/editor.cc:2371
+msgid "Start to edit cursor"
+msgstr "Démarrer depuis le curseur d'édition"
+
+#: gtk_ardour/editor.cc:2372
+msgid "Edit cursor to end"
+msgstr "Curseur d'édition à la fin"
+
+#: gtk_ardour/editor.cc:2374
+msgid "Trim"
+msgstr "Élaguer"
+
+#: gtk_ardour/editor.cc:2377
+msgid "Split"
+msgstr "Séparer"
+
+#: gtk_ardour/editor.cc:2380
+msgid "Make mono regions"
+msgstr "Créer des régions mono"
+
+#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428
+msgid "Duplicate"
+msgstr "Dupliquer"
+
+#: gtk_ardour/editor.cc:2384
+msgid "Fill Track"
+msgstr "Remplir la piste"
+
+#: gtk_ardour/editor.cc:2388
+msgid "Destroy"
+msgstr "Détruire"
+
+#: gtk_ardour/editor.cc:2418
+msgid "Play range"
+msgstr "Jouer l'intervalle"
+
+#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446
+msgid "Loop range"
+msgstr "Boucler sur l'intervalle"
+
+#: gtk_ardour/editor.cc:2421
+msgid "Create chunk from range"
+msgstr "Nouveau fragment à partir de l'intervalle"
+
+#: gtk_ardour/editor.cc:2423
+msgid "Create Region"
+msgstr "Créer une région"
+
+#: gtk_ardour/editor.cc:2424
+msgid "Separate Region"
+msgstr "Séparer la région"
+
+#: gtk_ardour/editor.cc:2425
+msgid "Crop Region to range"
+msgstr "Découper la région vers l'intervalle"
+
+#: gtk_ardour/editor.cc:2426
+#, fuzzy
+msgid "Bounce range"
+msgstr "Bounce intervalle"
+
+#: gtk_ardour/editor.cc:2432
+msgid "Fill range w/Region"
+msgstr "Remplir l'intervalle avec une région"
+
+#: gtk_ardour/editor.cc:2434
+msgid "Range"
+msgstr "Intervalle"
+
+#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538
+msgid "Play from edit cursor"
+msgstr "Jouer à partir du curseur d'édition"
+
+#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539
+msgid "Play from start"
+msgstr "Jouer depuis le début"
+
+#: gtk_ardour/editor.cc:2451
+msgid "Play region"
+msgstr "Jouer la région"
+
+#: gtk_ardour/editor.cc:2453
+msgid "Loop Region"
+msgstr "Boucler sur la région"
+
+#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540
+#: gtk_ardour/library_ui.cc:972
+msgid "Play"
+msgstr "Jouer"
+
+#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548
+msgid "Select All in track"
+msgstr "Tout sélectionner dans la piste"
+
+#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549
+msgid "Select All"
+msgstr "Tout sélectionner"
+
+#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550
+msgid "Invert in track"
+msgstr "Inverser dans la piste"
+
+#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551
+msgid "Invert"
+msgstr "Inverser"
+
+#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553
+msgid "Select loop range"
+msgstr "Sélectionner l'intervalle de boucle"
+
+#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554
+msgid "Select punch range"
+msgstr "Sélectionner l'intervalle d'insertion"
+
+#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565
+#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369
+msgid "Cut"
+msgstr "Couper"
+
+#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566
+#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371
+msgid "Copy"
+msgstr "Copier"
+
+#: gtk_ardour/editor.cc:2482
+msgid "Paste at edit cursor"
+msgstr "Coller au curseur d'édition"
+
+#: gtk_ardour/editor.cc:2483
+msgid "Paste at mouse"
+msgstr "Coller au pointeur de la souris"
+
+#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923
+msgid "Align"
+msgstr "Aligner"
+
+#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925
+msgid "Align Relative"
+msgstr "Aligner relativement"
+
+#: gtk_ardour/editor.cc:2492
+msgid "Insert chunk"
+msgstr "Insérer un fragment"
+
+#: gtk_ardour/editor.cc:2496
+msgid "New Region from range"
+msgstr "Nouvelle région à partir de l'intervalle"
+
+#: gtk_ardour/editor.cc:2497
+#, fuzzy
+msgid "Separate Range"
+msgstr "Séparer l'intervalle"
+
+#: gtk_ardour/editor.cc:2507
+msgid "Insert Region"
+msgstr "Insérer une région"
+
+#: gtk_ardour/editor.cc:2508
+msgid "Insert external sndfile"
+msgstr "Insérer un fichier son externe"
+
+#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438
+msgid "Import"
+msgstr "Importer"
+
+#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574
+msgid "Nudge entire track fwd"
+msgstr "Décaler la piste entière en avant"
+
+#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575
+msgid "Nudge track after edit cursor fwd"
+msgstr "Décaler la piste vers l'avant après le curseur d'édition"
+
+#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576
+msgid "Nudge entire track bwd"
+msgstr "Décaler la piste entière vers l'arrière"
+
+#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577
+msgid "Nudge track after edit cursor bwd"
+msgstr "Décaler la piste vers l'arrière après le curseur d'édition"
+
+#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920
+#: gtk_ardour/redirect_box.cc:373
+msgid "Paste"
+msgstr "Coller"
+
+#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645
+#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799
+msgid "add marker"
+msgstr "ajouter un marqueur"
+
+#: gtk_ardour/editor.cc:3084
+msgid "select/move objects"
+msgstr "sélectionner/déplacer des objets"
+
+#: gtk_ardour/editor.cc:3085
+msgid "select/move ranges"
+msgstr "sélectionner/déplacer des intervalles"
+
+#: gtk_ardour/editor.cc:3086
+msgid "draw gain automation"
+msgstr "dessiner l'automatisation du gain"
+
+#: gtk_ardour/editor.cc:3087
+msgid "select zoom range"
+msgstr "sélectionner la plage de zoom"
+
+#: gtk_ardour/editor.cc:3088
+msgid "stretch/shrink regions"
+msgstr "étirer/rétrécir les régions"
+
+#: gtk_ardour/editor.cc:3089
+#, fuzzy
+msgid "listen to specific regions"
+msgstr "Écouter des régions spécifiques"
+
+#: gtk_ardour/editor.cc:3213
+msgid "Start:"
+msgstr "Début :"
+
+#: gtk_ardour/editor.cc:3214
+msgid "End:"
+msgstr "Fin :"
+
+#: gtk_ardour/editor.cc:3215
+msgid "Edit:"
+msgstr "Éditer :"
+
+#: gtk_ardour/editor.cc:3429
+msgid "incorrectly formatted URI list, ignored"
+msgstr "liste d'URI mal formattée, ignorée"
+
+#: gtk_ardour/editor.cc:3611
+#, fuzzy
+msgid "set selected trackview"
+msgstr "définir la vue de piste sélectionnée"
+
+#: gtk_ardour/editor.cc:3647
+#, fuzzy
+msgid "set selected control point"
+msgstr "Enlever le point de contrôle"
+
+#: gtk_ardour/editor.cc:3719
+#, fuzzy
+msgid "set selected regionview"
+msgstr "définir la vue de région sélectionnée"
+
+#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835
+#, fuzzy
+msgid "set selected regions"
+msgstr "définir les régions sélectionnées"
+
+#: gtk_ardour/editor.cc:3891
+msgid "Undo"
+msgstr "Annuler"
+
+#: gtk_ardour/editor.cc:3893
+msgid "Undo (%1)"
+msgstr "Annuler (%1)"
+
+#: gtk_ardour/editor.cc:3903
+msgid "Redo"
+msgstr "Refaire"
+
+#: gtk_ardour/editor.cc:3905
+msgid "Redo (%1)"
+msgstr "Refaire (%1)"
+
+#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946
+msgid "... as new track"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947
+#, fuzzy
+msgid "... as new region"
+msgstr "aligner la région"
+
+#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452
+msgid "Import audio (copy)"
+msgstr "Importer audio (copie)"
+
+#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457
+msgid "Embed audio (link)"
+msgstr "Incorporer audio (lien)"
+
+#: gtk_ardour/editor.cc:3953
+msgid "Remove last capture"
+msgstr "Enlever la dernière capture"
+
+#: gtk_ardour/editor.cc:3974
+msgid "Duplicate how many times?"
+msgstr "Dupliquer combien de fois ?"
+
+#: gtk_ardour/editor.cc:4550
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If left alone, no audio files used by it will be cleaned.\n"
+"If deleted, audio files used by it alone by will cleaned."
+msgstr ""
+"La liste de lecture %1 n'est pas utilisée.\n"
+"Si vous la convervez, aucun fichier audio qu'elle utilise ne sera nettoyé.\n"
+"Si vous l'effacez, les fichiers audio qu'elle seule utilise seront nettoyés."
+
+#: gtk_ardour/editor.cc:4555
+msgid "Delete playlist"
+msgstr "Supprimer la playlist"
+
+#: gtk_ardour/editor.cc:4556
+msgid "Keep playlist"
+msgstr "Garder la playlist"
+
+#: gtk_ardour/editor.cc:4557
+msgid "Cancel cleanup"
+msgstr "Annuler le nettoyage"
+
+#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258
+#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290
+msgid ""
+"programming error: control point canvas item has no control point object "
+"pointer!"
+msgstr ""
+"erreur de programmation : point de contrôle de l'objet canvas sans pointeur "
+"d'objet point de contrôle !"
+
+#: gtk_ardour/editor_canvas_events.cc:717
+msgid "programming error: line canvas item has no line object pointer!"
+msgstr ""
+"erreur de programmation : ligne de l'objet canvas sans pointeur d'objet "
+"ligne !"
+
+#: gtk_ardour/editor_canvas_events.cc:744
+#: gtk_ardour/editor_canvas_events.cc:784
+#: gtk_ardour/editor_canvas_events.cc:823
+msgid "programming error: no \"rect\" pointer associated with selection item"
+msgstr ""
+"erreur de programmation : aucun pointeur \"rect\" n'est associé à l'object "
+"sélection"
+
+#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298
+#: gtk_ardour/mixer_ui.cc:670
+msgid "Show All"
+msgstr "Tout montrer"
+
+#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299
+#: gtk_ardour/mixer_ui.cc:671
+msgid "Hide All"
+msgstr "Tout cacher"
+
+#: gtk_ardour/editor_edit_groups.cc:98
+msgid "Name for new edit group"
+msgstr "Nom du nouveau groupe d'édition"
+
+#: gtk_ardour/editor_export_audio.cc:60
+msgid ""
+"There is no range to export.\n"
+"\n"
+"Select a range using the range mouse mode"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707
+msgid "programming error: no ImageFrameView selected"
+msgstr "erreur de programmation : aucun ImageFrameView selectionné"
+
+#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930
+msgid "programming error: no MarkerView selected"
+msgstr "erreur de programmation : aucun MarkerView sélectionné"
+
+#: gtk_ardour/editor_keys.cc:187
+#, fuzzy
+msgid "keyboard selection"
+msgstr "étendre la sélection"
+
+#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376
+#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526
+#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584
+#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650
+#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700
+#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960
+#: gtk_ardour/editor_mouse.cc:4075
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr ""
+"erreur de programmation : objet canvas de marqueur sans pointeur d'objet "
+"marqueur !"
+
+#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681
+msgid "remove marker"
+msgstr "enlever le marqueur"
+
+#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494
+#, fuzzy
+msgid "Locate to"
+msgstr "Locate to"
+
+#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495
+msgid "Play from"
+msgstr "Jouer depuis"
+
+#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496
+msgid "Set from playhead"
+msgstr "Jouer depuis la tête de lecture"
+
+#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497
+msgid "Set from range"
+msgstr "Définir à partir de l'intervalle"
+
+#: gtk_ardour/editor_markers.cc:479
+msgid "Set Loop Range"
+msgstr "Définir l'intervalle de boucle"
+
+#: gtk_ardour/editor_markers.cc:480
+msgid "Set Punch Range"
+msgstr "Définir l'intervalle d'insertion"
+
+#: gtk_ardour/editor_markers.cc:736
+msgid "ardour: rename mark"
+msgstr "ardour : renommer le marqueur"
+
+#: gtk_ardour/editor_markers.cc:738
+msgid "ardour: rename range"
+msgstr "ardour : renommer l'intervalle"
+
+#: gtk_ardour/editor_markers.cc:792
+msgid "set loop range"
+msgstr "définir l'intervalle de boucle"
+
+#: gtk_ardour/editor_markers.cc:818
+msgid "set punch range"
+msgstr "définir l'intervalle d'insertion"
+
+#: gtk_ardour/editor_mouse.cc:99
+msgid "Editor::event_frame() used on unhandled event type %1"
+msgstr "Editor::event_frame() utilisé sur un évènement non géré de type %1"
+
+#: gtk_ardour/editor_mouse.cc:1555
+msgid "programming error: start_grab called without drag item"
+msgstr "erreur de programmation : start_grab appelé sans objet a ramasser"
+
+#: gtk_ardour/editor_mouse.cc:1760
+msgid "change fade in length"
+msgstr "modifier la longueur du fondu d'ouverture"
+
+#: gtk_ardour/editor_mouse.cc:1778
+#, fuzzy
+msgid "programming error: fade out canvas item has no regionview data pointer!"
+msgstr ""
+"programming error: fade out canvas item has no regionview data pointer!"
+
+#: gtk_ardour/editor_mouse.cc:1852
+msgid "change fade out length"
+msgstr "modifier la longueur du fondu de fermeture"
+
+#: gtk_ardour/editor_mouse.cc:1871
+msgid "programming error: cursor canvas item has no cursor data pointer!"
+msgstr ""
+"erreur de programmation : objet canvas de curseur sans pointeur de données "
+"curseur"
+
+#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470
+msgid ""
+"programming error: meter marker canvas item has no marker object pointer!"
+msgstr ""
+"erreur de programmation: meter marker canvas item has no marker object "
+"pointer!"
+
+#: gtk_ardour/editor_mouse.cc:2163
+msgid "move meter mark"
+msgstr "déplacer le marqueur de vu-mètre"
+
+#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335
+#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439
+msgid ""
+"programming error: tempo marker canvas item has no marker object pointer!"
+msgstr ""
+"erreur de programmation : objet canvas de marqueur de tempo sans pointeur "
+"d'objet marqueur !"
+
+#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340
+#: gtk_ardour/editor_tempodisplay.cc:425
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr ""
+"erreur de programmation : le marqueur du tempo n'est pas un marqueur de "
+"tempo !"
+
+#: gtk_ardour/editor_mouse.cc:2245
+msgid "move tempo mark"
+msgstr "déplacer le marqueur de tempo"
+
+#: gtk_ardour/editor_mouse.cc:2388
+msgid "programming error: line canvas item has no line pointer!"
+msgstr ""
+"erreur de programmation : objet canvas de ligne sans pointeur de ligne !"
+
+#: gtk_ardour/editor_mouse.cc:2497
+#, fuzzy
+msgid "move region(s)"
+msgstr "enlever la région"
+
+#: gtk_ardour/editor_mouse.cc:2509
+msgid "Drag region copy"
+msgstr "Déplacer la copie de la région"
+
+#: gtk_ardour/editor_mouse.cc:2579
+#, fuzzy
+msgid "copy region(s)"
+msgstr "Déplacer la/les région(s)"
+
+#: gtk_ardour/editor_mouse.cc:2612
+#, fuzzy
+msgid "Drag region brush"
+msgstr "Déplacer la/les région(s)"
+
+#: gtk_ardour/editor_mouse.cc:3425
+#, fuzzy
+msgid "selection grab"
+msgstr "attraper la sélection"
+
+#: gtk_ardour/editor_mouse.cc:3571
+msgid "range selection"
+msgstr "sélection d'intervalle"
+
+#: gtk_ardour/editor_mouse.cc:3587
+msgid "trim selection start"
+msgstr "élaguer le début de la sélection"
+
+#: gtk_ardour/editor_mouse.cc:3603
+msgid "trim selection end"
+msgstr "élaguer la fin de la sélection"
+
+#: gtk_ardour/editor_mouse.cc:3620
+msgid "move selection"
+msgstr "déplacer la sélection"
+
+#: gtk_ardour/editor_mouse.cc:3995
+msgid "Start point trim"
+msgstr "Point de départ d'élaguage"
+
+#: gtk_ardour/editor_mouse.cc:4023
+msgid "End point trim"
+msgstr "Point de fin d'élaguage"
+
+#: gtk_ardour/editor_mouse.cc:4062
+msgid "trimmed region"
+msgstr "région élaguée"
+
+#: gtk_ardour/editor_mouse.cc:4203
+msgid "new range marker"
+msgstr "nouveau marqueur d'intervalle"
+
+#: gtk_ardour/editor_mouse.cc:4422
+msgid "select regions"
+msgstr "sélectionner les régions"
+
+#: gtk_ardour/editor_mouse.cc:4451
+msgid "Name for region:"
+msgstr "Nom de la région :"
+
+#: gtk_ardour/editor_mouse.cc:4517
+msgid "timestretch"
+msgstr "déformation temporelle"
+
+#: gtk_ardour/editor_ops.cc:117
+msgid "split"
+msgstr "séparer"
+
+#: gtk_ardour/editor_ops.cc:153
+msgid "remove region"
+msgstr "enlever la région"
+
+#: gtk_ardour/editor_ops.cc:172
+msgid ""
+" This is destructive, will possibly delete audio files\n"
+"It cannot be undone\n"
+"Do you really want to destroy %1 ?"
+msgstr ""
+" Ceci est destructif, et effacera peut-être des fichiers audio\n"
+"Cela ne pourra être annulé\n"
+"Voulez-vous vraiment détruire %1 ?"
+
+#: gtk_ardour/editor_ops.cc:176
+msgid "these regions"
+msgstr "ces régions"
+
+#: gtk_ardour/editor_ops.cc:176
+msgid "this region"
+msgstr "cette région"
+
+#: gtk_ardour/editor_ops.cc:179
+msgid "Yes, destroy them."
+msgstr "Oui, les détruire."
+
+#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434
+msgid "Yes, destroy it."
+msgstr "Oui, la supprimer."
+
+#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435
+#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300
+msgid "No, do nothing."
+msgstr "Non, ne rien faire."
+
+#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307
+msgid "extend selection"
+msgstr "étendre la sélection"
+
+#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357
+#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427
+msgid "nudge forward"
+msgstr "décaler vers l'avant"
+
+#: gtk_ardour/editor_ops.cc:491
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr "build_region_boundary_cache appelé avec snap_type = %1"
+
+#: gtk_ardour/editor_ops.cc:1305
+msgid "set selection from range"
+msgstr "définir la sélection à partir de l'intervalle"
+
+#: gtk_ardour/editor_ops.cc:1421
+msgid "clear markers"
+msgstr "effacer les marqueurs"
+
+#: gtk_ardour/editor_ops.cc:1433
+msgid "clear ranges"
+msgstr "effacer les intervalles"
+
+#: gtk_ardour/editor_ops.cc:1452
+msgid "clear locations"
+msgstr "effacer les emplacements"
+
+#: gtk_ardour/editor_ops.cc:1503
+msgid "insert dragged region"
+msgstr "insérer la région déplacée"
+
+#: gtk_ardour/editor_ops.cc:1538
+msgid "insert region"
+msgstr "insérer une région"
+
+#: gtk_ardour/editor_ops.cc:1744
+msgid "ardour: rename region"
+msgstr "ardour : renommer la région"
+
+#: gtk_ardour/editor_ops.cc:1891
+msgid "You can't import an audiofile until you have a session loaded."
+msgstr ""
+"Vous ne pouvez pas importer un fichier audio avant d'avoir chargé une "
+"session."
+
+#: gtk_ardour/editor_ops.cc:1901
+#, fuzzy
+msgid "Import selected as tracks"
+msgstr "Import sélectionné"
+
+#: gtk_ardour/editor_ops.cc:1904
+#, fuzzy
+msgid "Import selected to region list"
+msgstr "définir les régions sélectionnées"
+
+#: gtk_ardour/editor_ops.cc:1933
+msgid "ardour: audio import in progress"
+msgstr "ardour : importation audio en cours"
+
+#: gtk_ardour/editor_ops.cc:1937
+msgid "Cancel Import"
+msgstr "Annuler l'importation"
+
+#: gtk_ardour/editor_ops.cc:1944
+msgid "ardour: importing %1"
+msgstr "ardour : importation de %1"
+
+#: gtk_ardour/editor_ops.cc:1990
+msgid "%1 it anyway"
+msgstr "le %1 quand même"
+
+#: gtk_ardour/editor_ops.cc:1996
+#, fuzzy
+msgid "Don't %1 it"
+msgstr "Ne pas %1"
+
+#: gtk_ardour/editor_ops.cc:1997
+msgid "%1 all without questions"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1998
+#, fuzzy
+msgid "Cancel entire import"
+msgstr "Annuler l'importation"
+
+#: gtk_ardour/editor_ops.cc:2004
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr ""
+"%1\n"
+"La fréquence d'échantillonage de ce fichier audio ne correspond pas à celle "
+"de la session !"
+
+#: gtk_ardour/editor_ops.cc:2032
+msgid "You can't embed an audiofile until you have a session loaded."
+msgstr ""
+"Vous ne pouvez pas incorporer un fichier audio avant d'avoir chargé une "
+"session."
+
+#: gtk_ardour/editor_ops.cc:2039
+msgid "Add to External Region list"
+msgstr "Ajouter à la liste des régions externes"
+
+#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210
+#: gtk_ardour/editor_ops.cc:2286
+msgid "Editor: cannot open file \"%1\" (%2)"
+msgstr "Éditeur : impossible d'ouvrir le fichier \"%1\" (%2)"
+
+#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312
+msgid "could not open %1"
+msgstr "impossible d'ouvrir %1"
+
+#: gtk_ardour/editor_ops.cc:2171
+#, fuzzy
+msgid "Insert selected as new tracks"
+msgstr "définir la vue de piste sélectionnée"
+
+#: gtk_ardour/editor_ops.cc:2186
+msgid "Insert selected"
+msgstr "Insertion sélectionnée"
+
+#: gtk_ardour/editor_ops.cc:2327
+msgid "insert sndfile"
+msgstr "Insérer un fichier son"
+
+#: gtk_ardour/editor_ops.cc:2464
+msgid "separate"
+msgstr "séparer"
+
+#: gtk_ardour/editor_ops.cc:2528
+msgid "trim to selection"
+msgstr "élaguer selon la sélection"
+
+#: gtk_ardour/editor_ops.cc:2568
+msgid "region fill"
+msgstr "remplissage de la région"
+
+#: gtk_ardour/editor_ops.cc:2626
+msgid "fill selection"
+msgstr "remplir la sélection"
+
+#: gtk_ardour/editor_ops.cc:2650
+msgid "Place the edit cursor at the desired sync point"
+msgstr "Placer le curseur d'édition au point de synchro. désiré"
+
+#: gtk_ardour/editor_ops.cc:2656
+msgid "set sync from edit cursor"
+msgstr "définir la synchro. au curseur d'édition"
+
+#: gtk_ardour/editor_ops.cc:2668
+msgid "remove sync"
+msgstr "enlever la synchro."
+
+#: gtk_ardour/editor_ops.cc:2682
+msgid "naturalize"
+msgstr "normaliser"
+
+#: gtk_ardour/editor_ops.cc:2746
+msgid "align selection (relative)"
+msgstr "Aligner la sélection (relativement)"
+
+#: gtk_ardour/editor_ops.cc:2774
+msgid "align selection"
+msgstr "aligner la sélection"
+
+#: gtk_ardour/editor_ops.cc:2786
+msgid "align region"
+msgstr "aligner la région"
+
+#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858
+#, fuzzy
+msgid "trim to edit"
+msgstr "élaguer to edit"
+
+#: gtk_ardour/editor_ops.cc:2909
+#, fuzzy
+msgid "ardour: freeze"
+msgstr "ardour :"
+
+#: gtk_ardour/editor_ops.cc:2914
+#, fuzzy
+msgid "Cancel Freeze"
+msgstr "Annuler"
+
+#: gtk_ardour/editor_ops.cc:2951
+#, fuzzy
+msgid "bounce range"
+msgstr "bounce intervalle"
+
+#: gtk_ardour/editor_ops.cc:3004
+msgid "cut"
+msgstr "couper"
+
+#: gtk_ardour/editor_ops.cc:3007
+msgid "copy"
+msgstr "copier"
+
+#: gtk_ardour/editor_ops.cc:3020
+msgid " objects"
+msgstr " objets"
+
+#: gtk_ardour/editor_ops.cc:3046
+msgid " range"
+msgstr " intervalle"
+
+#: gtk_ardour/editor_ops.cc:3201
+msgid "paste"
+msgstr "coller"
+
+#: gtk_ardour/editor_ops.cc:3236
+msgid "paste chunk"
+msgstr "coller le fragment"
+
+#: gtk_ardour/editor_ops.cc:3276
+msgid "duplicate region"
+msgstr "dupliquer la région"
+
+#: gtk_ardour/editor_ops.cc:3309
+msgid "duplicate selection"
+msgstr "dupliquer la sélection"
+
+#: gtk_ardour/editor_ops.cc:3349
+msgid "clear playlist"
+msgstr "effacer la liste de lecture"
+
+#: gtk_ardour/editor_ops.cc:3378
+msgid "nudge track"
+msgstr "décaler la piste"
+
+#: gtk_ardour/editor_ops.cc:3431
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"Voulez-vous vraiment supprimer la dernière capture ?\n"
+"(cette opération est destructive et ne pourra pas être annulée)"
+
+#: gtk_ardour/editor_ops.cc:3463
+msgid "normalize"
+msgstr "normaliser"
+
+#: gtk_ardour/editor_ops.cc:3510
+msgid "reverse regions"
+msgstr "inverser les régions"
+
+#: gtk_ardour/editor_region_list.cc:223
+msgid "hidden"
+msgstr "caché"
+
+#: gtk_ardour/editor_region_list.cc:408
+msgid "Show all"
+msgstr "Tout montrer"
+
+#: gtk_ardour/editor_region_list.cc:417
+msgid "Ascending"
+msgstr "Montant"
+
+#: gtk_ardour/editor_region_list.cc:419
+msgid "Descending"
+msgstr "Descendant"
+
+#: gtk_ardour/editor_region_list.cc:423
+msgid "By Region Name"
+msgstr "Par nom de région"
+
+#: gtk_ardour/editor_region_list.cc:425
+msgid "By Region Length"
+msgstr "Par longueur de région"
+
+#: gtk_ardour/editor_region_list.cc:427
+msgid "By Region Position"
+msgstr "Par position de région"
+
+#: gtk_ardour/editor_region_list.cc:429
+msgid "By Region Timestamp"
+msgstr "Par date de région"
+
+#: gtk_ardour/editor_region_list.cc:431
+msgid "By Region Start in File"
+msgstr "Par début de région dans le fichier"
+
+#: gtk_ardour/editor_region_list.cc:433
+msgid "By Region End in File"
+msgstr "Par fin de région dans le fichier"
+
+#: gtk_ardour/editor_region_list.cc:435
+msgid "By Source File Name"
+msgstr "Par nom de fichier source"
+
+#: gtk_ardour/editor_region_list.cc:437
+msgid "By Source File Length"
+msgstr "Par longueur de fichier source"
+
+#: gtk_ardour/editor_region_list.cc:439
+msgid "By Source File Creation Date"
+msgstr "Par date de création du fichier source"
+
+#: gtk_ardour/editor_region_list.cc:441
+msgid "By Source Filesystem"
+msgstr "Par système de fichier source"
+
+#: gtk_ardour/editor_region_list.cc:444
+msgid "Sorting"
+msgstr "Tri"
+
+#: gtk_ardour/editor_region_list.cc:808
+msgid "Regions/length"
+msgstr "Région/longueur"
+
+#: gtk_ardour/editor_region_list.cc:812
+msgid "Regions/position"
+msgstr "Régions/position"
+
+#: gtk_ardour/editor_region_list.cc:816
+msgid "Regions/creation"
+msgstr "Régions/création"
+
+#: gtk_ardour/editor_region_list.cc:820
+msgid "Regions/start"
+msgstr "Régions/début"
+
+#: gtk_ardour/editor_region_list.cc:824
+msgid "Regions/end"
+msgstr "Régions/fin"
+
+#: gtk_ardour/editor_region_list.cc:828
+msgid "Regions/file name"
+msgstr "Régions/nom de fichier"
+
+#: gtk_ardour/editor_region_list.cc:832
+msgid "Regions/file size"
+msgstr "Régions/taille de fichier"
+
+#: gtk_ardour/editor_region_list.cc:836
+msgid "Regions/file date"
+msgstr "Région/date de fichier"
+
+#: gtk_ardour/editor_region_list.cc:840
+msgid "Regions/file system"
+msgstr "Région/système de fichier"
+
+#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73
+#: gtk_ardour/editor_route_list.cc:231
+msgid "editor"
+msgstr "éditeur"
+
+#: gtk_ardour/editor_route_list.cc:300
+msgid "Show All AbstractTracks"
+msgstr "Montrer toutes les PistesAbstraites"
+
+#: gtk_ardour/editor_route_list.cc:301
+msgid "Hide All AbstractTracks"
+msgstr "Cacher toutes les PistesAbstraites"
+
+#: gtk_ardour/editor_route_list.cc:302
+msgid "Show All AudioBus"
+msgstr "Montrer tous les BusAudio"
+
+#: gtk_ardour/editor_route_list.cc:303
+msgid "Hide All AudioBus"
+msgstr "Cacher tous les BusAudio"
+
+#: gtk_ardour/editor_rulers.cc:311
+msgid "New location marker"
+msgstr "Nouveau marqueur d'emplacement"
+
+#: gtk_ardour/editor_rulers.cc:312
+msgid "Clear all locations"
+msgstr "Effacer tous les emplacements"
+
+#: gtk_ardour/editor_rulers.cc:317
+msgid "Clear all ranges"
+msgstr "Effacer tous les intervalles"
+
+#: gtk_ardour/editor_rulers.cc:326
+msgid "New Tempo"
+msgstr "Nouveau tempo"
+
+#: gtk_ardour/editor_rulers.cc:327
+msgid "Clear tempo"
+msgstr "Effacer le tempo"
+
+#: gtk_ardour/editor_rulers.cc:332
+msgid "New Meter"
+msgstr "Nouveau vu-mètre"
+
+#: gtk_ardour/editor_rulers.cc:333
+msgid "Clear meter"
+msgstr "Effacer les vu-mètre"
+
+#: gtk_ardour/editor_rulers.cc:341
+msgid "Min:Secs"
+msgstr "Mins:Secs"
+
+#: gtk_ardour/editor_selection_list.cc:117
+msgid "name for chunk:"
+msgstr "nom du fragment :"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Create chunk"
+msgstr "Créer un fragment"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Forget it"
+msgstr "Oublier"
+
+#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295
+msgid "add"
+msgstr "ajouter"
+
+#: gtk_ardour/editor_tempodisplay.cc:276
+msgid "add tempo mark"
+msgstr "ajouter un marqueur de tempo"
+
+#: gtk_ardour/editor_tempodisplay.cc:318
+msgid "add meter mark"
+msgstr "ajouter un marqueur de vu-mètre"
+
+#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383
+msgid "done"
+msgstr "terminé"
+
+#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404
+msgid "replace tempo mark"
+msgstr "remplacer le marqueur de tempo"
+
+#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr "erreur de programmation : marker for meter is not a meter marker!"
+
+#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487
+msgid "remove tempo mark"
+msgstr "enlever le marqueur de tempo"
+
+#: gtk_ardour/editor_timefx.cc:50
+msgid "Quick but Ugly"
+msgstr "Rapide mais sale"
+
+#: gtk_ardour/editor_timefx.cc:51
+msgid "Skip Anti-aliasing"
+msgstr "Sauter l'anti-crénelage"
+
+#: gtk_ardour/editor_timefx.cc:53
+msgid "Stretch/Shrink it"
+msgstr "Étirer/Rétrécir"
+
+#: gtk_ardour/editor_timefx.cc:57
+msgid "ardour: timestretch"
+msgstr "ardour : déformation temporelle"
+
+#: gtk_ardour/editor_timefx.cc:58
+msgid "TimeStretchDialog"
+msgstr "TimeStretchDialog"
+
+#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83
+#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85
+msgid "TimeStretchButton"
+msgstr "TimeStretchButton"
+
+#: gtk_ardour/editor_timefx.cc:86
+msgid "TimeStretchProgress"
+msgstr "TimeStretchProgress"
+
+#: gtk_ardour/editor_timefx.cc:151
+msgid "timestretch cannot be started - thread creation error"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410
+#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189
+msgid "22.05kHz"
+msgstr "22.05 kHz"
+
+#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413
+#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949
+#: gtk_ardour/export_dialog.cc:1191
+msgid "44.1kHz"
+msgstr "44.1 kHz"
+
+#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416
+#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193
+msgid "48kHz"
+msgstr "48 kHz"
+
+#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419
+#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195
+msgid "88.2kHz"
+msgstr "88.2 kHz"
+
+#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422
+#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197
+msgid "96kHz"
+msgstr "96 kHz"
+
+#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425
+#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199
+msgid "192kHz"
+msgstr "192 kHz"
+
+#: gtk_ardour/export_dialog.cc:73
+msgid "best"
+msgstr "meilleur"
+
+#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964
+msgid "fastest"
+msgstr "rapide"
+
+#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966
+msgid "linear"
+msgstr "linéaire"
+
+#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968
+msgid "better"
+msgstr "meilleur"
+
+#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970
+msgid "intermediate"
+msgstr "intermédiaire"
+
+#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979
+msgid "Rectangular"
+msgstr "Rectangulaire"
+
+#: gtk_ardour/export_dialog.cc:84
+msgid "Shaped Noise"
+msgstr "Shaped noise"
+
+#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981
+msgid "Triangular"
+msgstr "Triangulaire"
+
+#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336
+msgid "stereo"
+msgstr "stéréo"
+
+#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497
+#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219
+#: gtk_ardour/utils.cc:334
+msgid "mono"
+msgstr "mono"
+
+#: gtk_ardour/export_dialog.cc:97
+msgid "CUE"
+msgstr "CUE"
+
+#: gtk_ardour/export_dialog.cc:98
+msgid "TOC"
+msgstr "TOC"
+
+#: gtk_ardour/export_dialog.cc:106
+msgid "FORMAT"
+msgstr "FORMAT"
+
+#: gtk_ardour/export_dialog.cc:107
+msgid "SAMPLE RATE"
+msgstr "VITESSE D'ÉCHANTILLONAGE"
+
+#: gtk_ardour/export_dialog.cc:108
+msgid "CONVERSION QUALITY"
+msgstr "QUALITÉ DE LA CONVERSION"
+
+#: gtk_ardour/export_dialog.cc:109
+msgid "DITHER TYPE"
+msgstr "TYPE D'INTERPOLATION"
+
+#: gtk_ardour/export_dialog.cc:110
+#, fuzzy
+msgid "CD MARKER FILE TYPE"
+msgstr "TYPE DE FICHIER DU MARQUEUR DE CD"
+
+#: gtk_ardour/export_dialog.cc:111
+msgid "CHANNELS"
+msgstr "VOIES"
+
+#: gtk_ardour/export_dialog.cc:112
+msgid "FILE TYPE"
+msgstr "TYPE DE FICHIER"
+
+#: gtk_ardour/export_dialog.cc:113
+msgid "SAMPLE FORMAT"
+msgstr "FORMAT D'ÉCHANTILLON"
+
+#: gtk_ardour/export_dialog.cc:114
+msgid "SAMPLE ENDIANNESS"
+msgstr "ENDIANNESS DES ÉCHANTILLONS"
+
+#: gtk_ardour/export_dialog.cc:115
+#, fuzzy
+msgid "EXPORT CD MARKER FILE ONLY"
+msgstr "EXPORTER SEULEMENT LE FICHIER DE MARQUEUR DE CD"
+
+#: gtk_ardour/export_dialog.cc:116
+msgid "EXPORT TO FILE"
+msgstr "EXPORTER VERS FICHIER"
+
+#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118
+#: gtk_ardour/option_editor.cc:119
+msgid "Browse"
+msgstr "Parcourir"
+
+#: gtk_ardour/export_dialog.cc:119
+msgid "Specific tracks ..."
+msgstr "Pistes spécifiques..."
+
+#: gtk_ardour/export_dialog.cc:131
+msgid "ardour: export"
+msgstr "ardour : exporter"
+
+#: gtk_ardour/export_dialog.cc:132
+msgid "ardour_export"
+msgstr "ardour_exporter"
+
+#: gtk_ardour/export_dialog.cc:156
+msgid "Output"
+msgstr "Sortie"
+
+#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626
+msgid "Track"
+msgstr "Piste"
+
+#: gtk_ardour/export_dialog.cc:287
+msgid "slereg"
+msgstr "slereg"
+
+#: gtk_ardour/export_dialog.cc:658
+msgid "Editor: cannot open \"%1\" as export file for CD toc file"
+msgstr ""
+"Editeur : impossible d'ouvrir \"%1\" comme fichier de table des matières de "
+"CD"
+
+#: gtk_ardour/export_dialog.cc:780
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD cue file"
+msgstr ""
+"Editeur : impossible d'ouvrir \"%1\" comme fichier d'exportation de marqueur "
+"de piste CD"
+
+#: gtk_ardour/export_dialog.cc:799
+msgid "WAV"
+msgstr "WAV"
+
+#: gtk_ardour/export_dialog.cc:1051
+msgid "Stop Export"
+msgstr "Arrêter l'exportation"
+
+#: gtk_ardour/gain_automation_time_axis.cc:60
+#, fuzzy
+msgid "add gain automation event"
+msgstr "ajouter les évènements d'automatisation à "
+
+#: gtk_ardour/gain_meter.cc:68
+msgid "Cannot create slider pixmaps"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:83
+msgid "dbFS"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134
+#: gtk_ardour/gain_meter.cc:728
+msgid "pre"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724
+#, fuzzy
+msgid "input"
+msgstr "entrée %1"
+
+#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732
+#, fuzzy
+msgid "post"
+msgstr "port"
+
+#: gtk_ardour/gain_meter.cc:146
+msgid "tupni"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470
+#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537
+#, fuzzy
+msgid "-inf"
+msgstr "entrée"
+
+#: gtk_ardour/imageframe_socket_handler.cc:127
+msgid "Image Compositor Socket has been shutdown/closed"
+msgstr "La socket du compositeur d'image a été arrêtée/fermée"
+
+#: gtk_ardour/imageframe_time_axis.cc:295
+msgid "0.5 seconds"
+msgstr "0.5 secondes"
+
+#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259
+msgid "1 seconds"
+msgstr "1 seconde"
+
+#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260
+msgid "1.5 seconds"
+msgstr "1.5 secondes"
+
+#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261
+msgid "2 seconds"
+msgstr "2 secondes"
+
+#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262
+msgid "2.5 seconds"
+msgstr "2.5 secondes"
+
+#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263
+msgid "3 seconds"
+msgstr "3 secondes"
+
+#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268
+msgid "Duration (sec)"
+msgstr "Durée (s)"
+
+#: gtk_ardour/imageframe_time_axis.cc:310
+msgid "Remove Frame"
+msgstr "Enlever une trame"
+
+#: gtk_ardour/imageframe_time_axis.cc:313
+msgid "Image Frame"
+msgstr "Trame d'image"
+
+#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274
+msgid "Rename Track"
+msgstr "Renommer la piste"
+
+#: gtk_ardour/io_selector.cc:64
+msgid "%1 input"
+msgstr "entrée %1"
+
+#: gtk_ardour/io_selector.cc:66
+msgid "%1 output"
+msgstr "sortie %1"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103
+msgid "Inputs"
+msgstr "Entrées"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104
+msgid "Outputs"
+msgstr "Sorties"
+
+#: gtk_ardour/io_selector.cc:142
+msgid "Add Input"
+msgstr "Ajouter une entrée"
+
+#: gtk_ardour/io_selector.cc:142
+msgid "Add Output"
+msgstr "Ajouter une sortie"
+
+#: gtk_ardour/io_selector.cc:143
+msgid "Remove Input"
+msgstr "Enlever une entrée"
+
+#: gtk_ardour/io_selector.cc:143
+msgid "Remove Output"
+msgstr "Enlever une sortie"
+
+#: gtk_ardour/io_selector.cc:144
+msgid "Disconnect All"
+msgstr "Déconnecter tout"
+
+#: gtk_ardour/io_selector.cc:158
+msgid "Available connections"
+msgstr "Connexions disponibles"
+
+#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636
+#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724
+msgid "port"
+msgstr "port"
+
+#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587
+msgid "There are no more JACK ports available."
+msgstr "Il n'y a plus de ports JACK disponibles"
+
+#: gtk_ardour/io_selector.cc:790
+msgid "ardour: "
+msgstr "ardour :"
+
+#: gtk_ardour/keyboard.cc:419
+msgid "KeyboardTarget: keyname \"%1\" is unknown."
+msgstr "KeyboardTarget : nom de touche \"%1\" inconnue"
+
+#: gtk_ardour/keyboard.cc:645
+msgid ""
+"Your system is completely broken - NumLock uses \"%1\"as its modifier. This "
+"is madness - see the man page for xmodmap to find out how to fix this."
+msgstr ""
+"Votre système débloque complétement -- la touche de verrouillage numérique "
+"utilise \"%1\" comme modificateur. C'est n'importe quoi -- consultez la page "
+"de manuel de xmodmap pour trouver comment réparer ça."
+
+#: gtk_ardour/keyboard.cc:653
+msgid ""
+"Your system generates \"%1\" when the NumLock key is pressed. This can cause "
+"problems when editing so Ardour will use %2 to mean Meta rather than %1"
+msgstr ""
+"Votre système génère \"%1\" quand la touche de verrouillage numérique est "
+"pressée. Cela peut causer des problèmes pendant l'édition, aussi Ardour "
+"utilisera %2 comme touche Meta plutôt que %1"
+
+#: gtk_ardour/keyboard.cc:714
+msgid "You have %1 keys bound to \"mod1\""
+msgstr "Vous avez %1 touches affectées à \"mod1\""
+
+#: gtk_ardour/keyboard.cc:729
+msgid "You have %1 keys bound to \"mod2\""
+msgstr "Vous avez %1 touches affectées à \"mod2\""
+
+#: gtk_ardour/keyboard.cc:744
+msgid "You have %1 keys bound to \"mod3\""
+msgstr "Vous avez %1 touches affectées à \"mod3\""
+
+#: gtk_ardour/keyboard.cc:759
+msgid "You have %1 keys bound to \"mod4\""
+msgstr "Vous avez %1 touches affectées à \"mod4\""
+
+#: gtk_ardour/keyboard.cc:774
+msgid "You have %1 keys bound to \"mod5\""
+msgstr "Vous avez %1 touches affectées à \"mod5\""
+
+#: gtk_ardour/keyboard_target.cc:72
+msgid "KeyboardTarget: empty string passed to add_binding."
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:78
+msgid "KeyboardTarget: no translation found for \"%1\""
+msgstr "KeyboardTarget : aucune traduction trouvée pour \"%1\""
+
+#: gtk_ardour/keyboard_target.cc:83
+msgid "KeyboardTarget: unknown action \"%1\""
+msgstr "KeyboardTarget : action \"%1\" inconnue"
+
+#: gtk_ardour/keyboard_target.cc:248
+msgid "misformed binding node - ignored"
+msgstr "misformed binding node -- ignored"
+
+#: gtk_ardour/library_ui.cc:62
+#, fuzzy
+msgid "Soundfile Library"
+msgstr "Bibliothèque audio"
+
+#: gtk_ardour/library_ui.cc:63
+msgid "Filesystem"
+msgstr "Système de fichier"
+
+#: gtk_ardour/library_ui.cc:66
+msgid "Split Channels"
+msgstr "Séparer les voies"
+
+#: gtk_ardour/library_ui.cc:69
+msgid "ardour: soundfile selector"
+msgstr "ardour : sélection de fichier son"
+
+#: gtk_ardour/library_ui.cc:430
+msgid "Add to Library..."
+msgstr "Ajouter à la bibliothèque..."
+
+#: gtk_ardour/library_ui.cc:431
+msgid "Remove..."
+msgstr "Enlever..."
+
+#: gtk_ardour/library_ui.cc:432
+msgid "Find..."
+msgstr "Chercher..."
+
+#: gtk_ardour/library_ui.cc:433
+msgid "Add Folder"
+msgstr "Ajouter un dossier"
+
+#: gtk_ardour/library_ui.cc:434
+msgid "Add audio file or directory"
+msgstr "Ajouter un fichier ou un dossier"
+
+#: gtk_ardour/library_ui.cc:713
+msgid "Importing"
+msgstr "Importation en cours"
+
+#: gtk_ardour/library_ui.cc:748
+msgid "%1 not added to database"
+msgstr "%1 n'a pas été ajouté à la base de données"
+
+#: gtk_ardour/library_ui.cc:767
+msgid "Folder name:"
+msgstr "Nom du dossier :"
+
+#: gtk_ardour/library_ui.cc:838
+msgid "Should not be reached"
+msgstr "Ne devrait pas être atteint"
+
+#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096
+msgid "file \"%1\" could not be opened"
+msgstr "le fichier \"%1\" n'a pu être ouvert"
+
+#: gtk_ardour/library_ui.cc:956
+msgid "Field"
+msgstr "Champ"
+
+#: gtk_ardour/library_ui.cc:957
+msgid "Value"
+msgstr "Valeur"
+
+#: gtk_ardour/library_ui.cc:973
+msgid "Stop"
+msgstr "Arrêter"
+
+#: gtk_ardour/library_ui.cc:974
+msgid "Add Field..."
+msgstr "Ajouter un champ..."
+
+#: gtk_ardour/library_ui.cc:975
+msgid "Remove Field"
+msgstr "Enlever un champ"
+
+#: gtk_ardour/library_ui.cc:979
+msgid "Soundfile Info"
+msgstr "Information du fichier son"
+
+#: gtk_ardour/library_ui.cc:1106
+msgid "file \"%1\" appears not to be an audio file"
+msgstr "le fichier \"%1\" ne semble pas être un fichier audio"
+
+#: gtk_ardour/library_ui.cc:1159
+msgid "Could not read file: %1 (%2)."
+msgstr "Impossible delire le fichier %1 (%2)."
+
+#: gtk_ardour/library_ui.cc:1177
+msgid "Could not access soundfile: "
+msgstr "Impossible d'accéder au fichier son : "
+
+#: gtk_ardour/library_ui.cc:1222
+msgid "Field name:"
+msgstr "Nom de champ :"
+
+#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367
+msgid "Field value:"
+msgstr "Valeur du champ :"
+
+#: gtk_ardour/library_ui.cc:1295
+msgid "Find"
+msgstr "Trouver"
+
+#: gtk_ardour/library_ui.cc:1296
+msgid "AND"
+msgstr "ET"
+
+#: gtk_ardour/library_ui.cc:1297
+msgid "OR"
+msgstr "OU"
+
+#: gtk_ardour/library_ui.cc:1300
+msgid "ardour: locate soundfiles"
+msgstr "ardour : trouver fichiers audio"
+
+#: gtk_ardour/library_ui.cc:1426
+msgid "Results"
+msgstr "Résultats"
+
+#: gtk_ardour/library_ui.cc:1427
+msgid "Uris"
+msgstr "Uris"
+
+#: gtk_ardour/library_ui.cc:1439
+msgid "Create multi-channel region"
+msgstr "Créer une région multi-voie"
+
+#: gtk_ardour/library_ui.cc:1442
+msgid "Ardour: Search Results"
+msgstr "Ardour : résultat de la recherche"
+
+#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50
+msgid "Set"
+msgstr "Définir"
+
+#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51
+msgid "Go"
+msgstr "Aller"
+
+#: gtk_ardour/location_ui.cc:54
+msgid "CD"
+msgstr "CD"
+
+#: gtk_ardour/location_ui.cc:55
+msgid "Hidden"
+msgstr "Caché"
+
+#: gtk_ardour/location_ui.cc:57
+msgid "SCMS"
+msgstr "SCMS"
+
+#: gtk_ardour/location_ui.cc:58
+msgid "Pre-Emphasis"
+msgstr "Pré-emphase"
+
+#: gtk_ardour/location_ui.cc:592
+msgid "Add New Location"
+msgstr "Ajouter un nouvel emplacement"
+
+#: gtk_ardour/location_ui.cc:593
+msgid "Add New Range"
+msgstr "Ajouter un nouvel intervalle"
+
+#: gtk_ardour/location_ui.cc:597
+msgid "ardour: locations"
+msgstr "ardour : emplacements"
+
+#: gtk_ardour/location_ui.cc:598
+msgid "ardour_locations"
+msgstr "ardour_emplacements"
+
+#: gtk_ardour/location_ui.cc:629
+#, fuzzy
+msgid "Location (CD Index) Markers"
+msgstr "Marqueurs d'emplacements (Index de CD)"
+
+#: gtk_ardour/location_ui.cc:649
+#, fuzzy
+msgid "Range (CD Track) Markers"
+msgstr "Marqueurs d'intervalles (Piste de CD)"
+
+#: gtk_ardour/location_ui.cc:814
+msgid "add range marker"
+msgstr "ajouter marqueur d'intervalle"
+
+#: gtk_ardour/main.cc:76
+msgid "ardour is killing itself for a clean exit\n"
+msgstr "ardour se termine lui-même pour une sortie propre\n"
+
+#: gtk_ardour/main.cc:85
+msgid "stopping user interface\n"
+msgstr "en train d'arrêter l'interface utilisateur\n"
+
+#: gtk_ardour/main.cc:104
+#, c-format
+msgid "%d(%d): received signal %d\n"
+msgstr "%d(%d) : reçu le signal %d\n"
+
+#: gtk_ardour/main.cc:190
+msgid "cannot become new process group leader (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:217
+msgid "cannot setup signal handling for %1"
+msgstr "impossible d'installer le gestionnaire de signaux pour %1"
+
+#: gtk_ardour/main.cc:228
+msgid "cannot set default signal mask (%1)"
+msgstr "impossible de définir le masque de signalisation"
+
+#: gtk_ardour/main.cc:253
+msgid ""
+"Without a UI style file, ardour will look strange.\n"
+" Please set ARDOUR_UI_RC to point to a valid UI style file"
+msgstr ""
+"Sans un fichier de style pour son IHM, ardour aura une apparence bizarre.\n"
+"Veuillez faire pointer ARDOUR_UI_RC vers un fichier de style d'IHM valide"
+
+#: gtk_ardour/main.cc:292
+msgid ""
+"Ardour could not connect to JACK.\n"
+"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 ""
+"Ardour n'a pas pu se connecter à JACK.\n"
+"Il y a plusieurs raisons possibles :\n"
+"\n"
+"1) JACK n'est pas lancé.\n"
+"2) JACK tourne sous un autre utilisateur, peut-être root.\n"
+"3) Il y a un autre client appelé \"ardour\".\n"
+"\n"
+"Veuillez étudier les possibilités, et peut-être (re)lancer JACK."
+
+#: gtk_ardour/main.cc:305
+msgid "ardour: unplugged"
+msgstr "ardour : déconnecté"
+
+#: gtk_ardour/main.cc:363
+msgid "Ardour/GTK "
+msgstr "Ardour/GTK"
+
+#: gtk_ardour/main.cc:365
+msgid ""
+"\n"
+" (built using "
+msgstr ""
+"\n"
+" (fonctionnant avec "
+
+#: gtk_ardour/main.cc:369
+msgid " with libardour "
+msgstr " avec libardour "
+
+#: gtk_ardour/main.cc:374
+msgid " and GCC version "
+msgstr ""
+
+#: gtk_ardour/main.cc:384
+msgid "Copyright (C) 1999-2005 Paul Davis"
+msgstr "Copyright (C) 1999-2005 Paul Davis"
+
+#: gtk_ardour/main.cc:385
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+msgstr ""
+"Certaines parties Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+
+#: gtk_ardour/main.cc:387
+msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
+msgstr "Ardour est distribué sans AUCUNE GARANTIE"
+
+#: gtk_ardour/main.cc:388
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr "ni même pour la COMMERCIALISATION ou pour UN BUT PARTICULIER."
+
+#: gtk_ardour/main.cc:389
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr "Ceci est un logiciel libre, et vous êtes encouragé à le distribuer "
+
+#: gtk_ardour/main.cc:390
+msgid "under certain conditions; see the source for copying conditions."
+msgstr ""
+"sous certaines conditions ; voir le fichier source pour les conditions de "
+"distribution."
+
+#: gtk_ardour/main.cc:399
+msgid "could not create ARDOUR GUI"
+msgstr "impossible de créer l'interface utilisateur d'ARDOUR"
+
+#: gtk_ardour/main.cc:419
+msgid "Could not connect to JACK server as \"%1\""
+msgstr "Impossible de se connecter au serveur JACK en tant que \"%1\""
+
+#: gtk_ardour/main.cc:424
+msgid "could not initialize Ardour."
+msgstr "impossible d'initialiser Ardour."
+
+#: gtk_ardour/main.cc:435
+msgid "could not load command line session \"%1\""
+msgstr "impossible de charger la session indiqué en ligne de commande \"%1\""
+
+#: gtk_ardour/main.cc:455
+msgid ""
+"\n"
+"\n"
+"A session named \"%1\" already exists.\n"
+"To avoid this message, start ardour as \"ardour %1"
+msgstr ""
+"\n"
+"\n"
+"Une session nommé \"%1\" existe déjà.\n"
+"Pour éviter ce message, lancez ardour comme cela : \"ardour %1"
+
+#: gtk_ardour/main.cc:466
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as \"ardour --new %1"
+msgstr ""
+"\n"
+"\n"
+"Aucune session nommée \"%1\" n'existe.\n"
+"Pour la créer depuis la ligne de commande, lancez ardour comme cela : "
+"\"ardour --new %1"
+
+#: gtk_ardour/marker.cc:354
+#, fuzzy
+msgid "MarkerText"
+msgstr "Marqueur"
+
+#: gtk_ardour/marker_time_axis.cc:271
+msgid "Remove Marker"
+msgstr "Enlever les marqueurs"
+
+#: gtk_ardour/marker_time_axis.cc:273
+msgid "Marker"
+msgstr "Marqueur"
+
+#: gtk_ardour/meter_bridge.cc:74
+msgid "ardour: meter bridge"
+msgstr "ardour : bandeau de vu-mètre"
+
+#: gtk_ardour/meter_bridge.cc:75
+msgid "ardour_meter_bridge"
+msgstr "ardour_bandeau_vu-mètre"
+
+#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93
+#, c-format
+msgid "# of %u-sample overs"
+msgstr "# de %u-échantillons en dépassement"
+
+#: gtk_ardour/meter_bridge_strip.cc:219
+#, fuzzy
+msgid "New name for meter:"
+msgstr "Nouveau nom du vu-mètre :"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507
+#: gtk_ardour/region_editor.cc:45
+msgid "mute"
+msgstr "muet"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508
+msgid "solo"
+msgstr "solo"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506
+msgid "RECORD"
+msgstr "ENREGISTRER"
+
+#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514
+msgid "polarity"
+msgstr "polarité"
+
+#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509
+msgid "comments"
+msgstr "commentaires"
+
+#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810
+msgid "INPUT"
+msgstr "ENTRÉE"
+
+#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831
+msgid "OUTPUT"
+msgstr "SORTIE"
+
+#: gtk_ardour/mixer_strip.cc:173
+msgid "Pan automation mode"
+msgstr "Mode d'automatisation de panoramique"
+
+#: gtk_ardour/mixer_strip.cc:174
+msgid "Gain automation mode"
+msgstr "Mode d'automatisation du gain"
+
+#: gtk_ardour/mixer_strip.cc:176
+msgid "Pan automation type"
+msgstr "Type d'automatisation de panoramique"
+
+#: gtk_ardour/mixer_strip.cc:177
+msgid "Gain automation type"
+msgstr "dessiner l'automatisation du gain"
+
+#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232
+#: gtk_ardour/mixer_strip.cc:979
+msgid "trim"
+msgstr "élaguer"
+
+#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233
+#: gtk_ardour/mixer_strip.cc:983
+msgid "abs"
+msgstr "abs"
+
+#: gtk_ardour/mixer_strip.cc:240
+msgid "gain automation mode"
+msgstr "mode d'automatisation du gain"
+
+#: gtk_ardour/mixer_strip.cc:241
+msgid "pan automation mode"
+msgstr "mode d'automatisation de panoramique"
+
+#: gtk_ardour/mixer_strip.cc:242
+msgid "gain automation state"
+msgstr "état de l'automatisation du gain"
+
+#: gtk_ardour/mixer_strip.cc:243
+msgid "pan automation state"
+msgstr "état de l'automatisation de panoramique"
+
+#: gtk_ardour/mixer_strip.cc:259
+msgid "varispeed"
+msgstr "varispeed"
+
+#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174
+msgid "click to add/edit comments"
+msgstr "cliquer pour ajouter/éditer des commentaires"
+
+#: gtk_ardour/mixer_strip.cc:463
+msgid "unknown strip width \"%1\" in XML GUI information"
+msgstr ""
+"largeur de tranche inconnue \"%1\" dans les données XML de l'interface "
+"utilisateur"
+
+#: gtk_ardour/mixer_strip.cc:522
+msgid "REC"
+msgstr "ENR."
+
+#: gtk_ardour/mixer_strip.cc:525
+#, fuzzy
+msgid "cmt"
+msgstr "cmt"
+
+#: gtk_ardour/mixer_strip.cc:530
+msgid "pol"
+msgstr "pol"
+
+#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620
+#: gtk_ardour/redirect_box.cc:1180
+msgid "Not connected to JACK - no I/O changes are possible"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667
+msgid "could not register new ports required for that connection"
+msgstr "impossible de définir les nouveaux ports requis pour cette connexion"
+
+#: gtk_ardour/mixer_strip.cc:813
+msgid "IN"
+msgstr "ENTRÉE"
+
+#: gtk_ardour/mixer_strip.cc:834
+msgid "OUT"
+msgstr "SORTIE"
+
+#: gtk_ardour/mixer_strip.cc:950
+#, fuzzy
+msgid "aplay"
+msgstr "aplay"
+
+#: gtk_ardour/mixer_strip.cc:956
+#, fuzzy
+msgid "awrite"
+msgstr "awrite"
+
+#: gtk_ardour/mixer_strip.cc:1134
+msgid ": comment editor"
+msgstr ": éditeur de commentaires"
+
+#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224
+msgid "no group"
+msgstr "aucun groupe"
+
+#: gtk_ardour/mixer_strip.cc:1227
+msgid "~G"
+msgstr "~G"
+
+#: gtk_ardour/mixer_ui.cc:52
+msgid "Strips"
+msgstr "Tranches"
+
+#: gtk_ardour/mixer_ui.cc:56
+msgid "Snapshots"
+msgstr "Instantanés"
+
+#: gtk_ardour/mixer_ui.cc:61
+msgid "***"
+msgstr "***"
+
+#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17
+#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144
+#: gtk_ardour/tempo_dialog.cc:162
+msgid "Bar"
+msgstr "Mesure"
+
+#: gtk_ardour/mixer_ui.cc:121
+msgid "Mix Groups"
+msgstr "Groupes de mixage"
+
+#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373
+msgid "ardour: mixer"
+msgstr "ardour : console de mixage"
+
+#: gtk_ardour/mixer_ui.cc:192
+msgid "ardour_mixer"
+msgstr "ardour_console_de_mixage"
+
+#: gtk_ardour/mixer_ui.cc:342
+msgid "ardour: mixer: "
+msgstr "ardour : console de mixage :"
+
+#: gtk_ardour/mixer_ui.cc:641
+msgid "signal"
+msgstr "signal"
+
+#: gtk_ardour/mixer_ui.cc:672
+msgid "Show All AudioTrack MixerStrips"
+msgstr "Montrer toutes les tranches de mixage de piste audio"
+
+#: gtk_ardour/mixer_ui.cc:673
+msgid "Hide All AudioTrack MixerStrips"
+msgstr "Cacher toutes les tranches de mixage de piste audio"
+
+#: gtk_ardour/mixer_ui.cc:674
+msgid "Show All AudioBus MixerStrips"
+msgstr "Montrer toutes les tranches de mixage de bus audio"
+
+#: gtk_ardour/mixer_ui.cc:675
+msgid "Hide All AudioBus MixerStrips"
+msgstr "Cacher toutes les tranches de mixage de bus audio"
+
+#: gtk_ardour/mixer_ui.cc:687
+msgid "track display list item for renamed strip not found!"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:700
+msgid "Name for new mix group"
+msgstr "Nom pour le nouveau groupe de mixage"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Session name:"
+msgstr "Nom de la session :"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Create"
+msgstr "Créer"
+
+#: gtk_ardour/new_session_dialog.cc:40
+#, fuzzy
+msgid "use control outs"
+msgstr "utiliser les sorties de contrôle"
+
+#: gtk_ardour/new_session_dialog.cc:41
+msgid "use master outs"
+msgstr "utiliser les sorties maître"
+
+#: gtk_ardour/new_session_dialog.cc:42
+msgid "automatically connect track inputs to physical ports"
+msgstr "connecter les entrées de piste aux ports physiques automatiquement"
+
+#: gtk_ardour/new_session_dialog.cc:43
+msgid "automatically connect track outputs to master outs"
+msgstr "connecter les sorties de piste aux sorties maître automatiquement"
+
+#: gtk_ardour/new_session_dialog.cc:44
+msgid "automatically connect track outputs to physical ports"
+msgstr "connecter les sorties de piste aux ports physiques automatiquement"
+
+#: gtk_ardour/new_session_dialog.cc:45
+msgid "manually connect track outputs"
+msgstr "connecter les sorties de piste manuellement"
+
+#: gtk_ardour/new_session_dialog.cc:50
+msgid "Advanced..."
+msgstr "Avancé..."
+
+#: gtk_ardour/new_session_dialog.cc:52
+msgid "show again"
+msgstr "montrer à nouveau"
+
+#: gtk_ardour/new_session_dialog.cc:55
+msgid "Hardware Inputs: use"
+msgstr "Entrées matérielles : utiliser"
+
+#: gtk_ardour/new_session_dialog.cc:56
+msgid "Hardware Outputs: use"
+msgstr "Sorties matérielles : utiliser"
+
+#: gtk_ardour/new_session_dialog.cc:62
+msgid "new session setup"
+msgstr "nouveau paramétrage de session"
+
+#: gtk_ardour/new_session_dialog.cc:63
+msgid "ardour_new_session"
+msgstr "ardour_nouvelle_session"
+
+#: gtk_ardour/new_session_dialog.cc:72
+msgid "This session will playback and record at %1 Hz"
+msgstr "Cette session sera lue et enregistrée à %1 Hz"
+
+#: gtk_ardour/new_session_dialog.cc:74
+msgid ""
+"This rate is set by JACK and cannot be changed.\n"
+"If you want to use a different sample rate\n"
+"please exit and restart JACK"
+msgstr ""
+"Cette fréquence est fixée par JACK et ne peut pas être changée.\n"
+"Si vous voulez utiliser une autre fréquence d'échantillonage\n"
+"veuillez arrêter puis relancer JACK"
+
+#: gtk_ardour/new_session_dialog.cc:155
+msgid "Session template"
+msgstr "Modèle de session"
+
+#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20
+#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146
+#: gtk_ardour/tempo_dialog.cc:164
+msgid "Location"
+msgstr "Emplacement"
+
+#: gtk_ardour/new_session_dialog.cc:178
+msgid "Configuration"
+msgstr "Configuration"
+
+#: gtk_ardour/new_session_dialog.cc:269
+msgid "blank"
+msgstr "vide"
+
+#: gtk_ardour/new_session_dialog.cc:328
+msgid "No template - create tracks/busses manually"
+msgstr "Pas de modèle -- créez les pistes/bus manuellement"
+
+#: gtk_ardour/new_session_dialog.cc:337
+msgid "No template"
+msgstr "Pas de modèle"
+
+#: gtk_ardour/option_editor.cc:48
+msgid "Internal"
+msgstr "Interne"
+
+#: gtk_ardour/option_editor.cc:49
+msgid "Slave to MTC"
+msgstr "Esclave du MTC"
+
+#: gtk_ardour/option_editor.cc:50
+msgid "Sync with JACK"
+msgstr "Synchro. avec JACK"
+
+#: gtk_ardour/option_editor.cc:51
+msgid "never used but stops crashes"
+msgstr "jamais utilisé mais arrête les plantages"
+
+#: gtk_ardour/option_editor.cc:56
+msgid "Later regions are higher"
+msgstr "Les dernières régions sont placées au-dessus"
+
+#: gtk_ardour/option_editor.cc:57
+msgid "Most recently added/moved/trimmed regions are higher"
+msgstr ""
+"Les régions ajoutées/déplacées/élaguées en dernier sont placées au-dessus"
+
+#: gtk_ardour/option_editor.cc:58
+#, fuzzy
+msgid "Most recently added regions are higher"
+msgstr ""
+"Les régions ajoutées/déplacées/élaguées en dernier sont placées au-dessus"
+
+#: gtk_ardour/option_editor.cc:63
+#, fuzzy
+msgid "Span entire region overlap"
+msgstr "Mesurer le recouvrement de régions en entier"
+
+#: gtk_ardour/option_editor.cc:64
+msgid "Short fades at the start of the overlap"
+msgstr "Fondus courts en début de recouvrement"
+
+#: gtk_ardour/option_editor.cc:82
+msgid "Automatically create crossfades"
+msgstr "Créer des fondus enchaînés automatiquement"
+
+#: gtk_ardour/option_editor.cc:83
+msgid "New full-overlap crossfades are unmuted"
+msgstr ""
+"Les nouveaux fondus enchaînés avec recouvrement complet ne sont pas muets"
+
+#: gtk_ardour/option_editor.cc:84
+msgid "Region layering mode"
+msgstr "Mode de superposition des régions"
+
+#: gtk_ardour/option_editor.cc:85
+msgid "Crossfade model"
+msgstr "Modèle de fondu enchaîné"
+
+#: gtk_ardour/option_editor.cc:90
+#, fuzzy
+msgid "Latched solo"
+msgstr "Solo collé"
+
+#: gtk_ardour/option_editor.cc:91
+msgid "Solo via bus"
+msgstr "Solo via le bus"
+
+#: gtk_ardour/option_editor.cc:96
+msgid "Show waveforms while recording"
+msgstr "Montrer les formes d'onde pendant l'enregistrement"
+
+#: gtk_ardour/option_editor.cc:97
+msgid "Narrow mixer strips"
+msgstr "Rétrécir les tranches de mixage"
+
+#: gtk_ardour/option_editor.cc:98
+msgid "Show measure lines"
+msgstr "Montrer les barres de mesures"
+
+#: gtk_ardour/option_editor.cc:99
+msgid "Follow playhead"
+msgstr "Suivre la tête de lecture"
+
+#: gtk_ardour/option_editor.cc:103
+msgid "Send MTC"
+msgstr "Envoyer MTC"
+
+#: gtk_ardour/option_editor.cc:104
+msgid "Send MMC"
+msgstr "Envoyer MMC"
+
+#: gtk_ardour/option_editor.cc:105
+msgid "JACK time master"
+msgstr "JACK horloge maître"
+
+#: gtk_ardour/option_editor.cc:107
+#, fuzzy
+msgid "SMPTE offset is negative"
+msgstr "Décalage SMPTE"
+
+#: gtk_ardour/option_editor.cc:111
+#, fuzzy
+msgid "Send MIDI parameter feedback"
+msgstr "Envoyer le retour de paramètre MIDI"
+
+#: gtk_ardour/option_editor.cc:112
+#, fuzzy
+msgid "MIDI parameter control"
+msgstr "Recevoir le contrôle de paramètre MIDI"
+
+#: gtk_ardour/option_editor.cc:113
+#, fuzzy
+msgid "MMC control"
+msgstr "Port MMC"
+
+#: gtk_ardour/option_editor.cc:131
+#, fuzzy
+msgid "Auto-connect new track inputs to hardware"
+msgstr "Auto-connexion des nouvelles pistes"
+
+#: gtk_ardour/option_editor.cc:132
+#, fuzzy
+msgid "Auto-connect new track outputs to hardware"
+msgstr "Auto-connexion des nouvelles pistes"
+
+#: gtk_ardour/option_editor.cc:133
+#, fuzzy
+msgid "Auto-connect new track outputs to master bus"
+msgstr "connecter les sorties de piste aux sorties maître automatiquement"
+
+#: gtk_ardour/option_editor.cc:134
+#, fuzzy
+msgid "Manually connect new track outputs"
+msgstr "connecter les sorties de piste manuellement"
+
+#: gtk_ardour/option_editor.cc:135
+msgid "Use Hardware Monitoring"
+msgstr "Utiliser la pré-écoute matérielle"
+
+#: gtk_ardour/option_editor.cc:136
+msgid "Use Software Monitoring"
+msgstr "Utiliser la pré-écoute logicielle"
+
+#: gtk_ardour/option_editor.cc:137
+msgid "Stop plugins with transport"
+msgstr "Arrêter les greffons avec le transport"
+
+#: gtk_ardour/option_editor.cc:138
+msgid "Run plugins while recording"
+msgstr "Activer les greffons durant l'enregistrement"
+
+#: gtk_ardour/option_editor.cc:139
+#, fuzzy
+msgid "Verify remove last capture"
+msgstr "Enlever la dernière capture"
+
+#: gtk_ardour/option_editor.cc:140
+msgid "Stop recording on xrun"
+msgstr "Arrêter l'enregistrement en cas de xrun"
+
+#: gtk_ardour/option_editor.cc:141
+msgid "Stop transport at end of session"
+msgstr "Arrêter le transport à la fin de la session"
+
+#: gtk_ardour/option_editor.cc:142
+msgid "Debug keyboard events"
+msgstr "Déboguer les évènements clavier"
+
+#: gtk_ardour/option_editor.cc:143
+msgid "-12dB gain reduction for ffwd/rew"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:152
+msgid "ardour: options editor"
+msgstr "ardour : éditeur d'options"
+
+#: gtk_ardour/option_editor.cc:153
+msgid "ardour_option_editor"
+msgstr "ardour_éditeur_d_options"
+
+#: gtk_ardour/option_editor.cc:183
+msgid "Misc"
+msgstr "Divers"
+
+#: gtk_ardour/option_editor.cc:184
+msgid "Sync"
+msgstr "Synchro."
+
+#: gtk_ardour/option_editor.cc:185
+msgid "Paths/Files"
+msgstr "Chemins/Fichiers"
+
+#: gtk_ardour/option_editor.cc:186
+msgid "Display"
+msgstr "Affichage"
+
+#: gtk_ardour/option_editor.cc:187
+msgid "Kbd/Mouse"
+msgstr "Clavier/Souris"
+
+#: gtk_ardour/option_editor.cc:188
+msgid "Click"
+msgstr "Clic"
+
+#: gtk_ardour/option_editor.cc:190
+msgid "Layers & Fades"
+msgstr "Couches & fondus"
+
+#: gtk_ardour/option_editor.cc:195
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gtk_ardour/option_editor.cc:268
+msgid "24 FPS"
+msgstr "24 TPS"
+
+#: gtk_ardour/option_editor.cc:270
+#, fuzzy
+msgid "25 FPS"
+msgstr "25 TPS"
+
+#: gtk_ardour/option_editor.cc:272
+#, fuzzy
+msgid "30 FPS"
+msgstr "30 TPS drop"
+
+#: gtk_ardour/option_editor.cc:278
+#, fuzzy
+msgid "30 FPS drop"
+msgstr "30 TPS drop"
+
+#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379
+#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736
+#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800
+msgid "Medium"
+msgstr "Moyen"
+
+#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738
+#: gtk_ardour/option_editor.cc:804
+msgid "Faster"
+msgstr "Plus rapide"
+
+#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714
+#: gtk_ardour/option_editor.cc:776
+msgid "Short"
+msgstr "Court"
+
+#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716
+#: gtk_ardour/option_editor.cc:780
+msgid "Long"
+msgstr "Long"
+
+#: gtk_ardour/option_editor.cc:396
+msgid "Broadcast WAVE/floating point"
+msgstr "Broadcast WAVE/virgule flottante"
+
+#: gtk_ardour/option_editor.cc:397
+msgid "WAVE/floating point"
+msgstr "WAVE/virgule flottante"
+
+#: gtk_ardour/option_editor.cc:417
+msgid "session RAID path"
+msgstr "chemin de session RAID"
+
+#: gtk_ardour/option_editor.cc:422
+msgid "Native Format"
+msgstr "Format natif"
+
+#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460
+#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409
+msgid "internal"
+msgstr "interne"
+
+#: gtk_ardour/option_editor.cc:537
+msgid "Short crossfade length (msecs)"
+msgstr "fondu enchaîné court (ms)"
+
+#: gtk_ardour/option_editor.cc:710
+msgid "Meter Peak Hold"
+msgstr "Maintien du pic de vu-mètre"
+
+#: gtk_ardour/option_editor.cc:730
+msgid "Meter Falloff"
+msgstr "Temps de chute du vu-mètre"
+
+#: gtk_ardour/option_editor.cc:847
+msgid "Positional Sync"
+msgstr "Synchro. positionelle"
+
+#: gtk_ardour/option_editor.cc:902
+msgid "SMPTE Frames/second"
+msgstr "Trames SMPTE/seconde"
+
+#: gtk_ardour/option_editor.cc:903
+msgid "SMPTE Offset"
+msgstr "Décalage SMPTE"
+
+#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013
+#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211
+#, fuzzy
+msgid "online"
+msgstr "linéaire"
+
+#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014
+#: gtk_ardour/option_editor.cc:1208
+#, fuzzy
+msgid "offline"
+msgstr "linéaire"
+
+#: gtk_ardour/option_editor.cc:1319
+msgid "Use as click"
+msgstr "Utiliser comme clic"
+
+#: gtk_ardour/option_editor.cc:1344
+msgid "Use as click emphasis"
+msgstr "Utiliser comme emphase de clic"
+
+#: gtk_ardour/option_editor.cc:1478
+msgid "--unknown--"
+msgstr "--inconnu--"
+
+#: gtk_ardour/option_editor.cc:1595
+msgid "Click audio file"
+msgstr "Fichier audio de clic"
+
+#: gtk_ardour/option_editor.cc:1601
+msgid "Click emphasis audiofile"
+msgstr "Fichier audio d'emphase de clic"
+
+#: gtk_ardour/option_editor.cc:1638
+msgid ""
+"The auditioner is a dedicated mixer strip used\n"
+"for listening to specific regions outside the context\n"
+"of the overall mix. It can be connected just like any\n"
+"other mixer strip."
+msgstr ""
+"L'auditioneur est une tranche de mixage dédiée utilisée\n"
+"pour écouter des régions spécifiques en dehors du contexte\n"
+"du mixage global. Il peut être connecté tout comme n'importe\n"
+"quelle autre tranche de mixage."
+
+#: gtk_ardour/option_editor.cc:1887
+msgid "Edit using"
+msgstr "Édition en utilisant"
+
+#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924
+msgid "+ button"
+msgstr "touche +"
+
+#: gtk_ardour/option_editor.cc:1917
+msgid "Delete using"
+msgstr "Effacer en utilisant"
+
+#: gtk_ardour/option_editor.cc:1947
+msgid "Ignore snap using"
+msgstr "Ignorer clac en utilisant"
+
+#: gtk_ardour/opts.cc:46
+msgid "Usage: "
+msgstr "Usage :"
+
+#: gtk_ardour/opts.cc:47
+msgid " -v, --version Show version information\n"
+msgstr ""
+" -v, --version Montre les informations de version\n"
+
+#: gtk_ardour/opts.cc:48
+msgid " -h, --help Print this message\n"
+msgstr " -h, --help Affiche ce message\n"
+
+#: gtk_ardour/opts.cc:49
+msgid ""
+" -b, --bindings Print all possible keyboard binding "
+"names\n"
+msgstr ""
+" -b, --bindings Affiche tous raccourcis clavier "
+"possibles\n"
+
+#: gtk_ardour/opts.cc:50
+msgid " -n, --show-splash Show splash screen\n"
+msgstr " -n, --show-splash Afficher l'écran de démarrage\n"
+
+#: gtk_ardour/opts.cc:51
+msgid ""
+" -c, --name name Use a specific jack client name, default "
+"is ardour\n"
+msgstr ""
+" -c, --name nom Utiliser un nom de client jack "
+"spécifique, la valeur par défaut est ardour\n"
+
+#: gtk_ardour/opts.cc:52
+msgid ""
+" -N, --new session-name Create a new session from the command "
+"line\n"
+msgstr " -N, --new nom-de-session Nom de la session à charger\n"
+
+#: gtk_ardour/opts.cc:53
+msgid ""
+" -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:55
+msgid " -V, --novst Do not use VST support\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:57
+msgid " [session-name] Name of session to load\n"
+msgstr " [nom-de-session] Nom de la session à charger\n"
+
+#: gtk_ardour/opts.cc:58
+msgid " -C, --curvetest filename Curve algorithm debugger\n"
+msgstr ""
+" -C, --curvetest nom-de-fichier Débogueur d'algorithme de courbe\n"
+
+#: gtk_ardour/pan_automation_time_axis.cc:58
+msgid "You can't graphically edit panning of more than stream"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:78
+#, fuzzy
+msgid "add pan automation event"
+msgstr "ajouter les évènements d'automatisation à "
+
+#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441
+msgid "Bypass"
+msgstr "Bypass"
+
+#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222
+#, fuzzy
+msgid "link"
+msgstr "entrée"
+
+#: gtk_ardour/panner_ui.cc:103
+msgid "panning link control"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:105
+msgid "panning link direction"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:232
+msgid "L"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:344
+#, c-format
+msgid "panner for channel %u"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:451
+#, fuzzy
+msgid "Reset all"
+msgstr "Réinitialiser"
+
+#: gtk_ardour/playlist_selector.cc:46
+msgid "Playlists grouped by track"
+msgstr ""
+
+#: gtk_ardour/playlist_selector.cc:53
+#, fuzzy
+msgid "close"
+msgstr "Fermer"
+
+#: gtk_ardour/playlist_selector.cc:59
+#, fuzzy
+msgid "ardour: playlists"
+msgstr "ardour : greffons"
+
+#: gtk_ardour/playlist_selector.cc:104
+#, fuzzy
+msgid "ardour: playlist for "
+msgstr "ardour : éditeur : "
+
+#: gtk_ardour/playlist_selector.cc:122
+#, fuzzy
+msgid "Other tracks"
+msgstr "décaler la piste"
+
+#: gtk_ardour/playlist_selector.cc:138
+msgid "unassigned"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:41
+msgid "Available LADSPA plugins"
+msgstr "Greffons LADSPA disponibles"
+
+#: gtk_ardour/plugin_selector.cc:42
+msgid "Type"
+msgstr "Type"
+
+#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51
+msgid "# Inputs"
+msgstr "# entrées"
+
+#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52
+msgid "# Outputs"
+msgstr "# sorties"
+
+#: gtk_ardour/plugin_selector.cc:50
+msgid "Available VST plugins"
+msgstr "Greffons VST disponibles"
+
+#: gtk_ardour/plugin_selector.cc:58
+msgid "To be added"
+msgstr "À ajouter"
+
+#: gtk_ardour/plugin_selector.cc:72
+msgid "ardour: plugins"
+msgstr "ardour : greffons"
+
+#: gtk_ardour/plugin_selector.cc:82
+msgid "Add a plugin to the effect list"
+msgstr "Ajouter un greffon à la liste d'effets"
+
+#: gtk_ardour/plugin_selector.cc:84
+msgid "Remove a plugin from the effect list"
+msgstr "Retirer un greffon à la liste d'effets"
+
+#: gtk_ardour/plugin_selector.cc:88
+msgid "Update"
+msgstr "Rafraîchir"
+
+#: gtk_ardour/plugin_selector.cc:89
+msgid "Update available plugins"
+msgstr "Rafraîchir les greffons disponibles"
+
+#: gtk_ardour/plugin_selector.cc:110
+msgid "LADSPA"
+msgstr "LADSPA"
+
+#: gtk_ardour/plugin_selector.cc:113
+msgid "VST"
+msgstr "VST"
+
+#: gtk_ardour/plugin_ui.cc:83
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this "
+"version of ardour)"
+msgstr ""
+"type de greffon éditeur inconnu (note : pas de support VST dans cette "
+"version d'ardour)"
+
+#: gtk_ardour/plugin_ui.cc:269
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr ""
+"Éditeur de greffon : impossible de construire l'élément de contrôle pour le "
+"port %1"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "in"
+msgstr "entrée"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "ins"
+msgstr "entrées"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "out"
+msgstr "sortie"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "outs"
+msgstr "sorties"
+
+#: gtk_ardour/plugin_ui.cc:382
+msgid "automation control"
+msgstr "contrôle d'automatisation"
+
+#: gtk_ardour/plugin_ui.cc:869
+msgid "save"
+msgstr "enregistrer"
+
+#: gtk_ardour/plugin_ui.cc:870
+msgid "bypass"
+msgstr "bypass"
+
+#: gtk_ardour/plugin_ui.cc:892
+#, fuzzy
+msgid "Plugin preset %1 not found"
+msgstr "Pré-réglage de greffon %1 non trouvé"
+
+#: gtk_ardour/plugin_ui.cc:903
+msgid "Name for plugin settings:"
+msgstr "Nom pour les paramètres du greffon :"
+
+#: gtk_ardour/redirect_automation_line.cc:53
+msgid "redirect automation created for non-plugin"
+msgstr "rediriger l'automatisation créée pour le non-greffon"
+
+#: gtk_ardour/redirect_automation_time_axis.cc:92
+msgid "add automation event to "
+msgstr "ajouter les évènements d'automatisation à "
+
+#: gtk_ardour/redirect_box.cc:213
+msgid "New send"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:214
+#, fuzzy
+msgid "Show send controls"
+msgstr "Contrôle de la vitesse avec molette"
+
+#: gtk_ardour/redirect_box.cc:360
+msgid "New Plugin ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:361
+#, fuzzy
+msgid "New Insert"
+msgstr "Nouvelle entrée"
+
+#: gtk_ardour/redirect_box.cc:362
+msgid "New Send ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:380
+#, fuzzy
+msgid "Select all"
+msgstr "Tout sélectionner"
+
+#: gtk_ardour/redirect_box.cc:381
+#, fuzzy
+msgid "Deselect all"
+msgstr "Tout sélectionner"
+
+#: gtk_ardour/redirect_box.cc:389
+#, fuzzy
+msgid "Inserts"
+msgstr "Inverser"
+
+#: gtk_ardour/redirect_box.cc:390
+#, fuzzy
+msgid "Sends"
+msgstr "Secondes"
+
+#: gtk_ardour/redirect_box.cc:393
+#, fuzzy
+msgid "Select all ..."
+msgstr "Tout sélectionner"
+
+#: gtk_ardour/redirect_box.cc:406
+#, fuzzy
+msgid "Activate All"
+msgstr "Activer"
+
+#: gtk_ardour/redirect_box.cc:407
+#, fuzzy
+msgid "Deactivate All"
+msgstr "Désactiver"
+
+#: gtk_ardour/redirect_box.cc:488
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:500
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:513
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:616
+msgid "Pre-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:619
+msgid "Post-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:781
+msgid ""
+"You cannot reorder this set of redirects\n"
+"in that way because the inputs and\n"
+"outputs do not work correctly."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:903
+#, fuzzy
+msgid "ardour: rename redirect"
+msgstr "ardour : renommer la région"
+
+#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043
+msgid ""
+"Copying the set of redirects on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:1064
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this track?\n"
+"(this cannot be undone)"
+msgstr ""
+"Voulez-vous vraiment supprimer la piste \"%1\" ?\n"
+"(cela ne pourra pas être annulé)"
+
+#: gtk_ardour/redirect_box.cc:1067
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this bus?\n"
+"(this cannot be undone)"
+msgstr ""
+"Voulez-vous vraiment supprimer la piste \"%1\" ?\n"
+"(cela ne pourra pas être annulé)"
+
+#: gtk_ardour/redirect_box.cc:1071
+#, fuzzy
+msgid "Yes, remove them all"
+msgstr "Oui, le supprimer."
+
+#: gtk_ardour/redirect_box.cc:1114
+#, fuzzy
+msgid "ardour: %1"
+msgstr "ardour :"
+
+#: gtk_ardour/redirect_box.cc:1156
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "ardour :"
+
+#: gtk_ardour/region_editor.cc:43
+msgid "NAME:"
+msgstr "NOM :"
+
+#: gtk_ardour/region_editor.cc:44
+msgid "lock"
+msgstr "verrouiller"
+
+#: gtk_ardour/region_editor.cc:46
+msgid "opaque"
+msgstr "opaque"
+
+#: gtk_ardour/region_editor.cc:49
+msgid "Layer"
+msgstr "Couche"
+
+#: gtk_ardour/region_editor.cc:57
+msgid "ENVELOPE"
+msgstr "ENVELOPPE"
+
+#: gtk_ardour/region_editor.cc:108
+msgid "mute this region"
+msgstr "Assourdir cette région"
+
+#: gtk_ardour/region_editor.cc:109
+msgid "regions underneath this one cannot be heard"
+msgstr "les régions en dessous de celle-ci ne peuvent être entendues"
+
+#: gtk_ardour/region_editor.cc:110
+msgid "prevent any changes to this region"
+msgstr "empêche toute modification de cette région"
+
+#: gtk_ardour/region_editor.cc:111
+msgid "use the gain envelope during playback"
+msgstr "utiliser l'enveloppe de gain pendant la lecture"
+
+#: gtk_ardour/region_editor.cc:112
+msgid "show the gain envelope"
+msgstr "montrer l'enveloppe de gain"
+
+#: gtk_ardour/region_editor.cc:113
+msgid "use fade in curve during playback"
+msgstr "utiliser une courbe de fondu d'ouverture durant la lecture"
+
+#: gtk_ardour/region_editor.cc:114
+msgid "use fade out curve during playback"
+msgstr "utiliser une courbe de fondu de fermeture durant la lecture"
+
+#: gtk_ardour/region_editor.cc:115
+msgid "audition this region"
+msgstr "écouter cette région"
+
+#: gtk_ardour/region_editor.cc:148
+msgid "START:"
+msgstr "DÉBUT :"
+
+#: gtk_ardour/region_editor.cc:150
+msgid "END:"
+msgstr "FIN :"
+
+#: gtk_ardour/region_editor.cc:152
+msgid "LENGTH:"
+msgstr "LONGUEUR :"
+
+#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198
+#: gtk_ardour/region_editor.cc:234
+msgid "active"
+msgstr "actif"
+
+#: gtk_ardour/region_editor.cc:179
+msgid "visible"
+msgstr "visible"
+
+#: gtk_ardour/region_editor.cc:197
+msgid "FADE IN"
+msgstr "FONDU D'OUVERTURE"
+
+#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235
+msgid "msecs"
+msgstr "ms"
+
+#: gtk_ardour/region_editor.cc:233
+msgid "FADE OUT"
+msgstr "FONDU DE FERMETURE"
+
+#: gtk_ardour/region_editor.cc:276
+msgid "ardour: region "
+msgstr "ardour : région "
+
+#: gtk_ardour/region_editor.cc:410
+msgid "fade in edit"
+msgstr "édition de fondu d'ouverture"
+
+#: gtk_ardour/region_editor.cc:422
+msgid "fade out edit"
+msgstr "édition de fondu de fermeture"
+
+#: gtk_ardour/regionview.cc:1169
+#, fuzzy
+msgid "add gain control point"
+msgstr "Enlever le point de contrôle"
+
+#: gtk_ardour/route_params_ui.cc:58
+msgid "Tracks/Buses"
+msgstr "Pistes/Bus"
+
+#: gtk_ardour/route_params_ui.cc:59
+msgid "Pre Redirects"
+msgstr "Pre redirections"
+
+#: gtk_ardour/route_params_ui.cc:60
+msgid "Post Redirects"
+msgstr "Post redirections"
+
+#: gtk_ardour/route_params_ui.cc:105
+msgid "Pre-fader Redirects"
+msgstr "Redirections pré-fader"
+
+#: gtk_ardour/route_params_ui.cc:106
+msgid "Post-fader Redirects"
+msgstr "Redirections post-fader"
+
+#: gtk_ardour/route_params_ui.cc:138
+msgid "ardour: track/bus inspector"
+msgstr "ardour : inspecteur de piste/bus"
+
+#: gtk_ardour/route_params_ui.cc:139
+msgid "ardour_route_parameters"
+msgstr "ardour_paramètres_de_route"
+
+#: gtk_ardour/route_params_ui.cc:189
+msgid "route display list item for renamed route not found!"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:448
+msgid "NO TRACK"
+msgstr "PAS DE PISTE"
+
+#: gtk_ardour/route_params_ui.cc:669
+msgid "ardour: track/bus inspector: "
+msgstr "ardour : inspecteur de piste/bus"
+
+#: gtk_ardour/route_params_ui.cc:673
+msgid "No Route Selected"
+msgstr "Aucune route sélectionnée"
+
+#: gtk_ardour/route_params_ui.cc:674
+msgid "ardour: track/bus/inspector: no route selected"
+msgstr "ardour : inspecteur de piste/bus : aucune route sélectionnée"
+
+#: gtk_ardour/route_ui.cc:134
+msgid "mute change"
+msgstr "modification de la sourdine"
+
+#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220
+msgid "solo change"
+msgstr "modification du solo"
+
+#: gtk_ardour/route_ui.cc:284
+#, fuzzy
+msgid "rec-enable change"
+msgstr "modification de rec-enable"
+
+#: gtk_ardour/route_ui.cc:423
+#, fuzzy
+msgid "Solo-safe"
+msgstr "Solo-safe"
+
+#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474
+msgid "MIDI Bind"
+msgstr "Assignement MIDI"
+
+#: gtk_ardour/route_ui.cc:445
+msgid "Pre Fader"
+msgstr "Pré fader"
+
+#: gtk_ardour/route_ui.cc:452
+msgid "Post Fader"
+msgstr "Post fader"
+
+#: gtk_ardour/route_ui.cc:459
+msgid "Control Outs"
+msgstr "Sorties de contrôle"
+
+#: gtk_ardour/route_ui.cc:466
+msgid "Main Outs"
+msgstr "Sorties principales"
+
+#: gtk_ardour/route_ui.cc:503
+msgid "mix group solo change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:537
+msgid "mix group mute change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:553
+msgid "mix group rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258
+msgid "ardour: color selection"
+msgstr "ardour : sélection de couleur"
+
+#: gtk_ardour/route_ui.cc:652
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"You may also lose the playlist used by this track.\n"
+"(cannot be undone)"
+msgstr ""
+"Voulez-vous vraiment supprimer la piste \"%1\" ?\n"
+"Vous perdrez peut-être aussi la liste de lecture utilisée par cette piste"
+"(cela ne pourra pas être annulé)"
+
+#: gtk_ardour/route_ui.cc:654
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Voulez-vous vraiment supprimer le bus \"%1\" ?\n"
+"(cela ne pourra pas être annulé)"
+
+#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299
+msgid "Yes, remove it."
+msgstr "Oui, le supprimer."
+
+#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358
+msgid "new name: "
+msgstr "nouveau nom :"
+
+#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31
+msgid "Beats per minute"
+msgstr "Temps par minute"
+
+#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35
+#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163
+msgid "Beat"
+msgstr "Temps"
+
+#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158
+msgid "Meter denominator"
+msgstr "Dénominateur du vu-mètre"
+
+#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159
+msgid "Beats per bar"
+msgstr "Temps par mesure"
+
+#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189
+msgid "whole (1)"
+msgstr "noire (1)"
+
+#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191
+msgid "second (2)"
+msgstr "croche (2)"
+
+#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193
+msgid "third (3)"
+msgstr "triolet (3)"
+
+#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195
+#: gtk_ardour/tempo_dialog.cc:203
+msgid "quarter (4)"
+msgstr "double croche (4)"
+
+#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197
+msgid "eighth (8)"
+msgstr "huitième (8)"
+
+#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199
+msgid "sixteenth (16)"
+msgstr "seizième (16)"
+
+#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201
+msgid "thirty-second (32)"
+msgstr "trente-deuxième (32)"
+
+#: gtk_ardour/tempo_dialog.cc:301
+msgid "garbaged note type entry (%1)"
+msgstr "entrée type de note endommagée (%1)"
+
+#: gtk_ardour/tempo_dialog.cc:311
+msgid "incomprehensible note type entry (%1)"
+msgstr "entrée type de note incompréhensible (%1)"
+
+#: gtk_ardour/time_axis_view.cc:95
+msgid "gTortnam"
+msgstr "gTortnam"
+
+#: gtk_ardour/time_axis_view.cc:446
+msgid "Largest"
+msgstr "Énorme"
+
+#: gtk_ardour/time_axis_view.cc:447
+msgid "Large"
+msgstr "Grand"
+
+#: gtk_ardour/time_axis_view.cc:448
+msgid "Larger"
+msgstr "Plus grand"
+
+#: gtk_ardour/time_axis_view.cc:450
+msgid "Smaller"
+msgstr "Plus petit"
+
+#: gtk_ardour/time_axis_view.cc:451
+msgid "Small"
+msgstr "Petit"
+
+#: gtk_ardour/time_axis_view.cc:785
+msgid "unknown track height name \"%1\" in XML GUI information"
+msgstr "nom de hauteur de piste inconnu \"%1\" dans les données XML de l'IHM"
+
+#: gtk_ardour/time_axis_view_item.cc:69
+msgid "TimeAxisViewItemName"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:258
+msgid "new duration %1 frames is out of bounds for %2"
+msgstr "la nouvelle durée %1 trames est hors limite pour %2"
+
+#: gtk_ardour/time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr "programming error: request for non-existent audio range (%1)!"
+
+#: gtk_ardour/utils.cc:57
+msgid ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+msgstr ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+
+#: gtk_ardour/utils.cc:66
+msgid "aeiou"
+msgstr "aeiou"
+
+#: gtk_ardour/utils.cc:75
+msgid "AEIOU"
+msgstr "AEIOU"
+
+#: gtk_ardour/utils.cc:84
+msgid "bcdfghjklmnpqrtvwxyz"
+msgstr "bcdfghjklmnpqrtvwxyz"
+
+#: gtk_ardour/utils.cc:93
+msgid "BCDFGHJKLMNPQRTVWXYZ"
+msgstr "BCDFGHJKLMNPQRTVWXYZ"
+
+#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265
+msgid "bad XPM header %1"
+msgstr "mauvais entête XPM %1"
+
+#: gtk_ardour/utils.cc:516
+msgid "missing RGBA style for \"%1\""
+msgstr ""
+
+#: gtk_ardour/visual_time_axis.cc:297
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Voulez-vous vraiment supprimer la piste \"%1\" ?\n"
+"(cela ne pourra pas être annulé)"
+
+#: gtk_ardour/visual_time_axis.cc:385
+msgid "A track already exists with that name"
+msgstr "Une piste portant le même nom existe déjà"
+
+#~ msgid "the exact time it was recorded"
+#~ msgstr "l'heure exacte de l'enregistrement"
+
+#~ msgid "existing material that was listened to while recording"
+#~ msgstr "son existant qui était écouté pendant l'enregistrement"
+
+#~ msgid "Seamless Looping"
+#~ msgstr "Bouclage sans a-coup"
+
+#~ msgid "Align recorded material with:"
+#~ msgstr "Aligner le son enregistré avec :"
+
+#~ msgid "Export to CD"
+#~ msgstr "Exporter sur CD"
+
+#~ msgid "programming error: location/marker map does not contain location!"
+#~ msgstr ""
+#~ "erreur de programmation : la carte d'emplacements/marqueurs ne contient "
+#~ "pas d'emplacements !"
+
+#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Impossible de trouver une image de bouton inverseur qui corresponde à "
+#~ "toggle-button-[0-9]*.xpm$"
+
+#~ msgid ""
+#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Impossible de trouver une image de petit bouton poussoir qui corresponde "
+#~ "à small-round-button-[0-9]*.xpm$"
+
+#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Impossible de trouver une image qui corresponde à hslider[0-9]*.xpm$"
+
+#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Impossible de trouver une image qui corresponde à vslider[0-9]*.xpm$"
+
+#~ msgid "Recieve MMC"
+#~ msgstr "Recevoir MMC"
+
+#~ msgid "Trace MIDI Input"
+#~ msgstr "Suivi des entrées MIDI"
+
+#~ msgid "Trace MIDI Output"
+#~ msgstr "Suivi des sortie MIDI"
+
+#, fuzzy
+#~ msgid "30 FPS non-drop"
+#~ msgstr "30 TPS sans-drop"
+
+#~ msgid "MTC Port"
+#~ msgstr "Port MTC"
+
+#~ msgid "MIDI Param Port"
+#~ msgstr "Port de paramètre MIDI"
+
+#~ msgid "attempt to timestretch a non-audio track!"
+#~ msgstr "tentative de déformation temporelle d'une piste non audio !"
+
+#~ msgid "cannot create timestretch thread - operation not carried out"
+#~ msgstr "cannot create timestretch thread - operation not carried out"
+
+#~ msgid "mouse brush"
+#~ msgstr "brosse de souris"
+
+#~ msgid "move region(s) between tracks"
+#~ msgstr "déplacer la/les région(s) entre les pistes"
+
+#~ msgid "copy region(s) between tracks"
+#~ msgstr "copier la/les région(s) entre les pistes"
+
+#~ msgid "ardour: tempo editor"
+#~ msgstr "ardour : éditeur de tempo"
+
+#~ msgid "ardour_add_track_bus"
+#~ msgstr "ardour_ajouter_piste_bus"
+
+#~ msgid "ok"
+#~ msgstr "OK"
+
+#, fuzzy
+#~ msgid "apply"
+#~ msgstr "aplay"
+
+#, fuzzy
+#~ msgid "fade"
+#~ msgstr "Fades"
+
+#, fuzzy
+#~ msgid "Edit left"
+#~ msgstr "Mode d'édition"
+
+#, fuzzy
+#~ msgid "Edit right"
+#~ msgstr "Édition en utilisant"
+
+#, fuzzy
+#~ msgid "Edit fade"
+#~ msgstr "Mode d'édition"
+
+#, fuzzy
+#~ msgid "Export region"
+#~ msgstr "Région"
+
+#, fuzzy
+#~ msgid "Bounce region"
+#~ msgstr "Bounce selection"
+
+#~ msgid "Region"
+#~ msgstr "Région"
+
+#~ msgid "Play selected region"
+#~ msgstr "Jouer l'emplacement sélectionné"
+
+#~ msgid "clear connections"
+#~ msgstr "effacer les connexions"
+
+#, fuzzy
+#~ msgid "Crossfades in use"
+#~ msgstr "Crossfade"
+
+#, fuzzy
+#~ msgid "outside this computer"
+#~ msgstr "Cacher cette piste"
+
+#, fuzzy
+#~ msgid "inside this computer"
+#~ msgstr "Cacher cette piste"
diff --git a/gtk2_ardour/po/it_IT.po b/gtk2_ardour/po/it_IT.po
new file mode 100644
index 0000000000..a497ec2cde
--- /dev/null
+++ b/gtk2_ardour/po/it_IT.po
@@ -0,0 +1,5079 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Paul Davis
+# This file is distributed under the same license as the PACKAGE package.
+# Filippo Pappalardo <filippo@email.it>, 2003.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ardour 0.354.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-09-19 18:09-0400\n"
+"PO-Revision-Date: 2003-05-20 13:03-0500\n"
+"Last-Translator: Filippo Pappalardo <filippo@email.it>\n"
+"Language-Team: Italian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gtk_ardour/about.cc:134
+msgid "Marcus Andersson"
+msgstr ""
+
+#: gtk_ardour/about.cc:135
+msgid "Jeremy Hall"
+msgstr ""
+
+#: gtk_ardour/about.cc:136
+msgid "Steve Harris"
+msgstr ""
+
+#: gtk_ardour/about.cc:137
+msgid "Tim Mayberry"
+msgstr ""
+
+#: gtk_ardour/about.cc:138
+msgid "Mark Stewart"
+msgstr ""
+
+#: gtk_ardour/about.cc:139
+msgid "Sam Chessman"
+msgstr ""
+
+#: gtk_ardour/about.cc:140
+msgid "Jack O'Quin"
+msgstr ""
+
+#: gtk_ardour/about.cc:141
+msgid "Matt Krai"
+msgstr ""
+
+#: gtk_ardour/about.cc:142
+msgid "Ben Bell"
+msgstr ""
+
+#: gtk_ardour/about.cc:143
+msgid "Gerard van Dongen"
+msgstr ""
+
+#: gtk_ardour/about.cc:144
+msgid "Thomas Charbonnel"
+msgstr ""
+
+#: gtk_ardour/about.cc:145
+msgid "Nick Mainsbridge"
+msgstr ""
+
+#: gtk_ardour/about.cc:146
+msgid "Colin Law"
+msgstr ""
+
+#: gtk_ardour/about.cc:147
+msgid "Sampo Savolainen"
+msgstr ""
+
+#: gtk_ardour/about.cc:148
+msgid "Joshua Leach"
+msgstr ""
+
+#: gtk_ardour/about.cc:149
+msgid "Rob Holland"
+msgstr ""
+
+#: gtk_ardour/about.cc:150
+msgid "Per Sigmond"
+msgstr ""
+
+#: gtk_ardour/about.cc:151
+msgid "Doug Mclain"
+msgstr ""
+
+#: gtk_ardour/about.cc:156
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+msgstr ""
+
+#: gtk_ardour/about.cc:157
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+msgstr ""
+
+#: gtk_ardour/about.cc:158
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+msgstr ""
+
+#: gtk_ardour/about.cc:159
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:160
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:162
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn@fastmail.fm>"
+msgstr ""
+
+#: gtk_ardour/about.cc:163
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop@nm.ru>"
+msgstr ""
+
+#: gtk_ardour/about.cc:181
+msgid ""
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n"
+msgstr ""
+
+#: gtk_ardour/about.cc:188
+msgid ""
+"Ardour: %1\n"
+"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+msgstr ""
+
+#: gtk_ardour/about.cc:206
+msgid ""
+"Primary author:\n"
+"\tPaul Davis\n"
+"\n"
+"Major developers:\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributors:\n"
+"\t"
+msgstr ""
+
+#: gtk_ardour/about.cc:243
+msgid "Authors"
+msgstr ""
+
+#: gtk_ardour/about.cc:244
+msgid "Translators"
+msgstr "Traduttori"
+
+#: gtk_ardour/about.cc:361
+msgid "cannot open splash image file \"%1\""
+msgstr "Editor: impossibile l'immagine per lo splash \"%1\" (%2)"
+
+#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33
+#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81
+#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977
+#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85
+#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777
+#: gtk_ardour/redirect_box.cc:900
+msgid "OK"
+msgstr ""
+
+#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92
+#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046
+#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72
+#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982
+#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733
+#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000
+#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129
+#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785
+#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86
+#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072
+#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33
+#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161
+msgid "Cancel"
+msgstr "Cancella"
+
+#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94
+msgid "Tracks"
+msgstr "Tracce"
+
+#: gtk_ardour/add_route_dialog.cc:43
+msgid "Busses"
+msgstr "Bus"
+
+#: gtk_ardour/add_route_dialog.cc:48
+msgid "ardour: add track/bus"
+msgstr "ardour: aggiungi traccia/bus"
+
+#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81
+msgid "Add"
+msgstr "Aggiungi"
+
+#: gtk_ardour/add_route_dialog.cc:86
+msgid "Name (template)"
+msgstr "Nome (modello)"
+
+#: gtk_ardour/ardour_ui.cc:798
+msgid ""
+"pre\n"
+"roll"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:799
+msgid ""
+"post\n"
+"roll"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:807
+msgid "% "
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:808
+msgid "spring"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:810
+msgid ""
+"punch\n"
+"in"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:811
+msgid ""
+"punch\n"
+"out"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:812
+msgid ""
+"auto\n"
+"return"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:813
+msgid ""
+"auto\n"
+"play"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:814
+msgid ""
+"auto\n"
+"input"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:815
+msgid "click"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:816
+msgid ""
+"follow\n"
+"PH"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:817
+msgid "AUDITIONING"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:818
+msgid "SOLO"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:870
+msgid "Percentage"
+msgstr "Percentuale"
+
+#: gtk_ardour/ardour_ui.cc:872
+msgid "Semitones"
+msgstr "Semitoni"
+
+#: gtk_ardour/ardour_ui.cc:875
+msgid "Sprung"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:877
+msgid "Wheel"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:902
+msgid ""
+"You cannot record-enable\n"
+"track %1\n"
+"because it has no input connections.\n"
+"You would be wasting space recording silence."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1073
+msgid "quit"
+msgstr "Esci"
+
+#: gtk_ardour/ardour_ui.cc:1082
+msgid ""
+"Ardour was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1107
+msgid "Save and %1"
+msgstr "Salva ed esci"
+
+#: gtk_ardour/ardour_ui.cc:1112
+msgid "Just %1"
+msgstr "%1 e basta"
+
+#: gtk_ardour/ardour_ui.cc:1117
+msgid "Don't %1"
+msgstr "Non uscire"
+
+#: gtk_ardour/ardour_ui.cc:1126
+#, fuzzy
+msgid "session"
+msgstr "Sessione"
+
+#: gtk_ardour/ardour_ui.cc:1128
+#, fuzzy
+msgid "snapshot"
+msgstr "Istantanea"
+
+#: gtk_ardour/ardour_ui.cc:1130
+#, fuzzy
+msgid ""
+"The %1\n"
+"\"%2\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
+msgstr ""
+"La sessione \"%1\"\n"
+"non è stata salvata.\n"
+"\n"
+"Qualsiasi cambiamento effettuato adesso\n"
+"sarà perduto se non viene salvato.\n"
+"\n"
+"Cosa vuoi fare?"
+
+#: gtk_ardour/ardour_ui.cc:1151
+msgid "Prompter"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1152
+msgid "ardour: save session?"
+msgstr "ardour: salvare la sessione?"
+
+#: gtk_ardour/ardour_ui.cc:1219
+#, fuzzy, c-format
+msgid "disconnected"
+msgstr "Disconnetti"
+
+#: gtk_ardour/ardour_ui.cc:1226
+#, c-format
+msgid "SR: %.1f kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1230
+#, c-format
+msgid "SR: %u kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1243
+#, c-format
+msgid "DSP Load: %.1f%%"
+msgstr "Carico DSP: %.1f%%"
+
+#: gtk_ardour/ardour_ui.cc:1253
+#, c-format
+msgid "Disk r:%5.1f w:%5.1f MB/s"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1267
+#, c-format
+msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1294
+msgid "space: 24hrs+"
+msgstr "Spazio: 24hrs+"
+
+#: gtk_ardour/ardour_ui.cc:1324
+#, c-format
+msgid "space: %02dh:%02dm:%02ds"
+msgstr "Spazio: %02dh:%02dm:%02ds"
+
+#: gtk_ardour/ardour_ui.cc:1575
+msgid "programming error: impossible control method"
+msgstr "errore di programmazione: metodo di controllo impossibile"
+
+#: gtk_ardour/ardour_ui.cc:1800
+msgid "cancel"
+msgstr "cancella"
+
+#: gtk_ardour/ardour_ui.cc:1801
+msgid "rescan"
+msgstr "Aggiorna"
+
+#: gtk_ardour/ardour_ui.cc:1842
+msgid "open session"
+msgstr "apri sessione"
+
+#: gtk_ardour/ardour_ui.cc:1897
+msgid "Patience is a virtue.\n"
+msgstr "La pazienza è una virtù.\n"
+
+#: gtk_ardour/ardour_ui.cc:1906
+msgid "You cannot add a track without a session already loaded."
+msgstr ""
+"Non si può aggiungere una traccia senza prima aver caricato una sessione."
+
+#: gtk_ardour/ardour_ui.cc:1913
+msgid "could not create new audio track"
+msgstr "Impossibile creare una nuova traccia audio"
+
+#: gtk_ardour/ardour_ui.cc:1917
+msgid "could not create new audio bus"
+msgstr "Impossibile creare un nuovo bus audio"
+
+#: gtk_ardour/ardour_ui.cc:1936
+msgid ""
+"There are insufficient JACK ports available\n"
+"to create a new track or bus.\n"
+"You should save Ardour, exit and\n"
+"restart JACK with more ports."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2071
+msgid ""
+"Please create 1 or more track\n"
+"before trying to record.\n"
+"Check the Session menu."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2312
+#, fuzzy
+msgid ""
+"JACK has either been shutdown or it\n"
+"disconnected Ardour because Ardour\n"
+"was not fast enough. You can save the\n"
+"session and/or try to reconnect to JACK ."
+msgstr ""
+"JACK è stato chiuso oppure ha disconnesso\n"
+"Ardour per non essere stato abbastanza veloce.\n"
+"E' consigliato salvare la sessione e riavviare\n"
+"sia JACK che Ardour."
+
+#: gtk_ardour/ardour_ui.cc:2328
+msgid "Unable to create all required ports"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2336
+#, fuzzy
+msgid "Unable to start the session running"
+msgstr "Vai all'inizio della sessione"
+
+#: gtk_ardour/ardour_ui.cc:2472
+msgid "No Stream"
+msgstr "Nessun flusso"
+
+#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518
+msgid "none"
+msgstr "Nessuno"
+
+#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527
+#: gtk_ardour/automation_time_axis.cc:189
+#: gtk_ardour/automation_time_axis.cc:218
+#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211
+#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947
+#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659
+msgid "off"
+msgstr "Off"
+
+#: gtk_ardour/ardour_ui.cc:2548
+msgid "Name for snapshot"
+msgstr "Nome dell' istantanea"
+
+#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294
+msgid "Name for mix template:"
+msgstr "Nome per il modello di mixaggio"
+
+#: gtk_ardour/ardour_ui.cc:2717
+msgid "-template"
+msgstr "-modello"
+
+#: gtk_ardour/ardour_ui.cc:2760
+msgid "Session %1 already exists at %2"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2832
+msgid ""
+"You do not have write access to this session.\n"
+"This prevents the session from being loaded."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "La sessione \"%1 (istantanea %2)\" non è stata caricata correttamente"
+
+#: gtk_ardour/ardour_ui.cc:2966
+msgid ""
+"No audio files were ready for cleanup\n"
+"\n"
+"If this seems suprising, check for any existing\n"
+"snapshots. These may still include regions that\n"
+"require some unused files to continue to exist."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001
+msgid "files"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003
+msgid "file"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3026
+msgid "ardour: cleanup"
+msgstr "ardour: pulisci"
+
+#: gtk_ardour/ardour_ui.cc:3040
+msgid ""
+"Cleanup is a destructive operation.\n"
+"ALL undo/redo information will be lost if you cleanup.\n"
+"Unused audio files will be moved to a \"dead sounds\" location."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3045
+msgid "Proceed with cleanup"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3061
+#, fuzzy
+msgid "CleanupDialog"
+msgstr "Pulisci"
+
+#: gtk_ardour/ardour_ui.cc:3062
+#, fuzzy
+msgid "ardour cleanup"
+msgstr "ardour: pulisci"
+
+#: gtk_ardour/ardour_ui.cc:3063
+#, fuzzy
+msgid "ardour_cleanup"
+msgstr "ardour: pulisci"
+
+#: gtk_ardour/ardour_ui.cc:3086
+msgid "cleaned files"
+msgstr "files ripuliti"
+
+#: gtk_ardour/ardour_ui.cc:3087
+#, fuzzy
+msgid ""
+"The following %1 %2 were not in use.\n"
+"The next time you flush the wastebasket\n"
+"it will release an additional %3 %4bytes\n"
+"of disk space"
+msgstr ""
+"I seguenti %1 files non erano utilizzati.\n"
+"La prossima volta che il cestino verr svuotato\n"
+"Saranno liberati %2 megabytes di spazio su disco"
+
+#: gtk_ardour/ardour_ui.cc:3110
+#, fuzzy
+msgid "deleted file"
+msgstr "files eliminati"
+
+#: gtk_ardour/ardour_ui.cc:3111
+#, fuzzy
+msgid ""
+"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"
+msgstr ""
+"I seguenti %1 files sono stati eliminati, rilasciati %2 megabytes di spazio "
+"disco"
+
+#: gtk_ardour/ardour_ui.cc:3226
+msgid "Recording was stopped because your system could not keep up."
+msgstr "Registazione fermata perche' il sistema non ha retto"
+
+#: gtk_ardour/ardour_ui.cc:3248
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3266
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3291
+msgid "Recover from crash"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3292
+msgid "Ignore crash data"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3293
+msgid ""
+"This session appears to have been in\n"
+"middle of recording when ardour or\n"
+"the computer was shutdown.\n"
+"\n"
+"Ardour can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3338
+msgid "Could not disconnect from JACK"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3351
+msgid "Could not reconnect to JACK"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:60
+msgid "UI: cannot setup editor"
+msgstr "IU: impossibile avviare l'editor"
+
+#: gtk_ardour/ardour_ui2.cc:65
+msgid "UI: cannot setup mixer"
+msgstr "IU: impossibile avviare il mixer"
+
+#: gtk_ardour/ardour_ui2.cc:70
+msgid "UI: cannot setup meter_bridge"
+msgstr "IU: impossibile avviare il meter_bridge"
+
+#: gtk_ardour/ardour_ui2.cc:98
+msgid "MMC + Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:99
+msgid "MMC"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:100
+msgid "Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:117
+msgid "MMC ID"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:215
+msgid "Play from playhead"
+msgstr "Suona dal cursore"
+
+#: gtk_ardour/ardour_ui2.cc:216
+msgid "Stop playback"
+msgstr "Ferma"
+
+#: gtk_ardour/ardour_ui2.cc:217
+msgid "Play range/selection"
+msgstr "Suona intervallo/selezione"
+
+#: gtk_ardour/ardour_ui2.cc:218
+msgid "Go to start of session"
+msgstr "Vai all'inizio della sessione"
+
+#: gtk_ardour/ardour_ui2.cc:219
+msgid "Go to end of session"
+msgstr "Vai alla fine della sessione"
+
+#: gtk_ardour/ardour_ui2.cc:220
+msgid "Play loop range"
+msgstr "Suona l'intervallo di loop"
+
+#: gtk_ardour/ardour_ui2.cc:221
+msgid "Return to last playback start when stopped"
+msgstr "Torna al punto d'inizio una volta fermato"
+
+#: gtk_ardour/ardour_ui2.cc:222
+msgid "Start playback after any locate"
+msgstr "Comincia a suonare dopo ogni posizione"
+
+#: gtk_ardour/ardour_ui2.cc:223
+msgid "Be sensible about input monitoring"
+msgstr "Monitorizza le entrate"
+
+#: gtk_ardour/ardour_ui2.cc:224
+msgid "Start recording at auto-punch start"
+msgstr "Comincia a registrare al'inizio dell'auto-punch"
+
+#: gtk_ardour/ardour_ui2.cc:225
+msgid "Stop recording at auto-punch end"
+msgstr "Ferma la registrazione alla fine dell'auto-punch"
+
+#: gtk_ardour/ardour_ui2.cc:226
+msgid "Enable/Disable audio click"
+msgstr "Abilita/Disabilita il click audio"
+
+#: gtk_ardour/ardour_ui2.cc:227
+#, fuzzy
+msgid "Enable/Disable follow playhead"
+msgstr "Abilita/Disabilita il click audio"
+
+#: gtk_ardour/ardour_ui2.cc:228
+msgid "Shuttle speed control"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:229
+#, fuzzy, c-format
+msgid "Select semitones or %%-age for speed display"
+msgstr "Seleziona semitoni o percentuale di velocita' del display"
+
+#: gtk_ardour/ardour_ui2.cc:230
+msgid "Select sprung or wheel behaviour"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:231
+msgid "Current transport speed"
+msgstr "Velocita' del trasporto attuale"
+
+#: gtk_ardour/ardour_ui2.cc:312
+msgid "Primary clock"
+msgstr "Orologio principale"
+
+#: gtk_ardour/ardour_ui2.cc:313
+msgid "secondary clock"
+msgstr "orologio secondario"
+
+#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751
+#: gtk_ardour/ardour_ui2.cc:770
+msgid "stopped"
+msgstr "fermato"
+
+#: gtk_ardour/ardour_ui2.cc:431
+msgid "ardour: clock"
+msgstr "ardour: orologio"
+
+#: gtk_ardour/ardour_ui2.cc:721
+msgid "st"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:731
+msgid "sprung"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:742
+msgid "wheel"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dependents.cc:74
+msgid "keyboard_target: error setting binding state: invalid node"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dialogs.cc:158
+msgid "close session"
+msgstr "chiudi la sessione"
+
+#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895
+msgid "New"
+msgstr "Nuovo"
+
+#: gtk_ardour/ardour_ui_ed.cc:76
+msgid "Open"
+msgstr "Apri"
+
+#: gtk_ardour/ardour_ui_ed.cc:77
+msgid "Recent"
+msgstr "Recenti"
+
+#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+msgid "Close"
+msgstr "Chiudi"
+
+#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488
+msgid "Add Track/Bus"
+msgstr "Aggiungi Tracce/Bus"
+
+#: gtk_ardour/ardour_ui_ed.cc:99
+msgid "Connect"
+msgstr "Connetti"
+
+#: gtk_ardour/ardour_ui_ed.cc:100
+msgid "Image Compositor"
+msgstr "Compositore d'Immagini"
+
+#: gtk_ardour/ardour_ui_ed.cc:114
+msgid "Save"
+msgstr "Salva"
+
+#: gtk_ardour/ardour_ui_ed.cc:118
+msgid "Snapshot"
+msgstr "Istantanea"
+
+#: gtk_ardour/ardour_ui_ed.cc:126
+msgid "Save Template..."
+msgstr "Salva Modello..."
+
+#: gtk_ardour/ardour_ui_ed.cc:133
+msgid "Export session to audiofile..."
+msgstr "Esporta la sessione come file audio..."
+
+#: gtk_ardour/ardour_ui_ed.cc:134
+msgid "Export range to audiofile..."
+msgstr "Esporta l'intervallo come file audio..."
+
+#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312
+#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118
+#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227
+msgid "Export"
+msgstr "Esporta"
+
+#: gtk_ardour/ardour_ui_ed.cc:146
+msgid "Cleanup unused sources"
+msgstr "Pulisci sorgenti inutilizzate"
+
+#: gtk_ardour/ardour_ui_ed.cc:147
+msgid "Flush wastebasket"
+msgstr "Svuota il cestino"
+
+#: gtk_ardour/ardour_ui_ed.cc:149
+msgid "Cleanup"
+msgstr "Pulisci"
+
+#: gtk_ardour/ardour_ui_ed.cc:154
+msgid "Quit"
+msgstr "Esci"
+
+#: gtk_ardour/ardour_ui_ed.cc:156
+msgid "Session"
+msgstr "Sessione"
+
+#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287
+#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499
+#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570
+#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412
+msgid "Edit"
+msgstr "Modifica"
+
+#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572
+#: gtk_ardour/mixer_strip.cc:631
+msgid "Disconnect"
+msgstr "Disconnetti"
+
+#: gtk_ardour/ardour_ui_ed.cc:174
+#, fuzzy
+msgid "Reconnect"
+msgstr "Connetti"
+
+#: gtk_ardour/ardour_ui_ed.cc:192
+msgid "Latency"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:195
+msgid "JACK"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:205
+msgid "Editor"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:206
+msgid "Mixer"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:212
+msgid "Options Editor"
+msgstr "Editor delle Opzioni"
+
+#: gtk_ardour/ardour_ui_ed.cc:219
+msgid "Audio Library"
+msgstr "Libreria Audio"
+
+#: gtk_ardour/ardour_ui_ed.cc:225
+#, fuzzy
+msgid "Track/Bus Inspector"
+msgstr "Tracce/Bus"
+
+#: gtk_ardour/ardour_ui_ed.cc:232
+msgid "Connections"
+msgstr "Connessioni"
+
+#: gtk_ardour/ardour_ui_ed.cc:240
+msgid "Meter Bridge"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:248
+msgid "Locations"
+msgstr "Posizioni"
+
+#: gtk_ardour/ardour_ui_ed.cc:255
+msgid "Big Clock"
+msgstr "Orologio grande"
+
+#: gtk_ardour/ardour_ui_ed.cc:261
+msgid "About"
+msgstr "Circa"
+
+#: gtk_ardour/ardour_ui_ed.cc:264
+msgid "Windows"
+msgstr "Finestre"
+
+#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203
+msgid "SMPTE"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202
+#: gtk_ardour/editor_rulers.cc:359
+msgid "Bars:Beats"
+msgstr "Battuta:Battiti"
+
+#: gtk_ardour/audio_clock.cc:1642
+msgid "Minutes:Seconds"
+msgstr "Minuti:Secondi"
+
+#: gtk_ardour/audio_clock.cc:1643
+msgid "Audio Frames"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356
+#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713
+#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774
+#: gtk_ardour/option_editor.cc:794
+msgid "Off"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1646
+msgid "Mode"
+msgstr "Modo"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523
+msgid "m"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524
+msgid "s"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104
+msgid "r"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:108
+msgid "g"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:109
+msgid "p"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44
+#: gtk_ardour/visual_time_axis.cc:90
+msgid "h"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:111
+msgid "a"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89
+msgid "v"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:185
+msgid "Record"
+msgstr "Registra"
+
+#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191
+msgid "Solo"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236
+#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433
+msgid "Mute"
+msgstr "Muto"
+
+#: gtk_ardour/audio_time_axis.cc:188
+msgid "Edit Group"
+msgstr "Modifica Gruppo"
+
+#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110
+msgid "Display Height"
+msgstr "Altezza"
+
+#: gtk_ardour/audio_time_axis.cc:190
+msgid "Playlist"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752
+msgid "Automation"
+msgstr "Automazione"
+
+#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111
+msgid "Visual options"
+msgstr "Opzioni di visualizzazione"
+
+#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112
+msgid "Hide this track"
+msgstr "Nascondi traccia"
+
+#: gtk_ardour/audio_time_axis.cc:349
+msgid "No group"
+msgstr "nessun gruppo"
+
+#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447
+#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229
+msgid "Height"
+msgstr "Altezza"
+
+#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266
+#: gtk_ardour/marker_time_axis.cc:230
+msgid "Color"
+msgstr "Colore"
+
+#: gtk_ardour/audio_time_axis.cc:720
+msgid "Hide all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:721
+msgid "Show all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:729
+msgid "show all automation"
+msgstr "mostra tutte le automazioni"
+
+#: gtk_ardour/audio_time_axis.cc:732
+msgid "show existing automation"
+msgstr "mostra le automazioni esistenti"
+
+#: gtk_ardour/audio_time_axis.cc:735
+msgid "hide all automation"
+msgstr "nascondi tutte le automazioni"
+
+#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204
+#: gtk_ardour/editor.cc:234
+msgid "gain"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244
+msgid "pan"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388
+msgid "Plugins"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95
+msgid "Show waveforms"
+msgstr "Mostra le forme Wave"
+
+#: gtk_ardour/audio_time_axis.cc:766
+msgid "Traditional"
+msgstr "Tradizionale"
+
+#: gtk_ardour/audio_time_axis.cc:769
+msgid "Rectified"
+msgstr "Rettificato"
+
+#: gtk_ardour/audio_time_axis.cc:772
+msgid "Waveform"
+msgstr "Forme wave"
+
+#: gtk_ardour/audio_time_axis.cc:782
+#, fuzzy
+msgid "align with existing material"
+msgstr "Materiale esistente"
+
+#: gtk_ardour/audio_time_axis.cc:787
+#, fuzzy
+msgid "align with capture time"
+msgstr "Tempo di registrazione"
+
+#: gtk_ardour/audio_time_axis.cc:793
+#, fuzzy
+msgid "Alignment"
+msgstr "Allinea"
+
+#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288
+msgid "Active"
+msgstr "Attivo"
+
+#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386
+#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467
+#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269
+#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233
+#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83
+msgid "Remove"
+msgstr "Rimuovi"
+
+#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880
+#: gtk_ardour/audio_time_axis.cc:911
+#, fuzzy
+msgid "Name for playlist"
+msgstr "Nome dell' istantanea"
+
+#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433
+msgid "a track already exists with that name"
+msgstr "esiste già una traccia con quel nome"
+
+#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001
+#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539
+msgid "programming error: "
+msgstr "errore di programmazione: "
+
+#: gtk_ardour/audio_time_axis.cc:1889
+msgid "Current: %1"
+msgstr "Corrente %1"
+
+#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452
+#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226
+#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377
+msgid "Rename"
+msgstr "Rinomina"
+
+#: gtk_ardour/audio_time_axis.cc:1896
+msgid "New Copy"
+msgstr "Nuova Copia"
+
+#: gtk_ardour/audio_time_axis.cc:1898
+msgid "Clear Current"
+msgstr "Pulisci Corrente"
+
+#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472
+#: gtk_ardour/editor.cc:2557
+msgid "Select"
+msgstr "Seleziona"
+
+#: gtk_ardour/automation_line.cc:904
+msgid "automation event move"
+msgstr ""
+
+#: gtk_ardour/automation_line.cc:906
+msgid "automation range drag"
+msgstr ""
+
+#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64
+#, fuzzy
+msgid "remove control point"
+msgstr "Rimuovi il punto di sincronizzazione"
+
+#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010
+msgid "clear"
+msgstr "pulisci"
+
+#: gtk_ardour/automation_time_axis.cc:80
+msgid "track height"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:81
+#, fuzzy
+msgid "automation state"
+msgstr "stato dell'automazione pan"
+
+#: gtk_ardour/automation_time_axis.cc:82
+#, fuzzy
+msgid "clear track"
+msgstr "azzera gli intervalli"
+
+#: gtk_ardour/automation_time_axis.cc:83
+#, fuzzy
+msgid "hide track"
+msgstr "Nascondi traccia"
+
+#: gtk_ardour/automation_time_axis.cc:191
+#: gtk_ardour/automation_time_axis.cc:229
+#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213
+#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419
+#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50
+msgid "play"
+msgstr "suona"
+
+#: gtk_ardour/automation_time_axis.cc:193
+#: gtk_ardour/automation_time_axis.cc:240
+#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215
+#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422
+#: gtk_ardour/plugin_ui.cc:663
+msgid "write"
+msgstr "scrivi"
+
+#: gtk_ardour/automation_time_axis.cc:195
+#: gtk_ardour/automation_time_axis.cc:251
+#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217
+#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953
+#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665
+msgid "touch"
+msgstr "crea"
+
+#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274
+#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428
+msgid "???"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:276
+msgid "clear automation"
+msgstr "pulisci l'automazione"
+
+#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453
+#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398
+msgid "Hide"
+msgstr "Nascondi"
+
+#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52
+#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364
+msgid "Clear"
+msgstr "Pulisci"
+
+#: gtk_ardour/automation_time_axis.cc:474
+#, fuzzy
+msgid "State"
+msgstr "Inizio:"
+
+#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49
+msgid "Input Connections"
+msgstr "Connessioni in entrata"
+
+#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48
+msgid "Output Connections"
+msgstr "Connessioni in uscita"
+
+#: gtk_ardour/connection_editor.cc:49
+#, fuzzy
+msgid "New Input"
+msgstr "Nuova entrata"
+
+#: gtk_ardour/connection_editor.cc:50
+#, fuzzy
+msgid "New Output"
+msgstr "Nuova uscita"
+
+#: gtk_ardour/connection_editor.cc:51
+#, fuzzy
+msgid "Delete"
+msgstr "Elimina"
+
+#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96
+#, fuzzy
+msgid "Add Port"
+msgstr "Aggiungi una entrata"
+
+#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105
+#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786
+#, fuzzy
+msgid "Rescan"
+msgstr "Aggiorna"
+
+#: gtk_ardour/connection_editor.cc:101
+msgid "Available Ports"
+msgstr "Connessioni disponibili"
+
+#: gtk_ardour/connection_editor.cc:183
+msgid "ardour: connections"
+msgstr "ardour: connessioni"
+
+#: gtk_ardour/connection_editor.cc:513
+#, c-format
+msgid "in %d"
+msgstr ""
+
+#: gtk_ardour/connection_editor.cc:644
+msgid "Name for new connection:"
+msgstr "Nome della nuova connessione"
+
+#: gtk_ardour/crossfade_edit.cc:71
+#, fuzzy
+msgid "crossfade editor"
+msgstr "modifica lo smorzamento in entrata"
+
+#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449
+#, fuzzy
+msgid "Reset"
+msgstr "azzera"
+
+#: gtk_ardour/crossfade_edit.cc:78
+#, fuzzy
+msgid "Fade"
+msgstr "Smorzamenti"
+
+#: gtk_ardour/crossfade_edit.cc:79
+msgid "Out (dry)"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:80
+#, fuzzy
+msgid "Out"
+msgstr "Uscite"
+
+#: gtk_ardour/crossfade_edit.cc:81
+msgid "In (dry)"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:82
+msgid "In"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:84
+#, fuzzy
+msgid "With Pre-roll"
+msgstr "con pre-roll"
+
+#: gtk_ardour/crossfade_edit.cc:85
+#, fuzzy
+msgid "With Post-roll"
+msgstr "con post-roll"
+
+#: gtk_ardour/crossfade_edit.cc:93
+msgid "Fade In"
+msgstr "SMORZA Entrata"
+
+#: gtk_ardour/crossfade_edit.cc:94
+msgid "Fade Out"
+msgstr "SMORZA Uscita"
+
+#: gtk_ardour/crossfade_edit.cc:98
+msgid "ardour: x-fade edit"
+msgstr "ardour: modifica lo smorzamento incrociato"
+
+#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311
+#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189
+msgid "Audition"
+msgstr ""
+
+#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804
+msgid "Regions/name"
+msgstr "Regioni/nome"
+
+#: gtk_ardour/editor.cc:108
+msgid "Chunks"
+msgstr "Spezzoni"
+
+#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079
+msgid "Slide"
+msgstr ""
+
+#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077
+msgid "Splice"
+msgstr ""
+
+#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136
+#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96
+#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977
+msgid "None"
+msgstr "Nessuno"
+
+#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124
+msgid "CD Frames"
+msgstr ""
+
+#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126
+msgid "SMPTE Frames"
+msgstr ""
+
+#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128
+msgid "SMPTE Seconds"
+msgstr ""
+
+#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130
+msgid "SMPTE Minutes"
+msgstr ""
+
+#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132
+msgid "Seconds"
+msgstr "Secondi"
+
+#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134
+msgid "Minutes"
+msgstr "Minuti"
+
+#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106
+msgid "Beats/32"
+msgstr "Battiti/32"
+
+#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104
+msgid "Beats/16"
+msgstr "Battiti/16"
+
+#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102
+msgid "Beats/8"
+msgstr "Battiti/8"
+
+#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100
+msgid "Beats/4"
+msgstr "Battiti/4"
+
+#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098
+msgid "Beats/3"
+msgstr "Battiti/3"
+
+#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108
+msgid "Beats"
+msgstr "Battiti"
+
+#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110
+msgid "Bars"
+msgstr "Battute"
+
+#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112
+msgid "Marks"
+msgstr "Marcatori"
+
+#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114
+#: gtk_ardour/editor.cc:4182
+msgid "Edit Cursor"
+msgstr "Cursore di modifica"
+
+#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116
+msgid "Region starts"
+msgstr "Regioni/inizio"
+
+#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118
+msgid "Region ends"
+msgstr "Regioni/fine"
+
+#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122
+msgid "Region syncs"
+msgstr "Regioni/sincronizzazione"
+
+#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120
+msgid "Region bounds"
+msgstr "Regioni/confini"
+
+#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153
+#: gtk_ardour/time_axis_view.cc:449
+msgid "Normal"
+msgstr "Normale"
+
+#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155
+msgid "Magnetic"
+msgstr "Magnetico"
+
+#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174
+#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237
+msgid "Left"
+msgstr "Sinistra"
+
+#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176
+#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238
+msgid "Right"
+msgstr "Destra"
+
+#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178
+msgid "Center"
+msgstr "Centro"
+
+#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180
+msgid "Playhead"
+msgstr "Inizio"
+
+#: gtk_ardour/editor.cc:201
+msgid "Mins:Secs"
+msgstr "Min:Sec"
+
+#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353
+msgid "Frames"
+msgstr ""
+
+#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373
+msgid "Tempo"
+msgstr ""
+
+#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367
+msgid "Meter"
+msgstr ""
+
+#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379
+msgid "Location Markers"
+msgstr "Marcatori di posizione"
+
+#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385
+msgid "Range Markers"
+msgstr "Marcatori di intervallo"
+
+#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391
+msgid "Loop/Punch Ranges"
+msgstr "Intervalli di Loop/Punch"
+
+#: gtk_ardour/editor.cc:221
+msgid ""
+"editor\n"
+"mixer"
+msgstr ""
+
+#: gtk_ardour/editor.cc:232
+msgid "range"
+msgstr "intervallo"
+
+#: gtk_ardour/editor.cc:233
+msgid "object"
+msgstr "oggetto"
+
+#: gtk_ardour/editor.cc:235
+msgid "zoom"
+msgstr ""
+
+#: gtk_ardour/editor.cc:236
+msgid "timefx"
+msgstr ""
+
+#: gtk_ardour/editor.cc:237
+msgid "listen"
+msgstr ""
+
+#: gtk_ardour/editor.cc:239
+msgid "mode"
+msgstr "modo"
+
+#: gtk_ardour/editor.cc:240
+msgid "automation"
+msgstr "automazione"
+
+#: gtk_ardour/editor.cc:242
+msgid "Edit Mode"
+msgstr "Modalità di modifica"
+
+#: gtk_ardour/editor.cc:243
+msgid "Snap To"
+msgstr "Allinea a"
+
+#: gtk_ardour/editor.cc:244
+msgid "Snap Mode"
+msgstr "Modalita' di Allineamento"
+
+#: gtk_ardour/editor.cc:245
+msgid "Zoom Focus"
+msgstr ""
+
+#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364
+#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579
+msgid "Nudge"
+msgstr "Sposta"
+
+#: gtk_ardour/editor.cc:511
+msgid "Zoom in"
+msgstr "Zoom avanti"
+
+#: gtk_ardour/editor.cc:512
+msgid "Zoom out"
+msgstr "Zoom indietro"
+
+#: gtk_ardour/editor.cc:517
+msgid "Zoom to session"
+msgstr "Zoom alla selezione"
+
+#: gtk_ardour/editor.cc:536
+msgid "Zoom Span"
+msgstr ""
+
+#: gtk_ardour/editor.cc:566
+msgid "Edit Groups"
+msgstr "Modifica Gruppi"
+
+#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142
+msgid "-all-"
+msgstr "-tutto-"
+
+#: gtk_ardour/editor.cc:718
+msgid "Nudge region/selection forwards"
+msgstr "Sposta regione/selezione in avanti"
+
+#: gtk_ardour/editor.cc:719
+msgid "Nudge region/selection backwards"
+msgstr "Sposta regione/selezione indietro"
+
+#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308
+msgid "ardour: editor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:729
+msgid "ardour_editor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:846
+msgid "VerboseCanvasCursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1405
+msgid "FirstActionMessage"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1407
+msgid "Start a new session\n"
+msgstr "Inizia una nuova sessione\n"
+
+#: gtk_ardour/editor.cc:1408
+msgid "via Session menu"
+msgstr "tramite il menu Sessione"
+
+#: gtk_ardour/editor.cc:1703
+msgid "ardour: editor: "
+msgstr ""
+
+#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796
+#: gtk_ardour/editor_markers.cc:797
+msgid "Loop"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810
+#: gtk_ardour/editor_markers.cc:823
+msgid "Punch"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688
+msgid "programming error: fade in canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986
+#: gtk_ardour/redirect_box.cc:401
+msgid "Deactivate"
+msgstr "Disattiva"
+
+#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988
+#: gtk_ardour/redirect_box.cc:398
+msgid "Activate"
+msgstr "Attiva"
+
+#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993
+msgid "Linear"
+msgstr "Lineare"
+
+#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994
+#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734
+#: gtk_ardour/option_editor.cc:796
+msgid "Slowest"
+msgstr "Piu' Lento"
+
+#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995
+#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735
+#: gtk_ardour/option_editor.cc:798
+msgid "Slow"
+msgstr "Lento"
+
+#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996
+#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737
+#: gtk_ardour/option_editor.cc:802
+msgid "Fast"
+msgstr "Veloce"
+
+#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997
+#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739
+#: gtk_ardour/option_editor.cc:806
+msgid "Fastest"
+msgstr "Più Veloce"
+
+#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113
+msgid "Freeze"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2109
+msgid "Unfreeze"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328
+#, fuzzy
+msgid "Unmute"
+msgstr "muto"
+
+#: gtk_ardour/editor.cc:2247
+msgid "Convert to short"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2249
+msgid "Convert to full"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2260
+#, fuzzy
+msgid "Crossfade"
+msgstr "Smorzamento Incrociato"
+
+#: gtk_ardour/editor.cc:2303
+msgid "Popup region editor"
+msgstr "Mostra l'editor di regione"
+
+#: gtk_ardour/editor.cc:2304
+#, fuzzy
+msgid "Raise to top layer"
+msgstr "Porta la regione al primo livello"
+
+#: gtk_ardour/editor.cc:2305
+#, fuzzy
+msgid "Lower to bottom layer"
+msgstr "Porta la regione all'ultimo livello"
+
+#: gtk_ardour/editor.cc:2307
+msgid "Define sync point"
+msgstr "Definisci il punto di sincronizzazione"
+
+#: gtk_ardour/editor.cc:2308
+msgid "Remove sync point"
+msgstr "Rimuovi il punto di sincronizzazione"
+
+#: gtk_ardour/editor.cc:2313
+#, fuzzy
+msgid "Bounce"
+msgstr "Fai il Bounce dell'intervallo"
+
+#: gtk_ardour/editor.cc:2323
+msgid "Lock"
+msgstr "Blocca"
+
+#: gtk_ardour/editor.cc:2324
+msgid "Unlock"
+msgstr "Sblocca"
+
+#: gtk_ardour/editor.cc:2334
+msgid "Original position"
+msgstr "Posizione originale"
+
+#: gtk_ardour/editor.cc:2340
+msgid "Toggle envelope visibility"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2341
+#, fuzzy
+msgid "Toggle envelope active"
+msgstr "attivo/passivo"
+
+#: gtk_ardour/editor.cc:2345
+#, fuzzy
+msgid "DeNormalize"
+msgstr "Normalizza"
+
+#: gtk_ardour/editor.cc:2347
+msgid "Normalize"
+msgstr "Normalizza"
+
+#: gtk_ardour/editor.cc:2350
+msgid "Reverse"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2359
+#, fuzzy
+msgid "Nudge fwd"
+msgstr "Sposta"
+
+#: gtk_ardour/editor.cc:2360
+#, fuzzy
+msgid "Nudge bwd"
+msgstr "Sposta"
+
+#: gtk_ardour/editor.cc:2361
+msgid "Nudge fwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2362
+msgid "Nudge bwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2371
+msgid "Start to edit cursor"
+msgstr "Inizio al cursore di modifica"
+
+#: gtk_ardour/editor.cc:2372
+msgid "Edit cursor to end"
+msgstr "Cursore di modifica alla fine"
+
+#: gtk_ardour/editor.cc:2374
+msgid "Trim"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2377
+msgid "Split"
+msgstr "Dividi"
+
+#: gtk_ardour/editor.cc:2380
+msgid "Make mono regions"
+msgstr "Crea regioni mono"
+
+#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428
+msgid "Duplicate"
+msgstr "Duplica"
+
+#: gtk_ardour/editor.cc:2384
+msgid "Fill Track"
+msgstr "Riempi Traccia"
+
+#: gtk_ardour/editor.cc:2388
+msgid "Destroy"
+msgstr "Distruggi"
+
+#: gtk_ardour/editor.cc:2418
+msgid "Play range"
+msgstr "Suona l'intervallo"
+
+#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446
+msgid "Loop range"
+msgstr "Intervallo di loop"
+
+#: gtk_ardour/editor.cc:2421
+msgid "Create chunk from range"
+msgstr "Crea uno spezzone dall'intervallo"
+
+#: gtk_ardour/editor.cc:2423
+msgid "Create Region"
+msgstr "Crea una Regione"
+
+#: gtk_ardour/editor.cc:2424
+msgid "Separate Region"
+msgstr "Separa la Regione"
+
+#: gtk_ardour/editor.cc:2425
+msgid "Crop Region to range"
+msgstr "Ridimensiona la Regione alla selezione"
+
+#: gtk_ardour/editor.cc:2426
+msgid "Bounce range"
+msgstr "Fai il Bounce dell'intervallo"
+
+#: gtk_ardour/editor.cc:2432
+msgid "Fill range w/Region"
+msgstr "Riempi intervallo con Regione"
+
+#: gtk_ardour/editor.cc:2434
+msgid "Range"
+msgstr "Intervallo"
+
+#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538
+msgid "Play from edit cursor"
+msgstr "Suona dal cursore di modifica"
+
+#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539
+msgid "Play from start"
+msgstr "Suona dall'inizio"
+
+#: gtk_ardour/editor.cc:2451
+#, fuzzy
+msgid "Play region"
+msgstr "Suona la Regione"
+
+#: gtk_ardour/editor.cc:2453
+msgid "Loop Region"
+msgstr "Regione in loop"
+
+#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540
+#: gtk_ardour/library_ui.cc:972
+msgid "Play"
+msgstr "Suona"
+
+#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548
+msgid "Select All in track"
+msgstr "Seleziona tutto nella traccia"
+
+#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549
+msgid "Select All"
+msgstr "Seleziona tutto"
+
+#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550
+msgid "Invert in track"
+msgstr "Inerti nella traccia"
+
+#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551
+msgid "Invert"
+msgstr "Inverti"
+
+#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553
+msgid "Select loop range"
+msgstr "Seleziona l'intervallo di loop"
+
+#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554
+msgid "Select punch range"
+msgstr "Seleziona l'intervallo di punch"
+
+#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565
+#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369
+msgid "Cut"
+msgstr "Taglia"
+
+#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566
+#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371
+msgid "Copy"
+msgstr "Copia"
+
+#: gtk_ardour/editor.cc:2482
+#, fuzzy
+msgid "Paste at edit cursor"
+msgstr "Inizio al cursore di modifica"
+
+#: gtk_ardour/editor.cc:2483
+#, fuzzy
+msgid "Paste at mouse"
+msgstr "utilizza le uscite master"
+
+#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923
+msgid "Align"
+msgstr "Allinea"
+
+#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925
+msgid "Align Relative"
+msgstr "Allinea Realtivo"
+
+#: gtk_ardour/editor.cc:2492
+msgid "Insert chunk"
+msgstr "Inserisci lo Spezzone"
+
+#: gtk_ardour/editor.cc:2496
+msgid "New Region from range"
+msgstr "Nuova Regione dall'intervallo"
+
+#: gtk_ardour/editor.cc:2497
+msgid "Separate Range"
+msgstr "Separa l'intervallo"
+
+#: gtk_ardour/editor.cc:2507
+msgid "Insert Region"
+msgstr "Inserisci la Regione"
+
+#: gtk_ardour/editor.cc:2508
+msgid "Insert external sndfile"
+msgstr "Inserisci un file audio esterno"
+
+#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438
+msgid "Import"
+msgstr "Importa"
+
+#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574
+msgid "Nudge entire track fwd"
+msgstr "Sposta l'intera traccia in avanti"
+
+#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575
+msgid "Nudge track after edit cursor fwd"
+msgstr "Avanza la traccia dopo il cursore di modifica"
+
+#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576
+msgid "Nudge entire track bwd"
+msgstr "Arretra l'intera traccia"
+
+#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577
+msgid "Nudge track after edit cursor bwd"
+msgstr "Arretra la traccia dopo il cursore di modifica"
+
+#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920
+#: gtk_ardour/redirect_box.cc:373
+msgid "Paste"
+msgstr "Incolla"
+
+#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645
+#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799
+msgid "add marker"
+msgstr "aggiungi marcatore"
+
+#: gtk_ardour/editor.cc:3084
+msgid "select/move objects"
+msgstr "seleziona/muovi gli oggetti"
+
+#: gtk_ardour/editor.cc:3085
+msgid "select/move ranges"
+msgstr "seleziona/muovi range"
+
+#: gtk_ardour/editor.cc:3086
+msgid "draw gain automation"
+msgstr "disegna l'automazione gain"
+
+#: gtk_ardour/editor.cc:3087
+msgid "select zoom range"
+msgstr "seleziona l'intervallo di zoom"
+
+#: gtk_ardour/editor.cc:3088
+msgid "stretch/shrink regions"
+msgstr "allunga/restringi le regioni"
+
+#: gtk_ardour/editor.cc:3089
+#, fuzzy
+msgid "listen to specific regions"
+msgstr "Esegui la regione selezionata come loop"
+
+#: gtk_ardour/editor.cc:3213
+msgid "Start:"
+msgstr "Inizio:"
+
+#: gtk_ardour/editor.cc:3214
+msgid "End:"
+msgstr "Fine:"
+
+#: gtk_ardour/editor.cc:3215
+msgid "Edit:"
+msgstr "Modifica:"
+
+#: gtk_ardour/editor.cc:3429
+msgid "incorrectly formatted URI list, ignored"
+msgstr "Lista URI formattata in modo non corretto, ignorata"
+
+#: gtk_ardour/editor.cc:3611
+#, fuzzy
+msgid "set selected trackview"
+msgstr "Inserisci selezione"
+
+#: gtk_ardour/editor.cc:3647
+#, fuzzy
+msgid "set selected control point"
+msgstr "Rimuovi il punto di sincronizzazione"
+
+#: gtk_ardour/editor.cc:3719
+#, fuzzy
+msgid "set selected regionview"
+msgstr "Esegui la regione selezionata come loop"
+
+#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835
+#, fuzzy
+msgid "set selected regions"
+msgstr "Esegui la regione selezionata come loop"
+
+#: gtk_ardour/editor.cc:3891
+msgid "Undo"
+msgstr "Annulla"
+
+#: gtk_ardour/editor.cc:3893
+msgid "Undo (%1)"
+msgstr "Annulla (%1)"
+
+#: gtk_ardour/editor.cc:3903
+msgid "Redo"
+msgstr "Ripristina"
+
+#: gtk_ardour/editor.cc:3905
+msgid "Redo (%1)"
+msgstr "Ripristina (%1)"
+
+#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946
+msgid "... as new track"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947
+#, fuzzy
+msgid "... as new region"
+msgstr "Sposta Regione/i"
+
+#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452
+msgid "Import audio (copy)"
+msgstr "Importa audio (copia)"
+
+#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457
+msgid "Embed audio (link)"
+msgstr "Incorpora audio (collegamento)"
+
+#: gtk_ardour/editor.cc:3953
+msgid "Remove last capture"
+msgstr "Rimuovi l'ultima registrazione"
+
+#: gtk_ardour/editor.cc:3974
+msgid "Duplicate how many times?"
+msgstr "Quante volte duplico?"
+
+#: gtk_ardour/editor.cc:4550
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If left alone, no audio files used by it will be cleaned.\n"
+"If deleted, audio files used by it alone by will cleaned."
+msgstr ""
+
+#: gtk_ardour/editor.cc:4555
+msgid "Delete playlist"
+msgstr ""
+
+#: gtk_ardour/editor.cc:4556
+msgid "Keep playlist"
+msgstr ""
+
+#: gtk_ardour/editor.cc:4557
+#, fuzzy
+msgid "Cancel cleanup"
+msgstr "Pulisci"
+
+#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258
+#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290
+msgid ""
+"programming error: control point canvas item has no control point object "
+"pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:717
+msgid "programming error: line canvas item has no line object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:744
+#: gtk_ardour/editor_canvas_events.cc:784
+#: gtk_ardour/editor_canvas_events.cc:823
+msgid "programming error: no \"rect\" pointer associated with selection item"
+msgstr ""
+
+#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298
+#: gtk_ardour/mixer_ui.cc:670
+msgid "Show All"
+msgstr "Mostra Tutto"
+
+#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299
+#: gtk_ardour/mixer_ui.cc:671
+msgid "Hide All"
+msgstr "Nascondi tutto"
+
+#: gtk_ardour/editor_edit_groups.cc:98
+msgid "Name for new edit group"
+msgstr "Nome per il nuovo gruppo"
+
+#: gtk_ardour/editor_export_audio.cc:60
+msgid ""
+"There is no range to export.\n"
+"\n"
+"Select a range using the range mouse mode"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707
+msgid "programming error: no ImageFrameView selected"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930
+msgid "programming error: no MarkerView selected"
+msgstr ""
+
+#: gtk_ardour/editor_keys.cc:187
+#, fuzzy
+msgid "keyboard selection"
+msgstr "Esegui la regione selezionata come loop"
+
+#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376
+#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526
+#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584
+#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650
+#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700
+#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960
+#: gtk_ardour/editor_mouse.cc:4075
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681
+msgid "remove marker"
+msgstr "rimuovi marcatore"
+
+#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494
+msgid "Locate to"
+msgstr "Posiziona a"
+
+#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495
+msgid "Play from"
+msgstr "Suona da"
+
+#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496
+msgid "Set from playhead"
+msgstr "Imposta dall'inizio"
+
+#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497
+msgid "Set from range"
+msgstr "Imposta dall'intervallo"
+
+#: gtk_ardour/editor_markers.cc:479
+msgid "Set Loop Range"
+msgstr "Imposta l'intervallo di loop"
+
+#: gtk_ardour/editor_markers.cc:480
+msgid "Set Punch Range"
+msgstr "Imposta l'intervallo di Punch"
+
+#: gtk_ardour/editor_markers.cc:736
+msgid "ardour: rename mark"
+msgstr "ardour: rinomina il marcatore"
+
+#: gtk_ardour/editor_markers.cc:738
+#, fuzzy
+msgid "ardour: rename range"
+msgstr "ardour: rinomina la regione"
+
+#: gtk_ardour/editor_markers.cc:792
+#, fuzzy
+msgid "set loop range"
+msgstr "Seleziona l'intervallo di loop"
+
+#: gtk_ardour/editor_markers.cc:818
+#, fuzzy
+msgid "set punch range"
+msgstr "Seleziona l'intervallo di punch"
+
+#: gtk_ardour/editor_mouse.cc:99
+msgid "Editor::event_frame() used on unhandled event type %1"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1555
+msgid "programming error: start_grab called without drag item"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1760
+msgid "change fade in length"
+msgstr "modifica la lunghezza dello smorzamento in entrata"
+
+#: gtk_ardour/editor_mouse.cc:1778
+msgid "programming error: fade out canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1852
+msgid "change fade out length"
+msgstr "cambia la durata dello smorzamento in uscita"
+
+#: gtk_ardour/editor_mouse.cc:1871
+msgid "programming error: cursor canvas item has no cursor data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470
+msgid ""
+"programming error: meter marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2163
+#, fuzzy
+msgid "move meter mark"
+msgstr "rimuovi marcatore"
+
+#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335
+#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439
+msgid ""
+"programming error: tempo marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340
+#: gtk_ardour/editor_tempodisplay.cc:425
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2245
+#, fuzzy
+msgid "move tempo mark"
+msgstr "rimuovi marcatore"
+
+#: gtk_ardour/editor_mouse.cc:2388
+msgid "programming error: line canvas item has no line pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2497
+#, fuzzy
+msgid "move region(s)"
+msgstr "fai il Reverse della regione"
+
+#: gtk_ardour/editor_mouse.cc:2509
+msgid "Drag region copy"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2579
+#, fuzzy
+msgid "copy region(s)"
+msgstr "Sposta Regione/i"
+
+#: gtk_ardour/editor_mouse.cc:2612
+#, fuzzy
+msgid "Drag region brush"
+msgstr "Sposta Regione/i"
+
+#: gtk_ardour/editor_mouse.cc:3425
+#, fuzzy
+msgid "selection grab"
+msgstr "seleziona l'intervallo di zoom"
+
+#: gtk_ardour/editor_mouse.cc:3571
+#, fuzzy
+msgid "range selection"
+msgstr "Suona intervallo/selezione"
+
+#: gtk_ardour/editor_mouse.cc:3587
+#, fuzzy
+msgid "trim selection start"
+msgstr "Regioni/inizio"
+
+#: gtk_ardour/editor_mouse.cc:3603
+#, fuzzy
+msgid "trim selection end"
+msgstr "Importa selezione"
+
+#: gtk_ardour/editor_mouse.cc:3620
+#, fuzzy
+msgid "move selection"
+msgstr "Esegui la regione selezionata come loop"
+
+#: gtk_ardour/editor_mouse.cc:3995
+#, fuzzy
+msgid "Start point trim"
+msgstr "Inizio al cursore di modifica"
+
+#: gtk_ardour/editor_mouse.cc:4023
+msgid "End point trim"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:4062
+msgid "trimmed region"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:4203
+#, fuzzy
+msgid "new range marker"
+msgstr "agggiungi marcatore di intervallo"
+
+#: gtk_ardour/editor_mouse.cc:4422
+#, fuzzy
+msgid "select regions"
+msgstr "Esegui la regione selezionata come loop"
+
+#: gtk_ardour/editor_mouse.cc:4451
+msgid "Name for region:"
+msgstr "Nome per la Regione"
+
+#: gtk_ardour/editor_mouse.cc:4517
+msgid "timestretch"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:117
+#, fuzzy
+msgid "split"
+msgstr "Dividi"
+
+#: gtk_ardour/editor_ops.cc:153
+#, fuzzy
+msgid "remove region"
+msgstr "fai il Reverse della regione"
+
+#: gtk_ardour/editor_ops.cc:172
+msgid ""
+" This is destructive, will possibly delete audio files\n"
+"It cannot be undone\n"
+"Do you really want to destroy %1 ?"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "these regions"
+msgstr "fai il Reverse della regione"
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "this region"
+msgstr "Metti in muto questa regione"
+
+#: gtk_ardour/editor_ops.cc:179
+#, fuzzy
+msgid "Yes, destroy them."
+msgstr "Si, rimuovi."
+
+#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434
+msgid "Yes, destroy it."
+msgstr "Si, rimuovi."
+
+#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435
+#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300
+msgid "No, do nothing."
+msgstr "No, non fare niente."
+
+#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307
+msgid "extend selection"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357
+#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427
+msgid "nudge forward"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:491
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1305
+#, fuzzy
+msgid "set selection from range"
+msgstr "Nuova Regione dall'intervallo"
+
+#: gtk_ardour/editor_ops.cc:1421
+msgid "clear markers"
+msgstr "azzera i marcatori"
+
+#: gtk_ardour/editor_ops.cc:1433
+msgid "clear ranges"
+msgstr "azzera gli intervalli"
+
+#: gtk_ardour/editor_ops.cc:1452
+msgid "clear locations"
+msgstr "azzera le posizioni"
+
+#: gtk_ardour/editor_ops.cc:1503
+#, fuzzy
+msgid "insert dragged region"
+msgstr "Inserisci la Regione"
+
+#: gtk_ardour/editor_ops.cc:1538
+#, fuzzy
+msgid "insert region"
+msgstr "Inserisci la Regione"
+
+#: gtk_ardour/editor_ops.cc:1744
+msgid "ardour: rename region"
+msgstr "ardour: rinomina la regione"
+
+#: gtk_ardour/editor_ops.cc:1891
+msgid "You can't import an audiofile until you have a session loaded."
+msgstr ""
+"Non si può importare un file audio senza prima aver caricato una sessione"
+
+#: gtk_ardour/editor_ops.cc:1901
+#, fuzzy
+msgid "Import selected as tracks"
+msgstr "Importa selezione"
+
+#: gtk_ardour/editor_ops.cc:1904
+#, fuzzy
+msgid "Import selected to region list"
+msgstr "Esegui la regione selezionata come loop"
+
+#: gtk_ardour/editor_ops.cc:1933
+msgid "ardour: audio import in progress"
+msgstr "ardour: importazione audio in corso"
+
+#: gtk_ardour/editor_ops.cc:1937
+msgid "Cancel Import"
+msgstr "Annullare l'importazione"
+
+#: gtk_ardour/editor_ops.cc:1944
+msgid "ardour: importing %1"
+msgstr "ardour: importazione di %1"
+
+#: gtk_ardour/editor_ops.cc:1990
+msgid "%1 it anyway"
+msgstr "%1 comunque"
+
+#: gtk_ardour/editor_ops.cc:1996
+#, fuzzy
+msgid "Don't %1 it"
+msgstr "Non uscire"
+
+#: gtk_ardour/editor_ops.cc:1997
+msgid "%1 all without questions"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1998
+#, fuzzy
+msgid "Cancel entire import"
+msgstr "Annullare l'importazione"
+
+#: gtk_ardour/editor_ops.cc:2004
+#, fuzzy
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr "Il sample rate del file audio non corrisponde a quello della sessione!"
+
+#: gtk_ardour/editor_ops.cc:2032
+msgid "You can't embed an audiofile until you have a session loaded."
+msgstr ""
+"Non si può collegare un file audio senza prima aver caricato una sessione"
+
+#: gtk_ardour/editor_ops.cc:2039
+msgid "Add to External Region list"
+msgstr "Aggiungi alla lista di Regioni Esterne"
+
+#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210
+#: gtk_ardour/editor_ops.cc:2286
+msgid "Editor: cannot open file \"%1\" (%2)"
+msgstr "Editor: impossibile aprire il file \"%1\" (%2)"
+
+#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312
+msgid "could not open %1"
+msgstr "impossibile aprire %1"
+
+#: gtk_ardour/editor_ops.cc:2171
+#, fuzzy
+msgid "Insert selected as new tracks"
+msgstr "Inserisci selezione"
+
+#: gtk_ardour/editor_ops.cc:2186
+msgid "Insert selected"
+msgstr "Inserisci selezione"
+
+#: gtk_ardour/editor_ops.cc:2327
+#, fuzzy
+msgid "insert sndfile"
+msgstr "Inserisci un file audio esterno"
+
+#: gtk_ardour/editor_ops.cc:2464
+#, fuzzy
+msgid "separate"
+msgstr "Separa l'intervallo"
+
+#: gtk_ardour/editor_ops.cc:2528
+#, fuzzy
+msgid "trim to selection"
+msgstr "ardour: selezione del colore"
+
+#: gtk_ardour/editor_ops.cc:2568
+msgid "region fill"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2626
+#, fuzzy
+msgid "fill selection"
+msgstr "Suona intervallo/selezione"
+
+#: gtk_ardour/editor_ops.cc:2650
+msgid "Place the edit cursor at the desired sync point"
+msgstr ""
+"Posiziona il cursore di modifica al punto di sincronizzazione desiderato"
+
+#: gtk_ardour/editor_ops.cc:2656
+#, fuzzy
+msgid "set sync from edit cursor"
+msgstr "Suona dal cursore di modifica"
+
+#: gtk_ardour/editor_ops.cc:2668
+#, fuzzy
+msgid "remove sync"
+msgstr "Rimuovi il punto di sincronizzazione"
+
+#: gtk_ardour/editor_ops.cc:2682
+#, fuzzy
+msgid "naturalize"
+msgstr "Normalizza"
+
+#: gtk_ardour/editor_ops.cc:2746
+#, fuzzy
+msgid "align selection (relative)"
+msgstr "Allinea Realtivo"
+
+#: gtk_ardour/editor_ops.cc:2774
+#, fuzzy
+msgid "align selection"
+msgstr "ardour: selezione del colore"
+
+#: gtk_ardour/editor_ops.cc:2786
+#, fuzzy
+msgid "align region"
+msgstr "Sposta Regione/i"
+
+#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858
+#, fuzzy
+msgid "trim to edit"
+msgstr "Inizio al cursore di modifica"
+
+#: gtk_ardour/editor_ops.cc:2909
+#, fuzzy
+msgid "ardour: freeze"
+msgstr "ardour: rinomina la regione"
+
+#: gtk_ardour/editor_ops.cc:2914
+#, fuzzy
+msgid "Cancel Freeze"
+msgstr "Cancella"
+
+#: gtk_ardour/editor_ops.cc:2951
+#, fuzzy
+msgid "bounce range"
+msgstr "Fai il Bounce dell'intervallo"
+
+#: gtk_ardour/editor_ops.cc:3004
+msgid "cut"
+msgstr "taglia"
+
+#: gtk_ardour/editor_ops.cc:3007
+msgid "copy"
+msgstr "copia"
+
+#: gtk_ardour/editor_ops.cc:3020
+msgid " objects"
+msgstr "oggetti"
+
+#: gtk_ardour/editor_ops.cc:3046
+msgid " range"
+msgstr " intervallo"
+
+#: gtk_ardour/editor_ops.cc:3201
+#, fuzzy
+msgid "paste"
+msgstr "Incolla"
+
+#: gtk_ardour/editor_ops.cc:3236
+#, fuzzy
+msgid "paste chunk"
+msgstr "Crea uno Spezzone"
+
+#: gtk_ardour/editor_ops.cc:3276
+#, fuzzy
+msgid "duplicate region"
+msgstr "Esegui la regione selezionata come loop"
+
+#: gtk_ardour/editor_ops.cc:3309
+#, fuzzy
+msgid "duplicate selection"
+msgstr "ardour: selezione del colore"
+
+#: gtk_ardour/editor_ops.cc:3349
+#, fuzzy
+msgid "clear playlist"
+msgstr "azzera le posizioni"
+
+#: gtk_ardour/editor_ops.cc:3378
+#, fuzzy
+msgid "nudge track"
+msgstr "Nascondi traccia"
+
+#: gtk_ardour/editor_ops.cc:3431
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"Si vuole realmente rimuovere l'ultima registrazione?\n"
+"(questa azione non potrà essere annullata)"
+
+#: gtk_ardour/editor_ops.cc:3463
+#, fuzzy
+msgid "normalize"
+msgstr "Normalizza"
+
+#: gtk_ardour/editor_ops.cc:3510
+msgid "reverse regions"
+msgstr "fai il Reverse della regione"
+
+#: gtk_ardour/editor_region_list.cc:223
+#, fuzzy
+msgid "hidden"
+msgstr "Nascosto"
+
+#: gtk_ardour/editor_region_list.cc:408
+msgid "Show all"
+msgstr "Mostra tutto"
+
+#: gtk_ardour/editor_region_list.cc:417
+msgid "Ascending"
+msgstr "Ascendente"
+
+#: gtk_ardour/editor_region_list.cc:419
+msgid "Descending"
+msgstr "Discendente"
+
+#: gtk_ardour/editor_region_list.cc:423
+msgid "By Region Name"
+msgstr "Per Nome di Regione"
+
+#: gtk_ardour/editor_region_list.cc:425
+msgid "By Region Length"
+msgstr "Per Lunghezza di Regione"
+
+#: gtk_ardour/editor_region_list.cc:427
+msgid "By Region Position"
+msgstr "Per Posizione della Regione"
+
+#: gtk_ardour/editor_region_list.cc:429
+msgid "By Region Timestamp"
+msgstr "Per Data di Regione"
+
+#: gtk_ardour/editor_region_list.cc:431
+msgid "By Region Start in File"
+msgstr "Per Inizio di Regione nel file"
+
+#: gtk_ardour/editor_region_list.cc:433
+msgid "By Region End in File"
+msgstr "Per Fine di Regione nel file"
+
+#: gtk_ardour/editor_region_list.cc:435
+msgid "By Source File Name"
+msgstr "Per Nome di sorgente del file"
+
+#: gtk_ardour/editor_region_list.cc:437
+msgid "By Source File Length"
+msgstr "Per Lunghezza di sorgente del file"
+
+#: gtk_ardour/editor_region_list.cc:439
+msgid "By Source File Creation Date"
+msgstr "Per Data di creazione di sorgente del file"
+
+#: gtk_ardour/editor_region_list.cc:441
+msgid "By Source Filesystem"
+msgstr "Per Filesystem di sorgente"
+
+#: gtk_ardour/editor_region_list.cc:444
+msgid "Sorting"
+msgstr "Ordinamento"
+
+#: gtk_ardour/editor_region_list.cc:808
+msgid "Regions/length"
+msgstr "Regioni/lunghezza"
+
+#: gtk_ardour/editor_region_list.cc:812
+msgid "Regions/position"
+msgstr "Regioni/posizione"
+
+#: gtk_ardour/editor_region_list.cc:816
+msgid "Regions/creation"
+msgstr "Regioni/creazione"
+
+#: gtk_ardour/editor_region_list.cc:820
+msgid "Regions/start"
+msgstr "Regioni/inizio"
+
+#: gtk_ardour/editor_region_list.cc:824
+msgid "Regions/end"
+msgstr "Regioni/fine"
+
+#: gtk_ardour/editor_region_list.cc:828
+msgid "Regions/file name"
+msgstr "Regioni/nome file"
+
+#: gtk_ardour/editor_region_list.cc:832
+msgid "Regions/file size"
+msgstr "Regioni/dimensioni file"
+
+#: gtk_ardour/editor_region_list.cc:836
+msgid "Regions/file date"
+msgstr "Regioni/data file"
+
+#: gtk_ardour/editor_region_list.cc:840
+msgid "Regions/file system"
+msgstr "Regioni/file system"
+
+#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73
+#: gtk_ardour/editor_route_list.cc:231
+msgid "editor"
+msgstr ""
+
+#: gtk_ardour/editor_route_list.cc:300
+msgid "Show All AbstractTracks"
+msgstr "Mostra tutte le Tracce"
+
+#: gtk_ardour/editor_route_list.cc:301
+msgid "Hide All AbstractTracks"
+msgstr "Nascondi tutte le Tracce"
+
+#: gtk_ardour/editor_route_list.cc:302
+msgid "Show All AudioBus"
+msgstr "Mostra tutti i Bus Audio"
+
+#: gtk_ardour/editor_route_list.cc:303
+msgid "Hide All AudioBus"
+msgstr "Nascondi tutti i Bus Audio"
+
+#: gtk_ardour/editor_rulers.cc:311
+msgid "New location marker"
+msgstr "Marcatore di nuova posizione"
+
+#: gtk_ardour/editor_rulers.cc:312
+msgid "Clear all locations"
+msgstr "Pulisci tutte le posizioni"
+
+#: gtk_ardour/editor_rulers.cc:317
+msgid "Clear all ranges"
+msgstr "Pulisci tutti gli intervalli"
+
+#: gtk_ardour/editor_rulers.cc:326
+msgid "New Tempo"
+msgstr "Nuovo tempo"
+
+#: gtk_ardour/editor_rulers.cc:327
+msgid "Clear tempo"
+msgstr "Pulisci tempo"
+
+#: gtk_ardour/editor_rulers.cc:332
+msgid "New Meter"
+msgstr "Nuovo Meter"
+
+#: gtk_ardour/editor_rulers.cc:333
+msgid "Clear meter"
+msgstr "Pulisci Meter"
+
+#: gtk_ardour/editor_rulers.cc:341
+msgid "Min:Secs"
+msgstr "Min:Sec"
+
+#: gtk_ardour/editor_selection_list.cc:117
+msgid "name for chunk:"
+msgstr "Nome dello Spezzone"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Create chunk"
+msgstr "Crea uno Spezzone"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Forget it"
+msgstr "Annulla"
+
+#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295
+msgid "add"
+msgstr "Aggiungi"
+
+#: gtk_ardour/editor_tempodisplay.cc:276
+#, fuzzy
+msgid "add tempo mark"
+msgstr "agggiungi marcatore di intervallo"
+
+#: gtk_ardour/editor_tempodisplay.cc:318
+#, fuzzy
+msgid "add meter mark"
+msgstr "agggiungi marcatore di intervallo"
+
+#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383
+msgid "done"
+msgstr "fatto"
+
+#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404
+msgid "replace tempo mark"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487
+#, fuzzy
+msgid "remove tempo mark"
+msgstr "rimuovi marcatore"
+
+#: gtk_ardour/editor_timefx.cc:50
+msgid "Quick but Ugly"
+msgstr "Rapido ma inaccurato"
+
+#: gtk_ardour/editor_timefx.cc:51
+msgid "Skip Anti-aliasing"
+msgstr "Salta l'Anti-aliasing"
+
+#: gtk_ardour/editor_timefx.cc:53
+msgid "Stretch/Shrink it"
+msgstr "Allunga/Restringi"
+
+#: gtk_ardour/editor_timefx.cc:57
+msgid "ardour: timestretch"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:58
+msgid "TimeStretchDialog"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83
+#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85
+msgid "TimeStretchButton"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:86
+msgid "TimeStretchProgress"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:151
+msgid "timestretch cannot be started - thread creation error"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410
+#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189
+msgid "22.05kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413
+#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949
+#: gtk_ardour/export_dialog.cc:1191
+msgid "44.1kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416
+#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193
+msgid "48kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419
+#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195
+msgid "88.2kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422
+#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197
+msgid "96kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425
+#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199
+msgid "192kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:73
+msgid "best"
+msgstr "migliore"
+
+#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964
+msgid "fastest"
+msgstr "più veloce"
+
+#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966
+msgid "linear"
+msgstr "lineare"
+
+#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968
+msgid "better"
+msgstr "meglio"
+
+#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970
+msgid "intermediate"
+msgstr "medio"
+
+#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979
+msgid "Rectangular"
+msgstr "Rettangolare"
+
+#: gtk_ardour/export_dialog.cc:84
+msgid "Shaped Noise"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981
+msgid "Triangular"
+msgstr "Triangolare"
+
+#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336
+msgid "stereo"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497
+#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219
+#: gtk_ardour/utils.cc:334
+msgid "mono"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:97
+msgid "CUE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:98
+msgid "TOC"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:106
+msgid "FORMAT"
+msgstr "FORMATO"
+
+#: gtk_ardour/export_dialog.cc:107
+msgid "SAMPLE RATE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:108
+msgid "CONVERSION QUALITY"
+msgstr "QUALITÀ DI CONVERSIONE"
+
+#: gtk_ardour/export_dialog.cc:109
+msgid "DITHER TYPE"
+msgstr "TIPO DI DITHER"
+
+#: gtk_ardour/export_dialog.cc:110
+#, fuzzy
+msgid "CD MARKER FILE TYPE"
+msgstr "TIPO DI FILE"
+
+#: gtk_ardour/export_dialog.cc:111
+msgid "CHANNELS"
+msgstr "CANALI"
+
+#: gtk_ardour/export_dialog.cc:112
+msgid "FILE TYPE"
+msgstr "TIPO DI FILE"
+
+#: gtk_ardour/export_dialog.cc:113
+msgid "SAMPLE FORMAT"
+msgstr "FORMATO DEL CAMPIONE"
+
+#: gtk_ardour/export_dialog.cc:114
+msgid "SAMPLE ENDIANNESS"
+msgstr "ENDIANNES DEL CAMPIONE"
+
+#: gtk_ardour/export_dialog.cc:115
+#, fuzzy
+msgid "EXPORT CD MARKER FILE ONLY"
+msgstr "TIPO DI FILE"
+
+#: gtk_ardour/export_dialog.cc:116
+msgid "EXPORT TO FILE"
+msgstr "ESPORTA SU FILE"
+
+#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118
+#: gtk_ardour/option_editor.cc:119
+msgid "Browse"
+msgstr "Naviga"
+
+#: gtk_ardour/export_dialog.cc:119
+msgid "Specific tracks ..."
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:131
+msgid "ardour: export"
+msgstr "ardour: esportazione"
+
+#: gtk_ardour/export_dialog.cc:132
+#, fuzzy
+msgid "ardour_export"
+msgstr "ardour: esportazione"
+
+#: gtk_ardour/export_dialog.cc:156
+#, fuzzy
+msgid "Output"
+msgstr "Uscite"
+
+#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626
+msgid "Track"
+msgstr "Traccia"
+
+#: gtk_ardour/export_dialog.cc:287
+msgid "slereg"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:658
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD toc file"
+msgstr ""
+"Editor: impossibile aprire \"%1\" come file da esportare a marcatori di "
+"tracce per CD"
+
+#: gtk_ardour/export_dialog.cc:780
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD cue file"
+msgstr ""
+"Editor: impossibile aprire \"%1\" come file da esportare a marcatori di "
+"tracce per CD"
+
+#: gtk_ardour/export_dialog.cc:799
+msgid "WAV"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:1051
+msgid "Stop Export"
+msgstr "Ferma esportazione"
+
+#: gtk_ardour/gain_automation_time_axis.cc:60
+#, fuzzy
+msgid "add gain automation event"
+msgstr "aggiungi evento di automazione a "
+
+#: gtk_ardour/gain_meter.cc:68
+msgid "Cannot create slider pixmaps"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:83
+msgid "dbFS"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134
+#: gtk_ardour/gain_meter.cc:728
+msgid "pre"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724
+#, fuzzy
+msgid "input"
+msgstr "entrata %1"
+
+#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732
+#, fuzzy
+msgid "post"
+msgstr "entrata"
+
+#: gtk_ardour/gain_meter.cc:146
+msgid "tupni"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470
+#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537
+msgid "-inf"
+msgstr ""
+
+#: gtk_ardour/imageframe_socket_handler.cc:127
+msgid "Image Compositor Socket has been shutdown/closed"
+msgstr ""
+
+#: gtk_ardour/imageframe_time_axis.cc:295
+#, fuzzy
+msgid "0.5 seconds"
+msgstr "Secondi"
+
+#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259
+#, fuzzy
+msgid "1 seconds"
+msgstr "Secondi"
+
+#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260
+#, fuzzy
+msgid "1.5 seconds"
+msgstr "Secondi"
+
+#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261
+#, fuzzy
+msgid "2 seconds"
+msgstr "Secondi"
+
+#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262
+#, fuzzy
+msgid "2.5 seconds"
+msgstr "Secondi"
+
+#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263
+#, fuzzy
+msgid "3 seconds"
+msgstr "Secondi"
+
+#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268
+#, fuzzy
+msgid "Duration (sec)"
+msgstr "Sposta Regione/i"
+
+#: gtk_ardour/imageframe_time_axis.cc:310
+#, fuzzy
+msgid "Remove Frame"
+msgstr "Rimuovi Campo"
+
+#: gtk_ardour/imageframe_time_axis.cc:313
+msgid "Image Frame"
+msgstr ""
+
+#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274
+#, fuzzy
+msgid "Rename Track"
+msgstr "Rinomina"
+
+#: gtk_ardour/io_selector.cc:64
+msgid "%1 input"
+msgstr "entrata %1"
+
+#: gtk_ardour/io_selector.cc:66
+msgid "%1 output"
+msgstr "uscita %1"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103
+msgid "Inputs"
+msgstr "Entrate"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104
+msgid "Outputs"
+msgstr "Uscite"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Input"
+msgstr "aggiungi una entrata"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Output"
+msgstr "aggiungi una uscita"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Input"
+msgstr "Rimuovi il punto di sincronizzazione"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Output"
+msgstr "# Uscite"
+
+#: gtk_ardour/io_selector.cc:144
+#, fuzzy
+msgid "Disconnect All"
+msgstr "Disconnetti"
+
+#: gtk_ardour/io_selector.cc:158
+msgid "Available connections"
+msgstr "Connessioni disponibili"
+
+#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636
+#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724
+msgid "port"
+msgstr "entrata"
+
+#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587
+msgid "There are no more JACK ports available."
+msgstr ""
+
+#: gtk_ardour/io_selector.cc:790
+msgid "ardour: "
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:419
+msgid "KeyboardTarget: keyname \"%1\" is unknown."
+msgstr "KeyboardTarget: il keyname \"%1\" è sconosciuto"
+
+#: gtk_ardour/keyboard.cc:645
+msgid ""
+"Your system is completely broken - NumLock uses \"%1\"as its modifier. This "
+"is madness - see the man page for xmodmap to find out how to fix this."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:653
+msgid ""
+"Your system generates \"%1\" when the NumLock key is pressed. This can cause "
+"problems when editing so Ardour will use %2 to mean Meta rather than %1"
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:714
+msgid "You have %1 keys bound to \"mod1\""
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:729
+msgid "You have %1 keys bound to \"mod2\""
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:744
+msgid "You have %1 keys bound to \"mod3\""
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:759
+msgid "You have %1 keys bound to \"mod4\""
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:774
+msgid "You have %1 keys bound to \"mod5\""
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:72
+msgid "KeyboardTarget: empty string passed to add_binding."
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:78
+msgid "KeyboardTarget: no translation found for \"%1\""
+msgstr "KeyboardTarget: nessuna traduzione trovata per \"%1\""
+
+#: gtk_ardour/keyboard_target.cc:83
+msgid "KeyboardTarget: unknown action \"%1\""
+msgstr "KeyboardTarget: \"1\" azione sconosciuta"
+
+#: gtk_ardour/keyboard_target.cc:248
+msgid "misformed binding node - ignored"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:62
+msgid "Soundfile Library"
+msgstr "Libreria Audio"
+
+#: gtk_ardour/library_ui.cc:63
+msgid "Filesystem"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:66
+msgid "Split Channels"
+msgstr "Dividi i Canali"
+
+#: gtk_ardour/library_ui.cc:69
+msgid "ardour: soundfile selector"
+msgstr "ardour: selezione del file audio"
+
+#: gtk_ardour/library_ui.cc:430
+msgid "Add to Library..."
+msgstr "Aggiungi alla libreria..."
+
+#: gtk_ardour/library_ui.cc:431
+msgid "Remove..."
+msgstr "Rimuovi..."
+
+#: gtk_ardour/library_ui.cc:432
+msgid "Find..."
+msgstr "Trova..."
+
+#: gtk_ardour/library_ui.cc:433
+msgid "Add Folder"
+msgstr "Crea una Cartella"
+
+#: gtk_ardour/library_ui.cc:434
+msgid "Add audio file or directory"
+msgstr "Aggiungi un file audio o una cartella"
+
+#: gtk_ardour/library_ui.cc:713
+msgid "Importing"
+msgstr "Importazione"
+
+#: gtk_ardour/library_ui.cc:748
+msgid "%1 not added to database"
+msgstr "%1 non aggiunto al database"
+
+#: gtk_ardour/library_ui.cc:767
+msgid "Folder name:"
+msgstr "Nome della Cartella:"
+
+#: gtk_ardour/library_ui.cc:838
+msgid "Should not be reached"
+msgstr "Impossibile aprire"
+
+#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096
+msgid "file \"%1\" could not be opened"
+msgstr "Impossibile aprire \"%1\""
+
+#: gtk_ardour/library_ui.cc:956
+msgid "Field"
+msgstr "Campo"
+
+#: gtk_ardour/library_ui.cc:957
+msgid "Value"
+msgstr "Valore"
+
+#: gtk_ardour/library_ui.cc:973
+msgid "Stop"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:974
+msgid "Add Field..."
+msgstr "Aggiungi Campo"
+
+#: gtk_ardour/library_ui.cc:975
+msgid "Remove Field"
+msgstr "Rimuovi Campo"
+
+#: gtk_ardour/library_ui.cc:979
+msgid "Soundfile Info"
+msgstr "Info sul file audio"
+
+#: gtk_ardour/library_ui.cc:1106
+msgid "file \"%1\" appears not to be an audio file"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1159
+msgid "Could not read file: %1 (%2)."
+msgstr "Editor: impossibile aprire il file %1 (%2)."
+
+#: gtk_ardour/library_ui.cc:1177
+msgid "Could not access soundfile: "
+msgstr "Impossibile accedere al file audio"
+
+#: gtk_ardour/library_ui.cc:1222
+msgid "Field name:"
+msgstr "Nome del campo:"
+
+#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367
+msgid "Field value:"
+msgstr "Valore del campo"
+
+#: gtk_ardour/library_ui.cc:1295
+msgid "Find"
+msgstr "Trova"
+
+#: gtk_ardour/library_ui.cc:1296
+msgid "AND"
+msgstr "E"
+
+#: gtk_ardour/library_ui.cc:1297
+msgid "OR"
+msgstr "O"
+
+#: gtk_ardour/library_ui.cc:1300
+msgid "ardour: locate soundfiles"
+msgstr "ardour: localizza file audio"
+
+#: gtk_ardour/library_ui.cc:1426
+msgid "Results"
+msgstr "Risultati"
+
+#: gtk_ardour/library_ui.cc:1427
+msgid "Uris"
+msgstr "Uri"
+
+#: gtk_ardour/library_ui.cc:1439
+msgid "Create multi-channel region"
+msgstr "Crea regione a più canali"
+
+#: gtk_ardour/library_ui.cc:1442
+msgid "Ardour: Search Results"
+msgstr "Ardour: Risultati della Ricerca"
+
+#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50
+msgid "Set"
+msgstr "Imposta"
+
+#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51
+msgid "Go"
+msgstr "Vai"
+
+#: gtk_ardour/location_ui.cc:54
+msgid "CD"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:55
+msgid "Hidden"
+msgstr "Nascosto"
+
+#: gtk_ardour/location_ui.cc:57
+msgid "SCMS"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:58
+msgid "Pre-Emphasis"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:592
+msgid "Add New Location"
+msgstr "Aggiungi una nuova Posizione"
+
+#: gtk_ardour/location_ui.cc:593
+msgid "Add New Range"
+msgstr "Aggiungi un nuovo Intervallo"
+
+#: gtk_ardour/location_ui.cc:597
+msgid "ardour: locations"
+msgstr "ardour: posizioni"
+
+#: gtk_ardour/location_ui.cc:598
+msgid "ardour_locations"
+msgstr "ardour_posizioni"
+
+#: gtk_ardour/location_ui.cc:629
+#, fuzzy
+msgid "Location (CD Index) Markers"
+msgstr "Marcatori di posizione"
+
+#: gtk_ardour/location_ui.cc:649
+#, fuzzy
+msgid "Range (CD Track) Markers"
+msgstr "Marcatori di intervallo"
+
+#: gtk_ardour/location_ui.cc:814
+msgid "add range marker"
+msgstr "agggiungi marcatore di intervallo"
+
+#: gtk_ardour/main.cc:76
+msgid "ardour is killing itself for a clean exit\n"
+msgstr "ardour sta forzando la chiusura per un'uscita pulita\n"
+
+#: gtk_ardour/main.cc:85
+msgid "stopping user interface\n"
+msgstr "chiusura dell'interfaccia\n"
+
+#: gtk_ardour/main.cc:104
+#, fuzzy, c-format
+msgid "%d(%d): received signal %d\n"
+msgstr "%d: ricevuto segnale %d\n"
+
+#: gtk_ardour/main.cc:190
+msgid "cannot become new process group leader (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:217
+msgid "cannot setup signal handling for %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:228
+msgid "cannot set default signal mask (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:253
+#, fuzzy
+msgid ""
+"Without a UI style file, ardour will look strange.\n"
+" Please set ARDOUR_UI_RC to point to a valid UI style file"
+msgstr ""
+"Senza uno Stile per l'Interfaccia, ardour apparirà strano\n"
+"Impostare la variabile ARDOUR_UI_RC per puntare ad uno Stile"
+
+#: gtk_ardour/main.cc:292
+msgid ""
+"Ardour could not connect to JACK.\n"
+"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 ""
+
+#: gtk_ardour/main.cc:305
+msgid "ardour: unplugged"
+msgstr "ardour: scollegato"
+
+#: gtk_ardour/main.cc:363
+msgid "Ardour/GTK "
+msgstr ""
+
+#: gtk_ardour/main.cc:365
+msgid ""
+"\n"
+" (built using "
+msgstr ""
+
+#: gtk_ardour/main.cc:369
+#, fuzzy
+msgid " with libardour "
+msgstr " con libardour "
+
+#: gtk_ardour/main.cc:374
+msgid " and GCC version "
+msgstr ""
+
+#: gtk_ardour/main.cc:384
+msgid "Copyright (C) 1999-2005 Paul Davis"
+msgstr ""
+
+#: gtk_ardour/main.cc:385
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+msgstr ""
+
+#: gtk_ardour/main.cc:387
+msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
+msgstr ""
+
+#: gtk_ardour/main.cc:388
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr ""
+
+#: gtk_ardour/main.cc:389
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr ""
+
+#: gtk_ardour/main.cc:390
+msgid "under certain conditions; see the source for copying conditions."
+msgstr ""
+
+#: gtk_ardour/main.cc:399
+msgid "could not create ARDOUR GUI"
+msgstr "Impossibile creare l'interfaccia di Ardour"
+
+#: gtk_ardour/main.cc:419
+msgid "Could not connect to JACK server as \"%1\""
+msgstr ""
+
+#: gtk_ardour/main.cc:424
+msgid "could not initialize Ardour."
+msgstr "impossibile avviare Ardour"
+
+#: gtk_ardour/main.cc:435
+msgid "could not load command line session \"%1\""
+msgstr "Impossibile caricare la sessione \"%1\" da linea di comando"
+
+#: gtk_ardour/main.cc:455
+msgid ""
+"\n"
+"\n"
+"A session named \"%1\" already exists.\n"
+"To avoid this message, start ardour as \"ardour %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:466
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as \"ardour --new %1"
+msgstr ""
+
+#: gtk_ardour/marker.cc:354
+#, fuzzy
+msgid "MarkerText"
+msgstr "Marcatori"
+
+#: gtk_ardour/marker_time_axis.cc:271
+#, fuzzy
+msgid "Remove Marker"
+msgstr "rimuovi marcatore"
+
+#: gtk_ardour/marker_time_axis.cc:273
+#, fuzzy
+msgid "Marker"
+msgstr "Marcatori"
+
+#: gtk_ardour/meter_bridge.cc:74
+msgid "ardour: meter bridge"
+msgstr ""
+
+#: gtk_ardour/meter_bridge.cc:75
+msgid "ardour_meter_bridge"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93
+#, c-format
+msgid "# of %u-sample overs"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:219
+msgid "New name for meter:"
+msgstr "Nuovo nome per il meter:"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507
+#: gtk_ardour/region_editor.cc:45
+msgid "mute"
+msgstr "muto"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508
+msgid "solo"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506
+msgid "RECORD"
+msgstr "REGISTRA"
+
+#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514
+msgid "polarity"
+msgstr "polarità"
+
+#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509
+msgid "comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810
+msgid "INPUT"
+msgstr "ENTRATA"
+
+#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831
+msgid "OUTPUT"
+msgstr "USCITA"
+
+#: gtk_ardour/mixer_strip.cc:173
+msgid "Pan automation mode"
+msgstr "Modalita' automazione pan"
+
+#: gtk_ardour/mixer_strip.cc:174
+msgid "Gain automation mode"
+msgstr "Modalita' automazione gain"
+
+#: gtk_ardour/mixer_strip.cc:176
+msgid "Pan automation type"
+msgstr "Tipo di automazione pan"
+
+#: gtk_ardour/mixer_strip.cc:177
+msgid "Gain automation type"
+msgstr "Tipo di automazione gain"
+
+#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232
+#: gtk_ardour/mixer_strip.cc:979
+msgid "trim"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233
+#: gtk_ardour/mixer_strip.cc:983
+msgid "abs"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:240
+msgid "gain automation mode"
+msgstr "modalita' di automazione gain"
+
+#: gtk_ardour/mixer_strip.cc:241
+msgid "pan automation mode"
+msgstr "modalita' di automazione pan"
+
+#: gtk_ardour/mixer_strip.cc:242
+msgid "gain automation state"
+msgstr "stato dell'automazione gain"
+
+#: gtk_ardour/mixer_strip.cc:243
+msgid "pan automation state"
+msgstr "stato dell'automazione pan"
+
+#: gtk_ardour/mixer_strip.cc:259
+msgid "varispeed"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174
+msgid "click to add/edit comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:463
+msgid "unknown strip width \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:522
+msgid "REC"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:525
+#, fuzzy
+msgid "cmt"
+msgstr "taglia"
+
+#: gtk_ardour/mixer_strip.cc:530
+msgid "pol"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620
+#: gtk_ardour/redirect_box.cc:1180
+msgid "Not connected to JACK - no I/O changes are possible"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667
+msgid "could not register new ports required for that connection"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:813
+msgid "IN"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:834
+msgid "OUT"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:950
+msgid "aplay"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:956
+msgid "awrite"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:1134
+#, fuzzy
+msgid ": comment editor"
+msgstr "IU: impossibile avviare l'editor"
+
+#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224
+msgid "no group"
+msgstr "nessun gruppo"
+
+#: gtk_ardour/mixer_strip.cc:1227
+msgid "~G"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:52
+msgid "Strips"
+msgstr "Strisce"
+
+#: gtk_ardour/mixer_ui.cc:56
+msgid "Snapshots"
+msgstr "Istantanee"
+
+#: gtk_ardour/mixer_ui.cc:61
+msgid "***"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17
+#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144
+#: gtk_ardour/tempo_dialog.cc:162
+msgid "Bar"
+msgstr "Battuta"
+
+#: gtk_ardour/mixer_ui.cc:121
+msgid "Mix Groups"
+msgstr "Gruppi di mixaggio"
+
+#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373
+msgid "ardour: mixer"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:192
+msgid "ardour_mixer"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:342
+msgid "ardour: mixer: "
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:641
+msgid "signal"
+msgstr "segnale"
+
+#: gtk_ardour/mixer_ui.cc:672
+msgid "Show All AudioTrack MixerStrips"
+msgstr "Mostra tutte le Tracce del Mixer"
+
+#: gtk_ardour/mixer_ui.cc:673
+msgid "Hide All AudioTrack MixerStrips"
+msgstr "Nascondi tutte le Tracce del Mixer"
+
+#: gtk_ardour/mixer_ui.cc:674
+msgid "Show All AudioBus MixerStrips"
+msgstr "Mostra tutti i Bus del Mixer"
+
+#: gtk_ardour/mixer_ui.cc:675
+msgid "Hide All AudioBus MixerStrips"
+msgstr "Nascondi tutti i Bus del Mixer"
+
+#: gtk_ardour/mixer_ui.cc:687
+msgid "track display list item for renamed strip not found!"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:700
+msgid "Name for new mix group"
+msgstr "Nome del nuovo gruppo di mixaggio"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Session name:"
+msgstr "Nome della sessione:"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Create"
+msgstr "Crea"
+
+#: gtk_ardour/new_session_dialog.cc:40
+msgid "use control outs"
+msgstr "utilizza le uscite di controllo"
+
+#: gtk_ardour/new_session_dialog.cc:41
+msgid "use master outs"
+msgstr "utilizza le uscite master"
+
+#: gtk_ardour/new_session_dialog.cc:42
+#, fuzzy
+msgid "automatically connect track inputs to physical ports"
+msgstr "autoconnetti le entrate delle tracce alle entrate fisiche"
+
+#: gtk_ardour/new_session_dialog.cc:43
+#, fuzzy
+msgid "automatically connect track outputs to master outs"
+msgstr "autoconnetti le uscite delle tracce alle uscite master"
+
+#: gtk_ardour/new_session_dialog.cc:44
+#, fuzzy
+msgid "automatically connect track outputs to physical ports"
+msgstr "autoconnetti le uscite delle tracce alle uscite fisiche"
+
+#: gtk_ardour/new_session_dialog.cc:45
+msgid "manually connect track outputs"
+msgstr "connetti manualmente le uscite delle tracce"
+
+#: gtk_ardour/new_session_dialog.cc:50
+msgid "Advanced..."
+msgstr "Avanzate..."
+
+#: gtk_ardour/new_session_dialog.cc:52
+msgid "show again"
+msgstr "mostra ancora"
+
+#: gtk_ardour/new_session_dialog.cc:55
+msgid "Hardware Inputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:56
+msgid "Hardware Outputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:62
+msgid "new session setup"
+msgstr "impostazione di nuova sessione"
+
+#: gtk_ardour/new_session_dialog.cc:63
+msgid "ardour_new_session"
+msgstr "ardour_nuova_sessione"
+
+#: gtk_ardour/new_session_dialog.cc:72
+msgid "This session will playback and record at %1 Hz"
+msgstr "Questa sessione suonera' e registrera' a %1 Hz"
+
+#: gtk_ardour/new_session_dialog.cc:74
+msgid ""
+"This rate is set by JACK and cannot be changed.\n"
+"If you want to use a different sample rate\n"
+"please exit and restart JACK"
+msgstr ""
+"Questo e' impostato da JACK e non pu essere cambiato.\n"
+"Se si vuole utilizzare un sample rate differente\n"
+"bisogna chiudere e riavviare JACK"
+
+#: gtk_ardour/new_session_dialog.cc:155
+#, fuzzy
+msgid "Session template"
+msgstr "usa un modello esistente"
+
+#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20
+#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146
+#: gtk_ardour/tempo_dialog.cc:164
+msgid "Location"
+msgstr "Posizione"
+
+#: gtk_ardour/new_session_dialog.cc:178
+msgid "Configuration"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:269
+msgid "blank"
+msgstr "vuoto"
+
+#: gtk_ardour/new_session_dialog.cc:328
+msgid "No template - create tracks/busses manually"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:337
+#, fuzzy
+msgid "No template"
+msgstr "-modello"
+
+#: gtk_ardour/option_editor.cc:48
+msgid "Internal"
+msgstr "interno"
+
+#: gtk_ardour/option_editor.cc:49
+#, fuzzy
+msgid "Slave to MTC"
+msgstr "Invia MTC"
+
+#: gtk_ardour/option_editor.cc:50
+msgid "Sync with JACK"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:51
+msgid "never used but stops crashes"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:56
+#, fuzzy
+msgid "Later regions are higher"
+msgstr "Porta la regione giù di un livello"
+
+#: gtk_ardour/option_editor.cc:57
+msgid "Most recently added/moved/trimmed regions are higher"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:58
+#, fuzzy
+msgid "Most recently added regions are higher"
+msgstr "Porta la regione giù di un livello"
+
+#: gtk_ardour/option_editor.cc:63
+#, fuzzy
+msgid "Span entire region overlap"
+msgstr "Porta la regione su di un livello"
+
+#: gtk_ardour/option_editor.cc:64
+msgid "Short fades at the start of the overlap"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:82
+#, fuzzy
+msgid "Automatically create crossfades"
+msgstr "Smorzamento incrociato automatico in caso sovrapposizione"
+
+#: gtk_ardour/option_editor.cc:83
+msgid "New full-overlap crossfades are unmuted"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:84
+#, fuzzy
+msgid "Region layering mode"
+msgstr "Regioni/fine"
+
+#: gtk_ardour/option_editor.cc:85
+#, fuzzy
+msgid "Crossfade model"
+msgstr "Smorzamento Incrociato"
+
+#: gtk_ardour/option_editor.cc:90
+msgid "Latched solo"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:91
+msgid "Solo via bus"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:96
+msgid "Show waveforms while recording"
+msgstr "Mostra le forme Wave in registrazione"
+
+#: gtk_ardour/option_editor.cc:97
+msgid "Narrow mixer strips"
+msgstr "Strisce del Mixer strette"
+
+#: gtk_ardour/option_editor.cc:98
+msgid "Show measure lines"
+msgstr "Mostra le linee delle Misure"
+
+#: gtk_ardour/option_editor.cc:99
+msgid "Follow playhead"
+msgstr "Segui il cursore"
+
+#: gtk_ardour/option_editor.cc:103
+msgid "Send MTC"
+msgstr "Invia MTC"
+
+#: gtk_ardour/option_editor.cc:104
+msgid "Send MMC"
+msgstr "Invia MMC"
+
+#: gtk_ardour/option_editor.cc:105
+msgid "JACK time master"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:107
+msgid "SMPTE offset is negative"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:111
+msgid "Send MIDI parameter feedback"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:112
+msgid "MIDI parameter control"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:113
+#, fuzzy
+msgid "MMC control"
+msgstr "Porta MMC"
+
+#: gtk_ardour/option_editor.cc:131
+#, fuzzy
+msgid "Auto-connect new track inputs to hardware"
+msgstr "Connetti automaticamente nuove tracce"
+
+#: gtk_ardour/option_editor.cc:132
+#, fuzzy
+msgid "Auto-connect new track outputs to hardware"
+msgstr "Connetti automaticamente nuove tracce"
+
+#: gtk_ardour/option_editor.cc:133
+#, fuzzy
+msgid "Auto-connect new track outputs to master bus"
+msgstr "autoconnetti le uscite delle tracce alle uscite master"
+
+#: gtk_ardour/option_editor.cc:134
+#, fuzzy
+msgid "Manually connect new track outputs"
+msgstr "connetti manualmente le uscite delle tracce"
+
+#: gtk_ardour/option_editor.cc:135
+msgid "Use Hardware Monitoring"
+msgstr "Usa il Monitoraggio Hardware"
+
+#: gtk_ardour/option_editor.cc:136
+msgid "Use Software Monitoring"
+msgstr "Usa il Monitoraggio Software"
+
+#: gtk_ardour/option_editor.cc:137
+msgid "Stop plugins with transport"
+msgstr "Ferma i plugin durante il transport"
+
+#: gtk_ardour/option_editor.cc:138
+msgid "Run plugins while recording"
+msgstr "Avvia i plugin durante la registrazione"
+
+#: gtk_ardour/option_editor.cc:139
+#, fuzzy
+msgid "Verify remove last capture"
+msgstr "Rimuovi l'ultima registrazione"
+
+#: gtk_ardour/option_editor.cc:140
+msgid "Stop recording on xrun"
+msgstr "Ferma la registrazione in caso di xrun"
+
+#: gtk_ardour/option_editor.cc:141
+msgid "Stop transport at end of session"
+msgstr "Ferma il transport a fine sessione"
+
+#: gtk_ardour/option_editor.cc:142
+msgid "Debug keyboard events"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:143
+msgid "-12dB gain reduction for ffwd/rew"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:152
+msgid "ardour: options editor"
+msgstr "ardour: editor delle opzioni"
+
+#: gtk_ardour/option_editor.cc:153
+msgid "ardour_option_editor"
+msgstr "ardour_editor_delle_opzioni"
+
+#: gtk_ardour/option_editor.cc:183
+msgid "Misc"
+msgstr "Varie"
+
+#: gtk_ardour/option_editor.cc:184
+msgid "Sync"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:185
+msgid "Paths/Files"
+msgstr "Percorsi/File"
+
+#: gtk_ardour/option_editor.cc:186
+msgid "Display"
+msgstr "Interfaccia"
+
+#: gtk_ardour/option_editor.cc:187
+msgid "Kbd/Mouse"
+msgstr "Tastiera/Mouse"
+
+#: gtk_ardour/option_editor.cc:188
+msgid "Click"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:190
+msgid "Layers & Fades"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:195
+msgid "MIDI"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:268
+msgid "24 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:270
+msgid "25 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:272
+msgid "30 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:278
+msgid "30 FPS drop"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379
+#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736
+#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800
+msgid "Medium"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738
+#: gtk_ardour/option_editor.cc:804
+#, fuzzy
+msgid "Faster"
+msgstr "Veloce"
+
+#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714
+#: gtk_ardour/option_editor.cc:776
+#, fuzzy
+msgid "Short"
+msgstr "entrata"
+
+#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716
+#: gtk_ardour/option_editor.cc:780
+msgid "Long"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:396
+msgid "Broadcast WAVE/floating point"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:397
+msgid "WAVE/floating point"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:417
+msgid "session RAID path"
+msgstr "Percorso RAID della sessione"
+
+#: gtk_ardour/option_editor.cc:422
+msgid "Native Format"
+msgstr "Formato Nativo"
+
+#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460
+#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409
+msgid "internal"
+msgstr "interno"
+
+#: gtk_ardour/option_editor.cc:537
+msgid "Short crossfade length (msecs)"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:710
+msgid "Meter Peak Hold"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:730
+msgid "Meter Falloff"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:847
+msgid "Positional Sync"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:902
+msgid "SMPTE Frames/second"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:903
+msgid "SMPTE Offset"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013
+#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211
+#, fuzzy
+msgid "online"
+msgstr "lineare"
+
+#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014
+#: gtk_ardour/option_editor.cc:1208
+#, fuzzy
+msgid "offline"
+msgstr "lineare"
+
+#: gtk_ardour/option_editor.cc:1319
+msgid "Use as click"
+msgstr "Usa come click"
+
+#: gtk_ardour/option_editor.cc:1344
+msgid "Use as click emphasis"
+msgstr "Usa come enfasi del click"
+
+#: gtk_ardour/option_editor.cc:1478
+msgid "--unknown--"
+msgstr "--sconosciuto--"
+
+#: gtk_ardour/option_editor.cc:1595
+msgid "Click audio file"
+msgstr "File audio del click"
+
+#: gtk_ardour/option_editor.cc:1601
+msgid "Click emphasis audiofile"
+msgstr "Pecorso del file di enfasi click"
+
+#: gtk_ardour/option_editor.cc:1638
+msgid ""
+"The auditioner is a dedicated mixer strip used\n"
+"for listening to specific regions outside the context\n"
+"of the overall mix. It can be connected just like any\n"
+"other mixer strip."
+msgstr ""
+"L'auditioner è una speciale striscia del mixer,\n"
+"usata per ascoltare specifiche regioni al di fuori\n"
+"del contesto del mixaggio. Può essere connessa proprio\n"
+"come ogni altra striscia del mixer."
+
+#: gtk_ardour/option_editor.cc:1887
+msgid "Edit using"
+msgstr "Modifica usando"
+
+#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924
+msgid "+ button"
+msgstr "+ pulsante"
+
+#: gtk_ardour/option_editor.cc:1917
+msgid "Delete using"
+msgstr "Elimina usando"
+
+#: gtk_ardour/option_editor.cc:1947
+msgid "Ignore snap using"
+msgstr "Ignora l'allineamento automatico usando"
+
+#: gtk_ardour/opts.cc:46
+msgid "Usage: "
+msgstr "Utilizzo: "
+
+#: gtk_ardour/opts.cc:47
+msgid " -v, --version Show version information\n"
+msgstr " -v, --versione Mostra info sulla versione\n"
+
+#: gtk_ardour/opts.cc:48
+msgid " -h, --help Print this message\n"
+msgstr " -h, --help Mostra questo messaggio\n"
+
+#: gtk_ardour/opts.cc:49
+msgid ""
+" -b, --bindings Print all possible keyboard binding "
+"names\n"
+msgstr ""
+" -b, --bindings Mostra tutte le possibili combinazioni di "
+"tasti\n"
+
+#: gtk_ardour/opts.cc:50
+#, fuzzy
+msgid " -n, --show-splash Show splash screen\n"
+msgstr ""
+" -n, --no-splash Non mostrare la schermata d'avvio\n"
+
+#: gtk_ardour/opts.cc:51
+#, fuzzy
+msgid ""
+" -c, --name name Use a specific jack client name, default "
+"is ardour\n"
+msgstr ""
+" -c, --jack-client-name name Utilizza nome specifico per jack, "
+"predefinito e' ardour\n"
+
+#: gtk_ardour/opts.cc:52
+#, fuzzy
+msgid ""
+" -N, --new session-name Create a new session from the command "
+"line\n"
+msgstr " [nome sessione] Nome della sessione da caricare\n"
+
+#: gtk_ardour/opts.cc:53
+msgid ""
+" -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:55
+#, fuzzy
+msgid " -V, --novst Do not use VST support\n"
+msgstr ""
+" -n, --no-splash Non mostrare la schermata d'avvio\n"
+
+#: gtk_ardour/opts.cc:57
+msgid " [session-name] Name of session to load\n"
+msgstr " [nome sessione] Nome della sessione da caricare\n"
+
+#: gtk_ardour/opts.cc:58
+msgid " -C, --curvetest filename Curve algorithm debugger\n"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:58
+msgid "You can't graphically edit panning of more than stream"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:78
+#, fuzzy
+msgid "add pan automation event"
+msgstr "aggiungi evento di automazione a "
+
+#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441
+#, fuzzy
+msgid "Bypass"
+msgstr "Battute"
+
+#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222
+#, fuzzy
+msgid "link"
+msgstr "vuoto"
+
+#: gtk_ardour/panner_ui.cc:103
+msgid "panning link control"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:105
+msgid "panning link direction"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:232
+msgid "L"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:344
+#, c-format
+msgid "panner for channel %u"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:451
+#, fuzzy
+msgid "Reset all"
+msgstr "azzera"
+
+#: gtk_ardour/playlist_selector.cc:46
+msgid "Playlists grouped by track"
+msgstr ""
+
+#: gtk_ardour/playlist_selector.cc:53
+#, fuzzy
+msgid "close"
+msgstr "Chiudi"
+
+#: gtk_ardour/playlist_selector.cc:59
+#, fuzzy
+msgid "ardour: playlists"
+msgstr "azzera le posizioni"
+
+#: gtk_ardour/playlist_selector.cc:104
+#, fuzzy
+msgid "ardour: playlist for "
+msgstr "ardour: editor delle opzioni"
+
+#: gtk_ardour/playlist_selector.cc:122
+#, fuzzy
+msgid "Other tracks"
+msgstr "Nascondi traccia"
+
+#: gtk_ardour/playlist_selector.cc:138
+msgid "unassigned"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:41
+msgid "Available LADSPA plugins"
+msgstr "Plugin LADSPA disponibili"
+
+#: gtk_ardour/plugin_selector.cc:42
+msgid "Type"
+msgstr "Tipo"
+
+#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51
+msgid "# Inputs"
+msgstr "# Entrate"
+
+#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52
+msgid "# Outputs"
+msgstr "# Uscite"
+
+#: gtk_ardour/plugin_selector.cc:50
+msgid "Available VST plugins"
+msgstr "Plugin VST disponibili"
+
+#: gtk_ardour/plugin_selector.cc:58
+msgid "To be added"
+msgstr "Da aggiungere"
+
+#: gtk_ardour/plugin_selector.cc:72
+msgid "ardour: plugins"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:82
+msgid "Add a plugin to the effect list"
+msgstr "Aggiungi un plugin alla lista degli effetti"
+
+#: gtk_ardour/plugin_selector.cc:84
+msgid "Remove a plugin from the effect list"
+msgstr "Rimuovi un plugin dalla lista degli effetti"
+
+#: gtk_ardour/plugin_selector.cc:88
+msgid "Update"
+msgstr "Aggiorna"
+
+#: gtk_ardour/plugin_selector.cc:89
+msgid "Update available plugins"
+msgstr "Aggiorna i plugin disponibili"
+
+#: gtk_ardour/plugin_selector.cc:110
+msgid "LADSPA"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:113
+msgid "VST"
+msgstr "VST"
+
+#: gtk_ardour/plugin_ui.cc:83
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this "
+"version of ardour)"
+msgstr ""
+"tipo di plugin fornito sconosciuto (nota: nessun supporto a VST in questa "
+"versione di ardour)"
+
+#: gtk_ardour/plugin_ui.cc:269
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr ""
+"Plugin Editor: impossibile creare elemento di controllo per la porta %1"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "in"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "ins"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "out"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "outs"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:382
+msgid "automation control"
+msgstr "controllo di automazione"
+
+#: gtk_ardour/plugin_ui.cc:869
+#, fuzzy
+msgid "save"
+msgstr "Salva"
+
+#: gtk_ardour/plugin_ui.cc:870
+msgid "bypass"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:892
+msgid "Plugin preset %1 not found"
+msgstr "Preset per plugin %1 non trovato"
+
+#: gtk_ardour/plugin_ui.cc:903
+msgid "Name for plugin settings:"
+msgstr "Nome per le impostazioni del plugin"
+
+#: gtk_ardour/redirect_automation_line.cc:53
+msgid "redirect automation created for non-plugin"
+msgstr "automazione di redirect creata per non-plugin"
+
+#: gtk_ardour/redirect_automation_time_axis.cc:92
+msgid "add automation event to "
+msgstr "aggiungi evento di automazione a "
+
+#: gtk_ardour/redirect_box.cc:213
+msgid "New send"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:214
+#, fuzzy
+msgid "Show send controls"
+msgstr "utilizza le uscite di controllo"
+
+#: gtk_ardour/redirect_box.cc:360
+msgid "New Plugin ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:361
+#, fuzzy
+msgid "New Insert"
+msgstr "Nuova entrata"
+
+#: gtk_ardour/redirect_box.cc:362
+msgid "New Send ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:380
+#, fuzzy
+msgid "Select all"
+msgstr "Seleziona tutto"
+
+#: gtk_ardour/redirect_box.cc:381
+#, fuzzy
+msgid "Deselect all"
+msgstr "Seleziona tutto"
+
+#: gtk_ardour/redirect_box.cc:389
+#, fuzzy
+msgid "Inserts"
+msgstr "Inverti"
+
+#: gtk_ardour/redirect_box.cc:390
+#, fuzzy
+msgid "Sends"
+msgstr "Secondi"
+
+#: gtk_ardour/redirect_box.cc:393
+#, fuzzy
+msgid "Select all ..."
+msgstr "Seleziona tutto"
+
+#: gtk_ardour/redirect_box.cc:406
+#, fuzzy
+msgid "Activate All"
+msgstr "Attiva"
+
+#: gtk_ardour/redirect_box.cc:407
+#, fuzzy
+msgid "Deactivate All"
+msgstr "Disattiva"
+
+#: gtk_ardour/redirect_box.cc:488
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:500
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:513
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:616
+msgid "Pre-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:619
+msgid "Post-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:781
+msgid ""
+"You cannot reorder this set of redirects\n"
+"in that way because the inputs and\n"
+"outputs do not work correctly."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:903
+#, fuzzy
+msgid "ardour: rename redirect"
+msgstr "ardour: rinomina la regione"
+
+#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043
+msgid ""
+"Copying the set of redirects on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:1064
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this track?\n"
+"(this cannot be undone)"
+msgstr ""
+"Si vuole realmente rimuovere la traccia \"%1\" ?\n"
+"(questa azione non potrà essere annullata)"
+
+#: gtk_ardour/redirect_box.cc:1067
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this bus?\n"
+"(this cannot be undone)"
+msgstr ""
+"Si vuole realmente rimuovere la traccia \"%1\" ?\n"
+"(questa azione non potrà essere annullata)"
+
+#: gtk_ardour/redirect_box.cc:1071
+#, fuzzy
+msgid "Yes, remove them all"
+msgstr "Si, rimuovi."
+
+#: gtk_ardour/redirect_box.cc:1114
+#, fuzzy
+msgid "ardour: %1"
+msgstr "ardour: orologio"
+
+#: gtk_ardour/redirect_box.cc:1156
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "ardour: regione"
+
+#: gtk_ardour/region_editor.cc:43
+msgid "NAME:"
+msgstr "NOME:"
+
+#: gtk_ardour/region_editor.cc:44
+msgid "lock"
+msgstr "blocca"
+
+#: gtk_ardour/region_editor.cc:46
+msgid "opaque"
+msgstr "opaco"
+
+#: gtk_ardour/region_editor.cc:49
+msgid "Layer"
+msgstr "Livello"
+
+#: gtk_ardour/region_editor.cc:57
+msgid "ENVELOPE"
+msgstr ""
+
+#: gtk_ardour/region_editor.cc:108
+msgid "mute this region"
+msgstr "Metti in muto questa regione"
+
+#: gtk_ardour/region_editor.cc:109
+msgid "regions underneath this one cannot be heard"
+msgstr "le regioni al di sotto di questa non posssono essere udite"
+
+#: gtk_ardour/region_editor.cc:110
+msgid "prevent any changes to this region"
+msgstr "impedisci qualsiasi cambio a questa regione"
+
+#: gtk_ardour/region_editor.cc:111
+msgid "use the gain envelope during playback"
+msgstr "usa la curva di gain suonando"
+
+#: gtk_ardour/region_editor.cc:112
+msgid "show the gain envelope"
+msgstr "mostra la curva di gain"
+
+#: gtk_ardour/region_editor.cc:113
+msgid "use fade in curve during playback"
+msgstr "usa la curva di smorzamento in entrata, suonando"
+
+#: gtk_ardour/region_editor.cc:114
+msgid "use fade out curve during playback"
+msgstr "usa la curva di smorzamento in uscita, suonando"
+
+#: gtk_ardour/region_editor.cc:115
+msgid "audition this region"
+msgstr "fai l'audition di questa regione"
+
+#: gtk_ardour/region_editor.cc:148
+msgid "START:"
+msgstr "INIZIO:"
+
+#: gtk_ardour/region_editor.cc:150
+msgid "END:"
+msgstr "FINE"
+
+#: gtk_ardour/region_editor.cc:152
+msgid "LENGTH:"
+msgstr "LUNGHEZZA"
+
+#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198
+#: gtk_ardour/region_editor.cc:234
+msgid "active"
+msgstr "attivo"
+
+#: gtk_ardour/region_editor.cc:179
+msgid "visible"
+msgstr "visibile"
+
+#: gtk_ardour/region_editor.cc:197
+msgid "FADE IN"
+msgstr "SMORZA ENTRATA"
+
+#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235
+msgid "msecs"
+msgstr "msec"
+
+#: gtk_ardour/region_editor.cc:233
+msgid "FADE OUT"
+msgstr "SMORZA USCITA"
+
+#: gtk_ardour/region_editor.cc:276
+msgid "ardour: region "
+msgstr "ardour: regione"
+
+#: gtk_ardour/region_editor.cc:410
+msgid "fade in edit"
+msgstr "modifica lo smorzamento in entrata"
+
+#: gtk_ardour/region_editor.cc:422
+msgid "fade out edit"
+msgstr "modifica lo smorzamento in uscita"
+
+#: gtk_ardour/regionview.cc:1169
+#, fuzzy
+msgid "add gain control point"
+msgstr "Rimuovi il punto di sincronizzazione"
+
+#: gtk_ardour/route_params_ui.cc:58
+msgid "Tracks/Buses"
+msgstr "Tracce/Bus"
+
+#: gtk_ardour/route_params_ui.cc:59
+msgid "Pre Redirects"
+msgstr "Pre Redirezionamenti"
+
+#: gtk_ardour/route_params_ui.cc:60
+msgid "Post Redirects"
+msgstr "Post Redirezionamenti"
+
+#: gtk_ardour/route_params_ui.cc:105
+#, fuzzy
+msgid "Pre-fader Redirects"
+msgstr "Pre Redirezionamenti"
+
+#: gtk_ardour/route_params_ui.cc:106
+#, fuzzy
+msgid "Post-fader Redirects"
+msgstr "Post Redirezionamenti"
+
+#: gtk_ardour/route_params_ui.cc:138
+#, fuzzy
+msgid "ardour: track/bus inspector"
+msgstr "ardour: aggiungi traccia/bus"
+
+#: gtk_ardour/route_params_ui.cc:139
+msgid "ardour_route_parameters"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:189
+msgid "route display list item for renamed route not found!"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:448
+msgid "NO TRACK"
+msgstr "NESSUNA TRACCIA"
+
+#: gtk_ardour/route_params_ui.cc:669
+#, fuzzy
+msgid "ardour: track/bus inspector: "
+msgstr "ardour: aggiungi traccia/bus"
+
+#: gtk_ardour/route_params_ui.cc:673
+msgid "No Route Selected"
+msgstr "Nessun Route Selezionato"
+
+#: gtk_ardour/route_params_ui.cc:674
+#, fuzzy
+msgid "ardour: track/bus/inspector: no route selected"
+msgstr "ardour: parametri di route: nessun route selezionato"
+
+#: gtk_ardour/route_ui.cc:134
+#, fuzzy
+msgid "mute change"
+msgstr "Imposta l'intervallo di Punch"
+
+#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220
+#, fuzzy
+msgid "solo change"
+msgstr "Intervallo di loop"
+
+#: gtk_ardour/route_ui.cc:284
+msgid "rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:423
+msgid "Solo-safe"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474
+msgid "MIDI Bind"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:445
+msgid "Pre Fader"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:452
+msgid "Post Fader"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:459
+msgid "Control Outs"
+msgstr "Uscite di Controllo"
+
+#: gtk_ardour/route_ui.cc:466
+msgid "Main Outs"
+msgstr "Uscite Principali"
+
+#: gtk_ardour/route_ui.cc:503
+msgid "mix group solo change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:537
+msgid "mix group mute change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:553
+msgid "mix group rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258
+msgid "ardour: color selection"
+msgstr "ardour: selezione del colore"
+
+#: gtk_ardour/route_ui.cc:652
+#, fuzzy
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"You may also lose the playlist used by this track.\n"
+"(cannot be undone)"
+msgstr ""
+"Si vuole realmente rimuovere la traccia \"%1\" ?\n"
+"(questa azione non potrà essere annullata)"
+
+#: gtk_ardour/route_ui.cc:654
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Si vuole realmente rimuovere il bus \"%1\" ?\n"
+"(questa azione non potrà essere annullata)"
+
+#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299
+msgid "Yes, remove it."
+msgstr "Si, rimuovi."
+
+#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358
+msgid "new name: "
+msgstr "nuovo nome: "
+
+#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31
+msgid "Beats per minute"
+msgstr "Battiti al minuto"
+
+#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35
+#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163
+msgid "Beat"
+msgstr "Battito"
+
+#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158
+msgid "Meter denominator"
+msgstr "Denominatore per il Meter"
+
+#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159
+msgid "Beats per bar"
+msgstr "Battiti per battuta"
+
+#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189
+msgid "whole (1)"
+msgstr "intero (1)"
+
+#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191
+msgid "second (2)"
+msgstr "mezzo (2)"
+
+#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193
+msgid "third (3)"
+msgstr "terzo (3)"
+
+#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195
+#: gtk_ardour/tempo_dialog.cc:203
+msgid "quarter (4)"
+msgstr "quarto (4)"
+
+#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197
+msgid "eighth (8)"
+msgstr "ottavo (8)"
+
+#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199
+msgid "sixteenth (16)"
+msgstr "sedicesimo (16)"
+
+#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201
+msgid "thirty-second (32)"
+msgstr "trentaduesimo (32)"
+
+#: gtk_ardour/tempo_dialog.cc:301
+msgid "garbaged note type entry (%1)"
+msgstr ""
+
+#: gtk_ardour/tempo_dialog.cc:311
+msgid "incomprehensible note type entry (%1)"
+msgstr ""
+
+#: gtk_ardour/time_axis_view.cc:95
+msgid "gTortnam"
+msgstr ""
+
+#: gtk_ardour/time_axis_view.cc:446
+msgid "Largest"
+msgstr "Ampissimo"
+
+#: gtk_ardour/time_axis_view.cc:447
+msgid "Large"
+msgstr "Più ampio"
+
+#: gtk_ardour/time_axis_view.cc:448
+msgid "Larger"
+msgstr "Ampio"
+
+#: gtk_ardour/time_axis_view.cc:450
+msgid "Smaller"
+msgstr "Piccolo"
+
+#: gtk_ardour/time_axis_view.cc:451
+msgid "Small"
+msgstr "Più piccolo"
+
+#: gtk_ardour/time_axis_view.cc:785
+msgid "unknown track height name \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:69
+msgid "TimeAxisViewItemName"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:258
+msgid "new duration %1 frames is out of bounds for %2"
+msgstr ""
+
+#: gtk_ardour/time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr ""
+
+#: gtk_ardour/utils.cc:57
+msgid ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+msgstr ""
+
+#: gtk_ardour/utils.cc:66
+msgid "aeiou"
+msgstr ""
+
+#: gtk_ardour/utils.cc:75
+msgid "AEIOU"
+msgstr ""
+
+#: gtk_ardour/utils.cc:84
+msgid "bcdfghjklmnpqrtvwxyz"
+msgstr ""
+
+#: gtk_ardour/utils.cc:93
+msgid "BCDFGHJKLMNPQRTVWXYZ"
+msgstr ""
+
+#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265
+msgid "bad XPM header %1"
+msgstr ""
+
+#: gtk_ardour/utils.cc:516
+msgid "missing RGBA style for \"%1\""
+msgstr ""
+
+#: gtk_ardour/visual_time_axis.cc:297
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Si vuole realmente rimuovere la traccia \"%1\" ?\n"
+"(questa azione non potrà essere annullata)"
+
+#: gtk_ardour/visual_time_axis.cc:385
+msgid "A track already exists with that name"
+msgstr "esiste già una traccia con quel nome"
+
+#~ msgid "Export to CD"
+#~ msgstr "Esporta a CD"
+
+#~ msgid "programming error: location/marker map does not contain location!"
+#~ msgstr ""
+#~ "errore di programmazione: la mappa di posizioni/marcatori non contiene "
+#~ "alcuna posizione!"
+
+#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$"
+#~ msgstr "Impossibile trovare una immagine per toggle-button-[0-9]*.xpm$"
+
+#~ msgid ""
+#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$"
+#~ msgstr "Impossibile trovare una immagine per small-round-button-[0-9]*.xpm$"
+
+#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$"
+#~ msgstr "Impossibile trovare una immagine per hslider[0-9]*.xpm$"
+
+#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$"
+#~ msgstr "Impossibile trovare una immagine per vslider[0-9]*.xpm$"
+
+#~ msgid "Trace MIDI Input"
+#~ msgstr "Tieni traccia delle Entrate MIDI"
+
+#~ msgid "Trace MIDI Output"
+#~ msgstr "Tieni traccia delle Uscite MIDI"
+
+#~ msgid "MTC Port"
+#~ msgstr "Porta MTC"
+
+#~ msgid "attempt to timestretch a non-audio track!"
+#~ msgstr "si tenta il timestretch su una traccia non audio!"
+
+#~ msgid "ardour: tempo editor"
+#~ msgstr "ardour: modifica il tempo"
+
+#~ msgid "ok"
+#~ msgstr "Ok"
+
+#~ msgid "apply"
+#~ msgstr "applica"
+
+#~ msgid "fade"
+#~ msgstr "smorzamento"
+
+#~ msgid "Edit left"
+#~ msgstr "Modifica a sinistra"
+
+#~ msgid "Edit right"
+#~ msgstr "Modifica a destra"
+
+#~ msgid "Edit fade"
+#~ msgstr "Modifica smorzamento"
+
+#~ msgid "Export region"
+#~ msgstr "Esporta regione"
+
+#, fuzzy
+#~ msgid "Bounce region"
+#~ msgstr "Fai il Bounce dell'intervallo"
+
+#~ msgid "Region"
+#~ msgstr "Regione"
+
+#~ msgid "Play selected region"
+#~ msgstr "Suona la regione selezionata"
+
+#~ msgid "clear connections"
+#~ msgstr "azzera le connessioni"
+
+#~ msgid "add comments/notes here"
+#~ msgstr "aggiungi note/commenti qui"
+
+#~ msgid "Crossfades in use"
+#~ msgstr "Smorzamenti Incrociati in uso"
+
+#, fuzzy
+#~ msgid "outside this computer"
+#~ msgstr "Nascondi traccia"
+
+#, fuzzy
+#~ msgid "inside this computer"
+#~ msgstr "Nascondi traccia"
diff --git a/gtk2_ardour/po/pt_BR.po b/gtk2_ardour/po/pt_BR.po
new file mode 100644
index 0000000000..afb3554583
--- /dev/null
+++ b/gtk2_ardour/po/pt_BR.po
@@ -0,0 +1,5104 @@
+# Ardour Brazilian Portuguese translation file
+# Copyright (C) 2003-2004 Paul Davis
+# This file is distributed under the same license as the Ardour package.
+# Authors: Alexander Franca <alexander@nautae.eti.br>
+# Chris Ross <chris.ross@tebibyte.org>
+# Leandro Marco <leandromarco@gmail.com>
+#
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ardour 0.688.4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-09-19 18:09-0400\n"
+"PO-Revision-Date: 2005-08-15 21:50-0000\n"
+"Last-Translator: Chris Ross, Alexander Franca & Leandro Marco\n"
+"Language-Team: Portuguese\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gtk_ardour/about.cc:134
+msgid "Marcus Andersson"
+msgstr ""
+
+#: gtk_ardour/about.cc:135
+msgid "Jeremy Hall"
+msgstr ""
+
+#: gtk_ardour/about.cc:136
+msgid "Steve Harris"
+msgstr ""
+
+#: gtk_ardour/about.cc:137
+msgid "Tim Mayberry"
+msgstr ""
+
+#: gtk_ardour/about.cc:138
+msgid "Mark Stewart"
+msgstr ""
+
+#: gtk_ardour/about.cc:139
+msgid "Sam Chessman"
+msgstr ""
+
+#: gtk_ardour/about.cc:140
+msgid "Jack O'Quin"
+msgstr ""
+
+#: gtk_ardour/about.cc:141
+msgid "Matt Krai"
+msgstr ""
+
+#: gtk_ardour/about.cc:142
+msgid "Ben Bell"
+msgstr ""
+
+#: gtk_ardour/about.cc:143
+msgid "Gerard van Dongen"
+msgstr ""
+
+#: gtk_ardour/about.cc:144
+msgid "Thomas Charbonnel"
+msgstr ""
+
+#: gtk_ardour/about.cc:145
+msgid "Nick Mainsbridge"
+msgstr ""
+
+#: gtk_ardour/about.cc:146
+msgid "Colin Law"
+msgstr ""
+
+#: gtk_ardour/about.cc:147
+msgid "Sampo Savolainen"
+msgstr ""
+
+#: gtk_ardour/about.cc:148
+msgid "Joshua Leach"
+msgstr ""
+
+#: gtk_ardour/about.cc:149
+msgid "Rob Holland"
+msgstr ""
+
+#: gtk_ardour/about.cc:150
+msgid "Per Sigmond"
+msgstr ""
+
+#: gtk_ardour/about.cc:151
+msgid "Doug Mclain"
+msgstr ""
+
+#: gtk_ardour/about.cc:156
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+msgstr ""
+
+#: gtk_ardour/about.cc:157
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+msgstr ""
+
+#: gtk_ardour/about.cc:158
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+msgstr ""
+
+#: gtk_ardour/about.cc:159
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:160
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:162
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn@fastmail.fm>"
+msgstr ""
+
+#: gtk_ardour/about.cc:163
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop@nm.ru>"
+msgstr ""
+
+#: gtk_ardour/about.cc:181
+msgid ""
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n"
+msgstr ""
+
+#: gtk_ardour/about.cc:188
+msgid ""
+"Ardour: %1\n"
+"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+msgstr ""
+"Ardour: %1\n"
+"(construído com ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+
+#: gtk_ardour/about.cc:206
+msgid ""
+"Primary author:\n"
+"\tPaul Davis\n"
+"\n"
+"Major developers:\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributors:\n"
+"\t"
+msgstr ""
+
+#: gtk_ardour/about.cc:243
+msgid "Authors"
+msgstr "Autores"
+
+#: gtk_ardour/about.cc:244
+msgid "Translators"
+msgstr "Tradutores"
+
+#: gtk_ardour/about.cc:361
+msgid "cannot open splash image file \"%1\""
+msgstr "não foi possível abrir o arquivo de imagem \"%1\""
+
+#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33
+#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81
+#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977
+#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85
+#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777
+#: gtk_ardour/redirect_box.cc:900
+msgid "OK"
+msgstr "OK"
+
+#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92
+#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046
+#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72
+#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982
+#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733
+#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000
+#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129
+#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785
+#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86
+#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072
+#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33
+#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94
+msgid "Tracks"
+msgstr "Trilhas"
+
+#: gtk_ardour/add_route_dialog.cc:43
+msgid "Busses"
+msgstr "Barramentos"
+
+#: gtk_ardour/add_route_dialog.cc:48
+msgid "ardour: add track/bus"
+msgstr "ardour: adicionar trilhas/barramento"
+
+#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81
+msgid "Add"
+msgstr "Adicionar"
+
+#: gtk_ardour/add_route_dialog.cc:86
+msgid "Name (template)"
+msgstr "Nome (esquema)"
+
+#: gtk_ardour/ardour_ui.cc:798
+msgid ""
+"pre\n"
+"roll"
+msgstr ""
+"pré\n"
+"rolagem"
+
+#: gtk_ardour/ardour_ui.cc:799
+msgid ""
+"post\n"
+"roll"
+msgstr ""
+"pós\n"
+"rolagem"
+
+#: gtk_ardour/ardour_ui.cc:807
+msgid "% "
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:808
+msgid "spring"
+msgstr "pular"
+
+#: gtk_ardour/ardour_ui.cc:810
+msgid ""
+"punch\n"
+"in"
+msgstr ""
+"iniciar\n"
+"inserção"
+
+#: gtk_ardour/ardour_ui.cc:811
+msgid ""
+"punch\n"
+"out"
+msgstr ""
+"finalizar\n"
+"inserção"
+
+#: gtk_ardour/ardour_ui.cc:812
+msgid ""
+"auto\n"
+"return"
+msgstr ""
+"retorno\n"
+"automático"
+
+#: gtk_ardour/ardour_ui.cc:813
+msgid ""
+"auto\n"
+"play"
+msgstr ""
+"reprodução\n"
+"automática"
+
+#: gtk_ardour/ardour_ui.cc:814
+msgid ""
+"auto\n"
+"input"
+msgstr ""
+"entrada\n"
+"automática"
+
+#: gtk_ardour/ardour_ui.cc:815
+msgid "click"
+msgstr "batimento"
+
+#: gtk_ardour/ardour_ui.cc:816
+msgid ""
+"follow\n"
+"PH"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:817
+msgid "AUDITIONING"
+msgstr "AUDIÇÃO"
+
+#: gtk_ardour/ardour_ui.cc:818
+msgid "SOLO"
+msgstr "SOLO"
+
+#: gtk_ardour/ardour_ui.cc:870
+msgid "Percentage"
+msgstr "Percentual"
+
+#: gtk_ardour/ardour_ui.cc:872
+msgid "Semitones"
+msgstr "Semitons"
+
+#: gtk_ardour/ardour_ui.cc:875
+msgid "Sprung"
+msgstr "Retornável"
+
+#: gtk_ardour/ardour_ui.cc:877
+msgid "Wheel"
+msgstr "Fixo"
+
+#: gtk_ardour/ardour_ui.cc:902
+msgid ""
+"You cannot record-enable\n"
+"track %1\n"
+"because it has no input connections.\n"
+"You would be wasting space recording silence."
+msgstr ""
+"Vocãonão pode habilitar para gravaãoo\n"
+"a trilha %1\n"
+"porque ela não tem conexãos de entrada.\n"
+"Você estaria desperdiçando espaço gravando silêncio."
+
+#: gtk_ardour/ardour_ui.cc:1073
+msgid "quit"
+msgstr "sair"
+
+#: gtk_ardour/ardour_ui.cc:1082
+msgid ""
+"Ardour was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
+msgstr ""
+"Ardour não pôde salvar sua sessão\n"
+"\n"
+"Se mesmo assim você deseja sair, por favor utilize\n"
+"a opção \"Apenas Sair\"."
+
+#: gtk_ardour/ardour_ui.cc:1107
+msgid "Save and %1"
+msgstr "Salvar e %1"
+
+#: gtk_ardour/ardour_ui.cc:1112
+msgid "Just %1"
+msgstr "Apenas %1"
+
+#: gtk_ardour/ardour_ui.cc:1117
+msgid "Don't %1"
+msgstr "Não %1"
+
+#: gtk_ardour/ardour_ui.cc:1126
+msgid "session"
+msgstr "sessão"
+
+#: gtk_ardour/ardour_ui.cc:1128
+msgid "snapshot"
+msgstr "capturar instantâneo"
+
+#: gtk_ardour/ardour_ui.cc:1130
+msgid ""
+"The %1\n"
+"\"%2\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
+msgstr ""
+"A \"%1\"\n"
+"\"%2\"\n"
+"ainda não foi salva.\n"
+"\n"
+"Qualquer alteração feita até o momento\n"
+"será perdida se você não salvar.\n"
+"\n"
+"O que você quer fazer?"
+
+#: gtk_ardour/ardour_ui.cc:1151
+msgid "Prompter"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1152
+msgid "ardour: save session?"
+msgstr "ardour: salvar sessão?"
+
+#: gtk_ardour/ardour_ui.cc:1219
+#, c-format
+msgid "disconnected"
+msgstr "desconectado"
+
+#: gtk_ardour/ardour_ui.cc:1226
+#, c-format
+msgid "SR: %.1f kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1230
+#, c-format
+msgid "SR: %u kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1243
+#, c-format
+msgid "DSP Load: %.1f%%"
+msgstr "DSP Carregada: %.1f%%"
+
+#: gtk_ardour/ardour_ui.cc:1253
+#, c-format
+msgid "Disk r:%5.1f w:%5.1f MB/s"
+msgstr "Disco r:%5.1f w:%5.1f MB/s"
+
+#: gtk_ardour/ardour_ui.cc:1267
+#, c-format
+msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1294
+msgid "space: 24hrs+"
+msgstr "espaço: 24hrs+"
+
+#: gtk_ardour/ardour_ui.cc:1324
+#, c-format
+msgid "space: %02dh:%02dm:%02ds"
+msgstr "espaço: %02dh:%02dm:%02ds"
+
+#: gtk_ardour/ardour_ui.cc:1575
+msgid "programming error: impossible control method"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1800
+msgid "cancel"
+msgstr "cancelar"
+
+#: gtk_ardour/ardour_ui.cc:1801
+msgid "rescan"
+msgstr "rescanear"
+
+#
+#: gtk_ardour/ardour_ui.cc:1842
+msgid "open session"
+msgstr "abrir sessão"
+
+#: gtk_ardour/ardour_ui.cc:1897
+msgid "Patience is a virtue.\n"
+msgstr "Paciência é uma virtude.\n"
+
+#: gtk_ardour/ardour_ui.cc:1906
+msgid "You cannot add a track without a session already loaded."
+msgstr ""
+"Você não pode adicionar uma trilha se uma sessão não estiver carregada."
+
+#: gtk_ardour/ardour_ui.cc:1913
+msgid "could not create new audio track"
+msgstr "não pôde criar uma nova trilha de áudio"
+
+#: gtk_ardour/ardour_ui.cc:1917
+msgid "could not create new audio bus"
+msgstr "não foi possível criar um novo barramento de áudio"
+
+#: gtk_ardour/ardour_ui.cc:1936
+msgid ""
+"There are insufficient JACK ports available\n"
+"to create a new track or bus.\n"
+"You should save Ardour, exit and\n"
+"restart JACK with more ports."
+msgstr ""
+"Não existe um número suficiente de portas do JACK disponíveis\n"
+"para criar uma nova trilha ou barramento.\n"
+"Você deve salvar Ardour, sair e\n"
+"reiniciar o JACK com mais portas."
+
+#: gtk_ardour/ardour_ui.cc:2071
+msgid ""
+"Please create 1 or more track\n"
+"before trying to record.\n"
+"Check the Session menu."
+msgstr ""
+"Faça favor criar um ou mais trilhas\n"
+"antes de tentar gravar.\n"
+"Vir o menu de Sessão."
+
+#: gtk_ardour/ardour_ui.cc:2312
+msgid ""
+"JACK has either been shutdown or it\n"
+"disconnected Ardour because Ardour\n"
+"was not fast enough. You can save the\n"
+"session and/or try to reconnect to JACK ."
+msgstr ""
+"O serviço de audio (JACK) foi terminado ou\n"
+"o mesmo desligou a sua conexão com o Ardour,\n"
+"talvez porque este não foi rápido o suficiente.\n"
+"A sessão corrente deverá ser salva e\n"
+"o serviço JACK reiniciado, tal como o Ardour."
+
+#: gtk_ardour/ardour_ui.cc:2328
+msgid "Unable to create all required ports"
+msgstr "Impossível criar todas as portas solicitadas"
+
+#: gtk_ardour/ardour_ui.cc:2336
+msgid "Unable to start the session running"
+msgstr "Impossível iniciar a sessão"
+
+#: gtk_ardour/ardour_ui.cc:2472
+msgid "No Stream"
+msgstr "Sem fluxo"
+
+#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518
+msgid "none"
+msgstr "nenhum"
+
+#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527
+#: gtk_ardour/automation_time_axis.cc:189
+#: gtk_ardour/automation_time_axis.cc:218
+#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211
+#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947
+#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659
+msgid "off"
+msgstr "desligado"
+
+#: gtk_ardour/ardour_ui.cc:2548
+msgid "Name for snapshot"
+msgstr "Nome para a imagem capturada"
+
+#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294
+msgid "Name for mix template:"
+msgstr "Nome para o esquema de mixer"
+
+#: gtk_ardour/ardour_ui.cc:2717
+msgid "-template"
+msgstr "-esquema/template"
+
+#: gtk_ardour/ardour_ui.cc:2760
+msgid "Session %1 already exists at %2"
+msgstr "Sessão %1 ainda existe à %2"
+
+#: gtk_ardour/ardour_ui.cc:2832
+msgid ""
+"You do not have write access to this session.\n"
+"This prevents the session from being loaded."
+msgstr ""
+"Você não tem permissão de escrita nesta sessão\n"
+"Isto impede que a sessão seja aberta."
+
+#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "A sessão \"%1 (instantâneo %2)\" não pôde ser carregada"
+
+#: gtk_ardour/ardour_ui.cc:2966
+msgid ""
+"No audio files were ready for cleanup\n"
+"\n"
+"If this seems suprising, check for any existing\n"
+"snapshots. These may still include regions that\n"
+"require some unused files to continue to exist."
+msgstr ""
+"Não existem arquivos de audio para serem limpos\n"
+"Se isto parece estranho, procure por instantâneos existentes.\n"
+"Eles podem conter regiões que requeiram a existência\n"
+"de arquivos não utlizados."
+
+#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001
+msgid "files"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003
+msgid "file"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3026
+msgid "ardour: cleanup"
+msgstr "ardour: limpar"
+
+#: gtk_ardour/ardour_ui.cc:3040
+msgid ""
+"Cleanup is a destructive operation.\n"
+"ALL undo/redo information will be lost if you cleanup.\n"
+"Unused audio files will be moved to a \"dead sounds\" location."
+msgstr ""
+"A limpeza é uma operação destrutiva\n"
+"TODAS as informações de desfazer/refazer serão perdidas se\n"
+"você continuar. Arquivos de audio não usados serão movidos\n"
+"para \"dead sounds\""
+
+#: gtk_ardour/ardour_ui.cc:3045
+msgid "Proceed with cleanup"
+msgstr "Continuar com a limpeza"
+
+#: gtk_ardour/ardour_ui.cc:3061
+msgid "CleanupDialog"
+msgstr "Limpar"
+
+#: gtk_ardour/ardour_ui.cc:3062
+msgid "ardour cleanup"
+msgstr "ardour limpar"
+
+#: gtk_ardour/ardour_ui.cc:3063
+msgid "ardour_cleanup"
+msgstr "ardour_limpar"
+
+#: gtk_ardour/ardour_ui.cc:3086
+msgid "cleaned files"
+msgstr "arquivos limpos"
+
+#: gtk_ardour/ardour_ui.cc:3087
+msgid ""
+"The following %1 %2 were not in use.\n"
+"The next time you flush the wastebasket\n"
+"it will release an additional %3 %4bytes\n"
+"of disk space"
+msgstr ""
+"Os seguintes %1 %2 não estão em uso.\n"
+"Na próxima vez limpe sua lixeira\n"
+"isto vai liberar %3 %4bytes\n"
+"de espaço no disco rígido"
+
+#: gtk_ardour/ardour_ui.cc:3110
+msgid "deleted file"
+msgstr "arquivo removido"
+
+#: gtk_ardour/ardour_ui.cc:3111
+msgid ""
+"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"
+msgstr ""
+"Os seguintes %1 arquivo%2 foram deletados, liberando %3 %4bytes de espaço no "
+"disco rígido"
+
+#: gtk_ardour/ardour_ui.cc:3226
+msgid "Recording was stopped because your system could not keep up."
+msgstr "A gravação foi encerrada porque seu sistema não consegue acompanhar"
+
+#: gtk_ardour/ardour_ui.cc:3248
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3266
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3291
+msgid "Recover from crash"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3292
+msgid "Ignore crash data"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3293
+msgid ""
+"This session appears to have been in\n"
+"middle of recording when ardour or\n"
+"the computer was shutdown.\n"
+"\n"
+"Ardour can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3338
+msgid "Could not disconnect from JACK"
+msgstr "Não foi possível se desconectar ao servidor JACK"
+
+#: gtk_ardour/ardour_ui.cc:3351
+#, fuzzy
+msgid "Could not reconnect to JACK"
+msgstr "Não foi possível se conectar ao servidor JACK"
+
+#: gtk_ardour/ardour_ui2.cc:60
+msgid "UI: cannot setup editor"
+msgstr "não foi possível iniciar o editor"
+
+#: gtk_ardour/ardour_ui2.cc:65
+msgid "UI: cannot setup mixer"
+msgstr "não foi possível iniciar o mixer"
+
+#: gtk_ardour/ardour_ui2.cc:70
+msgid "UI: cannot setup meter_bridge"
+msgstr "não foi possível iniciar o medidor volumétrico (VU)"
+
+#: gtk_ardour/ardour_ui2.cc:98
+msgid "MMC + Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:99
+msgid "MMC"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:100
+msgid "Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:117
+msgid "MMC ID"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:215
+msgid "Play from playhead"
+msgstr "Reproduzir a partir do início"
+
+#: gtk_ardour/ardour_ui2.cc:216
+msgid "Stop playback"
+msgstr "Parar reprodução"
+
+#: gtk_ardour/ardour_ui2.cc:217
+msgid "Play range/selection"
+msgstr "Reproduzir intervalo/seleção"
+
+#: gtk_ardour/ardour_ui2.cc:218
+msgid "Go to start of session"
+msgstr "Ir para o início da sessão"
+
+#: gtk_ardour/ardour_ui2.cc:219
+msgid "Go to end of session"
+msgstr "Ir para o fim da sessão"
+
+#: gtk_ardour/ardour_ui2.cc:220
+msgid "Play loop range"
+msgstr "Reproduzir intervalo"
+
+#: gtk_ardour/ardour_ui2.cc:221
+msgid "Return to last playback start when stopped"
+msgstr "Ir para o início da última reprodução quando parar"
+
+#: gtk_ardour/ardour_ui2.cc:222
+msgid "Start playback after any locate"
+msgstr "Iniciar reprodução após qualquer localização"
+
+#: gtk_ardour/ardour_ui2.cc:223
+msgid "Be sensible about input monitoring"
+msgstr "Sensível à monitoração na entrada"
+
+#: gtk_ardour/ardour_ui2.cc:224
+msgid "Start recording at auto-punch start"
+msgstr "Iniciar gravação no início do ponto-automático"
+
+#: gtk_ardour/ardour_ui2.cc:225
+msgid "Stop recording at auto-punch end"
+msgstr "Parar gravação no final do ponto-automático"
+
+#: gtk_ardour/ardour_ui2.cc:226
+msgid "Enable/Disable audio click"
+msgstr "Habilitar/desabilitar metrônomo"
+
+#: gtk_ardour/ardour_ui2.cc:227
+msgid "Enable/Disable follow playhead"
+msgstr "Habilitar/desbilitar reprodução contínua"
+
+#: gtk_ardour/ardour_ui2.cc:228
+msgid "Shuttle speed control"
+msgstr "Velocidade do controle"
+
+#: gtk_ardour/ardour_ui2.cc:229
+#, c-format
+msgid "Select semitones or %%-age for speed display"
+msgstr "Selecionar semitons ou percentual para a velocidade da tela"
+
+#: gtk_ardour/ardour_ui2.cc:230
+msgid "Select sprung or wheel behaviour"
+msgstr "Selecionar ajuste fixo ou retornável"
+
+#: gtk_ardour/ardour_ui2.cc:231
+msgid "Current transport speed"
+msgstr "Velocidade atual do transporte"
+
+#: gtk_ardour/ardour_ui2.cc:312
+msgid "Primary clock"
+msgstr "Relógio primeiramente"
+
+#: gtk_ardour/ardour_ui2.cc:313
+msgid "secondary clock"
+msgstr "Relógio secundário"
+
+#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751
+#: gtk_ardour/ardour_ui2.cc:770
+msgid "stopped"
+msgstr "parado"
+
+#: gtk_ardour/ardour_ui2.cc:431
+msgid "ardour: clock"
+msgstr "ardour: relógio"
+
+#: gtk_ardour/ardour_ui2.cc:721
+msgid "st"
+msgstr "o."
+
+#: gtk_ardour/ardour_ui2.cc:731
+msgid "sprung"
+msgstr "retornável"
+
+#: gtk_ardour/ardour_ui2.cc:742
+msgid "wheel"
+msgstr "fixo"
+
+#: gtk_ardour/ardour_ui_dependents.cc:74
+msgid "keyboard_target: error setting binding state: invalid node"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dialogs.cc:158
+msgid "close session"
+msgstr "fechar sessão"
+
+#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895
+msgid "New"
+msgstr "Novo"
+
+#: gtk_ardour/ardour_ui_ed.cc:76
+msgid "Open"
+msgstr "Abrir"
+
+#: gtk_ardour/ardour_ui_ed.cc:77
+msgid "Recent"
+msgstr "Recente"
+
+#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+msgid "Close"
+msgstr "Fechar"
+
+#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488
+msgid "Add Track/Bus"
+msgstr "Adicionar Trilha/Barramento"
+
+#: gtk_ardour/ardour_ui_ed.cc:99
+msgid "Connect"
+msgstr "Conectar"
+
+#: gtk_ardour/ardour_ui_ed.cc:100
+msgid "Image Compositor"
+msgstr "Compositor de imagem"
+
+#: gtk_ardour/ardour_ui_ed.cc:114
+msgid "Save"
+msgstr "Salvar"
+
+#: gtk_ardour/ardour_ui_ed.cc:118
+msgid "Snapshot"
+msgstr "Capturar instantâneo"
+
+#: gtk_ardour/ardour_ui_ed.cc:126
+msgid "Save Template..."
+msgstr "Salvar Esquema..."
+
+#: gtk_ardour/ardour_ui_ed.cc:133
+msgid "Export session to audiofile..."
+msgstr "Exportar sessão para arquivo de áudio"
+
+#: gtk_ardour/ardour_ui_ed.cc:134
+msgid "Export range to audiofile..."
+msgstr "Exportar intervalo para arquivo de áudio"
+
+#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312
+#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118
+#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227
+msgid "Export"
+msgstr "Exportar"
+
+#: gtk_ardour/ardour_ui_ed.cc:146
+msgid "Cleanup unused sources"
+msgstr "Limpar fontes não usadas"
+
+#: gtk_ardour/ardour_ui_ed.cc:147
+msgid "Flush wastebasket"
+msgstr "Esvaziar lixeira"
+
+#: gtk_ardour/ardour_ui_ed.cc:149
+msgid "Cleanup"
+msgstr "Limpar"
+
+#: gtk_ardour/ardour_ui_ed.cc:154
+msgid "Quit"
+msgstr "Sair"
+
+#: gtk_ardour/ardour_ui_ed.cc:156
+msgid "Session"
+msgstr "Sessão"
+
+#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287
+#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499
+#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570
+#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412
+msgid "Edit"
+msgstr "Editar"
+
+#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572
+#: gtk_ardour/mixer_strip.cc:631
+msgid "Disconnect"
+msgstr "Desconectar"
+
+#: gtk_ardour/ardour_ui_ed.cc:174
+#, fuzzy
+msgid "Reconnect"
+msgstr "Conectar"
+
+#: gtk_ardour/ardour_ui_ed.cc:192
+msgid "Latency"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:195
+msgid "JACK"
+msgstr "JACK"
+
+#: gtk_ardour/ardour_ui_ed.cc:205
+msgid "Editor"
+msgstr "Editor"
+
+#: gtk_ardour/ardour_ui_ed.cc:206
+msgid "Mixer"
+msgstr "Mixer"
+
+#: gtk_ardour/ardour_ui_ed.cc:212
+msgid "Options Editor"
+msgstr "Preferências"
+
+#: gtk_ardour/ardour_ui_ed.cc:219
+msgid "Audio Library"
+msgstr "Biblioteca de Ãudio"
+
+#: gtk_ardour/ardour_ui_ed.cc:225
+msgid "Track/Bus Inspector"
+msgstr "Inspetador de Trilhas/Barramentos"
+
+#: gtk_ardour/ardour_ui_ed.cc:232
+msgid "Connections"
+msgstr "Conexões"
+
+#: gtk_ardour/ardour_ui_ed.cc:240
+msgid "Meter Bridge"
+msgstr "VU (medidor volumétrico)"
+
+#: gtk_ardour/ardour_ui_ed.cc:248
+msgid "Locations"
+msgstr "Localizações"
+
+#: gtk_ardour/ardour_ui_ed.cc:255
+msgid "Big Clock"
+msgstr "Metrônomo"
+
+#: gtk_ardour/ardour_ui_ed.cc:261
+msgid "About"
+msgstr "Sobre"
+
+#: gtk_ardour/ardour_ui_ed.cc:264
+msgid "Windows"
+msgstr "Janelas"
+
+#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203
+msgid "SMPTE"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202
+#: gtk_ardour/editor_rulers.cc:359
+msgid "Bars:Beats"
+msgstr "Compassos:Batimentos"
+
+#: gtk_ardour/audio_clock.cc:1642
+msgid "Minutes:Seconds"
+msgstr "Minutos:Segundos"
+
+#: gtk_ardour/audio_clock.cc:1643
+msgid "Audio Frames"
+msgstr "Quadros de Ãudio"
+
+#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356
+#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713
+#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774
+#: gtk_ardour/option_editor.cc:794
+msgid "Off"
+msgstr "Desligar"
+
+#: gtk_ardour/audio_clock.cc:1646
+msgid "Mode"
+msgstr "Modo"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523
+msgid "m"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524
+msgid "s"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104
+msgid "r"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:108
+msgid "g"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:109
+msgid "p"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44
+#: gtk_ardour/visual_time_axis.cc:90
+msgid "h"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:111
+msgid "a"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89
+msgid "v"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:185
+msgid "Record"
+msgstr "Gravar"
+
+#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191
+msgid "Solo"
+msgstr "Solo"
+
+#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236
+#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433
+msgid "Mute"
+msgstr "Mutar"
+
+#: gtk_ardour/audio_time_axis.cc:188
+msgid "Edit Group"
+msgstr "Editar Grupo"
+
+#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110
+msgid "Display Height"
+msgstr "Altura"
+
+#: gtk_ardour/audio_time_axis.cc:190
+msgid "Playlist"
+msgstr "Lista de reprodução"
+
+#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752
+msgid "Automation"
+msgstr "Automação"
+
+#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111
+msgid "Visual options"
+msgstr "Opções de aparência"
+
+#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112
+msgid "Hide this track"
+msgstr "Ocultar esta trilha"
+
+#: gtk_ardour/audio_time_axis.cc:349
+msgid "No group"
+msgstr "Sem grupo"
+
+#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447
+#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229
+msgid "Height"
+msgstr "Altura"
+
+#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266
+#: gtk_ardour/marker_time_axis.cc:230
+msgid "Color"
+msgstr "Cor"
+
+#: gtk_ardour/audio_time_axis.cc:720
+msgid "Hide all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:721
+msgid "Show all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:729
+msgid "show all automation"
+msgstr "mostra toda a automação"
+
+#: gtk_ardour/audio_time_axis.cc:732
+msgid "show existing automation"
+msgstr "mostra a automação existente"
+
+#: gtk_ardour/audio_time_axis.cc:735
+msgid "hide all automation"
+msgstr "ocultar toda a automação"
+
+#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204
+#: gtk_ardour/editor.cc:234
+msgid "gain"
+msgstr "ganho"
+
+#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244
+msgid "pan"
+msgstr "pan"
+
+#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388
+msgid "Plugins"
+msgstr "Entradas"
+
+#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95
+msgid "Show waveforms"
+msgstr "Mostrar formas de onda áudio"
+
+#: gtk_ardour/audio_time_axis.cc:766
+msgid "Traditional"
+msgstr "Tradicional"
+
+#: gtk_ardour/audio_time_axis.cc:769
+msgid "Rectified"
+msgstr "Corrigido"
+
+#: gtk_ardour/audio_time_axis.cc:772
+msgid "Waveform"
+msgstr "Forma de onda"
+
+#: gtk_ardour/audio_time_axis.cc:782
+#, fuzzy
+msgid "align with existing material"
+msgstr "Material existente"
+
+#: gtk_ardour/audio_time_axis.cc:787
+#, fuzzy
+msgid "align with capture time"
+msgstr "Tempo de captura"
+
+#: gtk_ardour/audio_time_axis.cc:793
+#, fuzzy
+msgid "Alignment"
+msgstr "Alinhamento"
+
+#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288
+msgid "Active"
+msgstr "Ativar"
+
+#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386
+#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467
+#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269
+#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233
+#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83
+msgid "Remove"
+msgstr "Remover"
+
+#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880
+#: gtk_ardour/audio_time_axis.cc:911
+msgid "Name for playlist"
+msgstr "Nome para a lista de reprodução"
+
+#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433
+msgid "a track already exists with that name"
+msgstr "já existe uma trilha com este nome"
+
+#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001
+#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539
+msgid "programming error: "
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:1889
+msgid "Current: %1"
+msgstr "Atual: %1"
+
+#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452
+#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226
+#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377
+msgid "Rename"
+msgstr "Renomear"
+
+#: gtk_ardour/audio_time_axis.cc:1896
+msgid "New Copy"
+msgstr "Nova Cópia"
+
+#: gtk_ardour/audio_time_axis.cc:1898
+msgid "Clear Current"
+msgstr "Limpar Atual"
+
+#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472
+#: gtk_ardour/editor.cc:2557
+msgid "Select"
+msgstr "Selecionar"
+
+#: gtk_ardour/automation_line.cc:904
+msgid "automation event move"
+msgstr "mover evento de automação"
+
+#: gtk_ardour/automation_line.cc:906
+msgid "automation range drag"
+msgstr "arrastar intervalo de automação"
+
+#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64
+msgid "remove control point"
+msgstr "Remover ponto de controlo"
+
+#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010
+msgid "clear"
+msgstr "limpar"
+
+#: gtk_ardour/automation_time_axis.cc:80
+msgid "track height"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:81
+msgid "automation state"
+msgstr "estado do automação"
+
+#: gtk_ardour/automation_time_axis.cc:82
+msgid "clear track"
+msgstr "limpar trilha"
+
+#: gtk_ardour/automation_time_axis.cc:83
+msgid "hide track"
+msgstr "ocultar esta trilha"
+
+#: gtk_ardour/automation_time_axis.cc:191
+#: gtk_ardour/automation_time_axis.cc:229
+#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213
+#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419
+#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50
+msgid "play"
+msgstr "reproduzir"
+
+#: gtk_ardour/automation_time_axis.cc:193
+#: gtk_ardour/automation_time_axis.cc:240
+#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215
+#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422
+#: gtk_ardour/plugin_ui.cc:663
+msgid "write"
+msgstr "escrever"
+
+#: gtk_ardour/automation_time_axis.cc:195
+#: gtk_ardour/automation_time_axis.cc:251
+#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217
+#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953
+#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665
+msgid "touch"
+msgstr "marca como novo"
+
+#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274
+#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428
+msgid "???"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:276
+msgid "clear automation"
+msgstr "limpar automação"
+
+#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453
+#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398
+msgid "Hide"
+msgstr "Ocultar"
+
+#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52
+#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364
+msgid "Clear"
+msgstr "Limpar"
+
+#: gtk_ardour/automation_time_axis.cc:474
+msgid "State"
+msgstr "Estado"
+
+#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49
+msgid "Input Connections"
+msgstr "Conexões de entrada"
+
+#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48
+msgid "Output Connections"
+msgstr "Conexões de saída"
+
+#: gtk_ardour/connection_editor.cc:49
+msgid "New Input"
+msgstr "Nova entrada"
+
+#: gtk_ardour/connection_editor.cc:50
+msgid "New Output"
+msgstr "Nova saída"
+
+#: gtk_ardour/connection_editor.cc:51
+msgid "Delete"
+msgstr "Apagar"
+
+#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96
+msgid "Add Port"
+msgstr "Adicionar Porta"
+
+#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105
+#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786
+msgid "Rescan"
+msgstr "Rescanear"
+
+#: gtk_ardour/connection_editor.cc:101
+msgid "Available Ports"
+msgstr "Portas disponíveis"
+
+#: gtk_ardour/connection_editor.cc:183
+msgid "ardour: connections"
+msgstr "ardour: conexões"
+
+#: gtk_ardour/connection_editor.cc:513
+#, c-format
+msgid "in %d"
+msgstr "em %d"
+
+#: gtk_ardour/connection_editor.cc:644
+msgid "Name for new connection:"
+msgstr "Nome para a nova conexão:"
+
+#: gtk_ardour/crossfade_edit.cc:71
+#, fuzzy
+msgid "crossfade editor"
+msgstr "fade in na edição"
+
+#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449
+msgid "Reset"
+msgstr "Reiniciar"
+
+#: gtk_ardour/crossfade_edit.cc:78
+msgid "Fade"
+msgstr "Fade"
+
+#: gtk_ardour/crossfade_edit.cc:79
+msgid "Out (dry)"
+msgstr "Saída (flat)"
+
+#: gtk_ardour/crossfade_edit.cc:80
+msgid "Out"
+msgstr "Saídas"
+
+#: gtk_ardour/crossfade_edit.cc:81
+msgid "In (dry)"
+msgstr "Entrada (flat)"
+
+#: gtk_ardour/crossfade_edit.cc:82
+msgid "In"
+msgstr "Entrada"
+
+#: gtk_ardour/crossfade_edit.cc:84
+msgid "With Pre-roll"
+msgstr "Com pré-rolagem"
+
+#: gtk_ardour/crossfade_edit.cc:85
+msgid "With Post-roll"
+msgstr "Com pós-rolagem"
+
+#: gtk_ardour/crossfade_edit.cc:93
+msgid "Fade In"
+msgstr "Fade In"
+
+#: gtk_ardour/crossfade_edit.cc:94
+msgid "Fade Out"
+msgstr "Fade Out"
+
+#: gtk_ardour/crossfade_edit.cc:98
+msgid "ardour: x-fade edit"
+msgstr "ardour: editar cross fade"
+
+#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311
+#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189
+msgid "Audition"
+msgstr "Audição"
+
+#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804
+msgid "Regions/name"
+msgstr "Regiões/nome"
+
+#: gtk_ardour/editor.cc:108
+msgid "Chunks"
+msgstr "Trechos"
+
+#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079
+msgid "Slide"
+msgstr "Deslizar"
+
+#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077
+msgid "Splice"
+msgstr "Reunir"
+
+#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136
+#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96
+#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977
+msgid "None"
+msgstr "Nenhum"
+
+#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124
+msgid "CD Frames"
+msgstr "Quadros de CD"
+
+#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126
+msgid "SMPTE Frames"
+msgstr "SMPTE Frames"
+
+#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128
+msgid "SMPTE Seconds"
+msgstr "SMPTE segundo"
+
+#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130
+msgid "SMPTE Minutes"
+msgstr "SMPTE Minutos"
+
+#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132
+msgid "Seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134
+msgid "Minutes"
+msgstr "Minutos"
+
+# ## msgstr "Saídas Principais"
+#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106
+msgid "Beats/32"
+msgstr "Batimentos/32"
+
+#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104
+msgid "Beats/16"
+msgstr "Batimentos/16"
+
+#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102
+msgid "Beats/8"
+msgstr "Batimentos/8"
+
+#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100
+msgid "Beats/4"
+msgstr "Batimentos/4"
+
+#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098
+msgid "Beats/3"
+msgstr "Batimentos/3"
+
+#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108
+msgid "Beats"
+msgstr "Batimentos"
+
+#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110
+msgid "Bars"
+msgstr "Compassos"
+
+#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112
+msgid "Marks"
+msgstr "Marcas"
+
+#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114
+#: gtk_ardour/editor.cc:4182
+msgid "Edit Cursor"
+msgstr "Cursor de Edição"
+
+#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116
+msgid "Region starts"
+msgstr "Começo de regiões"
+
+#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118
+msgid "Region ends"
+msgstr "Fim de regiões"
+
+#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122
+msgid "Region syncs"
+msgstr "Sincronizações de região"
+
+#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120
+msgid "Region bounds"
+msgstr "Divisas de região"
+
+#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153
+#: gtk_ardour/time_axis_view.cc:449
+msgid "Normal"
+msgstr "Normal"
+
+#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155
+msgid "Magnetic"
+msgstr "Magnético"
+
+#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174
+#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237
+msgid "Left"
+msgstr "Esquerdo"
+
+#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176
+#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238
+msgid "Right"
+msgstr "Direito"
+
+#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178
+msgid "Center"
+msgstr "Centro"
+
+#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180
+msgid "Playhead"
+msgstr "Início"
+
+#: gtk_ardour/editor.cc:201
+msgid "Mins:Secs"
+msgstr "Mins:Segs"
+
+#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353
+msgid "Frames"
+msgstr "Quadros"
+
+#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373
+msgid "Tempo"
+msgstr "Tempo"
+
+#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367
+msgid "Meter"
+msgstr "VU (medidor volumétrico)"
+
+#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379
+msgid "Location Markers"
+msgstr "Marcas de Localização"
+
+#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385
+msgid "Range Markers"
+msgstr "Marcas de Intervalos"
+
+#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391
+msgid "Loop/Punch Ranges"
+msgstr "Intervalos Loop/Insersão"
+
+#: gtk_ardour/editor.cc:221
+msgid ""
+"editor\n"
+"mixer"
+msgstr ""
+
+#: gtk_ardour/editor.cc:232
+msgid "range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor.cc:233
+msgid "object"
+msgstr "objeto"
+
+#: gtk_ardour/editor.cc:235
+msgid "zoom"
+msgstr "zoom"
+
+#: gtk_ardour/editor.cc:236
+msgid "timefx"
+msgstr ""
+
+#: gtk_ardour/editor.cc:237
+msgid "listen"
+msgstr ""
+
+#: gtk_ardour/editor.cc:239
+msgid "mode"
+msgstr "modo"
+
+#: gtk_ardour/editor.cc:240
+msgid "automation"
+msgstr "automação"
+
+#: gtk_ardour/editor.cc:242
+msgid "Edit Mode"
+msgstr "Modo de edição"
+
+#: gtk_ardour/editor.cc:243
+msgid "Snap To"
+msgstr "Ajustar a"
+
+#: gtk_ardour/editor.cc:244
+msgid "Snap Mode"
+msgstr "Modo de Ajuste"
+
+#: gtk_ardour/editor.cc:245
+msgid "Zoom Focus"
+msgstr "Foco de Zoom"
+
+#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364
+#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579
+msgid "Nudge"
+msgstr "Retocar"
+
+#: gtk_ardour/editor.cc:511
+msgid "Zoom in"
+msgstr "Mais Zoom"
+
+#: gtk_ardour/editor.cc:512
+msgid "Zoom out"
+msgstr "Menos Zoom"
+
+#: gtk_ardour/editor.cc:517
+msgid "Zoom to session"
+msgstr "Zoom na sessão"
+
+#: gtk_ardour/editor.cc:536
+msgid "Zoom Span"
+msgstr "Alcance de zoom"
+
+#: gtk_ardour/editor.cc:566
+msgid "Edit Groups"
+msgstr "Editar Grupos"
+
+#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142
+msgid "-all-"
+msgstr "-tudo-"
+
+#: gtk_ardour/editor.cc:718
+msgid "Nudge region/selection forwards"
+msgstr "Avançar o mínimo região/seleção"
+
+#: gtk_ardour/editor.cc:719
+msgid "Nudge region/selection backwards"
+msgstr "Voltar o mínimo região/seleção"
+
+#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308
+msgid "ardour: editor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:729
+msgid "ardour_editor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:846
+msgid "VerboseCanvasCursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1405
+msgid "FirstActionMessage"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1407
+msgid "Start a new session\n"
+msgstr "Iniciar uma nova sessão\n"
+
+#: gtk_ardour/editor.cc:1408
+msgid "via Session menu"
+msgstr "via menu de Sessão"
+
+#: gtk_ardour/editor.cc:1703
+msgid "ardour: editor: "
+msgstr ""
+
+#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796
+#: gtk_ardour/editor_markers.cc:797
+msgid "Loop"
+msgstr "Ciclo"
+
+#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810
+#: gtk_ardour/editor_markers.cc:823
+msgid "Punch"
+msgstr "Inserção"
+
+#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688
+msgid "programming error: fade in canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986
+#: gtk_ardour/redirect_box.cc:401
+msgid "Deactivate"
+msgstr "Desativar"
+
+#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988
+#: gtk_ardour/redirect_box.cc:398
+msgid "Activate"
+msgstr "Ativar"
+
+#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993
+msgid "Linear"
+msgstr "Linear"
+
+#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994
+#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734
+#: gtk_ardour/option_editor.cc:796
+msgid "Slowest"
+msgstr "Menor"
+
+#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995
+#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735
+#: gtk_ardour/option_editor.cc:798
+msgid "Slow"
+msgstr "Devegar"
+
+#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996
+#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737
+#: gtk_ardour/option_editor.cc:802
+msgid "Fast"
+msgstr "Rapido"
+
+#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997
+#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739
+#: gtk_ardour/option_editor.cc:806
+msgid "Fastest"
+msgstr "Rapidamente"
+
+#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113
+msgid "Freeze"
+msgstr "Congelar"
+
+#: gtk_ardour/editor.cc:2109
+msgid "Unfreeze"
+msgstr "Descongelar"
+
+#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328
+msgid "Unmute"
+msgstr "Desmudo"
+
+#: gtk_ardour/editor.cc:2247
+msgid "Convert to short"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2249
+msgid "Convert to full"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2260
+msgid "Crossfade"
+msgstr "Fade cruzado"
+
+#: gtk_ardour/editor.cc:2303
+msgid "Popup region editor"
+msgstr "Editor de região"
+
+#: gtk_ardour/editor.cc:2304
+msgid "Raise to top layer"
+msgstr "Trazer região para frente, primeira camada"
+
+#: gtk_ardour/editor.cc:2305
+msgid "Lower to bottom layer"
+msgstr "Enviar região para a trás, última camada"
+
+#: gtk_ardour/editor.cc:2307
+msgid "Define sync point"
+msgstr "Definir ponto de sincronia"
+
+#: gtk_ardour/editor.cc:2308
+msgid "Remove sync point"
+msgstr "Remover ponto de sincronia"
+
+#: gtk_ardour/editor.cc:2313
+msgid "Bounce"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2323
+msgid "Lock"
+msgstr "Trancar"
+
+#: gtk_ardour/editor.cc:2324
+msgid "Unlock"
+msgstr "Destrancar"
+
+#: gtk_ardour/editor.cc:2334
+msgid "Original position"
+msgstr "Posição original"
+
+#: gtk_ardour/editor.cc:2340
+msgid "Toggle envelope visibility"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2341
+#, fuzzy
+msgid "Toggle envelope active"
+msgstr "ativo"
+
+#: gtk_ardour/editor.cc:2345
+msgid "DeNormalize"
+msgstr "Desnormalizar"
+
+#: gtk_ardour/editor.cc:2347
+msgid "Normalize"
+msgstr "Normalizar"
+
+#: gtk_ardour/editor.cc:2350
+msgid "Reverse"
+msgstr "Inverter horizontalmente"
+
+#: gtk_ardour/editor.cc:2359
+#, fuzzy
+msgid "Nudge fwd"
+msgstr "Retocar"
+
+#: gtk_ardour/editor.cc:2360
+#, fuzzy
+msgid "Nudge bwd"
+msgstr "Retocar"
+
+#: gtk_ardour/editor.cc:2361
+msgid "Nudge fwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2362
+msgid "Nudge bwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2371
+msgid "Start to edit cursor"
+msgstr "Do início ao cursor de edição"
+
+#: gtk_ardour/editor.cc:2372
+msgid "Edit cursor to end"
+msgstr "Do cursor de edição ao final"
+
+#: gtk_ardour/editor.cc:2374
+msgid "Trim"
+msgstr "Cortar"
+
+#: gtk_ardour/editor.cc:2377
+msgid "Split"
+msgstr "Separar"
+
+#: gtk_ardour/editor.cc:2380
+msgid "Make mono regions"
+msgstr "Criar regiões mono"
+
+#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428
+msgid "Duplicate"
+msgstr "Duplicar"
+
+#: gtk_ardour/editor.cc:2384
+msgid "Fill Track"
+msgstr "Preencher Trilha"
+
+#: gtk_ardour/editor.cc:2388
+msgid "Destroy"
+msgstr "Remover definitavente"
+
+#: gtk_ardour/editor.cc:2418
+msgid "Play range"
+msgstr "Reproduzir intervalo"
+
+#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446
+msgid "Loop range"
+msgstr "Loop no intervalo"
+
+#: gtk_ardour/editor.cc:2421
+msgid "Create chunk from range"
+msgstr "Criar trecho a partir da intervalo"
+
+#: gtk_ardour/editor.cc:2423
+msgid "Create Region"
+msgstr "Criar Região"
+
+#: gtk_ardour/editor.cc:2424
+msgid "Separate Region"
+msgstr "Separar Região"
+
+#: gtk_ardour/editor.cc:2425
+msgid "Crop Region to range"
+msgstr "Cortar região pela intervalo"
+
+#: gtk_ardour/editor.cc:2426
+#, fuzzy
+msgid "Bounce range"
+msgstr "região"
+
+#: gtk_ardour/editor.cc:2432
+msgid "Fill range w/Region"
+msgstr "Preencher intervalo com região"
+
+#: gtk_ardour/editor.cc:2434
+msgid "Range"
+msgstr "Intervalo"
+
+#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538
+msgid "Play from edit cursor"
+msgstr "Reproduzir a partir do cursor"
+
+#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539
+msgid "Play from start"
+msgstr "Reproduzir do início"
+
+#: gtk_ardour/editor.cc:2451
+msgid "Play region"
+msgstr "Reproduzir região"
+
+#: gtk_ardour/editor.cc:2453
+msgid "Loop Region"
+msgstr "Região de loop"
+
+#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540
+#: gtk_ardour/library_ui.cc:972
+msgid "Play"
+msgstr "Reproduzir"
+
+#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548
+msgid "Select All in track"
+msgstr "Selecionar tudo na trilha"
+
+#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549
+msgid "Select All"
+msgstr "Selecionar Tudo"
+
+#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550
+msgid "Invert in track"
+msgstr "Inverter verticalmente na trilha"
+
+#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551
+msgid "Invert"
+msgstr "Inverter verticalmente"
+
+#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553
+msgid "Select loop range"
+msgstr "Selecionar intervalo de loop"
+
+#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554
+msgid "Select punch range"
+msgstr "Selecionar intervalo de inserção"
+
+#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565
+#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369
+msgid "Cut"
+msgstr "Cortar"
+
+#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566
+#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371
+msgid "Copy"
+msgstr "Copiar"
+
+#: gtk_ardour/editor.cc:2482
+msgid "Paste at edit cursor"
+msgstr "Colar à cursor de edição"
+
+#: gtk_ardour/editor.cc:2483
+msgid "Paste at mouse"
+msgstr "Colar à mouse"
+
+#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923
+msgid "Align"
+msgstr "Alinhamento"
+
+#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925
+msgid "Align Relative"
+msgstr "Alinhamento Relativo"
+
+#: gtk_ardour/editor.cc:2492
+msgid "Insert chunk"
+msgstr "Inserir trecho"
+
+#: gtk_ardour/editor.cc:2496
+msgid "New Region from range"
+msgstr "Nova região a partir da intervalo"
+
+#: gtk_ardour/editor.cc:2497
+msgid "Separate Range"
+msgstr "Separar intervalo"
+
+#: gtk_ardour/editor.cc:2507
+msgid "Insert Region"
+msgstr "Inserir região"
+
+#: gtk_ardour/editor.cc:2508
+msgid "Insert external sndfile"
+msgstr "Inserir arquivo de áudio externo"
+
+#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438
+msgid "Import"
+msgstr "Importar"
+
+#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574
+msgid "Nudge entire track fwd"
+msgstr "Retorcar toda a trilha para frente"
+
+#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575
+msgid "Nudge track after edit cursor fwd"
+msgstr "Retocar trilha após o cursor de edição"
+
+#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576
+msgid "Nudge entire track bwd"
+msgstr "Retorcar toda a trilha para trás"
+
+#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577
+msgid "Nudge track after edit cursor bwd"
+msgstr "Retocar toda a trilha, do cursor de edição para trás"
+
+#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920
+#: gtk_ardour/redirect_box.cc:373
+msgid "Paste"
+msgstr "Colar"
+
+#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645
+#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799
+msgid "add marker"
+msgstr "adicionar marca"
+
+#: gtk_ardour/editor.cc:3084
+msgid "select/move objects"
+msgstr "selecionar/mover objetos"
+
+#: gtk_ardour/editor.cc:3085
+msgid "select/move ranges"
+msgstr "selecionar/mover intervalos"
+
+#: gtk_ardour/editor.cc:3086
+msgid "draw gain automation"
+msgstr "desenhar ganho automático"
+
+#: gtk_ardour/editor.cc:3087
+msgid "select zoom range"
+msgstr "selecionar intervalo de zoom"
+
+#: gtk_ardour/editor.cc:3088
+msgid "stretch/shrink regions"
+msgstr "esticar/encolher regiões"
+
+#: gtk_ardour/editor.cc:3089
+#, fuzzy
+msgid "listen to specific regions"
+msgstr "Ouça no região especifica"
+
+#: gtk_ardour/editor.cc:3213
+msgid "Start:"
+msgstr "Inicio:"
+
+#: gtk_ardour/editor.cc:3214
+msgid "End:"
+msgstr "Final:"
+
+#: gtk_ardour/editor.cc:3215
+msgid "Edit:"
+msgstr "Editar:"
+
+#: gtk_ardour/editor.cc:3429
+msgid "incorrectly formatted URI list, ignored"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3611
+#, fuzzy
+msgid "set selected trackview"
+msgstr "Inserir seleção"
+
+#: gtk_ardour/editor.cc:3647
+#, fuzzy
+msgid "set selected control point"
+msgstr "Remover ponto de controlo"
+
+#: gtk_ardour/editor.cc:3719
+#, fuzzy
+msgid "set selected regionview"
+msgstr "Loop região selecionada"
+
+#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835
+#, fuzzy
+msgid "set selected regions"
+msgstr "Loop região selecionada"
+
+#: gtk_ardour/editor.cc:3891
+msgid "Undo"
+msgstr "Desfazer"
+
+#: gtk_ardour/editor.cc:3893
+msgid "Undo (%1)"
+msgstr "Desfazer (%1)"
+
+#: gtk_ardour/editor.cc:3903
+msgid "Redo"
+msgstr "Refazer"
+
+#: gtk_ardour/editor.cc:3905
+msgid "Redo (%1)"
+msgstr "Refazer (%1)"
+
+#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946
+msgid "... as new track"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947
+#, fuzzy
+msgid "... as new region"
+msgstr "normalizar região"
+
+#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452
+msgid "Import audio (copy)"
+msgstr "Importar áudio (copiar)"
+
+#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457
+msgid "Embed audio (link)"
+msgstr "Encaixar áudio (link)"
+
+#: gtk_ardour/editor.cc:3953
+msgid "Remove last capture"
+msgstr "Remover última captura"
+
+#: gtk_ardour/editor.cc:3974
+msgid "Duplicate how many times?"
+msgstr "Duplicar quantas vezes?"
+
+#: gtk_ardour/editor.cc:4550
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If left alone, no audio files used by it will be cleaned.\n"
+"If deleted, audio files used by it alone by will cleaned."
+msgstr ""
+
+#: gtk_ardour/editor.cc:4555
+#, fuzzy
+msgid "Delete playlist"
+msgstr "Nome para a imagem capturada"
+
+#: gtk_ardour/editor.cc:4556
+#, fuzzy
+msgid "Keep playlist"
+msgstr "Nome para a imagem capturada"
+
+#: gtk_ardour/editor.cc:4557
+#, fuzzy
+msgid "Cancel cleanup"
+msgstr "Limpar"
+
+#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258
+#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290
+msgid ""
+"programming error: control point canvas item has no control point object "
+"pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:717
+msgid "programming error: line canvas item has no line object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:744
+#: gtk_ardour/editor_canvas_events.cc:784
+#: gtk_ardour/editor_canvas_events.cc:823
+msgid "programming error: no \"rect\" pointer associated with selection item"
+msgstr ""
+
+#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298
+#: gtk_ardour/mixer_ui.cc:670
+msgid "Show All"
+msgstr "Mostrar Tudo"
+
+#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299
+#: gtk_ardour/mixer_ui.cc:671
+msgid "Hide All"
+msgstr "Ocultar Tudo"
+
+#: gtk_ardour/editor_edit_groups.cc:98
+msgid "Name for new edit group"
+msgstr "Nome para o novo grupo de edição"
+
+#: gtk_ardour/editor_export_audio.cc:60
+msgid ""
+"There is no range to export.\n"
+"\n"
+"Select a range using the range mouse mode"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707
+msgid "programming error: no ImageFrameView selected"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930
+msgid "programming error: no MarkerView selected"
+msgstr ""
+
+#: gtk_ardour/editor_keys.cc:187
+#, fuzzy
+msgid "keyboard selection"
+msgstr "Separar Seleção"
+
+#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376
+#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526
+#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584
+#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650
+#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700
+#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960
+#: gtk_ardour/editor_mouse.cc:4075
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681
+msgid "remove marker"
+msgstr "remover marca"
+
+#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494
+msgid "Locate to"
+msgstr "Ir para"
+
+#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495
+msgid "Play from"
+msgstr "Reproduzir de"
+
+#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496
+msgid "Set from playhead"
+msgstr "Marcar aqui"
+
+#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497
+#, fuzzy
+msgid "Set from range"
+msgstr "Marcar um intervalo de loop"
+
+#: gtk_ardour/editor_markers.cc:479
+msgid "Set Loop Range"
+msgstr "Marcar um intervalo de loop"
+
+#: gtk_ardour/editor_markers.cc:480
+msgid "Set Punch Range"
+msgstr "Fazer intervalo de inserção"
+
+#: gtk_ardour/editor_markers.cc:736
+msgid "ardour: rename mark"
+msgstr "ardour: renomear marca"
+
+#: gtk_ardour/editor_markers.cc:738
+#, fuzzy
+msgid "ardour: rename range"
+msgstr "ardour: renomear região"
+
+#: gtk_ardour/editor_markers.cc:792
+#, fuzzy
+msgid "set loop range"
+msgstr "selecionar intervalo de zoom"
+
+#: gtk_ardour/editor_markers.cc:818
+#, fuzzy
+msgid "set punch range"
+msgstr "Selecionar intervalo atual"
+
+#: gtk_ardour/editor_mouse.cc:99
+msgid "Editor::event_frame() used on unhandled event type %1"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1555
+msgid "programming error: start_grab called without drag item"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1760
+#, fuzzy
+msgid "change fade in length"
+msgstr "fade in na edição"
+
+#: gtk_ardour/editor_mouse.cc:1778
+msgid "programming error: fade out canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1852
+#, fuzzy
+msgid "change fade out length"
+msgstr "fade out na edição"
+
+#: gtk_ardour/editor_mouse.cc:1871
+msgid "programming error: cursor canvas item has no cursor data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470
+msgid ""
+"programming error: meter marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2163
+#, fuzzy
+msgid "move meter mark"
+msgstr "remover marca"
+
+#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335
+#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439
+msgid ""
+"programming error: tempo marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340
+#: gtk_ardour/editor_tempodisplay.cc:425
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2245
+#, fuzzy
+msgid "move tempo mark"
+msgstr "remover marca"
+
+#: gtk_ardour/editor_mouse.cc:2388
+msgid "programming error: line canvas item has no line pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2497
+#, fuzzy
+msgid "move region(s)"
+msgstr "inverter horizontalmente as regiões"
+
+#: gtk_ardour/editor_mouse.cc:2509
+msgid "Drag region copy"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2579
+#, fuzzy
+msgid "copy region(s)"
+msgstr "normalizar região"
+
+#: gtk_ardour/editor_mouse.cc:2612
+#, fuzzy
+msgid "Drag region brush"
+msgstr "normalizar região"
+
+#: gtk_ardour/editor_mouse.cc:3425
+#, fuzzy
+msgid "selection grab"
+msgstr "Seleção"
+
+#: gtk_ardour/editor_mouse.cc:3571
+#, fuzzy
+msgid "range selection"
+msgstr "Reproduzir seleção"
+
+#: gtk_ardour/editor_mouse.cc:3587
+#, fuzzy
+msgid "trim selection start"
+msgstr "Desde a localização"
+
+#: gtk_ardour/editor_mouse.cc:3603
+#, fuzzy
+msgid "trim selection end"
+msgstr "Desde a localização"
+
+#: gtk_ardour/editor_mouse.cc:3620
+#, fuzzy
+msgid "move selection"
+msgstr "Saltar Seleção"
+
+#: gtk_ardour/editor_mouse.cc:3995
+#, fuzzy
+msgid "Start point trim"
+msgstr "Do início ao cursor de edição"
+
+#: gtk_ardour/editor_mouse.cc:4023
+msgid "End point trim"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:4062
+msgid "trimmed region"
+msgstr "região aparado"
+
+#: gtk_ardour/editor_mouse.cc:4203
+#, fuzzy
+msgid "new range marker"
+msgstr "adicionar marca de intervalo"
+
+#: gtk_ardour/editor_mouse.cc:4422
+#, fuzzy
+msgid "select regions"
+msgstr "Loop região selecionada"
+
+#: gtk_ardour/editor_mouse.cc:4451
+msgid "Name for region:"
+msgstr "Nome para a região:"
+
+#: gtk_ardour/editor_mouse.cc:4517
+#, fuzzy
+msgid "timestretch"
+msgstr "ardour: esticar no tempo"
+
+#: gtk_ardour/editor_ops.cc:117
+#, fuzzy
+msgid "split"
+msgstr "Separar"
+
+#: gtk_ardour/editor_ops.cc:153
+#, fuzzy
+msgid "remove region"
+msgstr "inverter horizontalmente as regiões"
+
+#: gtk_ardour/editor_ops.cc:172
+msgid ""
+" This is destructive, will possibly delete audio files\n"
+"It cannot be undone\n"
+"Do you really want to destroy %1 ?"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "these regions"
+msgstr "inverter horizontalmente as regiões"
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "this region"
+msgstr "mutar esta região"
+
+#: gtk_ardour/editor_ops.cc:179
+#, fuzzy
+msgid "Yes, destroy them."
+msgstr "Sim, remova definitivamente isto."
+
+#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434
+msgid "Yes, destroy it."
+msgstr "Sim, remova definitivamente isto."
+
+#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435
+#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300
+msgid "No, do nothing."
+msgstr "Não, não faça nada."
+
+#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307
+#, fuzzy
+msgid "extend selection"
+msgstr "Separar Seleção"
+
+#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357
+#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427
+msgid "nudge forward"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:491
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1305
+#, fuzzy
+msgid "set selection from range"
+msgstr "Nova região a partir da seleção"
+
+#: gtk_ardour/editor_ops.cc:1421
+msgid "clear markers"
+msgstr "limpar marcas"
+
+#: gtk_ardour/editor_ops.cc:1433
+msgid "clear ranges"
+msgstr "limpar intervalos"
+
+#: gtk_ardour/editor_ops.cc:1452
+msgid "clear locations"
+msgstr "limpar localizações"
+
+#: gtk_ardour/editor_ops.cc:1503
+#, fuzzy
+msgid "insert dragged region"
+msgstr "Inserir Região"
+
+#: gtk_ardour/editor_ops.cc:1538
+#, fuzzy
+msgid "insert region"
+msgstr "Inserir Região"
+
+#: gtk_ardour/editor_ops.cc:1744
+msgid "ardour: rename region"
+msgstr "ardour: renomear região"
+
+#: gtk_ardour/editor_ops.cc:1891
+msgid "You can't import an audiofile until you have a session loaded."
+msgstr ""
+"Você não pode importar um arquivo de áudio se tiver uma sessão carregada"
+
+#: gtk_ardour/editor_ops.cc:1901
+#, fuzzy
+msgid "Import selected as tracks"
+msgstr "Importar seleção"
+
+#: gtk_ardour/editor_ops.cc:1904
+#, fuzzy
+msgid "Import selected to region list"
+msgstr "Loop região selecionada"
+
+#: gtk_ardour/editor_ops.cc:1933
+msgid "ardour: audio import in progress"
+msgstr "ardour: efetuando importação de áudio"
+
+#: gtk_ardour/editor_ops.cc:1937
+msgid "Cancel Import"
+msgstr "Cancelar importação"
+
+#: gtk_ardour/editor_ops.cc:1944
+#, fuzzy
+msgid "ardour: importing %1"
+msgstr "ardour: exportar"
+
+#: gtk_ardour/editor_ops.cc:1990
+#, fuzzy
+msgid "%1 it anyway"
+msgstr "Embutir mesmo assim"
+
+#: gtk_ardour/editor_ops.cc:1996
+#, fuzzy
+msgid "Don't %1 it"
+msgstr "Não %1"
+
+#: gtk_ardour/editor_ops.cc:1997
+msgid "%1 all without questions"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1998
+#, fuzzy
+msgid "Cancel entire import"
+msgstr "Cancelar importação"
+
+#: gtk_ardour/editor_ops.cc:2004
+#, fuzzy
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr ""
+"A freqüência de áudio deste arquivo não corresponde à freqüência da sessão!"
+
+#: gtk_ardour/editor_ops.cc:2032
+msgid "You can't embed an audiofile until you have a session loaded."
+msgstr ""
+"Você não pode embutir um arquivo de áudio se tiver uma sessão carregada"
+
+#: gtk_ardour/editor_ops.cc:2039
+msgid "Add to External Region list"
+msgstr "Adicionar na lista de regiões"
+
+#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210
+#: gtk_ardour/editor_ops.cc:2286
+msgid "Editor: cannot open file \"%1\" (%2)"
+msgstr "Editor: não foi possível abrir o arquivo \"%1\" (%2)"
+
+#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312
+msgid "could not open %1"
+msgstr "não foi possível abrir %1"
+
+#: gtk_ardour/editor_ops.cc:2171
+#, fuzzy
+msgid "Insert selected as new tracks"
+msgstr "Inserir seleção"
+
+#: gtk_ardour/editor_ops.cc:2186
+msgid "Insert selected"
+msgstr "Inserir seleção"
+
+#: gtk_ardour/editor_ops.cc:2327
+#, fuzzy
+msgid "insert sndfile"
+msgstr "Inserir arquivo de áudio externo"
+
+#: gtk_ardour/editor_ops.cc:2464
+#, fuzzy
+msgid "separate"
+msgstr "Separar Região"
+
+#: gtk_ardour/editor_ops.cc:2528
+#, fuzzy
+msgid "trim to selection"
+msgstr "Desde a localização"
+
+#: gtk_ardour/editor_ops.cc:2568
+msgid "region fill"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2626
+#, fuzzy
+msgid "fill selection"
+msgstr "Reproduzir seleção continuamente"
+
+#: gtk_ardour/editor_ops.cc:2650
+msgid "Place the edit cursor at the desired sync point"
+msgstr "Coloque o cursor de edição no ponto de sincronia desejado"
+
+#: gtk_ardour/editor_ops.cc:2656
+#, fuzzy
+msgid "set sync from edit cursor"
+msgstr "Reproduzir a partir do cursor"
+
+#: gtk_ardour/editor_ops.cc:2668
+#, fuzzy
+msgid "remove sync"
+msgstr "Remover ponto de sincronia"
+
+#: gtk_ardour/editor_ops.cc:2682
+#, fuzzy
+msgid "naturalize"
+msgstr "Normalizar"
+
+#: gtk_ardour/editor_ops.cc:2746
+#, fuzzy
+msgid "align selection (relative)"
+msgstr "Alinhamento Relativo"
+
+#: gtk_ardour/editor_ops.cc:2774
+#, fuzzy
+msgid "align selection"
+msgstr "Saltar Seleção"
+
+#: gtk_ardour/editor_ops.cc:2786
+#, fuzzy
+msgid "align region"
+msgstr "normalizar região"
+
+#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858
+#, fuzzy
+msgid "trim to edit"
+msgstr "Do início ao cursor de edição"
+
+#: gtk_ardour/editor_ops.cc:2909
+#, fuzzy
+msgid "ardour: freeze"
+msgstr "ardour: renomear região"
+
+#: gtk_ardour/editor_ops.cc:2914
+#, fuzzy
+msgid "Cancel Freeze"
+msgstr "Cancelar"
+
+#: gtk_ardour/editor_ops.cc:2951
+#, fuzzy
+msgid "bounce range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor_ops.cc:3004
+msgid "cut"
+msgstr "cortar"
+
+#: gtk_ardour/editor_ops.cc:3007
+msgid "copy"
+msgstr "copiar"
+
+#: gtk_ardour/editor_ops.cc:3020
+msgid " objects"
+msgstr "objetos"
+
+#: gtk_ardour/editor_ops.cc:3046
+msgid " range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor_ops.cc:3201
+#, fuzzy
+msgid "paste"
+msgstr "Colar"
+
+#: gtk_ardour/editor_ops.cc:3236
+#, fuzzy
+msgid "paste chunk"
+msgstr "Criar trecho"
+
+#: gtk_ardour/editor_ops.cc:3276
+#, fuzzy
+msgid "duplicate region"
+msgstr "Loop região selecionada"
+
+#: gtk_ardour/editor_ops.cc:3309
+#, fuzzy
+msgid "duplicate selection"
+msgstr "Saltar Seleção"
+
+#: gtk_ardour/editor_ops.cc:3349
+#, fuzzy
+msgid "clear playlist"
+msgstr "Nome para a imagem capturada"
+
+#: gtk_ardour/editor_ops.cc:3378
+#, fuzzy
+msgid "nudge track"
+msgstr "Ocultar esta trilha"
+
+#: gtk_ardour/editor_ops.cc:3431
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"Você quer realmente remover definitivamente a última captura?\n"
+"(Isto não poderá ser desfeito)"
+
+#: gtk_ardour/editor_ops.cc:3463
+#, fuzzy
+msgid "normalize"
+msgstr "Normalizar"
+
+#: gtk_ardour/editor_ops.cc:3510
+msgid "reverse regions"
+msgstr "inverter horizontalmente as regiões"
+
+#: gtk_ardour/editor_region_list.cc:223
+#, fuzzy
+msgid "hidden"
+msgstr "Oculto"
+
+#: gtk_ardour/editor_region_list.cc:408
+msgid "Show all"
+msgstr "Mostrar tudo"
+
+#: gtk_ardour/editor_region_list.cc:417
+msgid "Ascending"
+msgstr "Ascendente"
+
+#: gtk_ardour/editor_region_list.cc:419
+msgid "Descending"
+msgstr "Descendente"
+
+#: gtk_ardour/editor_region_list.cc:423
+msgid "By Region Name"
+msgstr "Por Nome da Região"
+
+#: gtk_ardour/editor_region_list.cc:425
+msgid "By Region Length"
+msgstr "Por Tamanho da Região"
+
+#: gtk_ardour/editor_region_list.cc:427
+msgid "By Region Position"
+msgstr "Por Posição da Região"
+
+#: gtk_ardour/editor_region_list.cc:429
+msgid "By Region Timestamp"
+msgstr "Por tempo data/hora da Região"
+
+#: gtk_ardour/editor_region_list.cc:431
+msgid "By Region Start in File"
+msgstr "Por posição inicial da Região no arquivo"
+
+#: gtk_ardour/editor_region_list.cc:433
+msgid "By Region End in File"
+msgstr "Por posição final da Região no arquivo"
+
+#: gtk_ardour/editor_region_list.cc:435
+msgid "By Source File Name"
+msgstr "Por nome original do arquivo"
+
+#: gtk_ardour/editor_region_list.cc:437
+msgid "By Source File Length"
+msgstr "Por tamanho do arquivo original"
+
+#: gtk_ardour/editor_region_list.cc:439
+msgid "By Source File Creation Date"
+msgstr "Por data de criação do arquivo original"
+
+#: gtk_ardour/editor_region_list.cc:441
+msgid "By Source Filesystem"
+msgstr "Por sistema de arquivos original"
+
+#: gtk_ardour/editor_region_list.cc:444
+msgid "Sorting"
+msgstr "Ordernação"
+
+#: gtk_ardour/editor_region_list.cc:808
+msgid "Regions/length"
+msgstr "Regiões/tamanho"
+
+#: gtk_ardour/editor_region_list.cc:812
+msgid "Regions/position"
+msgstr "Regiões/posição"
+
+#: gtk_ardour/editor_region_list.cc:816
+msgid "Regions/creation"
+msgstr "Regiões/criação"
+
+#: gtk_ardour/editor_region_list.cc:820
+msgid "Regions/start"
+msgstr "Regiões/início"
+
+#: gtk_ardour/editor_region_list.cc:824
+msgid "Regions/end"
+msgstr "Regiões/final"
+
+#: gtk_ardour/editor_region_list.cc:828
+msgid "Regions/file name"
+msgstr "Regiões/nome do arquivo"
+
+#: gtk_ardour/editor_region_list.cc:832
+msgid "Regions/file size"
+msgstr "Regiões/tamanho do arquivo"
+
+#: gtk_ardour/editor_region_list.cc:836
+msgid "Regions/file date"
+msgstr "Regiões/data do arquivo"
+
+#: gtk_ardour/editor_region_list.cc:840
+msgid "Regions/file system"
+msgstr "Regiões/sistema de arquivos"
+
+#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73
+#: gtk_ardour/editor_route_list.cc:231
+msgid "editor"
+msgstr "editor"
+
+#: gtk_ardour/editor_route_list.cc:300
+msgid "Show All AbstractTracks"
+msgstr "Mostrar todas as trilhas abstratas"
+
+#: gtk_ardour/editor_route_list.cc:301
+msgid "Hide All AbstractTracks"
+msgstr "Ocultar todas as trilhas abstratas"
+
+#: gtk_ardour/editor_route_list.cc:302
+msgid "Show All AudioBus"
+msgstr "Mostrar todos os barramentos de áudio"
+
+#: gtk_ardour/editor_route_list.cc:303
+msgid "Hide All AudioBus"
+msgstr "Ocultar todos os barramentos de áudio"
+
+#: gtk_ardour/editor_rulers.cc:311
+msgid "New location marker"
+msgstr "Nova marca de localização"
+
+#: gtk_ardour/editor_rulers.cc:312
+msgid "Clear all locations"
+msgstr "Apagar todas as localizações"
+
+#: gtk_ardour/editor_rulers.cc:317
+msgid "Clear all ranges"
+msgstr "Remover todos os intervalos"
+
+#: gtk_ardour/editor_rulers.cc:326
+msgid "New Tempo"
+msgstr "Novo Andamento"
+
+#: gtk_ardour/editor_rulers.cc:327
+msgid "Clear tempo"
+msgstr "Apagar andamento"
+
+#: gtk_ardour/editor_rulers.cc:332
+msgid "New Meter"
+msgstr "Novo Meter"
+
+#: gtk_ardour/editor_rulers.cc:333
+msgid "Clear meter"
+msgstr "Apagar meter"
+
+#: gtk_ardour/editor_rulers.cc:341
+msgid "Min:Secs"
+msgstr "Min:Segs"
+
+#: gtk_ardour/editor_selection_list.cc:117
+msgid "name for chunk:"
+msgstr "nome para o trecho"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Create chunk"
+msgstr "Criar trecho"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Forget it"
+msgstr "Esqueça isto"
+
+#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295
+msgid "add"
+msgstr "adicionar"
+
+#: gtk_ardour/editor_tempodisplay.cc:276
+#, fuzzy
+msgid "add tempo mark"
+msgstr "adicionar marca de intervalo"
+
+#: gtk_ardour/editor_tempodisplay.cc:318
+#, fuzzy
+msgid "add meter mark"
+msgstr "adicionar marca de intervalo"
+
+#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383
+msgid "done"
+msgstr "pronto"
+
+#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404
+msgid "replace tempo mark"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487
+#, fuzzy
+msgid "remove tempo mark"
+msgstr "remover marca"
+
+#: gtk_ardour/editor_timefx.cc:50
+msgid "Quick but Ugly"
+msgstr "Rápido mas Feio"
+
+#: gtk_ardour/editor_timefx.cc:51
+msgid "Skip Anti-aliasing"
+msgstr "Pular Anti-aliasing"
+
+#: gtk_ardour/editor_timefx.cc:53
+msgid "Stretch/Shrink it"
+msgstr "Esticar/Encolher isto"
+
+#: gtk_ardour/editor_timefx.cc:57
+msgid "ardour: timestretch"
+msgstr "ardour: esticar no tempo"
+
+#: gtk_ardour/editor_timefx.cc:58
+msgid "TimeStretchDialog"
+msgstr "Diálogo esticar no tempo"
+
+#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83
+#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85
+msgid "TimeStretchButton"
+msgstr "Botão esticar no tempo"
+
+#: gtk_ardour/editor_timefx.cc:86
+msgid "TimeStretchProgress"
+msgstr "Progresso esticar no tempo"
+
+#: gtk_ardour/editor_timefx.cc:151
+msgid "timestretch cannot be started - thread creation error"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410
+#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189
+msgid "22.05kHz"
+msgstr "22.05kHz"
+
+#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413
+#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949
+#: gtk_ardour/export_dialog.cc:1191
+msgid "44.1kHz"
+msgstr "44.1kHz"
+
+#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416
+#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193
+msgid "48kHz"
+msgstr "48kHz"
+
+#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419
+#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195
+msgid "88.2kHz"
+msgstr "88.2kHz"
+
+#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422
+#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197
+msgid "96kHz"
+msgstr "96kHz"
+
+#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425
+#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199
+msgid "192kHz"
+msgstr "192kHz"
+
+#: gtk_ardour/export_dialog.cc:73
+msgid "best"
+msgstr "excelente"
+
+#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964
+msgid "fastest"
+msgstr "rapidamente"
+
+#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966
+msgid "linear"
+msgstr "linear"
+
+#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968
+msgid "better"
+msgstr "bom"
+
+#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970
+msgid "intermediate"
+msgstr "intermediário"
+
+#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979
+msgid "Rectangular"
+msgstr "Retangular"
+
+#: gtk_ardour/export_dialog.cc:84
+msgid "Shaped Noise"
+msgstr "Perfil de Ruído"
+
+#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981
+msgid "Triangular"
+msgstr "Triangular"
+
+#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336
+msgid "stereo"
+msgstr "estéreo"
+
+#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497
+#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219
+#: gtk_ardour/utils.cc:334
+msgid "mono"
+msgstr "mono"
+
+#: gtk_ardour/export_dialog.cc:97
+msgid "CUE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:98
+msgid "TOC"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:106
+msgid "FORMAT"
+msgstr "FORMATO"
+
+#: gtk_ardour/export_dialog.cc:107
+msgid "SAMPLE RATE"
+msgstr "FREQUÊNCIA DE AMOSTRAGEM"
+
+#: gtk_ardour/export_dialog.cc:108
+msgid "CONVERSION QUALITY"
+msgstr "QUALIDADE DE CONVERSÃO"
+
+#: gtk_ardour/export_dialog.cc:109
+msgid "DITHER TYPE"
+msgstr "TIPO DE INTERPOLAÇÃO"
+
+#: gtk_ardour/export_dialog.cc:110
+#, fuzzy
+msgid "CD MARKER FILE TYPE"
+msgstr "TIPO DE ARQUIVO"
+
+#: gtk_ardour/export_dialog.cc:111
+msgid "CHANNELS"
+msgstr "CANAIS"
+
+#: gtk_ardour/export_dialog.cc:112
+msgid "FILE TYPE"
+msgstr "TIPO DE ARQUIVO"
+
+#: gtk_ardour/export_dialog.cc:113
+msgid "SAMPLE FORMAT"
+msgstr "FORMATO DE AMOSTRA"
+
+#: gtk_ardour/export_dialog.cc:114
+msgid "SAMPLE ENDIANNESS"
+msgstr "REPRESENTAÇÃO BINÃRIA"
+
+#: gtk_ardour/export_dialog.cc:115
+#, fuzzy
+msgid "EXPORT CD MARKER FILE ONLY"
+msgstr "TIPO DE ARQUIVO"
+
+#: gtk_ardour/export_dialog.cc:116
+msgid "EXPORT TO FILE"
+msgstr "EXPORTAR PARA ARQUIVO"
+
+#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118
+#: gtk_ardour/option_editor.cc:119
+msgid "Browse"
+msgstr "Localizar"
+
+#: gtk_ardour/export_dialog.cc:119
+msgid "Specific tracks ..."
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:131
+msgid "ardour: export"
+msgstr "ardour: exportar"
+
+#: gtk_ardour/export_dialog.cc:132
+msgid "ardour_export"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:156
+#, fuzzy
+msgid "Output"
+msgstr "Saídas"
+
+#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626
+msgid "Track"
+msgstr "Trilha"
+
+#: gtk_ardour/export_dialog.cc:287
+msgid "slereg"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:658
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD toc file"
+msgstr ""
+"Editor: não foi possível abrir o arquivo \"%1\" para exportar marcadores de "
+"faixa de CD"
+
+#: gtk_ardour/export_dialog.cc:780
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD cue file"
+msgstr ""
+"Editor: não foi possível abrir o arquivo \"%1\" para exportar marcadores de "
+"faixa de CD"
+
+#: gtk_ardour/export_dialog.cc:799
+msgid "WAV"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:1051
+msgid "Stop Export"
+msgstr "Cancelar Exportação"
+
+#: gtk_ardour/gain_automation_time_axis.cc:60
+#, fuzzy
+msgid "add gain automation event"
+msgstr "adicionar evento de automação para "
+
+#: gtk_ardour/gain_meter.cc:68
+msgid "Cannot create slider pixmaps"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:83
+msgid "dbFS"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134
+#: gtk_ardour/gain_meter.cc:728
+msgid "pre"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724
+#, fuzzy
+msgid "input"
+msgstr "%1 entrada"
+
+#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732
+#, fuzzy
+msgid "post"
+msgstr "porta"
+
+#: gtk_ardour/gain_meter.cc:146
+msgid "tupni"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470
+#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537
+#, fuzzy
+msgid "-inf"
+msgstr "entrada"
+
+#: gtk_ardour/imageframe_socket_handler.cc:127
+msgid "Image Compositor Socket has been shutdown/closed"
+msgstr ""
+
+#: gtk_ardour/imageframe_time_axis.cc:295
+#, fuzzy
+msgid "0.5 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259
+#, fuzzy
+msgid "1 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260
+#, fuzzy
+msgid "1.5 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261
+#, fuzzy
+msgid "2 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262
+#, fuzzy
+msgid "2.5 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263
+#, fuzzy
+msgid "3 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268
+#, fuzzy
+msgid "Duration (sec)"
+msgstr "normalizar região"
+
+#: gtk_ardour/imageframe_time_axis.cc:310
+#, fuzzy
+msgid "Remove Frame"
+msgstr "Remover Campo"
+
+#: gtk_ardour/imageframe_time_axis.cc:313
+#, fuzzy
+msgid "Image Frame"
+msgstr "Quadros"
+
+#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274
+#, fuzzy
+msgid "Rename Track"
+msgstr "Renomear"
+
+#: gtk_ardour/io_selector.cc:64
+msgid "%1 input"
+msgstr "%1 entrada"
+
+#: gtk_ardour/io_selector.cc:66
+msgid "%1 output"
+msgstr "%1 saída"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103
+msgid "Inputs"
+msgstr "Entradas"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104
+msgid "Outputs"
+msgstr "Saídas"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Input"
+msgstr "adicionar entrada"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Output"
+msgstr "adicionar saída"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Input"
+msgstr "Remover ponto de sincronia"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Output"
+msgstr "# Saídas"
+
+#: gtk_ardour/io_selector.cc:144
+#, fuzzy
+msgid "Disconnect All"
+msgstr "Desconectar"
+
+#: gtk_ardour/io_selector.cc:158
+msgid "Available connections"
+msgstr "Conexões disponíveis"
+
+#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636
+#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724
+msgid "port"
+msgstr "porta"
+
+#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587
+msgid "There are no more JACK ports available."
+msgstr ""
+
+#: gtk_ardour/io_selector.cc:790
+msgid "ardour: "
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:419
+msgid "KeyboardTarget: keyname \"%1\" is unknown."
+msgstr "KeyboardTarget: nome da tecla \"%1\" é desconhecido."
+
+#: gtk_ardour/keyboard.cc:645
+msgid ""
+"Your system is completely broken - NumLock uses \"%1\"as its modifier. This "
+"is madness - see the man page for xmodmap to find out how to fix this."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:653
+msgid ""
+"Your system generates \"%1\" when the NumLock key is pressed. This can cause "
+"problems when editing so Ardour will use %2 to mean Meta rather than %1"
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:714
+msgid "You have %1 keys bound to \"mod1\""
+msgstr "Você já tem %1 atalho de teclado para \"mod1\""
+
+#: gtk_ardour/keyboard.cc:729
+msgid "You have %1 keys bound to \"mod2\""
+msgstr "Você já tem %1 atalho de teclado para \"mod2\""
+
+#: gtk_ardour/keyboard.cc:744
+msgid "You have %1 keys bound to \"mod3\""
+msgstr "Você já tem %1 atalho de teclado para \"mod3\""
+
+#: gtk_ardour/keyboard.cc:759
+msgid "You have %1 keys bound to \"mod4\""
+msgstr "Você já tem %1 atalho de teclado para \"mod4\""
+
+#: gtk_ardour/keyboard.cc:774
+msgid "You have %1 keys bound to \"mod5\""
+msgstr "Você já tem %1 atalho de teclado para \"mod5\""
+
+#: gtk_ardour/keyboard_target.cc:72
+msgid "KeyboardTarget: empty string passed to add_binding."
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:78
+msgid "KeyboardTarget: no translation found for \"%1\""
+msgstr "KeyboardTarget: sem tradução encontrada para \"%1\""
+
+#: gtk_ardour/keyboard_target.cc:83
+msgid "KeyboardTarget: unknown action \"%1\""
+msgstr "KeyboardTarget: ação desconhecida \"%1\""
+
+#: gtk_ardour/keyboard_target.cc:248
+msgid "misformed binding node - ignored"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:62
+msgid "Soundfile Library"
+msgstr "Biblioteca de Ãudio"
+
+#: gtk_ardour/library_ui.cc:63
+msgid "Filesystem"
+msgstr "Sistema de arquivos"
+
+#: gtk_ardour/library_ui.cc:66
+msgid "Split Channels"
+msgstr "Separar Canais"
+
+#: gtk_ardour/library_ui.cc:69
+msgid "ardour: soundfile selector"
+msgstr "ardour: seletor de arquivos de áudio"
+
+#: gtk_ardour/library_ui.cc:430
+msgid "Add to Library..."
+msgstr "Adicionar na Biblioteca..."
+
+#: gtk_ardour/library_ui.cc:431
+msgid "Remove..."
+msgstr "Remover..."
+
+#: gtk_ardour/library_ui.cc:432
+msgid "Find..."
+msgstr "Buscar..."
+
+#: gtk_ardour/library_ui.cc:433
+msgid "Add Folder"
+msgstr "Criar Diretório"
+
+#: gtk_ardour/library_ui.cc:434
+msgid "Add audio file or directory"
+msgstr "Adicionar arquivo ou diretório"
+
+#: gtk_ardour/library_ui.cc:713
+msgid "Importing"
+msgstr "Importando"
+
+#: gtk_ardour/library_ui.cc:748
+msgid "%1 not added to database"
+msgstr "%1 não foi adicionada ao banco de dados"
+
+#: gtk_ardour/library_ui.cc:767
+msgid "Folder name:"
+msgstr "Nome do diretório:"
+
+#: gtk_ardour/library_ui.cc:838
+msgid "Should not be reached"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096
+msgid "file \"%1\" could not be opened"
+msgstr "arquivo \"%1\" não pôde ser aberto"
+
+#: gtk_ardour/library_ui.cc:956
+msgid "Field"
+msgstr "Campo"
+
+#: gtk_ardour/library_ui.cc:957
+msgid "Value"
+msgstr "Valor"
+
+#: gtk_ardour/library_ui.cc:973
+msgid "Stop"
+msgstr "Parar"
+
+#: gtk_ardour/library_ui.cc:974
+msgid "Add Field..."
+msgstr "Adicionar Campo..."
+
+#: gtk_ardour/library_ui.cc:975
+msgid "Remove Field"
+msgstr "Remover Campo"
+
+#: gtk_ardour/library_ui.cc:979
+msgid "Soundfile Info"
+msgstr "Informação do arquivo de áudio"
+
+#: gtk_ardour/library_ui.cc:1106
+msgid "file \"%1\" appears not to be an audio file"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1159
+msgid "Could not read file: %1 (%2)."
+msgstr "Não foi possível ler o arquivo: %1 (%2)."
+
+#: gtk_ardour/library_ui.cc:1177
+msgid "Could not access soundfile: "
+msgstr "não foi possível acessar arquivo de áudio"
+
+#: gtk_ardour/library_ui.cc:1222
+msgid "Field name:"
+msgstr "Nome do campo:"
+
+#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367
+msgid "Field value:"
+msgstr "Valor do campo:"
+
+#: gtk_ardour/library_ui.cc:1295
+msgid "Find"
+msgstr "Buscar"
+
+#: gtk_ardour/library_ui.cc:1296
+msgid "AND"
+msgstr "E"
+
+#: gtk_ardour/library_ui.cc:1297
+msgid "OR"
+msgstr "OU"
+
+#: gtk_ardour/library_ui.cc:1300
+msgid "ardour: locate soundfiles"
+msgstr "ardour: localizar arquivos de áudio"
+
+#: gtk_ardour/library_ui.cc:1426
+msgid "Results"
+msgstr "Resultados"
+
+#: gtk_ardour/library_ui.cc:1427
+msgid "Uris"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1439
+msgid "Create multi-channel region"
+msgstr "Criar região multi-canal"
+
+#: gtk_ardour/library_ui.cc:1442
+msgid "Ardour: Search Results"
+msgstr "Ardour: Resultado da Busca"
+
+#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50
+msgid "Set"
+msgstr "Fazer"
+
+#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51
+msgid "Go"
+msgstr "Ir"
+
+#: gtk_ardour/location_ui.cc:54
+msgid "CD"
+msgstr "CD"
+
+#: gtk_ardour/location_ui.cc:55
+msgid "Hidden"
+msgstr "Oculto"
+
+#: gtk_ardour/location_ui.cc:57
+msgid "SCMS"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:58
+msgid "Pre-Emphasis"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:592
+msgid "Add New Location"
+msgstr "Adicionar Nova Localização"
+
+#: gtk_ardour/location_ui.cc:593
+msgid "Add New Range"
+msgstr "Adicionar Novo Intervalo"
+
+#: gtk_ardour/location_ui.cc:597
+msgid "ardour: locations"
+msgstr "ardour: localizações"
+
+#: gtk_ardour/location_ui.cc:598
+msgid "ardour_locations"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:629
+#, fuzzy
+msgid "Location (CD Index) Markers"
+msgstr "Marcas de Localização"
+
+#: gtk_ardour/location_ui.cc:649
+#, fuzzy
+msgid "Range (CD Track) Markers"
+msgstr "Marcas de Intervalos"
+
+#: gtk_ardour/location_ui.cc:814
+msgid "add range marker"
+msgstr "adicionar marca de intervalo"
+
+#: gtk_ardour/main.cc:76
+msgid "ardour is killing itself for a clean exit\n"
+msgstr "o ardour está se matando para uma saída limpa\n"
+
+#: gtk_ardour/main.cc:85
+msgid "stopping user interface\n"
+msgstr "interrompendo a interface do usuário\n"
+
+#: gtk_ardour/main.cc:104
+#, c-format
+msgid "%d(%d): received signal %d\n"
+msgstr ""
+
+#: gtk_ardour/main.cc:190
+msgid "cannot become new process group leader (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:217
+msgid "cannot setup signal handling for %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:228
+msgid "cannot set default signal mask (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:253
+#, fuzzy
+msgid ""
+"Without a UI style file, ardour will look strange.\n"
+" Please set ARDOUR_UI_RC to point to a valid UI style file"
+msgstr ""
+"Sem um arquivo de estilo o ardour vai ficar meio esquisito.\n"
+"Por favor, configure a variável ambiente ARDOUR_UI_RC para um arquivo válido"
+
+#: gtk_ardour/main.cc:292
+msgid ""
+"Ardour could not connect to JACK.\n"
+"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 ""
+"Ardour não pôde se conectar ao JACK.\n"
+"Podem existir várias razões para isso:\n"
+"\n"
+"1) JACK não está rodando.\n"
+"2) JACK está rodando como outro usuário, talvez o root.\n"
+"3) Já existe um outro cliente chamado \"ardour\".\n"
+"\n"
+"Por favor, considere essas razões, e talvez (re)inicie o JACK."
+
+#: gtk_ardour/main.cc:305
+msgid "ardour: unplugged"
+msgstr "ardour: desplugado"
+
+#: gtk_ardour/main.cc:363
+msgid "Ardour/GTK "
+msgstr ""
+
+#: gtk_ardour/main.cc:365
+msgid ""
+"\n"
+" (built using "
+msgstr ""
+
+#: gtk_ardour/main.cc:369
+#, fuzzy
+msgid " with libardour "
+msgstr " executando com libardour "
+
+#: gtk_ardour/main.cc:374
+msgid " and GCC version "
+msgstr ""
+
+#: gtk_ardour/main.cc:384
+msgid "Copyright (C) 1999-2005 Paul Davis"
+msgstr ""
+
+#: gtk_ardour/main.cc:385
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+msgstr ""
+
+#: gtk_ardour/main.cc:387
+msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
+msgstr "Ardour não oferece ABSOLUTAMENTE NENHUMA GARANTIA"
+
+#: gtk_ardour/main.cc:388
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr ""
+
+#: gtk_ardour/main.cc:389
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr "Isto é um Software Livre. Fique à vontade para redistribuí-lo "
+
+#: gtk_ardour/main.cc:390
+msgid "under certain conditions; see the source for copying conditions."
+msgstr "com algumas condições; veja o fonte para mais detalhes"
+
+#: gtk_ardour/main.cc:399
+msgid "could not create ARDOUR GUI"
+msgstr "não foi possível criar a INTERFACE ARDOUR"
+
+#: gtk_ardour/main.cc:419
+msgid "Could not connect to JACK server as \"%1\""
+msgstr "Não foi possível se conectar ao servidor JACK com \"%1\""
+
+#: gtk_ardour/main.cc:424
+msgid "could not initialize Ardour."
+msgstr "não foi possível iniciar o Ardour."
+
+#: gtk_ardour/main.cc:435
+msgid "could not load command line session \"%1\""
+msgstr "não foi possível carregar a sessão da linha de comando \"%1\""
+
+#: gtk_ardour/main.cc:455
+msgid ""
+"\n"
+"\n"
+"A session named \"%1\" already exists.\n"
+"To avoid this message, start ardour as \"ardour %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:466
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as \"ardour --new %1"
+msgstr ""
+
+#: gtk_ardour/marker.cc:354
+#, fuzzy
+msgid "MarkerText"
+msgstr "Marcas"
+
+#: gtk_ardour/marker_time_axis.cc:271
+msgid "Remove Marker"
+msgstr "Remover Marca"
+
+#: gtk_ardour/marker_time_axis.cc:273
+msgid "Marker"
+msgstr "Marca"
+
+#: gtk_ardour/meter_bridge.cc:74
+msgid "ardour: meter bridge"
+msgstr "ardour: VU (medidor volumétrico)"
+
+#: gtk_ardour/meter_bridge.cc:75
+msgid "ardour_meter_bridge"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93
+#, c-format
+msgid "# of %u-sample overs"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:219
+msgid "New name for meter:"
+msgstr "Novo nome para VU (medidor volumétrico)"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507
+#: gtk_ardour/region_editor.cc:45
+msgid "mute"
+msgstr "mudo"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508
+msgid "solo"
+msgstr "solo"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506
+msgid "RECORD"
+msgstr "GRAVAR"
+
+#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514
+msgid "polarity"
+msgstr "polaridade"
+
+#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509
+msgid "comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810
+msgid "INPUT"
+msgstr "ENTRADA"
+
+#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831
+msgid "OUTPUT"
+msgstr "SAÃDA"
+
+#: gtk_ardour/mixer_strip.cc:173
+msgid "Pan automation mode"
+msgstr "modo automático de pan"
+
+#: gtk_ardour/mixer_strip.cc:174
+msgid "Gain automation mode"
+msgstr "modo automático de ganho"
+
+#: gtk_ardour/mixer_strip.cc:176
+msgid "Pan automation type"
+msgstr "Tipo do pan automático"
+
+#: gtk_ardour/mixer_strip.cc:177
+msgid "Gain automation type"
+msgstr "Tipo do ganho automático"
+
+#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232
+#: gtk_ardour/mixer_strip.cc:979
+msgid "trim"
+msgstr "cortar"
+
+#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233
+#: gtk_ardour/mixer_strip.cc:983
+msgid "abs"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:240
+msgid "gain automation mode"
+msgstr "modo automático de ganho"
+
+#: gtk_ardour/mixer_strip.cc:241
+msgid "pan automation mode"
+msgstr "modo automático de pan"
+
+#: gtk_ardour/mixer_strip.cc:242
+msgid "gain automation state"
+msgstr "estado do ganho automático"
+
+#: gtk_ardour/mixer_strip.cc:243
+msgid "pan automation state"
+msgstr "estado do pan automático"
+
+#: gtk_ardour/mixer_strip.cc:259
+msgid "varispeed"
+msgstr "velocidade variável"
+
+#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174
+msgid "click to add/edit comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:463
+msgid "unknown strip width \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:522
+msgid "REC"
+msgstr "GRAV"
+
+#: gtk_ardour/mixer_strip.cc:525
+#, fuzzy
+msgid "cmt"
+msgstr "cortar"
+
+#: gtk_ardour/mixer_strip.cc:530
+msgid "pol"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620
+#: gtk_ardour/redirect_box.cc:1180
+msgid "Not connected to JACK - no I/O changes are possible"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667
+msgid "could not register new ports required for that connection"
+msgstr "não foi posível registrar portas novas solicitadas por este conneção"
+
+#: gtk_ardour/mixer_strip.cc:813
+msgid "IN"
+msgstr "ENTRADA"
+
+#: gtk_ardour/mixer_strip.cc:834
+msgid "OUT"
+msgstr "SAÃDA"
+
+#: gtk_ardour/mixer_strip.cc:950
+msgid "aplay"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:956
+msgid "awrite"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:1134
+#, fuzzy
+msgid ": comment editor"
+msgstr "não foi possível iniciar o editor"
+
+#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224
+msgid "no group"
+msgstr "sem grupo"
+
+#: gtk_ardour/mixer_strip.cc:1227
+msgid "~G"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:52
+msgid "Strips"
+msgstr "Painéis"
+
+#: gtk_ardour/mixer_ui.cc:56
+msgid "Snapshots"
+msgstr "Capturas"
+
+#: gtk_ardour/mixer_ui.cc:61
+msgid "***"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17
+#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144
+#: gtk_ardour/tempo_dialog.cc:162
+msgid "Bar"
+msgstr "Compasso"
+
+#: gtk_ardour/mixer_ui.cc:121
+msgid "Mix Groups"
+msgstr "Grupos de Mixer"
+
+#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373
+msgid "ardour: mixer"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:192
+msgid "ardour_mixer"
+msgstr "ardour_mixer"
+
+#: gtk_ardour/mixer_ui.cc:342
+msgid "ardour: mixer: "
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:641
+msgid "signal"
+msgstr "sinal"
+
+#: gtk_ardour/mixer_ui.cc:672
+msgid "Show All AudioTrack MixerStrips"
+msgstr "Mostrar painéis de mixer de todas as trilhas de áudio"
+
+#: gtk_ardour/mixer_ui.cc:673
+msgid "Hide All AudioTrack MixerStrips"
+msgstr "Ocultar os páineis de mixer de todas as trilhas de áudio "
+
+#: gtk_ardour/mixer_ui.cc:674
+msgid "Show All AudioBus MixerStrips"
+msgstr "Mostrar os painéis de mixer de todo os barramento de áudio"
+
+#: gtk_ardour/mixer_ui.cc:675
+msgid "Hide All AudioBus MixerStrips"
+msgstr "Ocultar os painéis de mixer de todo os barramento de áudio"
+
+#: gtk_ardour/mixer_ui.cc:687
+msgid "track display list item for renamed strip not found!"
+msgstr "não foi encontrada qualquer trilha para o painel de mixer"
+
+#: gtk_ardour/mixer_ui.cc:700
+msgid "Name for new mix group"
+msgstr "Nome para o novo grupo de mixer"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Session name:"
+msgstr "Nome da sessão:"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Create"
+msgstr "Criar"
+
+#: gtk_ardour/new_session_dialog.cc:40
+msgid "use control outs"
+msgstr "usar controles de saída"
+
+#: gtk_ardour/new_session_dialog.cc:41
+msgid "use master outs"
+msgstr "usar saída master"
+
+#: gtk_ardour/new_session_dialog.cc:42
+#, fuzzy
+msgid "automatically connect track inputs to physical ports"
+msgstr "conectar automaticamente entradas das trilhas com as portas físicas"
+
+#: gtk_ardour/new_session_dialog.cc:43
+#, fuzzy
+msgid "automatically connect track outputs to master outs"
+msgstr "concetar automaticamente saídas das trilhas com as saídas master"
+
+#: gtk_ardour/new_session_dialog.cc:44
+#, fuzzy
+msgid "automatically connect track outputs to physical ports"
+msgstr "conectar automaticamente saídas das trilhas com as portas físicas"
+
+#: gtk_ardour/new_session_dialog.cc:45
+msgid "manually connect track outputs"
+msgstr "conectar manualmente saídas das trilhas"
+
+#: gtk_ardour/new_session_dialog.cc:50
+msgid "Advanced..."
+msgstr "Avançado ..."
+
+#: gtk_ardour/new_session_dialog.cc:52
+msgid "show again"
+msgstr "mostra novamente"
+
+#: gtk_ardour/new_session_dialog.cc:55
+msgid "Hardware Inputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:56
+msgid "Hardware Outputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:62
+msgid "new session setup"
+msgstr "nova configuração para sessão"
+
+#: gtk_ardour/new_session_dialog.cc:63
+msgid "ardour_new_session"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:72
+msgid "This session will playback and record at %1 Hz"
+msgstr "Esta sessão será reproduzida e gravada em %1 Hz"
+
+#: gtk_ardour/new_session_dialog.cc:74
+msgid ""
+"This rate is set by JACK and cannot be changed.\n"
+"If you want to use a different sample rate\n"
+"please exit and restart JACK"
+msgstr ""
+"A freqüência de áudio é determinada pelo JACK e não pode ser mudada.\n"
+"Se você quiser usar outra freqüência de áudio\n"
+"por favor feche o programa e reinicie o JACK"
+
+#: gtk_ardour/new_session_dialog.cc:155
+#, fuzzy
+msgid "Session template"
+msgstr "usar esquema existente"
+
+#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20
+#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146
+#: gtk_ardour/tempo_dialog.cc:164
+msgid "Location"
+msgstr "Localização"
+
+#: gtk_ardour/new_session_dialog.cc:178
+msgid "Configuration"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:269
+msgid "blank"
+msgstr "vazio"
+
+#: gtk_ardour/new_session_dialog.cc:328
+msgid "No template - create tracks/busses manually"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:337
+#, fuzzy
+msgid "No template"
+msgstr "-esquema/template"
+
+#: gtk_ardour/option_editor.cc:48
+#, fuzzy
+msgid "Internal"
+msgstr "interno"
+
+#: gtk_ardour/option_editor.cc:49
+#, fuzzy
+msgid "Slave to MTC"
+msgstr "Enviar MTC"
+
+#: gtk_ardour/option_editor.cc:50
+msgid "Sync with JACK"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:51
+msgid "never used but stops crashes"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:56
+#, fuzzy
+msgid "Later regions are higher"
+msgstr "Enviar região uma camada para trás"
+
+#: gtk_ardour/option_editor.cc:57
+msgid "Most recently added/moved/trimmed regions are higher"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:58
+#, fuzzy
+msgid "Most recently added regions are higher"
+msgstr "Enviar região uma camada para trás"
+
+#: gtk_ardour/option_editor.cc:63
+#, fuzzy
+msgid "Span entire region overlap"
+msgstr "Trazer região uma camada para frente"
+
+#: gtk_ardour/option_editor.cc:64
+msgid "Short fades at the start of the overlap"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:82
+#, fuzzy
+msgid "Automatically create crossfades"
+msgstr "Fade cruzado automático no intervalo sobreposto"
+
+#: gtk_ardour/option_editor.cc:83
+msgid "New full-overlap crossfades are unmuted"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:84
+#, fuzzy
+msgid "Region layering mode"
+msgstr "Fim de regiões"
+
+#: gtk_ardour/option_editor.cc:85
+#, fuzzy
+msgid "Crossfade model"
+msgstr "Fade Cruzado automático"
+
+#: gtk_ardour/option_editor.cc:90
+msgid "Latched solo"
+msgstr "Solo alternado"
+
+#: gtk_ardour/option_editor.cc:91
+msgid "Solo via bus"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:96
+msgid "Show waveforms while recording"
+msgstr "Mostrar formas de onda áudio quando gravando"
+
+#: gtk_ardour/option_editor.cc:97
+msgid "Narrow mixer strips"
+msgstr "Estreitar painéis de mixer"
+
+#: gtk_ardour/option_editor.cc:98
+msgid "Show measure lines"
+msgstr "Mostrar linhas de medida"
+
+#: gtk_ardour/option_editor.cc:99
+msgid "Follow playhead"
+msgstr "Reproduzir a partir do início"
+
+#: gtk_ardour/option_editor.cc:103
+msgid "Send MTC"
+msgstr "Enviar MTC"
+
+#: gtk_ardour/option_editor.cc:104
+msgid "Send MMC"
+msgstr "Enviar MMC"
+
+#: gtk_ardour/option_editor.cc:105
+msgid "JACK time master"
+msgstr "Modo supervisor de tempo (JACK)"
+
+#: gtk_ardour/option_editor.cc:107
+#, fuzzy
+msgid "SMPTE offset is negative"
+msgstr "Compensar SMPTE"
+
+#: gtk_ardour/option_editor.cc:111
+msgid "Send MIDI parameter feedback"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:112
+msgid "MIDI parameter control"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:113
+#, fuzzy
+msgid "MMC control"
+msgstr "Porta MMC"
+
+#: gtk_ardour/option_editor.cc:131
+#, fuzzy
+msgid "Auto-connect new track inputs to hardware"
+msgstr "Conectar novas faixas automaticamente"
+
+#: gtk_ardour/option_editor.cc:132
+#, fuzzy
+msgid "Auto-connect new track outputs to hardware"
+msgstr "Conectar novas faixas automaticamente"
+
+#: gtk_ardour/option_editor.cc:133
+#, fuzzy
+msgid "Auto-connect new track outputs to master bus"
+msgstr "concetar automaticamente saídas das trilhas com as saídas master"
+
+#: gtk_ardour/option_editor.cc:134
+#, fuzzy
+msgid "Manually connect new track outputs"
+msgstr "conectar manualmente saídas das trilhas"
+
+#: gtk_ardour/option_editor.cc:135
+msgid "Use Hardware Monitoring"
+msgstr "Usar Monitoração de Hardware"
+
+#: gtk_ardour/option_editor.cc:136
+msgid "Use Software Monitoring"
+msgstr "Usar Monitoração de Software"
+
+#: gtk_ardour/option_editor.cc:137
+msgid "Stop plugins with transport"
+msgstr "Suspender efeitos/plugins em transporte"
+
+#: gtk_ardour/option_editor.cc:138
+msgid "Run plugins while recording"
+msgstr "Executar plugins enquanto grava"
+
+#: gtk_ardour/option_editor.cc:139
+#, fuzzy
+msgid "Verify remove last capture"
+msgstr "Remover última captura"
+
+#: gtk_ardour/option_editor.cc:140
+msgid "Stop recording on xrun"
+msgstr "Suspender gravaçãoo em caso de falha sincrônica (XRUN)"
+
+#: gtk_ardour/option_editor.cc:141
+msgid "Stop transport at end of session"
+msgstr "Suspender o transporte no final da sessão"
+
+#: gtk_ardour/option_editor.cc:142
+msgid "Debug keyboard events"
+msgstr "Debug eventos do teclado"
+
+#: gtk_ardour/option_editor.cc:143
+msgid "-12dB gain reduction for ffwd/rew"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:152
+msgid "ardour: options editor"
+msgstr "ardour: preferências"
+
+#: gtk_ardour/option_editor.cc:153
+msgid "ardour_option_editor"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:183
+msgid "Misc"
+msgstr "Miscelânea"
+
+#: gtk_ardour/option_editor.cc:184
+msgid "Sync"
+msgstr "Sincronia"
+
+#: gtk_ardour/option_editor.cc:185
+msgid "Paths/Files"
+msgstr "Diretórios/Arquivos"
+
+#: gtk_ardour/option_editor.cc:186
+msgid "Display"
+msgstr "Visualização"
+
+#: gtk_ardour/option_editor.cc:187
+msgid "Kbd/Mouse"
+msgstr "Teclado/Mouse"
+
+#: gtk_ardour/option_editor.cc:188
+msgid "Click"
+msgstr "Metrônomo"
+
+#: gtk_ardour/option_editor.cc:190
+msgid "Layers & Fades"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:195
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gtk_ardour/option_editor.cc:268
+msgid "24 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:270
+msgid "25 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:272
+msgid "30 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:278
+msgid "30 FPS drop"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379
+#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736
+#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800
+msgid "Medium"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738
+#: gtk_ardour/option_editor.cc:804
+#, fuzzy
+msgid "Faster"
+msgstr "Fades"
+
+#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714
+#: gtk_ardour/option_editor.cc:776
+#, fuzzy
+msgid "Short"
+msgstr "porta"
+
+#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716
+#: gtk_ardour/option_editor.cc:780
+msgid "Long"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:396
+msgid "Broadcast WAVE/floating point"
+msgstr "Broadcast WAVE/vírgula flutuante"
+
+#: gtk_ardour/option_editor.cc:397
+msgid "WAVE/floating point"
+msgstr "WAVE/vírgula flutuante"
+
+#: gtk_ardour/option_editor.cc:417
+msgid "session RAID path"
+msgstr "diretório para sessão RAID"
+
+#: gtk_ardour/option_editor.cc:422
+msgid "Native Format"
+msgstr "Formato Nativo"
+
+#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460
+#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409
+msgid "internal"
+msgstr "interno"
+
+#: gtk_ardour/option_editor.cc:537
+msgid "Short crossfade length (msecs)"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:710
+msgid "Meter Peak Hold"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:730
+msgid "Meter Falloff"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:847
+msgid "Positional Sync"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:902
+msgid "SMPTE Frames/second"
+msgstr "SMPTE Frames/segundo"
+
+#: gtk_ardour/option_editor.cc:903
+msgid "SMPTE Offset"
+msgstr "Compensar SMPTE"
+
+#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013
+#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211
+#, fuzzy
+msgid "online"
+msgstr "linear"
+
+#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014
+#: gtk_ardour/option_editor.cc:1208
+#, fuzzy
+msgid "offline"
+msgstr "linear"
+
+#: gtk_ardour/option_editor.cc:1319
+msgid "Use as click"
+msgstr "Usar com metrônomo"
+
+#: gtk_ardour/option_editor.cc:1344
+msgid "Use as click emphasis"
+msgstr "Usar com metrônomo acentuado"
+
+#: gtk_ardour/option_editor.cc:1478
+msgid "--unknown--"
+msgstr "--desconhecido--"
+
+#: gtk_ardour/option_editor.cc:1595
+msgid "Click audio file"
+msgstr "Metrônomo no arquivo de áudio"
+
+#: gtk_ardour/option_editor.cc:1601
+msgid "Click emphasis audiofile"
+msgstr "Metrônomo acentuado no arquivo de áudio"
+
+#: gtk_ardour/option_editor.cc:1638
+msgid ""
+"The auditioner is a dedicated mixer strip used\n"
+"for listening to specific regions outside the context\n"
+"of the overall mix. It can be connected just like any\n"
+"other mixer strip."
+msgstr ""
+"O auditor é um painel de mistura dedicado\n"
+"à escuta de determinadas regiões fora do contexto\n"
+"da mistura geral. Pode ser interconectado tal como\n"
+"qualquer outro painel de mistura."
+
+#: gtk_ardour/option_editor.cc:1887
+msgid "Edit using"
+msgstr "Editar com"
+
+#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924
+msgid "+ button"
+msgstr "+ button"
+
+#: gtk_ardour/option_editor.cc:1917
+msgid "Delete using"
+msgstr "Apagar com"
+
+#: gtk_ardour/option_editor.cc:1947
+msgid "Ignore snap using"
+msgstr "Ignorar ajuste com"
+
+#: gtk_ardour/opts.cc:46
+msgid "Usage: "
+msgstr "Usual: "
+
+#: gtk_ardour/opts.cc:47
+msgid " -v, --version Show version information\n"
+msgstr " -v, --version Mostra informação sobre a versão\n"
+
+#: gtk_ardour/opts.cc:48
+msgid " -h, --help Print this message\n"
+msgstr " -h, --help Mostra esta mensagem\n"
+
+#: gtk_ardour/opts.cc:49
+msgid ""
+" -b, --bindings Print all possible keyboard binding "
+"names\n"
+msgstr ""
+" -b, --bindings Mostra todos os atalhos de teclado "
+"possíveis nomes\n"
+
+#: gtk_ardour/opts.cc:50
+#, fuzzy
+msgid " -n, --show-splash Show splash screen\n"
+msgstr " -n, --no-splash Não mostra imagem de abertura\n"
+
+#: gtk_ardour/opts.cc:51
+#, fuzzy
+msgid ""
+" -c, --name name Use a specific jack client name, default "
+"is ardour\n"
+msgstr ""
+" -c, --jack-client-name nome Use o cliente jack especificado por nome. "
+"O padrão é o ardour\n"
+
+#: gtk_ardour/opts.cc:52
+#, fuzzy
+msgid ""
+" -N, --new session-name Create a new session from the command "
+"line\n"
+msgstr " [session-name] Nome da sessão para carregar\n"
+
+#: gtk_ardour/opts.cc:53
+msgid ""
+" -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:55
+#, fuzzy
+msgid " -V, --novst Do not use VST support\n"
+msgstr " -n, --no-splash Não mostra imagem de abertura\n"
+
+#: gtk_ardour/opts.cc:57
+msgid " [session-name] Name of session to load\n"
+msgstr " [session-name] Nome da sessão para carregar\n"
+
+#: gtk_ardour/opts.cc:58
+msgid " -C, --curvetest filename Curve algorithm debugger\n"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:58
+msgid "You can't graphically edit panning of more than stream"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:78
+#, fuzzy
+msgid "add pan automation event"
+msgstr "adicionar evento de automação para "
+
+#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441
+msgid "Bypass"
+msgstr "Ignorar"
+
+#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222
+#, fuzzy
+msgid "link"
+msgstr "entrada"
+
+#: gtk_ardour/panner_ui.cc:103
+msgid "panning link control"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:105
+msgid "panning link direction"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:232
+msgid "L"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:344
+#, c-format
+msgid "panner for channel %u"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:451
+msgid "Reset all"
+msgstr "reiniciar todos"
+
+#: gtk_ardour/playlist_selector.cc:46
+msgid "Playlists grouped by track"
+msgstr ""
+
+#: gtk_ardour/playlist_selector.cc:53
+msgid "close"
+msgstr "fechar"
+
+#: gtk_ardour/playlist_selector.cc:59
+#, fuzzy
+msgid "ardour: playlists"
+msgstr "ardour: plugins"
+
+#: gtk_ardour/playlist_selector.cc:104
+#, fuzzy
+msgid "ardour: playlist for "
+msgstr "ardour: plugins"
+
+#: gtk_ardour/playlist_selector.cc:122
+msgid "Other tracks"
+msgstr "Outras trilhas"
+
+# msgstr "Ocultar esta trilha"
+#: gtk_ardour/playlist_selector.cc:138
+msgid "unassigned"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:41
+msgid "Available LADSPA plugins"
+msgstr "LADSPA plugins disponíveis"
+
+#: gtk_ardour/plugin_selector.cc:42
+msgid "Type"
+msgstr "Tipo"
+
+#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51
+msgid "# Inputs"
+msgstr "# Entradas"
+
+#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52
+msgid "# Outputs"
+msgstr "# Saídas"
+
+#: gtk_ardour/plugin_selector.cc:50
+msgid "Available VST plugins"
+msgstr "VST plugins disponíveis"
+
+#: gtk_ardour/plugin_selector.cc:58
+msgid "To be added"
+msgstr "Para ser adicionada"
+
+#: gtk_ardour/plugin_selector.cc:72
+msgid "ardour: plugins"
+msgstr "ardour: plugins"
+
+#: gtk_ardour/plugin_selector.cc:82
+msgid "Add a plugin to the effect list"
+msgstr "Adicionar plugin na lista de efeitos"
+
+#: gtk_ardour/plugin_selector.cc:84
+msgid "Remove a plugin from the effect list"
+msgstr "Remover plugin da lista de efeitos"
+
+#: gtk_ardour/plugin_selector.cc:88
+msgid "Update"
+msgstr "Atualizar"
+
+#: gtk_ardour/plugin_selector.cc:89
+msgid "Update available plugins"
+msgstr "Atualizar plugins disponíveis"
+
+#: gtk_ardour/plugin_selector.cc:110
+msgid "LADSPA"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:113
+msgid "VST"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:83
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this "
+"version of ardour)"
+msgstr ""
+"tipo desconhecido do plugin fornecido para o editor (nota: sem suporte VST "
+"nesta versão do ardour)"
+
+#: gtk_ardour/plugin_ui.cc:269
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr ""
+"Plugin Editor: não foi possível construir elemento de controle para a porta %"
+"1"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "in"
+msgstr "entrada"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "ins"
+msgstr "entradas"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "out"
+msgstr "saída"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "outs"
+msgstr "saídas"
+
+#: gtk_ardour/plugin_ui.cc:382
+msgid "automation control"
+msgstr "controle de automação"
+
+#: gtk_ardour/plugin_ui.cc:869
+#, fuzzy
+msgid "save"
+msgstr "Salvar"
+
+#: gtk_ardour/plugin_ui.cc:870
+msgid "bypass"
+msgstr "ignorar"
+
+#: gtk_ardour/plugin_ui.cc:892
+msgid "Plugin preset %1 not found"
+msgstr "Pré-seleção do plugin %1 não encontrada"
+
+#: gtk_ardour/plugin_ui.cc:903
+msgid "Name for plugin settings:"
+msgstr "Nome para efeito/plugin"
+
+#: gtk_ardour/redirect_automation_line.cc:53
+msgid "redirect automation created for non-plugin"
+msgstr "redirecionamento automático criado para um não-efeito/não-plugin"
+
+#: gtk_ardour/redirect_automation_time_axis.cc:92
+msgid "add automation event to "
+msgstr "adicionar evento de automação para "
+
+#: gtk_ardour/redirect_box.cc:213
+msgid "New send"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:214
+#, fuzzy
+msgid "Show send controls"
+msgstr "Velocidade do controle"
+
+#: gtk_ardour/redirect_box.cc:360
+msgid "New Plugin ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:361
+#, fuzzy
+msgid "New Insert"
+msgstr "nova entrada"
+
+#: gtk_ardour/redirect_box.cc:362
+msgid "New Send ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:380
+#, fuzzy
+msgid "Select all"
+msgstr "Selecionar Tudo"
+
+#: gtk_ardour/redirect_box.cc:381
+#, fuzzy
+msgid "Deselect all"
+msgstr "Selecionar Tudo"
+
+#: gtk_ardour/redirect_box.cc:389
+#, fuzzy
+msgid "Inserts"
+msgstr "Inverter verticalmente"
+
+#: gtk_ardour/redirect_box.cc:390
+#, fuzzy
+msgid "Sends"
+msgstr "Segundos"
+
+#: gtk_ardour/redirect_box.cc:393
+#, fuzzy
+msgid "Select all ..."
+msgstr "Selecionar Tudo"
+
+#: gtk_ardour/redirect_box.cc:406
+#, fuzzy
+msgid "Activate All"
+msgstr "Ativar"
+
+#: gtk_ardour/redirect_box.cc:407
+#, fuzzy
+msgid "Deactivate All"
+msgstr "Desativar"
+
+#: gtk_ardour/redirect_box.cc:488
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:500
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:513
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:616
+msgid "Pre-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:619
+msgid "Post-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:781
+msgid ""
+"You cannot reorder this set of redirects\n"
+"in that way because the inputs and\n"
+"outputs do not work correctly."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:903
+#, fuzzy
+msgid "ardour: rename redirect"
+msgstr "ardour: renomear região"
+
+#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043
+msgid ""
+"Copying the set of redirects on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:1064
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this track?\n"
+"(this cannot be undone)"
+msgstr ""
+"Tem certeza de que deseja remover a trilha \"%1\" ?\n"
+"(não será possível voltar)"
+
+#: gtk_ardour/redirect_box.cc:1067
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this bus?\n"
+"(this cannot be undone)"
+msgstr ""
+"Tem certeza de que deseja remover a trilha \"%1\" ?\n"
+"(não será possível voltar)"
+
+#: gtk_ardour/redirect_box.cc:1071
+#, fuzzy
+msgid "Yes, remove them all"
+msgstr "Sim, remova isto."
+
+#: gtk_ardour/redirect_box.cc:1114
+#, fuzzy
+msgid "ardour: %1"
+msgstr "ardour: relógio"
+
+#: gtk_ardour/redirect_box.cc:1156
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "ardour: região"
+
+#: gtk_ardour/region_editor.cc:43
+msgid "NAME:"
+msgstr "NOME:"
+
+#: gtk_ardour/region_editor.cc:44
+msgid "lock"
+msgstr "bloquear"
+
+#: gtk_ardour/region_editor.cc:46
+msgid "opaque"
+msgstr "opaco"
+
+#: gtk_ardour/region_editor.cc:49
+msgid "Layer"
+msgstr "Camada"
+
+#: gtk_ardour/region_editor.cc:57
+msgid "ENVELOPE"
+msgstr "ENVELOPE"
+
+#: gtk_ardour/region_editor.cc:108
+msgid "mute this region"
+msgstr "mutar esta região"
+
+#: gtk_ardour/region_editor.cc:109
+msgid "regions underneath this one cannot be heard"
+msgstr "regiões abaixo desta não são ouvidas"
+
+#: gtk_ardour/region_editor.cc:110
+msgid "prevent any changes to this region"
+msgstr "bloquear qualquer ateração nesta região"
+
+#: gtk_ardour/region_editor.cc:111
+msgid "use the gain envelope during playback"
+msgstr "usar envelope de ganho durante a reprodução"
+
+#: gtk_ardour/region_editor.cc:112
+msgid "show the gain envelope"
+msgstr "mostrar envelope de ganho"
+
+#: gtk_ardour/region_editor.cc:113
+msgid "use fade in curve during playback"
+msgstr "usar curva de fade-in durante reprodução"
+
+#: gtk_ardour/region_editor.cc:114
+msgid "use fade out curve during playback"
+msgstr "usar curva de fade-out durante reprodução"
+
+#: gtk_ardour/region_editor.cc:115
+msgid "audition this region"
+msgstr "ouvir esta região"
+
+#: gtk_ardour/region_editor.cc:148
+msgid "START:"
+msgstr "INICIO"
+
+#: gtk_ardour/region_editor.cc:150
+msgid "END:"
+msgstr "FINAL:"
+
+#: gtk_ardour/region_editor.cc:152
+msgid "LENGTH:"
+msgstr "TAMANHO:"
+
+#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198
+#: gtk_ardour/region_editor.cc:234
+msgid "active"
+msgstr "ativo"
+
+#: gtk_ardour/region_editor.cc:179
+msgid "visible"
+msgstr "visível"
+
+#: gtk_ardour/region_editor.cc:197
+msgid "FADE IN"
+msgstr "FADE IN"
+
+#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235
+msgid "msecs"
+msgstr "milisecs."
+
+#: gtk_ardour/region_editor.cc:233
+msgid "FADE OUT"
+msgstr "FADE OUT"
+
+#: gtk_ardour/region_editor.cc:276
+msgid "ardour: region "
+msgstr "ardour: região"
+
+#: gtk_ardour/region_editor.cc:410
+msgid "fade in edit"
+msgstr "fade in na edição"
+
+#: gtk_ardour/region_editor.cc:422
+msgid "fade out edit"
+msgstr "fade out na edição"
+
+#: gtk_ardour/regionview.cc:1169
+#, fuzzy
+msgid "add gain control point"
+msgstr "Remover ponto de controlo"
+
+#: gtk_ardour/route_params_ui.cc:58
+msgid "Tracks/Buses"
+msgstr "Trilhas/Barramentos"
+
+#: gtk_ardour/route_params_ui.cc:59
+msgid "Pre Redirects"
+msgstr "Pré Redirecionamentos"
+
+#: gtk_ardour/route_params_ui.cc:60
+msgid "Post Redirects"
+msgstr "Pós Redirecionamentos"
+
+#: gtk_ardour/route_params_ui.cc:105
+#, fuzzy
+msgid "Pre-fader Redirects"
+msgstr "Pré Redirecionamentos"
+
+#: gtk_ardour/route_params_ui.cc:106
+#, fuzzy
+msgid "Post-fader Redirects"
+msgstr "Pós Redirecionamentos"
+
+#: gtk_ardour/route_params_ui.cc:138
+#, fuzzy
+msgid "ardour: track/bus inspector"
+msgstr "ardour: adicionar trilhas/barramento"
+
+#: gtk_ardour/route_params_ui.cc:139
+msgid "ardour_route_parameters"
+msgstr "ardour_route_parameters"
+
+#: gtk_ardour/route_params_ui.cc:189
+msgid "route display list item for renamed route not found!"
+msgstr "não foi encontrada qualquer elemento para encaminhamento"
+
+#: gtk_ardour/route_params_ui.cc:448
+msgid "NO TRACK"
+msgstr "NENHUMA TRILHA"
+
+#: gtk_ardour/route_params_ui.cc:669
+#, fuzzy
+msgid "ardour: track/bus inspector: "
+msgstr "ardour: adicionar trilhas/barramento"
+
+#: gtk_ardour/route_params_ui.cc:673
+msgid "No Route Selected"
+msgstr "Caminho não selecionado"
+
+#: gtk_ardour/route_params_ui.cc:674
+#, fuzzy
+msgid "ardour: track/bus/inspector: no route selected"
+msgstr "ardour: parâmetros de encaminhamento: caminho não seleccionado"
+
+#: gtk_ardour/route_ui.cc:134
+#, fuzzy
+msgid "mute change"
+msgstr "Fazer intervalo de inserção"
+
+#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220
+#, fuzzy
+msgid "solo change"
+msgstr "Loop no intervalo"
+
+#: gtk_ardour/route_ui.cc:284
+msgid "rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:423
+#, fuzzy
+msgid "Solo-safe"
+msgstr "Solo"
+
+#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474
+#, fuzzy
+msgid "MIDI Bind"
+msgstr "MIDI"
+
+#: gtk_ardour/route_ui.cc:445
+msgid "Pre Fader"
+msgstr "Pré Fade"
+
+#: gtk_ardour/route_ui.cc:452
+msgid "Post Fader"
+msgstr "Pós Fade"
+
+#: gtk_ardour/route_ui.cc:459
+msgid "Control Outs"
+msgstr "Controle de Saídas"
+
+#: gtk_ardour/route_ui.cc:466
+msgid "Main Outs"
+msgstr "Saídas Principais"
+
+#: gtk_ardour/route_ui.cc:503
+msgid "mix group solo change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:537
+msgid "mix group mute change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:553
+msgid "mix group rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258
+msgid "ardour: color selection"
+msgstr "ardour: seleção de cor"
+
+#: gtk_ardour/route_ui.cc:652
+#, fuzzy
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"You may also lose the playlist used by this track.\n"
+"(cannot be undone)"
+msgstr ""
+"Tem certeza de que deseja remover a trilha \"%1\" ?\n"
+"(não será possível voltar)"
+
+#: gtk_ardour/route_ui.cc:654
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Deseja realmente remover o barramento \"%1\" ?\n"
+"(esta operação não poderá ser desfeita)"
+
+#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299
+msgid "Yes, remove it."
+msgstr "Sim, remova isto."
+
+#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358
+msgid "new name: "
+msgstr "novo nome: "
+
+#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31
+msgid "Beats per minute"
+msgstr "Batimentos por minuto"
+
+#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35
+#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163
+msgid "Beat"
+msgstr "Batimentos"
+
+#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158
+msgid "Meter denominator"
+msgstr "Denominador métrico"
+
+#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159
+msgid "Beats per bar"
+msgstr "Batimentos por compasso"
+
+#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189
+msgid "whole (1)"
+msgstr "toda (1)"
+
+#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191
+msgid "second (2)"
+msgstr "segunda (2)"
+
+#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193
+msgid "third (3)"
+msgstr "terceira (3)"
+
+#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195
+#: gtk_ardour/tempo_dialog.cc:203
+msgid "quarter (4)"
+msgstr "quarta (4)"
+
+#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197
+msgid "eighth (8)"
+msgstr "oitava (8)"
+
+#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199
+msgid "sixteenth (16)"
+msgstr "décima sexta (16)"
+
+#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201
+msgid "thirty-second (32)"
+msgstr "trigésima segunda (32)"
+
+#: gtk_ardour/tempo_dialog.cc:301
+msgid "garbaged note type entry (%1)"
+msgstr "tipo de nota entrada descartada (%1)"
+
+#: gtk_ardour/tempo_dialog.cc:311
+msgid "incomprehensible note type entry (%1)"
+msgstr "tipo de nota entrada incompreensível (%1)"
+
+#: gtk_ardour/time_axis_view.cc:95
+msgid "gTortnam"
+msgstr "gTortnam"
+
+#: gtk_ardour/time_axis_view.cc:446
+msgid "Largest"
+msgstr "Enorme"
+
+#: gtk_ardour/time_axis_view.cc:447
+msgid "Large"
+msgstr "Grande"
+
+#: gtk_ardour/time_axis_view.cc:448
+msgid "Larger"
+msgstr "Maior"
+
+#: gtk_ardour/time_axis_view.cc:450
+msgid "Smaller"
+msgstr "Menor"
+
+#: gtk_ardour/time_axis_view.cc:451
+msgid "Small"
+msgstr "Pequeno"
+
+#: gtk_ardour/time_axis_view.cc:785
+msgid "unknown track height name \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:69
+msgid "TimeAxisViewItemName"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:258
+msgid "new duration %1 frames is out of bounds for %2"
+msgstr ""
+
+#: gtk_ardour/time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr ""
+
+#: gtk_ardour/utils.cc:57
+msgid ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+msgstr ""
+
+#: gtk_ardour/utils.cc:66
+msgid "aeiou"
+msgstr ""
+
+#: gtk_ardour/utils.cc:75
+msgid "AEIOU"
+msgstr ""
+
+#: gtk_ardour/utils.cc:84
+msgid "bcdfghjklmnpqrtvwxyz"
+msgstr ""
+
+#: gtk_ardour/utils.cc:93
+msgid "BCDFGHJKLMNPQRTVWXYZ"
+msgstr ""
+
+#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265
+msgid "bad XPM header %1"
+msgstr ""
+
+#: gtk_ardour/utils.cc:516
+msgid "missing RGBA style for \"%1\""
+msgstr ""
+
+#: gtk_ardour/visual_time_axis.cc:297
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Tem certeza de que deseja remover a trilha \"%1\" ?\n"
+"(não será possível voltar)"
+
+#: gtk_ardour/visual_time_axis.cc:385
+msgid "A track already exists with that name"
+msgstr "já existe uma trilha com este nome"
+
+#~ msgid "Seamless Looping"
+#~ msgstr "Fazendo loop sem emendas"
+
+#~ msgid "Export to CD"
+#~ msgstr "Exportar para CD"
+
+#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Nenhum ícone de pressionamento foi encontrado para o toggle-button-[0-9]*."
+#~ "xpm$"
+
+#~ msgid ""
+#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$"
+#~ msgstr ""
+#~ "Nenhum ícone de pressionamento foi encontrado para o small-round-button-"
+#~ "[0-9]*.xpm$"
+
+#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$"
+#~ msgstr "Nenhum ícone encontrado para hslider[0-9]*.xpm$"
+
+#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$"
+#~ msgstr "Nenhum ícone encontrado para vslider[0-9]*.xpm$"
+
+#~ msgid "Trace MIDI Input"
+#~ msgstr "Rastrear Entrada MIDI"
+
+#~ msgid "Trace MIDI Output"
+#~ msgstr "Rastrear Saída MIDI"
+
+#~ msgid "MTC Port"
+#~ msgstr "Porta MTC"
+
+#~ msgid "attempt to timestretch a non-audio track!"
+#~ msgstr "tentativa de esticar temporalmente uma faixa não-áudio"
+
+#~ msgid "ok"
+#~ msgstr "ok"
+
+#~ msgid "apply"
+#~ msgstr "aplicar"
+
+#~ msgid "fade"
+#~ msgstr "fade"
+
+#~ msgid "Edit left"
+#~ msgstr "Editar a esquerda"
+
+#~ msgid "Edit right"
+#~ msgstr "Editar a direita"
+
+#~ msgid "Edit fade"
+#~ msgstr "Editar fade"
+
+#~ msgid "Export region"
+#~ msgstr "Exportar região"
+
+#, fuzzy
+#~ msgid "Bounce region"
+#~ msgstr "Saltar Seleção"
+
+#~ msgid "Region"
+#~ msgstr "Região"
+
+#~ msgid "Play selected region"
+#~ msgstr "Reproduzir região selecionada"
+
+#~ msgid "clear connections"
+#~ msgstr "limpar conexões"
+
+#~ msgid "Crossfades in use"
+#~ msgstr "Fade Cruzado em uso"
+
+#, fuzzy
+#~ msgid "outside this computer"
+#~ msgstr "Ocultar esta trilha"
+
+#, fuzzy
+#~ msgid "inside this computer"
+#~ msgstr "Ocultar esta trilha"
diff --git a/gtk2_ardour/po/pt_PT.po b/gtk2_ardour/po/pt_PT.po
new file mode 100644
index 0000000000..aa3904beaf
--- /dev/null
+++ b/gtk2_ardour/po/pt_PT.po
@@ -0,0 +1,5094 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Paul Davis
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 0.814.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-09-19 18:09-0400\n"
+"PO-Revision-Date: 2004-12-07 13:00+0000\n"
+"Last-Translator: Rui Nuno Capela <rncbc@rncbc.org>\n"
+"Language-Team: Portuguese\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gtk_ardour/about.cc:134
+msgid "Marcus Andersson"
+msgstr ""
+
+#: gtk_ardour/about.cc:135
+msgid "Jeremy Hall"
+msgstr ""
+
+#: gtk_ardour/about.cc:136
+msgid "Steve Harris"
+msgstr ""
+
+#: gtk_ardour/about.cc:137
+msgid "Tim Mayberry"
+msgstr ""
+
+#: gtk_ardour/about.cc:138
+msgid "Mark Stewart"
+msgstr ""
+
+#: gtk_ardour/about.cc:139
+msgid "Sam Chessman"
+msgstr ""
+
+#: gtk_ardour/about.cc:140
+msgid "Jack O'Quin"
+msgstr ""
+
+#: gtk_ardour/about.cc:141
+msgid "Matt Krai"
+msgstr ""
+
+#: gtk_ardour/about.cc:142
+msgid "Ben Bell"
+msgstr ""
+
+#: gtk_ardour/about.cc:143
+msgid "Gerard van Dongen"
+msgstr ""
+
+#: gtk_ardour/about.cc:144
+msgid "Thomas Charbonnel"
+msgstr ""
+
+#: gtk_ardour/about.cc:145
+msgid "Nick Mainsbridge"
+msgstr ""
+
+#: gtk_ardour/about.cc:146
+msgid "Colin Law"
+msgstr ""
+
+#: gtk_ardour/about.cc:147
+msgid "Sampo Savolainen"
+msgstr ""
+
+#: gtk_ardour/about.cc:148
+msgid "Joshua Leach"
+msgstr ""
+
+#: gtk_ardour/about.cc:149
+msgid "Rob Holland"
+msgstr ""
+
+#: gtk_ardour/about.cc:150
+msgid "Per Sigmond"
+msgstr ""
+
+#: gtk_ardour/about.cc:151
+msgid "Doug Mclain"
+msgstr ""
+
+#: gtk_ardour/about.cc:156
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+msgstr ""
+
+#: gtk_ardour/about.cc:157
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+msgstr ""
+
+#: gtk_ardour/about.cc:158
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+msgstr ""
+
+#: gtk_ardour/about.cc:159
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:160
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:162
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn@fastmail.fm>"
+msgstr ""
+
+#: gtk_ardour/about.cc:163
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop@nm.ru>"
+msgstr ""
+
+#: gtk_ardour/about.cc:181
+#, fuzzy
+msgid ""
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n"
+msgstr ""
+"Copyright (C) 1999-2004 Paul Davis\n"
+"Ardour é fornecido ABSOLUTAMENTE SEM QUALQUER GARANTIA\n"
+"Sendo software livre, é permitida e até encorajada a sua distribuição\n"
+"desde que sejam respeitadas algumas condições;\n"
+"para mais informações, leia por favor o ficheiro COPYING.\n"
+
+#: gtk_ardour/about.cc:188
+#, fuzzy
+msgid ""
+"Ardour: %1\n"
+"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+msgstr ""
+"Ardour: %1\n"
+"(compilado com ardour/gtk %2 libardour: %3.%4.%5)"
+
+#: gtk_ardour/about.cc:206
+msgid ""
+"Primary author:\n"
+"\tPaul Davis\n"
+"\n"
+"Major developers:\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributors:\n"
+"\t"
+msgstr ""
+
+#: gtk_ardour/about.cc:243
+msgid "Authors"
+msgstr "Autores"
+
+#: gtk_ardour/about.cc:244
+msgid "Translators"
+msgstr "Tradutores"
+
+#: gtk_ardour/about.cc:361
+msgid "cannot open splash image file \"%1\""
+msgstr ""
+"Editor: não foi possível abrir o ficheiro de imagem inicial \"%1\" (%2)"
+
+#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33
+#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81
+#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977
+#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85
+#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777
+#: gtk_ardour/redirect_box.cc:900
+msgid "OK"
+msgstr ""
+
+#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92
+#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046
+#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72
+#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982
+#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733
+#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000
+#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129
+#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785
+#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86
+#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072
+#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33
+#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94
+msgid "Tracks"
+msgstr "Faixas"
+
+#: gtk_ardour/add_route_dialog.cc:43
+msgid "Busses"
+msgstr "Barramentos"
+
+#: gtk_ardour/add_route_dialog.cc:48
+msgid "ardour: add track/bus"
+msgstr "ardour: acrescentar faixa/barramento"
+
+#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81
+msgid "Add"
+msgstr "Acrescentar"
+
+#: gtk_ardour/add_route_dialog.cc:86
+msgid "Name (template)"
+msgstr "Nome (modelo)"
+
+#: gtk_ardour/ardour_ui.cc:798
+msgid ""
+"pre\n"
+"roll"
+msgstr ""
+"pré\n"
+"batimento"
+
+#: gtk_ardour/ardour_ui.cc:799
+msgid ""
+"post\n"
+"roll"
+msgstr ""
+"pós\n"
+"batimento"
+
+#: gtk_ardour/ardour_ui.cc:807
+msgid "% "
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:808
+msgid "spring"
+msgstr "saltar"
+
+#: gtk_ardour/ardour_ui.cc:810
+msgid ""
+"punch\n"
+"in"
+msgstr ""
+"início de\n"
+"inserção"
+
+#: gtk_ardour/ardour_ui.cc:811
+msgid ""
+"punch\n"
+"out"
+msgstr ""
+"final de\n"
+"inserção"
+
+#: gtk_ardour/ardour_ui.cc:812
+msgid ""
+"auto\n"
+"return"
+msgstr ""
+"retorno\n"
+"automático"
+
+#: gtk_ardour/ardour_ui.cc:813
+msgid ""
+"auto\n"
+"play"
+msgstr ""
+"reprodução\n"
+"automática"
+
+#: gtk_ardour/ardour_ui.cc:814
+msgid ""
+"auto\n"
+"input"
+msgstr ""
+"entrada\n"
+"automática"
+
+#: gtk_ardour/ardour_ui.cc:815
+msgid "click"
+msgstr "Batimento"
+
+#: gtk_ardour/ardour_ui.cc:816
+msgid ""
+"follow\n"
+"PH"
+msgstr ""
+"acompanhar\n"
+"c.reprod."
+
+#: gtk_ardour/ardour_ui.cc:817
+msgid "AUDITIONING"
+msgstr "AUDIÇÃO"
+
+#: gtk_ardour/ardour_ui.cc:818
+msgid "SOLO"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:870
+msgid "Percentage"
+msgstr "Percentagem"
+
+#: gtk_ardour/ardour_ui.cc:872
+msgid "Semitones"
+msgstr "Semitons"
+
+#: gtk_ardour/ardour_ui.cc:875
+msgid "Sprung"
+msgstr "Salto"
+
+#: gtk_ardour/ardour_ui.cc:877
+msgid "Wheel"
+msgstr "Roda"
+
+#: gtk_ardour/ardour_ui.cc:902
+msgid ""
+"You cannot record-enable\n"
+"track %1\n"
+"because it has no input connections.\n"
+"You would be wasting space recording silence."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1073
+msgid "quit"
+msgstr "sair"
+
+#: gtk_ardour/ardour_ui.cc:1082
+msgid ""
+"Ardour was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1107
+msgid "Save and %1"
+msgstr "Guardar e %1"
+
+#: gtk_ardour/ardour_ui.cc:1112
+msgid "Just %1"
+msgstr "Apenas %1"
+
+#: gtk_ardour/ardour_ui.cc:1117
+msgid "Don't %1"
+msgstr "Não %1"
+
+#: gtk_ardour/ardour_ui.cc:1126
+#, fuzzy
+msgid "session"
+msgstr "Sessão"
+
+#: gtk_ardour/ardour_ui.cc:1128
+#, fuzzy
+msgid "snapshot"
+msgstr "Capturar"
+
+#: gtk_ardour/ardour_ui.cc:1130
+#, fuzzy
+msgid ""
+"The %1\n"
+"\"%2\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
+msgstr ""
+"A sessão \"%1\"\n"
+"ainda não se encontra salvaguardada.\n"
+"\n"
+"Qualquer alteração feita até ao momento\n"
+"ficará perdida se não a salvaguardar agora.\n"
+"\n"
+"O que pretende fazer?"
+
+#: gtk_ardour/ardour_ui.cc:1151
+msgid "Prompter"
+msgstr "Alerta"
+
+#: gtk_ardour/ardour_ui.cc:1152
+msgid "ardour: save session?"
+msgstr "ardour: guardar sessão?"
+
+#: gtk_ardour/ardour_ui.cc:1219
+#, fuzzy, c-format
+msgid "disconnected"
+msgstr "Desligar"
+
+#: gtk_ardour/ardour_ui.cc:1226
+#, fuzzy, c-format
+msgid "SR: %.1f kHz / %4.1f msecs"
+msgstr "FA: %.1f kHz"
+
+#: gtk_ardour/ardour_ui.cc:1230
+#, c-format
+msgid "SR: %u kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1243
+#, c-format
+msgid "DSP Load: %.1f%%"
+msgstr "Carga DSP: %.1f%%"
+
+#: gtk_ardour/ardour_ui.cc:1253
+#, c-format
+msgid "Disk r:%5.1f w:%5.1f MB/s"
+msgstr "Disco r:%5.1f w:%5.1f MB/s"
+
+#: gtk_ardour/ardour_ui.cc:1267
+#, c-format
+msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1294
+msgid "space: 24hrs+"
+msgstr "espaço: 24hrs+"
+
+#: gtk_ardour/ardour_ui.cc:1324
+#, c-format
+msgid "space: %02dh:%02dm:%02ds"
+msgstr "espaço: %02dh:%02dm:%02ds"
+
+#: gtk_ardour/ardour_ui.cc:1575
+msgid "programming error: impossible control method"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1800
+msgid "cancel"
+msgstr "cancelar"
+
+#: gtk_ardour/ardour_ui.cc:1801
+msgid "rescan"
+msgstr "refrescar"
+
+#: gtk_ardour/ardour_ui.cc:1842
+msgid "open session"
+msgstr "abrir sessão"
+
+#: gtk_ardour/ardour_ui.cc:1897
+msgid "Patience is a virtue.\n"
+msgstr "A paciência é uma virtude.\n"
+
+#: gtk_ardour/ardour_ui.cc:1906
+msgid "You cannot add a track without a session already loaded."
+msgstr ""
+"Não é possível acrescentar uma faixa sem que haja uma sessão esteja "
+"carregada."
+
+#: gtk_ardour/ardour_ui.cc:1913
+msgid "could not create new audio track"
+msgstr "não foi possível criar uma nova faixa audio"
+
+#: gtk_ardour/ardour_ui.cc:1917
+msgid "could not create new audio bus"
+msgstr "não foi possível criar um novo barramento audio"
+
+#: gtk_ardour/ardour_ui.cc:1936
+msgid ""
+"There are insufficient JACK ports available\n"
+"to create a new track or bus.\n"
+"You should save Ardour, exit and\n"
+"restart JACK with more ports."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2071
+msgid ""
+"Please create 1 or more track\n"
+"before trying to record.\n"
+"Check the Session menu."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2312
+#, fuzzy
+msgid ""
+"JACK has either been shutdown or it\n"
+"disconnected Ardour because Ardour\n"
+"was not fast enough. You can save the\n"
+"session and/or try to reconnect to JACK ."
+msgstr ""
+"O serviço de audio (JACK) foi desactivado ou\n"
+"o mesmo desligou a sua ligação com o Ardour,\n"
+"talvez porque este não o acompanhava suficientemente.\n"
+"A sessão corrente deverá ser salvaguardada\n"
+"e o serviço JACK reiniciado, tal como o Ardour."
+
+#: gtk_ardour/ardour_ui.cc:2328
+msgid "Unable to create all required ports"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2336
+#, fuzzy
+msgid "Unable to start the session running"
+msgstr "Ir para o início da sessão"
+
+#: gtk_ardour/ardour_ui.cc:2472
+msgid "No Stream"
+msgstr "Sem Fluxo"
+
+#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518
+msgid "none"
+msgstr "nenhum"
+
+#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527
+#: gtk_ardour/automation_time_axis.cc:189
+#: gtk_ardour/automation_time_axis.cc:218
+#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211
+#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947
+#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659
+msgid "off"
+msgstr "desligado"
+
+#: gtk_ardour/ardour_ui.cc:2548
+msgid "Name for snapshot"
+msgstr "Nome para a imagem capturada"
+
+#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294
+msgid "Name for mix template:"
+msgstr "Nome para o modelo de mistura"
+
+#: gtk_ardour/ardour_ui.cc:2717
+msgid "-template"
+msgstr "-modelo"
+
+#: gtk_ardour/ardour_ui.cc:2760
+msgid "Session %1 already exists at %2"
+msgstr "Sessão %1 já existe em %2"
+
+#: gtk_ardour/ardour_ui.cc:2832
+msgid ""
+"You do not have write access to this session.\n"
+"This prevents the session from being loaded."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "Não foi possível carregar a sessão \"%1 (captura %2)\" com sucesso"
+
+#: gtk_ardour/ardour_ui.cc:2966
+msgid ""
+"No audio files were ready for cleanup\n"
+"\n"
+"If this seems suprising, check for any existing\n"
+"snapshots. These may still include regions that\n"
+"require some unused files to continue to exist."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001
+msgid "files"
+msgstr "ficheiros"
+
+#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003
+msgid "file"
+msgstr "ficheiro"
+
+#: gtk_ardour/ardour_ui.cc:3026
+msgid "ardour: cleanup"
+msgstr "ardour: limpeza"
+
+#: gtk_ardour/ardour_ui.cc:3040
+msgid ""
+"Cleanup is a destructive operation.\n"
+"ALL undo/redo information will be lost if you cleanup.\n"
+"Unused audio files will be moved to a \"dead sounds\" location."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3045
+msgid "Proceed with cleanup"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3061
+#, fuzzy
+msgid "CleanupDialog"
+msgstr "Apagar"
+
+#: gtk_ardour/ardour_ui.cc:3062
+#, fuzzy
+msgid "ardour cleanup"
+msgstr "ardour: limpeza"
+
+#: gtk_ardour/ardour_ui.cc:3063
+#, fuzzy
+msgid "ardour_cleanup"
+msgstr "ardour: limpeza"
+
+#: gtk_ardour/ardour_ui.cc:3086
+msgid "cleaned files"
+msgstr "ficheiros limpos"
+
+#: gtk_ardour/ardour_ui.cc:3087
+msgid ""
+"The following %1 %2 were not in use.\n"
+"The next time you flush the wastebasket\n"
+"it will release an additional %3 %4bytes\n"
+"of disk space"
+msgstr ""
+"Os seguintes %1 %2 não se encontram em uso.\n"
+"Da próxima vez que efectuar uma limpeza\n"
+"irão ser libertados %3 %4 de espaço em disco"
+
+#: gtk_ardour/ardour_ui.cc:3110
+msgid "deleted file"
+msgstr "ficheiro eliminado"
+
+#: gtk_ardour/ardour_ui.cc:3111
+msgid ""
+"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"
+msgstr ""
+"Os seguintes %1 ficheiro%2 foram eliminados, libertando %3 %4B de espaço em "
+"disco"
+
+#: gtk_ardour/ardour_ui.cc:3226
+msgid "Recording was stopped because your system could not keep up."
+msgstr ""
+"A gravação foi interrompida porque o seu sistema não foi capaz de a "
+"acompanhar."
+
+#: gtk_ardour/ardour_ui.cc:3248
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
+msgstr ""
+"O sistema de ficheiros em disco do seu computador\n"
+"não foi capaz de manter o serviço audio do Ardour.\n"
+"\n"
+"Especificamente, a velocidade de escrita de dados em disco\n"
+"foi insuficiente para acompanhar o ritmo de gravação.\n"
+
+#: gtk_ardour/ardour_ui.cc:3266
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
+msgstr ""
+"O sistema de ficheiros em disco do seu computador\n"
+"não foi capaz de manter o serviço audio do Ardour.\n"
+"\n"
+"Especificamente, a velocidade de leitura de dados em disco\n"
+"foi insuficiente para acompanhar o ritmo de reprodução.\n"
+
+#: gtk_ardour/ardour_ui.cc:3291
+msgid "Recover from crash"
+msgstr "Recuperação"
+
+#: gtk_ardour/ardour_ui.cc:3292
+msgid "Ignore crash data"
+msgstr "Ignorar informação de recuperação"
+
+#: gtk_ardour/ardour_ui.cc:3293
+msgid ""
+"This session appears to have been in\n"
+"middle of recording when ardour or\n"
+"the computer was shutdown.\n"
+"\n"
+"Ardour can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
+msgstr ""
+"Esta sessão parece ter estado a meio\n"
+"de uma gravação quando o Ardour ou\n"
+"o computador foi desligado.\n"
+"\n"
+"Pode ser tentada a recuperação do audio\n"
+"capturado até então ou simplesmente ignorá-lo.\n"
+"Por favor decida o que pretende fazer.\n"
+
+#: gtk_ardour/ardour_ui.cc:3338
+#, fuzzy
+msgid "Could not disconnect from JACK"
+msgstr "Não foi possível conectar ao serviço JACK como \"%1\""
+
+#: gtk_ardour/ardour_ui.cc:3351
+#, fuzzy
+msgid "Could not reconnect to JACK"
+msgstr "Não foi possível conectar ao serviço JACK como \"%1\""
+
+#: gtk_ardour/ardour_ui2.cc:60
+msgid "UI: cannot setup editor"
+msgstr "Não foi possível iniciar o painel principal de edição (editor)"
+
+#: gtk_ardour/ardour_ui2.cc:65
+msgid "UI: cannot setup mixer"
+msgstr "Não foi posivel iniciar o painel de mistura"
+
+#: gtk_ardour/ardour_ui2.cc:70
+msgid "UI: cannot setup meter_bridge"
+msgstr "Não foi possível iniciar o monitor volumétrico (vuímetro)"
+
+#: gtk_ardour/ardour_ui2.cc:98
+msgid "MMC + Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:99
+msgid "MMC"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:100
+msgid "Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:117
+msgid "MMC ID"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:215
+msgid "Play from playhead"
+msgstr "Reproduzir desde o cursor de reprodução"
+
+#: gtk_ardour/ardour_ui2.cc:216
+msgid "Stop playback"
+msgstr "Parar reprodução"
+
+#: gtk_ardour/ardour_ui2.cc:217
+msgid "Play range/selection"
+msgstr "Reproduzir selecção"
+
+#: gtk_ardour/ardour_ui2.cc:218
+msgid "Go to start of session"
+msgstr "Ir para o início da sessão"
+
+#: gtk_ardour/ardour_ui2.cc:219
+msgid "Go to end of session"
+msgstr "Ir para o final da sessão"
+
+#: gtk_ardour/ardour_ui2.cc:220
+msgid "Play loop range"
+msgstr "Reproduzir intervalo cíclico"
+
+#: gtk_ardour/ardour_ui2.cc:221
+msgid "Return to last playback start when stopped"
+msgstr "Ir para a última posição inicial do cursor de reprodução quando parar"
+
+#: gtk_ardour/ardour_ui2.cc:222
+msgid "Start playback after any locate"
+msgstr "Iniciar a reprodução após qualquer localização"
+
+#: gtk_ardour/ardour_ui2.cc:223
+msgid "Be sensible about input monitoring"
+msgstr "Seja sensível acerca de monitorização de entradas"
+
+#: gtk_ardour/ardour_ui2.cc:224
+msgid "Start recording at auto-punch start"
+msgstr "Iniciar gravação na posição inicial de inserção automática"
+
+#: gtk_ardour/ardour_ui2.cc:225
+msgid "Stop recording at auto-punch end"
+msgstr "Parar gravação na posição final de inserção automática"
+
+#: gtk_ardour/ardour_ui2.cc:226
+msgid "Enable/Disable audio click"
+msgstr "Ligar/Desligar o metrónomo"
+
+#: gtk_ardour/ardour_ui2.cc:227
+msgid "Enable/Disable follow playhead"
+msgstr "Ligar/Desligar acompanhamento ao cursor de reprodução"
+
+#: gtk_ardour/ardour_ui2.cc:228
+msgid "Shuttle speed control"
+msgstr "Controlo de velocidade"
+
+#: gtk_ardour/ardour_ui2.cc:229
+#, fuzzy, c-format
+msgid "Select semitones or %%-age for speed display"
+msgstr "Seleccionar semitons ou %-agem para visualização de velocidade"
+
+#: gtk_ardour/ardour_ui2.cc:230
+msgid "Select sprung or wheel behaviour"
+msgstr "Seleccionar modo de salto ou de rolamento"
+
+#: gtk_ardour/ardour_ui2.cc:231
+msgid "Current transport speed"
+msgstr "Velocidade de transporte actual"
+
+#: gtk_ardour/ardour_ui2.cc:312
+msgid "Primary clock"
+msgstr "Cronómetro principal"
+
+#: gtk_ardour/ardour_ui2.cc:313
+msgid "secondary clock"
+msgstr "Cronómetro secundário"
+
+#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751
+#: gtk_ardour/ardour_ui2.cc:770
+msgid "stopped"
+msgstr "parado"
+
+#: gtk_ardour/ardour_ui2.cc:431
+msgid "ardour: clock"
+msgstr "ardour: cronómetro"
+
+#: gtk_ardour/ardour_ui2.cc:721
+msgid "st"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:731
+msgid "sprung"
+msgstr "mola"
+
+#: gtk_ardour/ardour_ui2.cc:742
+msgid "wheel"
+msgstr "roda"
+
+#: gtk_ardour/ardour_ui_dependents.cc:74
+msgid "keyboard_target: error setting binding state: invalid node"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dialogs.cc:158
+msgid "close session"
+msgstr "fechar sessão"
+
+#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895
+msgid "New"
+msgstr "Novo"
+
+#: gtk_ardour/ardour_ui_ed.cc:76
+msgid "Open"
+msgstr "Abrir"
+
+#: gtk_ardour/ardour_ui_ed.cc:77
+msgid "Recent"
+msgstr "Recente"
+
+#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+msgid "Close"
+msgstr "Fechar"
+
+#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488
+msgid "Add Track/Bus"
+msgstr "Acrescentar Faixa/Barramento"
+
+#: gtk_ardour/ardour_ui_ed.cc:99
+msgid "Connect"
+msgstr "Ligar"
+
+#: gtk_ardour/ardour_ui_ed.cc:100
+msgid "Image Compositor"
+msgstr "Compositor de Imagem"
+
+#: gtk_ardour/ardour_ui_ed.cc:114
+msgid "Save"
+msgstr "Guardar"
+
+#: gtk_ardour/ardour_ui_ed.cc:118
+msgid "Snapshot"
+msgstr "Capturar"
+
+#: gtk_ardour/ardour_ui_ed.cc:126
+msgid "Save Template..."
+msgstr "Guardar Modelo..."
+
+#: gtk_ardour/ardour_ui_ed.cc:133
+msgid "Export session to audiofile..."
+msgstr "Exportar sessão para ficheiro audio..."
+
+#: gtk_ardour/ardour_ui_ed.cc:134
+msgid "Export range to audiofile..."
+msgstr "Exportar intervalo para ficheiro audio..."
+
+#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312
+#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118
+#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227
+msgid "Export"
+msgstr "Exportar"
+
+#: gtk_ardour/ardour_ui_ed.cc:146
+msgid "Cleanup unused sources"
+msgstr "Apagar originais em desuso"
+
+#: gtk_ardour/ardour_ui_ed.cc:147
+msgid "Flush wastebasket"
+msgstr "Limpeza"
+
+#: gtk_ardour/ardour_ui_ed.cc:149
+msgid "Cleanup"
+msgstr "Apagar"
+
+#: gtk_ardour/ardour_ui_ed.cc:154
+msgid "Quit"
+msgstr "Sair"
+
+#: gtk_ardour/ardour_ui_ed.cc:156
+msgid "Session"
+msgstr "Sessão"
+
+#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287
+#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499
+#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570
+#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412
+msgid "Edit"
+msgstr "Editar"
+
+#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572
+#: gtk_ardour/mixer_strip.cc:631
+msgid "Disconnect"
+msgstr "Desligar"
+
+#: gtk_ardour/ardour_ui_ed.cc:174
+#, fuzzy
+msgid "Reconnect"
+msgstr "Ligar"
+
+#: gtk_ardour/ardour_ui_ed.cc:192
+msgid "Latency"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:195
+#, fuzzy
+msgid "JACK"
+msgstr "RECUAR"
+
+#: gtk_ardour/ardour_ui_ed.cc:205
+msgid "Editor"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:206
+msgid "Mixer"
+msgstr "Mistura"
+
+#: gtk_ardour/ardour_ui_ed.cc:212
+msgid "Options Editor"
+msgstr "Opções"
+
+#: gtk_ardour/ardour_ui_ed.cc:219
+msgid "Audio Library"
+msgstr "Audioteca"
+
+#: gtk_ardour/ardour_ui_ed.cc:225
+#, fuzzy
+msgid "Track/Bus Inspector"
+msgstr "Faixas/Barramentos"
+
+#: gtk_ardour/ardour_ui_ed.cc:232
+msgid "Connections"
+msgstr "Ligações"
+
+#: gtk_ardour/ardour_ui_ed.cc:240
+msgid "Meter Bridge"
+msgstr "VUímetro"
+
+#: gtk_ardour/ardour_ui_ed.cc:248
+msgid "Locations"
+msgstr "Localizações"
+
+#: gtk_ardour/ardour_ui_ed.cc:255
+msgid "Big Clock"
+msgstr "Cronómetro Principal"
+
+#: gtk_ardour/ardour_ui_ed.cc:261
+msgid "About"
+msgstr "Acerca de"
+
+#: gtk_ardour/ardour_ui_ed.cc:264
+msgid "Windows"
+msgstr "Janelas"
+
+#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203
+msgid "SMPTE"
+msgstr ""
+
+#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202
+#: gtk_ardour/editor_rulers.cc:359
+msgid "Bars:Beats"
+msgstr "Comp:Bat"
+
+#: gtk_ardour/audio_clock.cc:1642
+msgid "Minutes:Seconds"
+msgstr "Mins:Segs"
+
+#: gtk_ardour/audio_clock.cc:1643
+msgid "Audio Frames"
+msgstr "Quadros Audio"
+
+#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356
+#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713
+#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774
+#: gtk_ardour/option_editor.cc:794
+msgid "Off"
+msgstr "Desligado"
+
+#: gtk_ardour/audio_clock.cc:1646
+msgid "Mode"
+msgstr "Modo"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523
+msgid "m"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524
+msgid "s"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:104
+msgid "r"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:108
+msgid "g"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:109
+msgid "p"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44
+#: gtk_ardour/visual_time_axis.cc:90
+msgid "h"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:111
+msgid "a"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89
+msgid "v"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:185
+msgid "Record"
+msgstr "Gravar"
+
+#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191
+msgid "Solo"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236
+#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433
+msgid "Mute"
+msgstr "Mudo"
+
+#: gtk_ardour/audio_time_axis.cc:188
+msgid "Edit Group"
+msgstr "Grupo"
+
+#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110
+msgid "Display Height"
+msgstr "Altura"
+
+#: gtk_ardour/audio_time_axis.cc:190
+msgid "Playlist"
+msgstr "Lista de Reprodução"
+
+#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752
+msgid "Automation"
+msgstr "Automatização"
+
+#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111
+msgid "Visual options"
+msgstr "Opções visuais"
+
+#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112
+msgid "Hide this track"
+msgstr "Esconder esta faixa"
+
+#: gtk_ardour/audio_time_axis.cc:349
+msgid "No group"
+msgstr "Sem grupo"
+
+#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447
+#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229
+msgid "Height"
+msgstr "Altura"
+
+#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266
+#: gtk_ardour/marker_time_axis.cc:230
+msgid "Color"
+msgstr "Cor"
+
+#: gtk_ardour/audio_time_axis.cc:720
+msgid "Hide all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:721
+msgid "Show all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:729
+msgid "show all automation"
+msgstr "Mostrar todos as automatizações"
+
+#: gtk_ardour/audio_time_axis.cc:732
+msgid "show existing automation"
+msgstr "Mostrar automatizações existentes"
+
+#: gtk_ardour/audio_time_axis.cc:735
+msgid "hide all automation"
+msgstr "Esconder todos as automatizações"
+
+#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204
+#: gtk_ardour/editor.cc:234
+msgid "gain"
+msgstr "ganho"
+
+#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244
+msgid "pan"
+msgstr "pan"
+
+#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388
+msgid "Plugins"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95
+msgid "Show waveforms"
+msgstr "Mostrar formas de onda"
+
+#: gtk_ardour/audio_time_axis.cc:766
+msgid "Traditional"
+msgstr "Tradicional"
+
+#: gtk_ardour/audio_time_axis.cc:769
+msgid "Rectified"
+msgstr "Rectificado"
+
+#: gtk_ardour/audio_time_axis.cc:772
+msgid "Waveform"
+msgstr "Forma de onda"
+
+#: gtk_ardour/audio_time_axis.cc:782
+#, fuzzy
+msgid "align with existing material"
+msgstr "Material existente"
+
+#: gtk_ardour/audio_time_axis.cc:787
+#, fuzzy
+msgid "align with capture time"
+msgstr "Tempo de captura"
+
+#: gtk_ardour/audio_time_axis.cc:793
+#, fuzzy
+msgid "Alignment"
+msgstr "Alinhar"
+
+#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288
+msgid "Active"
+msgstr "Activar"
+
+#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386
+#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467
+#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269
+#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233
+#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83
+msgid "Remove"
+msgstr "Remover"
+
+#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880
+#: gtk_ardour/audio_time_axis.cc:911
+msgid "Name for playlist"
+msgstr "Nome para lista de reprodução"
+
+#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433
+msgid "a track already exists with that name"
+msgstr "já existe uma faixa com este nome"
+
+#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001
+#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539
+msgid "programming error: "
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:1889
+msgid "Current: %1"
+msgstr "Actual: %1"
+
+#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452
+#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226
+#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377
+msgid "Rename"
+msgstr "Renomear"
+
+#: gtk_ardour/audio_time_axis.cc:1896
+msgid "New Copy"
+msgstr "Nova Cópia"
+
+#: gtk_ardour/audio_time_axis.cc:1898
+msgid "Clear Current"
+msgstr "Limpar Actual"
+
+#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472
+#: gtk_ardour/editor.cc:2557
+msgid "Select"
+msgstr "Seleccionar"
+
+#: gtk_ardour/automation_line.cc:904
+msgid "automation event move"
+msgstr "mover evento de automatização"
+
+#: gtk_ardour/automation_line.cc:906
+msgid "automation range drag"
+msgstr "deslocar intervalo de automatização"
+
+#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64
+msgid "remove control point"
+msgstr "remover ponto de controlo"
+
+#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010
+msgid "clear"
+msgstr "apagar"
+
+#: gtk_ardour/automation_time_axis.cc:80
+msgid "track height"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:81
+#, fuzzy
+msgid "automation state"
+msgstr "ponto de automatização de panorâmica"
+
+#: gtk_ardour/automation_time_axis.cc:82
+#, fuzzy
+msgid "clear track"
+msgstr "apagar intervalos"
+
+#: gtk_ardour/automation_time_axis.cc:83
+#, fuzzy
+msgid "hide track"
+msgstr "retocar faixa"
+
+#: gtk_ardour/automation_time_axis.cc:191
+#: gtk_ardour/automation_time_axis.cc:229
+#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213
+#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419
+#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50
+msgid "play"
+msgstr "reproduzir"
+
+#: gtk_ardour/automation_time_axis.cc:193
+#: gtk_ardour/automation_time_axis.cc:240
+#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215
+#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422
+#: gtk_ardour/plugin_ui.cc:663
+msgid "write"
+msgstr "escrita"
+
+#: gtk_ardour/automation_time_axis.cc:195
+#: gtk_ardour/automation_time_axis.cc:251
+#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217
+#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953
+#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665
+msgid "touch"
+msgstr "tocar"
+
+#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274
+#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428
+msgid "???"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:276
+msgid "clear automation"
+msgstr "apagar automatizações"
+
+#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453
+#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398
+msgid "Hide"
+msgstr "Esconder"
+
+#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52
+#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364
+msgid "Clear"
+msgstr "Apagar"
+
+#: gtk_ardour/automation_time_axis.cc:474
+#, fuzzy
+msgid "State"
+msgstr "Início"
+
+#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49
+msgid "Input Connections"
+msgstr "Ligações de Entrada"
+
+#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48
+msgid "Output Connections"
+msgstr "Ligações de Saída"
+
+#: gtk_ardour/connection_editor.cc:49
+#, fuzzy
+msgid "New Input"
+msgstr "nova entrada"
+
+#: gtk_ardour/connection_editor.cc:50
+#, fuzzy
+msgid "New Output"
+msgstr "nova saída"
+
+#: gtk_ardour/connection_editor.cc:51
+#, fuzzy
+msgid "Delete"
+msgstr "eliminar"
+
+#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96
+#, fuzzy
+msgid "Add Port"
+msgstr "acrescentar porta"
+
+#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105
+#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786
+#, fuzzy
+msgid "Rescan"
+msgstr "refrescar"
+
+#: gtk_ardour/connection_editor.cc:101
+msgid "Available Ports"
+msgstr "Portas Disponíveis"
+
+#: gtk_ardour/connection_editor.cc:183
+msgid "ardour: connections"
+msgstr "ardour: ligações"
+
+#: gtk_ardour/connection_editor.cc:513
+#, c-format
+msgid "in %d"
+msgstr "em %d"
+
+#: gtk_ardour/connection_editor.cc:644
+msgid "Name for new connection:"
+msgstr "Nome para a nova ligação:"
+
+#: gtk_ardour/crossfade_edit.cc:71
+#, fuzzy
+msgid "crossfade editor"
+msgstr "alterar evanescimento"
+
+#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449
+#, fuzzy
+msgid "Reset"
+msgstr "reiniciar"
+
+#: gtk_ardour/crossfade_edit.cc:78
+#, fuzzy
+msgid "Fade"
+msgstr "Desvanecimentos"
+
+#: gtk_ardour/crossfade_edit.cc:79
+#, fuzzy
+msgid "Out (dry)"
+msgstr "saída (limpa)"
+
+#: gtk_ardour/crossfade_edit.cc:80
+#, fuzzy
+msgid "Out"
+msgstr "Saída"
+
+#: gtk_ardour/crossfade_edit.cc:81
+#, fuzzy
+msgid "In (dry)"
+msgstr "entrada (limpa)"
+
+#: gtk_ardour/crossfade_edit.cc:82
+msgid "In"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:84
+#, fuzzy
+msgid "With Pre-roll"
+msgstr "com pré-batimento"
+
+#: gtk_ardour/crossfade_edit.cc:85
+#, fuzzy
+msgid "With Post-roll"
+msgstr "com pós-batimento"
+
+#: gtk_ardour/crossfade_edit.cc:93
+msgid "Fade In"
+msgstr "Evanescimento"
+
+#: gtk_ardour/crossfade_edit.cc:94
+msgid "Fade Out"
+msgstr "Desvanecimento"
+
+#: gtk_ardour/crossfade_edit.cc:98
+msgid "ardour: x-fade edit"
+msgstr "ardour: desvanecimento cruzado"
+
+#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311
+#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189
+msgid "Audition"
+msgstr "Audição"
+
+#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804
+msgid "Regions/name"
+msgstr "Regiões"
+
+#: gtk_ardour/editor.cc:108
+msgid "Chunks"
+msgstr "Trechos"
+
+#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079
+msgid "Slide"
+msgstr "Deslizar"
+
+#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077
+msgid "Splice"
+msgstr "Reunir"
+
+#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136
+#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96
+#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977
+msgid "None"
+msgstr "Nenhum"
+
+#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124
+msgid "CD Frames"
+msgstr "Quadros CD"
+
+#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126
+msgid "SMPTE Frames"
+msgstr "Quadros SMPTE"
+
+#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128
+msgid "SMPTE Seconds"
+msgstr "Segundos SMPTE"
+
+#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130
+msgid "SMPTE Minutes"
+msgstr "Minutos SMPTE"
+
+#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132
+msgid "Seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134
+msgid "Minutes"
+msgstr "Minutos"
+
+#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106
+msgid "Beats/32"
+msgstr "Batimentos/32"
+
+#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104
+msgid "Beats/16"
+msgstr "Batimentos/16"
+
+#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102
+msgid "Beats/8"
+msgstr "Batimentos/8"
+
+#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100
+msgid "Beats/4"
+msgstr "Batimentos/4"
+
+#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098
+msgid "Beats/3"
+msgstr "Batimentos/3"
+
+#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108
+msgid "Beats"
+msgstr "Batimentos"
+
+#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110
+msgid "Bars"
+msgstr "Compassos"
+
+#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112
+msgid "Marks"
+msgstr "Marcas"
+
+#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114
+#: gtk_ardour/editor.cc:4182
+msgid "Edit Cursor"
+msgstr "Cursor de Edição"
+
+#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116
+msgid "Region starts"
+msgstr "Inícios de região"
+
+#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118
+msgid "Region ends"
+msgstr "Finais de região"
+
+#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122
+msgid "Region syncs"
+msgstr "Sincronismos de região"
+
+#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120
+msgid "Region bounds"
+msgstr "Extremos de região"
+
+#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153
+#: gtk_ardour/time_axis_view.cc:449
+msgid "Normal"
+msgstr "Normal"
+
+#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155
+msgid "Magnetic"
+msgstr "Magnético"
+
+#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174
+#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237
+msgid "Left"
+msgstr "Esquerda"
+
+#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176
+#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238
+msgid "Right"
+msgstr "Direita"
+
+#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178
+msgid "Center"
+msgstr "Centro"
+
+#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180
+msgid "Playhead"
+msgstr "Cursor de Reprodução"
+
+#: gtk_ardour/editor.cc:201
+msgid "Mins:Secs"
+msgstr "Mins:Segs"
+
+#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353
+msgid "Frames"
+msgstr "Quadros"
+
+#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373
+msgid "Tempo"
+msgstr ""
+
+#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367
+msgid "Meter"
+msgstr "VUímetro"
+
+#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379
+msgid "Location Markers"
+msgstr "Localizações"
+
+#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385
+msgid "Range Markers"
+msgstr "Intervalos"
+
+#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391
+msgid "Loop/Punch Ranges"
+msgstr "Ciclos/Inserção"
+
+#: gtk_ardour/editor.cc:221
+msgid ""
+"editor\n"
+"mixer"
+msgstr ""
+"edição\n"
+"mistura"
+
+#: gtk_ardour/editor.cc:232
+msgid "range"
+msgstr "intervalo"
+
+#: gtk_ardour/editor.cc:233
+msgid "object"
+msgstr "objecto"
+
+#: gtk_ardour/editor.cc:235
+msgid "zoom"
+msgstr ""
+
+#: gtk_ardour/editor.cc:236
+msgid "timefx"
+msgstr ""
+
+#: gtk_ardour/editor.cc:237
+msgid "listen"
+msgstr ""
+
+#: gtk_ardour/editor.cc:239
+msgid "mode"
+msgstr "modo"
+
+#: gtk_ardour/editor.cc:240
+msgid "automation"
+msgstr "automatização"
+
+#: gtk_ardour/editor.cc:242
+msgid "Edit Mode"
+msgstr "Modo de Edição"
+
+#: gtk_ardour/editor.cc:243
+msgid "Snap To"
+msgstr "Ajustar a"
+
+#: gtk_ardour/editor.cc:244
+msgid "Snap Mode"
+msgstr "Modo de Ajuste"
+
+#: gtk_ardour/editor.cc:245
+msgid "Zoom Focus"
+msgstr "Zoom(focagem)"
+
+#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364
+#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579
+msgid "Nudge"
+msgstr "Retocar"
+
+#: gtk_ardour/editor.cc:511
+msgid "Zoom in"
+msgstr "Zoom(+)"
+
+#: gtk_ardour/editor.cc:512
+msgid "Zoom out"
+msgstr "Zoom(-)"
+
+#: gtk_ardour/editor.cc:517
+msgid "Zoom to session"
+msgstr "Zoom(sessão)"
+
+#: gtk_ardour/editor.cc:536
+msgid "Zoom Span"
+msgstr "Zoom(alcance)"
+
+#: gtk_ardour/editor.cc:566
+msgid "Edit Groups"
+msgstr "Grupos"
+
+#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142
+msgid "-all-"
+msgstr "-tudo-"
+
+#: gtk_ardour/editor.cc:718
+msgid "Nudge region/selection forwards"
+msgstr "Retocar região/selecção para a frente"
+
+#: gtk_ardour/editor.cc:719
+msgid "Nudge region/selection backwards"
+msgstr "Retocar região/selecção para trás"
+
+#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308
+msgid "ardour: editor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:729
+msgid "ardour_editor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:846
+msgid "VerboseCanvasCursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1405
+msgid "FirstActionMessage"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1407
+msgid "Start a new session\n"
+msgstr "Iniciar uma nova sessão\n"
+
+#: gtk_ardour/editor.cc:1408
+msgid "via Session menu"
+msgstr "via menu de Sessão"
+
+#: gtk_ardour/editor.cc:1703
+msgid "ardour: editor: "
+msgstr ""
+
+#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796
+#: gtk_ardour/editor_markers.cc:797
+msgid "Loop"
+msgstr "Ciclo"
+
+#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810
+#: gtk_ardour/editor_markers.cc:823
+msgid "Punch"
+msgstr "Inserção"
+
+#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688
+msgid "programming error: fade in canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986
+#: gtk_ardour/redirect_box.cc:401
+msgid "Deactivate"
+msgstr "Desactivar"
+
+#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988
+#: gtk_ardour/redirect_box.cc:398
+msgid "Activate"
+msgstr "Activar"
+
+#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993
+msgid "Linear"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994
+#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734
+#: gtk_ardour/option_editor.cc:796
+msgid "Slowest"
+msgstr "Mais lento"
+
+#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995
+#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735
+#: gtk_ardour/option_editor.cc:798
+msgid "Slow"
+msgstr "Lento"
+
+#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996
+#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737
+#: gtk_ardour/option_editor.cc:802
+msgid "Fast"
+msgstr "Rápido"
+
+#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997
+#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739
+#: gtk_ardour/option_editor.cc:806
+msgid "Fastest"
+msgstr "Mais Rápido"
+
+#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113
+msgid "Freeze"
+msgstr "Congelar"
+
+#: gtk_ardour/editor.cc:2109
+msgid "Unfreeze"
+msgstr "Descongelar"
+
+#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328
+#, fuzzy
+msgid "Unmute"
+msgstr "mudo"
+
+#: gtk_ardour/editor.cc:2247
+msgid "Convert to short"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2249
+msgid "Convert to full"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2260
+#, fuzzy
+msgid "Crossfade"
+msgstr "Desvanecimento cruzado"
+
+#: gtk_ardour/editor.cc:2303
+msgid "Popup region editor"
+msgstr "Editor de região"
+
+#: gtk_ardour/editor.cc:2304
+#, fuzzy
+msgid "Raise to top layer"
+msgstr "Elevar a região para o nível de topo"
+
+#: gtk_ardour/editor.cc:2305
+#, fuzzy
+msgid "Lower to bottom layer"
+msgstr "Descer a região para o nível de fundo"
+
+#: gtk_ardour/editor.cc:2307
+msgid "Define sync point"
+msgstr "Definir ponto de sincronia"
+
+#: gtk_ardour/editor.cc:2308
+msgid "Remove sync point"
+msgstr "Remover ponto de sincronia"
+
+#: gtk_ardour/editor.cc:2313
+#, fuzzy
+msgid "Bounce"
+msgstr "Rebater intervalo"
+
+#: gtk_ardour/editor.cc:2323
+msgid "Lock"
+msgstr "Bloquear"
+
+#: gtk_ardour/editor.cc:2324
+msgid "Unlock"
+msgstr "Desbloquear"
+
+#: gtk_ardour/editor.cc:2334
+msgid "Original position"
+msgstr "Posição original"
+
+#: gtk_ardour/editor.cc:2340
+msgid "Toggle envelope visibility"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2341
+#, fuzzy
+msgid "Toggle envelope active"
+msgstr "Activação"
+
+#: gtk_ardour/editor.cc:2345
+msgid "DeNormalize"
+msgstr "Denormalizar"
+
+#: gtk_ardour/editor.cc:2347
+msgid "Normalize"
+msgstr "Normalizar"
+
+#: gtk_ardour/editor.cc:2350
+msgid "Reverse"
+msgstr "Inverter"
+
+#: gtk_ardour/editor.cc:2359
+msgid "Nudge fwd"
+msgstr "Retocar p/frente"
+
+#: gtk_ardour/editor.cc:2360
+msgid "Nudge bwd"
+msgstr "Retocar p/trás"
+
+#: gtk_ardour/editor.cc:2361
+msgid "Nudge fwd by capture offset"
+msgstr "Retocar p/frente captura"
+
+#: gtk_ardour/editor.cc:2362
+msgid "Nudge bwd by capture offset"
+msgstr "Retocar p/trás captura"
+
+#: gtk_ardour/editor.cc:2371
+msgid "Start to edit cursor"
+msgstr "Do início ao cursor de edição"
+
+#: gtk_ardour/editor.cc:2372
+msgid "Edit cursor to end"
+msgstr "Do cursor de edição ao final"
+
+#: gtk_ardour/editor.cc:2374
+msgid "Trim"
+msgstr "Cortar"
+
+#: gtk_ardour/editor.cc:2377
+msgid "Split"
+msgstr "Separar"
+
+#: gtk_ardour/editor.cc:2380
+msgid "Make mono regions"
+msgstr "Criar regiões mono"
+
+#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428
+msgid "Duplicate"
+msgstr "Duplicar"
+
+#: gtk_ardour/editor.cc:2384
+msgid "Fill Track"
+msgstr "Preencher Faixa"
+
+#: gtk_ardour/editor.cc:2388
+msgid "Destroy"
+msgstr "Destruir"
+
+#: gtk_ardour/editor.cc:2418
+msgid "Play range"
+msgstr "Reproduzir intervalo"
+
+#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446
+msgid "Loop range"
+msgstr "Intervalo cíclico"
+
+#: gtk_ardour/editor.cc:2421
+msgid "Create chunk from range"
+msgstr "Criar trecho desde intervalo"
+
+#: gtk_ardour/editor.cc:2423
+msgid "Create Region"
+msgstr "Criar Região"
+
+#: gtk_ardour/editor.cc:2424
+msgid "Separate Region"
+msgstr "Separar Região"
+
+#: gtk_ardour/editor.cc:2425
+msgid "Crop Region to range"
+msgstr "Cortar Regão para intervalo"
+
+#: gtk_ardour/editor.cc:2426
+msgid "Bounce range"
+msgstr "Rebater intervalo"
+
+#: gtk_ardour/editor.cc:2432
+msgid "Fill range w/Region"
+msgstr "Preencher intervalo c/Região"
+
+#: gtk_ardour/editor.cc:2434
+msgid "Range"
+msgstr "Intervalo"
+
+#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538
+msgid "Play from edit cursor"
+msgstr "Reproduzir desde o cursor de edição"
+
+#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539
+msgid "Play from start"
+msgstr "Reproduzir desde o início"
+
+#: gtk_ardour/editor.cc:2451
+#, fuzzy
+msgid "Play region"
+msgstr "Reproduzir Região"
+
+#: gtk_ardour/editor.cc:2453
+msgid "Loop Region"
+msgstr "Região Cíclica"
+
+#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540
+#: gtk_ardour/library_ui.cc:972
+msgid "Play"
+msgstr "Reproduzir"
+
+#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548
+msgid "Select All in track"
+msgstr "Seleccionar tudo na faixa"
+
+#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549
+msgid "Select All"
+msgstr "Seleccionar tudo"
+
+#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550
+msgid "Invert in track"
+msgstr "Inverter na faixa"
+
+#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551
+msgid "Invert"
+msgstr "Inverter"
+
+#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553
+msgid "Select loop range"
+msgstr "Seleccionar intervalo de ciclo"
+
+#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554
+msgid "Select punch range"
+msgstr "Seleccionar intervalo de inserção"
+
+#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565
+#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369
+msgid "Cut"
+msgstr "Cortar"
+
+#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566
+#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371
+msgid "Copy"
+msgstr "Copiar"
+
+#: gtk_ardour/editor.cc:2482
+#, fuzzy
+msgid "Paste at edit cursor"
+msgstr "Do início ao cursor de edição"
+
+#: gtk_ardour/editor.cc:2483
+#, fuzzy
+msgid "Paste at mouse"
+msgstr "usar saídas principais"
+
+#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923
+msgid "Align"
+msgstr "Alinhar"
+
+#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925
+msgid "Align Relative"
+msgstr "Alinhar Relativamente"
+
+#: gtk_ardour/editor.cc:2492
+msgid "Insert chunk"
+msgstr "Inserir trecho"
+
+#: gtk_ardour/editor.cc:2496
+#, fuzzy
+msgid "New Region from range"
+msgstr "Nova região desde a selecção"
+
+#: gtk_ardour/editor.cc:2497
+msgid "Separate Range"
+msgstr "Separar Intervalo"
+
+#: gtk_ardour/editor.cc:2507
+msgid "Insert Region"
+msgstr "Inserir Região"
+
+#: gtk_ardour/editor.cc:2508
+msgid "Insert external sndfile"
+msgstr "Inserir ficheiro audio externo"
+
+#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438
+msgid "Import"
+msgstr "Importar"
+
+#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574
+msgid "Nudge entire track fwd"
+msgstr "Retocar toda a faixa p/frente"
+
+#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575
+msgid "Nudge track after edit cursor fwd"
+msgstr "Retocar a faixa p/frente do cursor de edição"
+
+#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576
+msgid "Nudge entire track bwd"
+msgstr "Retocar toda a faixa p/trás"
+
+#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577
+msgid "Nudge track after edit cursor bwd"
+msgstr "Retocar a faixa p/trás do cursor de edição"
+
+#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920
+#: gtk_ardour/redirect_box.cc:373
+msgid "Paste"
+msgstr "Colar"
+
+#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645
+#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799
+msgid "add marker"
+msgstr "adicionar marcador"
+
+#: gtk_ardour/editor.cc:3084
+msgid "select/move objects"
+msgstr "seleccionar/mover objectos"
+
+#: gtk_ardour/editor.cc:3085
+msgid "select/move ranges"
+msgstr "seleccionar/mover intervalos"
+
+#: gtk_ardour/editor.cc:3086
+msgid "draw gain automation"
+msgstr "desenhar automatização de ganho"
+
+#: gtk_ardour/editor.cc:3087
+msgid "select zoom range"
+msgstr "seleccionar zoom"
+
+#: gtk_ardour/editor.cc:3088
+msgid "stretch/shrink regions"
+msgstr "alongar/estreitar regiões"
+
+#: gtk_ardour/editor.cc:3089
+#, fuzzy
+msgid "listen to specific regions"
+msgstr "seleccionar regiões"
+
+#: gtk_ardour/editor.cc:3213
+msgid "Start:"
+msgstr "Início:"
+
+#: gtk_ardour/editor.cc:3214
+msgid "End:"
+msgstr "Final:"
+
+#: gtk_ardour/editor.cc:3215
+msgid "Edit:"
+msgstr "Editar:"
+
+#: gtk_ardour/editor.cc:3429
+msgid "incorrectly formatted URI list, ignored"
+msgstr "lista de URIs mal formada, ignorada"
+
+#: gtk_ardour/editor.cc:3611
+#, fuzzy
+msgid "set selected trackview"
+msgstr "seleccionar visualização de faixa"
+
+#: gtk_ardour/editor.cc:3647
+#, fuzzy
+msgid "set selected control point"
+msgstr "remover ponto de controlo"
+
+#: gtk_ardour/editor.cc:3719
+msgid "set selected regionview"
+msgstr "seleccionar visualização de região"
+
+#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835
+msgid "set selected regions"
+msgstr "seleccionar regiões"
+
+#: gtk_ardour/editor.cc:3891
+msgid "Undo"
+msgstr "Desfazer"
+
+#: gtk_ardour/editor.cc:3893
+msgid "Undo (%1)"
+msgstr "Desfazer (%1)"
+
+#: gtk_ardour/editor.cc:3903
+msgid "Redo"
+msgstr "Refazer"
+
+#: gtk_ardour/editor.cc:3905
+msgid "Redo (%1)"
+msgstr "Refazer (%1)"
+
+#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946
+msgid "... as new track"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947
+#, fuzzy
+msgid "... as new region"
+msgstr "alinhar região"
+
+#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452
+msgid "Import audio (copy)"
+msgstr "Importar audio (copiar)"
+
+#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457
+msgid "Embed audio (link)"
+msgstr "Intercalar audio (ligar)"
+
+#: gtk_ardour/editor.cc:3953
+msgid "Remove last capture"
+msgstr "Remover a última captura"
+
+#: gtk_ardour/editor.cc:3974
+msgid "Duplicate how many times?"
+msgstr "Duplicar quantas vezes?"
+
+#: gtk_ardour/editor.cc:4550
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If left alone, no audio files used by it will be cleaned.\n"
+"If deleted, audio files used by it alone by will cleaned."
+msgstr ""
+"A lista de reprodução %1 não se encontra actualmente em uso.\n"
+"Se for mantida assim, não serão elimnados os ficheiros de audio por ela "
+"empregues.\n"
+"Se for eliminada, todos os ficheiros de audio serão respectivamente "
+"eliminados."
+
+#: gtk_ardour/editor.cc:4555
+msgid "Delete playlist"
+msgstr "Eliminar lista de reprodução"
+
+#: gtk_ardour/editor.cc:4556
+#, fuzzy
+msgid "Keep playlist"
+msgstr "Manter lista de reprodução"
+
+#: gtk_ardour/editor.cc:4557
+msgid "Cancel cleanup"
+msgstr "Cancelar eliminação"
+
+#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258
+#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290
+msgid ""
+"programming error: control point canvas item has no control point object "
+"pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:717
+msgid "programming error: line canvas item has no line object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_canvas_events.cc:744
+#: gtk_ardour/editor_canvas_events.cc:784
+#: gtk_ardour/editor_canvas_events.cc:823
+msgid "programming error: no \"rect\" pointer associated with selection item"
+msgstr ""
+
+#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298
+#: gtk_ardour/mixer_ui.cc:670
+msgid "Show All"
+msgstr "Mostrar tudo"
+
+#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299
+#: gtk_ardour/mixer_ui.cc:671
+msgid "Hide All"
+msgstr "Ocultar tudo"
+
+#: gtk_ardour/editor_edit_groups.cc:98
+msgid "Name for new edit group"
+msgstr "Nome para o novo grupo de edição"
+
+#: gtk_ardour/editor_export_audio.cc:60
+msgid ""
+"There is no range to export.\n"
+"\n"
+"Select a range using the range mouse mode"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707
+msgid "programming error: no ImageFrameView selected"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930
+msgid "programming error: no MarkerView selected"
+msgstr ""
+
+#: gtk_ardour/editor_keys.cc:187
+#, fuzzy
+msgid "keyboard selection"
+msgstr "extender selecção"
+
+#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376
+#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526
+#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584
+#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650
+#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700
+#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960
+#: gtk_ardour/editor_mouse.cc:4075
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681
+msgid "remove marker"
+msgstr "remover marcador"
+
+#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494
+msgid "Locate to"
+msgstr "Localizar"
+
+#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495
+msgid "Play from"
+msgstr "Reproduzir desde"
+
+#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496
+msgid "Set from playhead"
+msgstr "Desde cursor de reprodução"
+
+#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497
+msgid "Set from range"
+msgstr "Seleccionar intervalo"
+
+#: gtk_ardour/editor_markers.cc:479
+msgid "Set Loop Range"
+msgstr "Seleccionar Intervalo Cíclico"
+
+#: gtk_ardour/editor_markers.cc:480
+msgid "Set Punch Range"
+msgstr "Seleccionar Intervalo de Inserção"
+
+#: gtk_ardour/editor_markers.cc:736
+msgid "ardour: rename mark"
+msgstr "ardour: renomear marca"
+
+#: gtk_ardour/editor_markers.cc:738
+#, fuzzy
+msgid "ardour: rename range"
+msgstr "ardour: renomear região"
+
+#: gtk_ardour/editor_markers.cc:792
+msgid "set loop range"
+msgstr "seleccionar intervalo cíclico"
+
+#: gtk_ardour/editor_markers.cc:818
+msgid "set punch range"
+msgstr "seleccionar intervalo de inserção"
+
+#: gtk_ardour/editor_mouse.cc:99
+msgid "Editor::event_frame() used on unhandled event type %1"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1555
+msgid "programming error: start_grab called without drag item"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1760
+msgid "change fade in length"
+msgstr "alterar duração de evanescimento"
+
+#: gtk_ardour/editor_mouse.cc:1778
+msgid "programming error: fade out canvas item has no regionview data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:1852
+msgid "change fade out length"
+msgstr "alterar duração desvanecimento"
+
+#: gtk_ardour/editor_mouse.cc:1871
+msgid "programming error: cursor canvas item has no cursor data pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470
+msgid ""
+"programming error: meter marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2163
+msgid "move meter mark"
+msgstr "remover marcador métrico"
+
+#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335
+#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439
+msgid ""
+"programming error: tempo marker canvas item has no marker object pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340
+#: gtk_ardour/editor_tempodisplay.cc:425
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2245
+msgid "move tempo mark"
+msgstr "remover marcador de tempo"
+
+#: gtk_ardour/editor_mouse.cc:2388
+msgid "programming error: line canvas item has no line pointer!"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2497
+#, fuzzy
+msgid "move region(s)"
+msgstr "remover região"
+
+#: gtk_ardour/editor_mouse.cc:2509
+msgid "Drag region copy"
+msgstr "Arraster cópia de região"
+
+#: gtk_ardour/editor_mouse.cc:2579
+#, fuzzy
+msgid "copy region(s)"
+msgstr "Arrastar regiões"
+
+#: gtk_ardour/editor_mouse.cc:2612
+#, fuzzy
+msgid "Drag region brush"
+msgstr "Arrastar regiões"
+
+#: gtk_ardour/editor_mouse.cc:3425
+msgid "selection grab"
+msgstr "selecção"
+
+#: gtk_ardour/editor_mouse.cc:3571
+msgid "range selection"
+msgstr "selecção de intervalo"
+
+#: gtk_ardour/editor_mouse.cc:3587
+msgid "trim selection start"
+msgstr "recortar início da selecção"
+
+#: gtk_ardour/editor_mouse.cc:3603
+msgid "trim selection end"
+msgstr "recortar final da selecção"
+
+#: gtk_ardour/editor_mouse.cc:3620
+msgid "move selection"
+msgstr "mover selecção"
+
+#: gtk_ardour/editor_mouse.cc:3995
+msgid "Start point trim"
+msgstr "Ponto inicial de recorte"
+
+#: gtk_ardour/editor_mouse.cc:4023
+msgid "End point trim"
+msgstr "Ponto final de recorte"
+
+#: gtk_ardour/editor_mouse.cc:4062
+msgid "trimmed region"
+msgstr "região recortada"
+
+#: gtk_ardour/editor_mouse.cc:4203
+msgid "new range marker"
+msgstr "novo marcador de região"
+
+#: gtk_ardour/editor_mouse.cc:4422
+msgid "select regions"
+msgstr "seleccionar regiões"
+
+#: gtk_ardour/editor_mouse.cc:4451
+msgid "Name for region:"
+msgstr "Nome para a região:"
+
+#: gtk_ardour/editor_mouse.cc:4517
+msgid "timestretch"
+msgstr "alongamento temporal"
+
+#: gtk_ardour/editor_ops.cc:117
+msgid "split"
+msgstr "separar"
+
+#: gtk_ardour/editor_ops.cc:153
+msgid "remove region"
+msgstr "remover região"
+
+#: gtk_ardour/editor_ops.cc:172
+msgid ""
+" This is destructive, will possibly delete audio files\n"
+"It cannot be undone\n"
+"Do you really want to destroy %1 ?"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "these regions"
+msgstr "inverter regiões"
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "this region"
+msgstr "emudecer esta região"
+
+#: gtk_ardour/editor_ops.cc:179
+#, fuzzy
+msgid "Yes, destroy them."
+msgstr "Sim, elimine-se."
+
+#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434
+msgid "Yes, destroy it."
+msgstr "Sim, elimine-se."
+
+#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435
+#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300
+msgid "No, do nothing."
+msgstr "Não, não fazer nada."
+
+#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307
+msgid "extend selection"
+msgstr "extender selecção"
+
+#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357
+#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427
+msgid "nudge forward"
+msgstr "retocar p/frente"
+
+#: gtk_ardour/editor_ops.cc:491
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1305
+#, fuzzy
+msgid "set selection from range"
+msgstr "selecção de intervalo"
+
+#: gtk_ardour/editor_ops.cc:1421
+msgid "clear markers"
+msgstr "apagar marcadores"
+
+#: gtk_ardour/editor_ops.cc:1433
+msgid "clear ranges"
+msgstr "apagar intervalos"
+
+#: gtk_ardour/editor_ops.cc:1452
+msgid "clear locations"
+msgstr "apagar localizações"
+
+#: gtk_ardour/editor_ops.cc:1503
+msgid "insert dragged region"
+msgstr "inserir região arrastada"
+
+#: gtk_ardour/editor_ops.cc:1538
+msgid "insert region"
+msgstr "inserir região"
+
+#: gtk_ardour/editor_ops.cc:1744
+msgid "ardour: rename region"
+msgstr "ardour: renomear região"
+
+#: gtk_ardour/editor_ops.cc:1891
+msgid "You can't import an audiofile until you have a session loaded."
+msgstr ""
+"Não é possível importar um ficheiro audio sem que haja uma sessão carregada"
+
+#: gtk_ardour/editor_ops.cc:1901
+#, fuzzy
+msgid "Import selected as tracks"
+msgstr "Importar selecção"
+
+#: gtk_ardour/editor_ops.cc:1904
+#, fuzzy
+msgid "Import selected to region list"
+msgstr "seleccionar regiões"
+
+#: gtk_ardour/editor_ops.cc:1933
+msgid "ardour: audio import in progress"
+msgstr "ardour: importação audio em curso"
+
+#: gtk_ardour/editor_ops.cc:1937
+msgid "Cancel Import"
+msgstr "Cancelar Importação"
+
+#: gtk_ardour/editor_ops.cc:1944
+msgid "ardour: importing %1"
+msgstr "ardour: em importação %1"
+
+#: gtk_ardour/editor_ops.cc:1990
+msgid "%1 it anyway"
+msgstr "%s de qualquer forma"
+
+#: gtk_ardour/editor_ops.cc:1996
+#, fuzzy
+msgid "Don't %1 it"
+msgstr "Não %1"
+
+#: gtk_ardour/editor_ops.cc:1997
+msgid "%1 all without questions"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1998
+#, fuzzy
+msgid "Cancel entire import"
+msgstr "Cancelar Importação"
+
+#: gtk_ardour/editor_ops.cc:2004
+#, fuzzy
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr ""
+"A frequência de amostragem deste ficheiro audio não é igual à de sessão"
+
+#: gtk_ardour/editor_ops.cc:2032
+msgid "You can't embed an audiofile until you have a session loaded."
+msgstr ""
+"Não é possível intercalar um ficheiro audio sem que haja uma sessão carregada"
+
+#: gtk_ardour/editor_ops.cc:2039
+msgid "Add to External Region list"
+msgstr "Acrescentar à lista de Regiões Externas"
+
+#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210
+#: gtk_ardour/editor_ops.cc:2286
+msgid "Editor: cannot open file \"%1\" (%2)"
+msgstr "Editor: não foi possível abrir o ficheiro \"%1\" (%2)"
+
+#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312
+msgid "could not open %1"
+msgstr "não foi possível abrir %1"
+
+#: gtk_ardour/editor_ops.cc:2171
+#, fuzzy
+msgid "Insert selected as new tracks"
+msgstr "seleccionar visualização de faixa"
+
+#: gtk_ardour/editor_ops.cc:2186
+msgid "Insert selected"
+msgstr "Inserir selecção"
+
+#: gtk_ardour/editor_ops.cc:2327
+msgid "insert sndfile"
+msgstr "inserir ficheiro audio"
+
+#: gtk_ardour/editor_ops.cc:2464
+#, fuzzy
+msgid "separate"
+msgstr "separar"
+
+#: gtk_ardour/editor_ops.cc:2528
+msgid "trim to selection"
+msgstr "recortar pela selecção"
+
+#: gtk_ardour/editor_ops.cc:2568
+msgid "region fill"
+msgstr "preencher região"
+
+#: gtk_ardour/editor_ops.cc:2626
+msgid "fill selection"
+msgstr "preencher selecção"
+
+#: gtk_ardour/editor_ops.cc:2650
+msgid "Place the edit cursor at the desired sync point"
+msgstr "Coloque o cursor de edição sobre o ponto de sincronia desejado"
+
+#: gtk_ardour/editor_ops.cc:2656
+#, fuzzy
+msgid "set sync from edit cursor"
+msgstr "sincronizar pelo cursor de edição"
+
+#: gtk_ardour/editor_ops.cc:2668
+msgid "remove sync"
+msgstr "remover sincronismo"
+
+#: gtk_ardour/editor_ops.cc:2682
+msgid "naturalize"
+msgstr "naturalizar"
+
+#: gtk_ardour/editor_ops.cc:2746
+msgid "align selection (relative)"
+msgstr "alinhar selecção (relativamente)"
+
+#: gtk_ardour/editor_ops.cc:2774
+msgid "align selection"
+msgstr "alinhar selecção"
+
+#: gtk_ardour/editor_ops.cc:2786
+msgid "align region"
+msgstr "alinhar região"
+
+#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858
+msgid "trim to edit"
+msgstr "recortar para edição"
+
+#: gtk_ardour/editor_ops.cc:2909
+#, fuzzy
+msgid "ardour: freeze"
+msgstr "ardour: renomear região"
+
+#: gtk_ardour/editor_ops.cc:2914
+#, fuzzy
+msgid "Cancel Freeze"
+msgstr "Cancelar"
+
+#: gtk_ardour/editor_ops.cc:2951
+msgid "bounce range"
+msgstr "intervalo de rebatimento"
+
+#: gtk_ardour/editor_ops.cc:3004
+msgid "cut"
+msgstr "corte"
+
+#: gtk_ardour/editor_ops.cc:3007
+msgid "copy"
+msgstr "cópia"
+
+#: gtk_ardour/editor_ops.cc:3020
+msgid " objects"
+msgstr " objectos"
+
+#: gtk_ardour/editor_ops.cc:3046
+msgid " range"
+msgstr " intervalo"
+
+#: gtk_ardour/editor_ops.cc:3201
+msgid "paste"
+msgstr "colar"
+
+#: gtk_ardour/editor_ops.cc:3236
+msgid "paste chunk"
+msgstr "colar trecho"
+
+#: gtk_ardour/editor_ops.cc:3276
+msgid "duplicate region"
+msgstr "duplicar região"
+
+#: gtk_ardour/editor_ops.cc:3309
+msgid "duplicate selection"
+msgstr "duplicar selecção"
+
+#: gtk_ardour/editor_ops.cc:3349
+msgid "clear playlist"
+msgstr "limpar lista de reprodução"
+
+#: gtk_ardour/editor_ops.cc:3378
+msgid "nudge track"
+msgstr "retocar faixa"
+
+#: gtk_ardour/editor_ops.cc:3431
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"Deseja realmente eliminar a última captura?\n"
+"(esta operação é destrutiva e não pode ser desfeita)"
+
+#: gtk_ardour/editor_ops.cc:3463
+msgid "normalize"
+msgstr "normalizar"
+
+#: gtk_ardour/editor_ops.cc:3510
+msgid "reverse regions"
+msgstr "inverter regiões"
+
+#: gtk_ardour/editor_region_list.cc:223
+msgid "hidden"
+msgstr "esconder"
+
+#: gtk_ardour/editor_region_list.cc:408
+msgid "Show all"
+msgstr "Mostrar tudo"
+
+#: gtk_ardour/editor_region_list.cc:417
+msgid "Ascending"
+msgstr "Crescente"
+
+#: gtk_ardour/editor_region_list.cc:419
+msgid "Descending"
+msgstr "Decrescente"
+
+#: gtk_ardour/editor_region_list.cc:423
+msgid "By Region Name"
+msgstr "Por Nome de Região"
+
+#: gtk_ardour/editor_region_list.cc:425
+msgid "By Region Length"
+msgstr "Por Tamanho de Região"
+
+#: gtk_ardour/editor_region_list.cc:427
+msgid "By Region Position"
+msgstr "Por Posição de Região"
+
+#: gtk_ardour/editor_region_list.cc:429
+msgid "By Region Timestamp"
+msgstr "Por Instante de Região"
+
+#: gtk_ardour/editor_region_list.cc:431
+msgid "By Region Start in File"
+msgstr "Por Posição Inicial da Região no Ficheiro"
+
+#: gtk_ardour/editor_region_list.cc:433
+msgid "By Region End in File"
+msgstr "Por Posição Final da Região no Ficheiro"
+
+#: gtk_ardour/editor_region_list.cc:435
+msgid "By Source File Name"
+msgstr "Por Nome do Ficheiro Original"
+
+#: gtk_ardour/editor_region_list.cc:437
+msgid "By Source File Length"
+msgstr "Por Tamanho do Ficheiro Original"
+
+#: gtk_ardour/editor_region_list.cc:439
+msgid "By Source File Creation Date"
+msgstr "Por Data de Criação do Ficheiro Original"
+
+#: gtk_ardour/editor_region_list.cc:441
+msgid "By Source Filesystem"
+msgstr "Por Sistema de Ficheiros Original"
+
+#: gtk_ardour/editor_region_list.cc:444
+msgid "Sorting"
+msgstr "Ordenação"
+
+#: gtk_ardour/editor_region_list.cc:808
+msgid "Regions/length"
+msgstr "Regiões/tamanho"
+
+#: gtk_ardour/editor_region_list.cc:812
+msgid "Regions/position"
+msgstr "Regiões/posição"
+
+#: gtk_ardour/editor_region_list.cc:816
+msgid "Regions/creation"
+msgstr "Regiões/criação"
+
+#: gtk_ardour/editor_region_list.cc:820
+msgid "Regions/start"
+msgstr "Regiões/início"
+
+#: gtk_ardour/editor_region_list.cc:824
+msgid "Regions/end"
+msgstr "Regiões/final"
+
+#: gtk_ardour/editor_region_list.cc:828
+msgid "Regions/file name"
+msgstr "Regiões/nome de ficheiro"
+
+#: gtk_ardour/editor_region_list.cc:832
+msgid "Regions/file size"
+msgstr "Regiões/tamanho de ficheiro"
+
+#: gtk_ardour/editor_region_list.cc:836
+msgid "Regions/file date"
+msgstr "Regiões/data do ficheiro"
+
+#: gtk_ardour/editor_region_list.cc:840
+msgid "Regions/file system"
+msgstr "Regiões/sistema de ficheiros"
+
+#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73
+#: gtk_ardour/editor_route_list.cc:231
+msgid "editor"
+msgstr ""
+
+#: gtk_ardour/editor_route_list.cc:300
+msgid "Show All AbstractTracks"
+msgstr "Mostar todas as faixas abstractas"
+
+#: gtk_ardour/editor_route_list.cc:301
+msgid "Hide All AbstractTracks"
+msgstr "Esconder todas as faixas abstractas"
+
+#: gtk_ardour/editor_route_list.cc:302
+msgid "Show All AudioBus"
+msgstr "Mostrar todos os barramentos audio"
+
+#: gtk_ardour/editor_route_list.cc:303
+msgid "Hide All AudioBus"
+msgstr "Esconder todos os barramentos audio"
+
+#: gtk_ardour/editor_rulers.cc:311
+msgid "New location marker"
+msgstr "Novo marcador de localização"
+
+#: gtk_ardour/editor_rulers.cc:312
+msgid "Clear all locations"
+msgstr "Apagar todas as localizações"
+
+#: gtk_ardour/editor_rulers.cc:317
+msgid "Clear all ranges"
+msgstr "Apagar todos os intervalos"
+
+#: gtk_ardour/editor_rulers.cc:326
+msgid "New Tempo"
+msgstr "Novo Tempo"
+
+#: gtk_ardour/editor_rulers.cc:327
+msgid "Clear tempo"
+msgstr "Apagar tempo"
+
+#: gtk_ardour/editor_rulers.cc:332
+msgid "New Meter"
+msgstr "Novo VUímetro"
+
+#: gtk_ardour/editor_rulers.cc:333
+msgid "Clear meter"
+msgstr "Apagar VUímetro"
+
+#: gtk_ardour/editor_rulers.cc:341
+msgid "Min:Secs"
+msgstr "Min:Segs"
+
+#: gtk_ardour/editor_selection_list.cc:117
+msgid "name for chunk:"
+msgstr "Nome para o trecho:"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Create chunk"
+msgstr "Criar trecho"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Forget it"
+msgstr "Esquecer"
+
+#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295
+msgid "add"
+msgstr "acrescentar"
+
+#: gtk_ardour/editor_tempodisplay.cc:276
+#, fuzzy
+msgid "add tempo mark"
+msgstr "acrescentar marcador de região"
+
+#: gtk_ardour/editor_tempodisplay.cc:318
+#, fuzzy
+msgid "add meter mark"
+msgstr "acrescentar marcador métrico"
+
+#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383
+msgid "done"
+msgstr "pronto"
+
+#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404
+msgid "replace tempo mark"
+msgstr "substituir marcador de tempo"
+
+#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487
+msgid "remove tempo mark"
+msgstr "remover marcador de tempo"
+
+#: gtk_ardour/editor_timefx.cc:50
+msgid "Quick but Ugly"
+msgstr "Rápido mas Feio"
+
+#: gtk_ardour/editor_timefx.cc:51
+msgid "Skip Anti-aliasing"
+msgstr "Ignorar Anti-aliasing"
+
+#: gtk_ardour/editor_timefx.cc:53
+msgid "Stretch/Shrink it"
+msgstr "Alongar/Estreitar"
+
+#: gtk_ardour/editor_timefx.cc:57
+msgid "ardour: timestretch"
+msgstr "ardour: alongamento temporal"
+
+#: gtk_ardour/editor_timefx.cc:58
+msgid "TimeStretchDialog"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83
+#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85
+msgid "TimeStretchButton"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:86
+msgid "TimeStretchProgress"
+msgstr ""
+
+#: gtk_ardour/editor_timefx.cc:151
+msgid "timestretch cannot be started - thread creation error"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410
+#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189
+msgid "22.05kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413
+#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949
+#: gtk_ardour/export_dialog.cc:1191
+msgid "44.1kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416
+#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193
+msgid "48kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419
+#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195
+msgid "88.2kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422
+#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197
+msgid "96kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425
+#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199
+msgid "192kHz"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:73
+msgid "best"
+msgstr "excelente"
+
+#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964
+msgid "fastest"
+msgstr "rápido"
+
+#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966
+msgid "linear"
+msgstr "linear"
+
+#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968
+msgid "better"
+msgstr "bom"
+
+#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970
+msgid "intermediate"
+msgstr "intermédio"
+
+#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979
+msgid "Rectangular"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:84
+msgid "Shaped Noise"
+msgstr "Forma de Ruído"
+
+#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981
+msgid "Triangular"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336
+msgid "stereo"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497
+#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219
+#: gtk_ardour/utils.cc:334
+msgid "mono"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:97
+msgid "CUE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:98
+msgid "TOC"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:106
+msgid "FORMAT"
+msgstr "FORMATO"
+
+#: gtk_ardour/export_dialog.cc:107
+msgid "SAMPLE RATE"
+msgstr "FREQUÊNCIA DE AMOSTRAGEM"
+
+#: gtk_ardour/export_dialog.cc:108
+msgid "CONVERSION QUALITY"
+msgstr "QUALIDADE DE CONVERSÃO"
+
+#: gtk_ardour/export_dialog.cc:109
+msgid "DITHER TYPE"
+msgstr "TIPO DE EXTRAPOLAÇÃO"
+
+#: gtk_ardour/export_dialog.cc:110
+msgid "CD MARKER FILE TYPE"
+msgstr "TIPO DE FICHEIRO MARCADORES CD"
+
+#: gtk_ardour/export_dialog.cc:111
+msgid "CHANNELS"
+msgstr "CANAIS"
+
+#: gtk_ardour/export_dialog.cc:112
+msgid "FILE TYPE"
+msgstr "TIPO DE FICHEIRO"
+
+#: gtk_ardour/export_dialog.cc:113
+msgid "SAMPLE FORMAT"
+msgstr "FORMATO DE AMOSTRA"
+
+#: gtk_ardour/export_dialog.cc:114
+msgid "SAMPLE ENDIANNESS"
+msgstr "REPRESENTAÇÃO BINÃRIA"
+
+#: gtk_ardour/export_dialog.cc:115
+#, fuzzy
+msgid "EXPORT CD MARKER FILE ONLY"
+msgstr "TIPO DE FICHEIRO MARCADORES CD"
+
+#: gtk_ardour/export_dialog.cc:116
+msgid "EXPORT TO FILE"
+msgstr "EXPORTAR PARA FICHEIRO"
+
+#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118
+#: gtk_ardour/option_editor.cc:119
+msgid "Browse"
+msgstr "Pesquisar"
+
+#: gtk_ardour/export_dialog.cc:119
+msgid "Specific tracks ..."
+msgstr "Faixas específicas ..."
+
+#: gtk_ardour/export_dialog.cc:131
+msgid "ardour: export"
+msgstr "ardour: exportar"
+
+#: gtk_ardour/export_dialog.cc:132
+msgid "ardour_export"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:156
+msgid "Output"
+msgstr "Saída"
+
+#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626
+msgid "Track"
+msgstr "Faixa"
+
+#: gtk_ardour/export_dialog.cc:287
+msgid "slereg"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:658
+msgid "Editor: cannot open \"%1\" as export file for CD toc file"
+msgstr ""
+"Editor: não foi possível abrir o ficheiro \"%1\" para exportação de "
+"marcadores CD (TOC)"
+
+#: gtk_ardour/export_dialog.cc:780
+msgid "Editor: cannot open \"%1\" as export file for CD cue file"
+msgstr ""
+"Editor: não foi possível abrir o ficheiro \"%1\" para exportação de "
+"marcadores CD (CUE)"
+
+#: gtk_ardour/export_dialog.cc:799
+msgid "WAV"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:1051
+msgid "Stop Export"
+msgstr "Cancelar Exportação"
+
+#: gtk_ardour/gain_automation_time_axis.cc:60
+#, fuzzy
+msgid "add gain automation event"
+msgstr "acrescentar evento de automatização a "
+
+#: gtk_ardour/gain_meter.cc:68
+msgid "Cannot create slider pixmaps"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:83
+msgid "dbFS"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134
+#: gtk_ardour/gain_meter.cc:728
+msgid "pre"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724
+#, fuzzy
+msgid "input"
+msgstr "%1 entrada"
+
+#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732
+#, fuzzy
+msgid "post"
+msgstr "porta"
+
+#: gtk_ardour/gain_meter.cc:146
+msgid "tupni"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470
+#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537
+#, fuzzy
+msgid "-inf"
+msgstr "entrada"
+
+#: gtk_ardour/imageframe_socket_handler.cc:127
+msgid "Image Compositor Socket has been shutdown/closed"
+msgstr "O ligação ao Compositor de Imagem foi desligada/fechada"
+
+#: gtk_ardour/imageframe_time_axis.cc:295
+#, fuzzy
+msgid "0.5 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259
+#, fuzzy
+msgid "1 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260
+#, fuzzy
+msgid "1.5 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261
+#, fuzzy
+msgid "2 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262
+#, fuzzy
+msgid "2.5 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263
+#, fuzzy
+msgid "3 seconds"
+msgstr "Segundos"
+
+#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268
+#, fuzzy
+msgid "Duration (sec)"
+msgstr "Arrastar regiões"
+
+#: gtk_ardour/imageframe_time_axis.cc:310
+#, fuzzy
+msgid "Remove Frame"
+msgstr "Remover Campo"
+
+#: gtk_ardour/imageframe_time_axis.cc:313
+#, fuzzy
+msgid "Image Frame"
+msgstr "Quadros CD"
+
+#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274
+#, fuzzy
+msgid "Rename Track"
+msgstr "Renomear"
+
+#: gtk_ardour/io_selector.cc:64
+msgid "%1 input"
+msgstr "%1 entrada"
+
+#: gtk_ardour/io_selector.cc:66
+msgid "%1 output"
+msgstr "%1 saída"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103
+msgid "Inputs"
+msgstr "Entradas"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104
+msgid "Outputs"
+msgstr "Saídas"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Input"
+msgstr "acrescentar entrada"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Output"
+msgstr "acrescentar saída"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Input"
+msgstr "Remover ponto de sincronia"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Output"
+msgstr "No.Saídas"
+
+#: gtk_ardour/io_selector.cc:144
+#, fuzzy
+msgid "Disconnect All"
+msgstr "Desligar"
+
+#: gtk_ardour/io_selector.cc:158
+msgid "Available connections"
+msgstr "Ligações disponíveis"
+
+#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636
+#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724
+msgid "port"
+msgstr "porta"
+
+#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587
+msgid "There are no more JACK ports available."
+msgstr ""
+
+#: gtk_ardour/io_selector.cc:790
+msgid "ardour: "
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:419
+msgid "KeyboardTarget: keyname \"%1\" is unknown."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:645
+msgid ""
+"Your system is completely broken - NumLock uses \"%1\"as its modifier. This "
+"is madness - see the man page for xmodmap to find out how to fix this."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:653
+msgid ""
+"Your system generates \"%1\" when the NumLock key is pressed. This can cause "
+"problems when editing so Ardour will use %2 to mean Meta rather than %1"
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:714
+msgid "You have %1 keys bound to \"mod1\""
+msgstr "Existem %1 teclas associadas a \"mod1\""
+
+#: gtk_ardour/keyboard.cc:729
+msgid "You have %1 keys bound to \"mod2\""
+msgstr "Existem %1 teclas associadas a \"mod2\""
+
+#: gtk_ardour/keyboard.cc:744
+msgid "You have %1 keys bound to \"mod3\""
+msgstr "Existem %1 teclas associadas a \"mod3\""
+
+#: gtk_ardour/keyboard.cc:759
+msgid "You have %1 keys bound to \"mod4\""
+msgstr "Existem %1 teclas associadas a \"mod4\""
+
+#: gtk_ardour/keyboard.cc:774
+msgid "You have %1 keys bound to \"mod5\""
+msgstr "Existem %1 teclas associadas a \"mod5\""
+
+#: gtk_ardour/keyboard_target.cc:72
+msgid "KeyboardTarget: empty string passed to add_binding."
+msgstr "KeyboardTarget: combinação nula ou inválida."
+
+#: gtk_ardour/keyboard_target.cc:78
+msgid "KeyboardTarget: no translation found for \"%1\""
+msgstr "KeyboardTarget: não existe tradução para \"%1\""
+
+#: gtk_ardour/keyboard_target.cc:83
+msgid "KeyboardTarget: unknown action \"%1\""
+msgstr "KeyboardTarget: acção desconhecida \"%1\""
+
+#: gtk_ardour/keyboard_target.cc:248
+msgid "misformed binding node - ignored"
+msgstr "combinação mal formada - ignorada"
+
+#: gtk_ardour/library_ui.cc:62
+msgid "Soundfile Library"
+msgstr "Audioteca"
+
+#: gtk_ardour/library_ui.cc:63
+msgid "Filesystem"
+msgstr "Ficheiros"
+
+#: gtk_ardour/library_ui.cc:66
+msgid "Split Channels"
+msgstr "Separar Canais"
+
+#: gtk_ardour/library_ui.cc:69
+msgid "ardour: soundfile selector"
+msgstr "ardor: selecção de ficheiro audio"
+
+#: gtk_ardour/library_ui.cc:430
+msgid "Add to Library..."
+msgstr "Acrescentar à Audioteca..."
+
+#: gtk_ardour/library_ui.cc:431
+msgid "Remove..."
+msgstr "Remover..."
+
+#: gtk_ardour/library_ui.cc:432
+msgid "Find..."
+msgstr "Procurar..."
+
+#: gtk_ardour/library_ui.cc:433
+msgid "Add Folder"
+msgstr "Acrescentar Directório/Pasta"
+
+#: gtk_ardour/library_ui.cc:434
+msgid "Add audio file or directory"
+msgstr "Acrescentar ficheiro ou directório/pasta"
+
+#: gtk_ardour/library_ui.cc:713
+msgid "Importing"
+msgstr "Em importação"
+
+#: gtk_ardour/library_ui.cc:748
+msgid "%1 not added to database"
+msgstr "%1 não foram acrescentados"
+
+#: gtk_ardour/library_ui.cc:767
+msgid "Folder name:"
+msgstr "Nome do directório/pasta:"
+
+#: gtk_ardour/library_ui.cc:838
+msgid "Should not be reached"
+msgstr "Não deve ser alcançada"
+
+#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096
+msgid "file \"%1\" could not be opened"
+msgstr "não foi possível abrir o ficheiro \"%1\""
+
+#: gtk_ardour/library_ui.cc:956
+msgid "Field"
+msgstr "Campo"
+
+#: gtk_ardour/library_ui.cc:957
+msgid "Value"
+msgstr "Valor"
+
+#: gtk_ardour/library_ui.cc:973
+msgid "Stop"
+msgstr "Parar"
+
+#: gtk_ardour/library_ui.cc:974
+msgid "Add Field..."
+msgstr "Acrescentar Campo..."
+
+#: gtk_ardour/library_ui.cc:975
+msgid "Remove Field"
+msgstr "Remover Campo"
+
+#: gtk_ardour/library_ui.cc:979
+msgid "Soundfile Info"
+msgstr "Informações"
+
+#: gtk_ardour/library_ui.cc:1106
+msgid "file \"%1\" appears not to be an audio file"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1159
+msgid "Could not read file: %1 (%2)."
+msgstr "Não foi possível ler o ficheiro \"%1\" (%2)"
+
+#: gtk_ardour/library_ui.cc:1177
+msgid "Could not access soundfile: "
+msgstr "Não foi possível aceder ao ficheiros audio: "
+
+#: gtk_ardour/library_ui.cc:1222
+msgid "Field name:"
+msgstr "Nome para o campo:"
+
+#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367
+msgid "Field value:"
+msgstr "Valor para o campo:"
+
+#: gtk_ardour/library_ui.cc:1295
+msgid "Find"
+msgstr "Procurar"
+
+#: gtk_ardour/library_ui.cc:1296
+msgid "AND"
+msgstr "E"
+
+#: gtk_ardour/library_ui.cc:1297
+msgid "OR"
+msgstr "OU"
+
+#: gtk_ardour/library_ui.cc:1300
+msgid "ardour: locate soundfiles"
+msgstr "ardour: localizar ficheiros audio"
+
+#: gtk_ardour/library_ui.cc:1426
+msgid "Results"
+msgstr "Resultados"
+
+#: gtk_ardour/library_ui.cc:1427
+msgid "Uris"
+msgstr "URIs"
+
+#: gtk_ardour/library_ui.cc:1439
+msgid "Create multi-channel region"
+msgstr "Criar região multi-canal"
+
+#: gtk_ardour/library_ui.cc:1442
+msgid "Ardour: Search Results"
+msgstr "Ardour: Resultados da Procura"
+
+#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50
+msgid "Set"
+msgstr "Seleccionar"
+
+#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51
+msgid "Go"
+msgstr "Ir"
+
+#: gtk_ardour/location_ui.cc:54
+msgid "CD"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:55
+msgid "Hidden"
+msgstr "Esconder"
+
+#: gtk_ardour/location_ui.cc:57
+msgid "SCMS"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:58
+msgid "Pre-Emphasis"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:592
+msgid "Add New Location"
+msgstr "Adicionar Nova Localização"
+
+#: gtk_ardour/location_ui.cc:593
+msgid "Add New Range"
+msgstr "Adicionar Novo Intervalo"
+
+#: gtk_ardour/location_ui.cc:597
+msgid "ardour: locations"
+msgstr "ardour: localizações"
+
+#: gtk_ardour/location_ui.cc:598
+msgid "ardour_locations"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:629
+#, fuzzy
+msgid "Location (CD Index) Markers"
+msgstr "Localizações"
+
+#: gtk_ardour/location_ui.cc:649
+#, fuzzy
+msgid "Range (CD Track) Markers"
+msgstr "Intervalos"
+
+#: gtk_ardour/location_ui.cc:814
+msgid "add range marker"
+msgstr "acrescentar marcador de região"
+
+#: gtk_ardour/main.cc:76
+msgid "ardour is killing itself for a clean exit\n"
+msgstr "ardour em modo de auto-destruição para uma saída em beleza\n"
+
+#: gtk_ardour/main.cc:85
+msgid "stopping user interface\n"
+msgstr "interface homem-máquina em fase terminal\n"
+
+#: gtk_ardour/main.cc:104
+#, fuzzy, c-format
+msgid "%d(%d): received signal %d\n"
+msgstr "%d: sinal %d recebido\n"
+
+#: gtk_ardour/main.cc:190
+msgid "cannot become new process group leader (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:217
+msgid "cannot setup signal handling for %1"
+msgstr "não foi possível estabelecer receptor de sinal %1"
+
+#: gtk_ardour/main.cc:228
+msgid "cannot set default signal mask (%1)"
+msgstr "não foi possível estabelecer máscara de sinal %1"
+
+#: gtk_ardour/main.cc:253
+msgid ""
+"Without a UI style file, ardour will look strange.\n"
+" Please set ARDOUR_UI_RC to point to a valid UI style file"
+msgstr ""
+"O Ardour vai aparecer algo esquisito sem um ficheiro\n"
+"de estilo visual para o interface de utilizador (UI).\n"
+"Por favor, indique um ficheiro de estilo visual válido em ARDOUR_UI_RC "
+"(variável de ambiente)"
+
+#: gtk_ardour/main.cc:292
+msgid ""
+"Ardour could not connect to JACK.\n"
+"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 ""
+"Não foi possível estabelecer ligação com o serviço JACK.\n"
+"Podem existir várias razões para tal:\n"
+"\n"
+"1) O serviço JACK não se encontra activo.\n"
+"2) O serviço JACK encontra-se activo por outro utilizador, talvez root.\n"
+"3) Já se encontra activo outro client chamado \"ardour\".\n"
+"\n"
+"Por favor, considere estas possibilidades e (re)inicie o serviço JACK."
+
+#: gtk_ardour/main.cc:305
+msgid "ardour: unplugged"
+msgstr "ardour: desligado"
+
+#: gtk_ardour/main.cc:363
+msgid "Ardour/GTK "
+msgstr ""
+
+#: gtk_ardour/main.cc:365
+msgid ""
+"\n"
+" (built using "
+msgstr ""
+
+#: gtk_ardour/main.cc:369
+#, fuzzy
+msgid " with libardour "
+msgstr " em execução com libardour "
+
+#: gtk_ardour/main.cc:374
+msgid " and GCC version "
+msgstr ""
+
+#: gtk_ardour/main.cc:384
+msgid "Copyright (C) 1999-2005 Paul Davis"
+msgstr ""
+
+#: gtk_ardour/main.cc:385
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+msgstr ""
+
+#: gtk_ardour/main.cc:387
+msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
+msgstr "Ardour é fornecido ABSOLUTAMENTE SEM QUALQUER GARANTIA"
+
+#: gtk_ardour/main.cc:388
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr ""
+
+#: gtk_ardour/main.cc:389
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr "Sendo software livre, é permitida e até encorajada a sua distribuição"
+
+#: gtk_ardour/main.cc:390
+#, fuzzy
+msgid "under certain conditions; see the source for copying conditions."
+msgstr ""
+"desde que sejam respeitadas algumas condições; para mais informações, leia "
+"por favor o ficheiro COPYING."
+
+#: gtk_ardour/main.cc:399
+msgid "could not create ARDOUR GUI"
+msgstr "não foi possível criar o interface gráfico (GUI)"
+
+#: gtk_ardour/main.cc:419
+msgid "Could not connect to JACK server as \"%1\""
+msgstr "Não foi possível conectar ao serviço JACK como \"%1\""
+
+#: gtk_ardour/main.cc:424
+msgid "could not initialize Ardour."
+msgstr "não foi possível inicializar o Ardour"
+
+#: gtk_ardour/main.cc:435
+msgid "could not load command line session \"%1\""
+msgstr "não foi possível carregar a sessão de linha de comando \"%1\""
+
+#: gtk_ardour/main.cc:455
+msgid ""
+"\n"
+"\n"
+"A session named \"%1\" already exists.\n"
+"To avoid this message, start ardour as \"ardour %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:466
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as \"ardour --new %1"
+msgstr ""
+
+#: gtk_ardour/marker.cc:354
+#, fuzzy
+msgid "MarkerText"
+msgstr "Marcas"
+
+#: gtk_ardour/marker_time_axis.cc:271
+#, fuzzy
+msgid "Remove Marker"
+msgstr "remover marcador"
+
+#: gtk_ardour/marker_time_axis.cc:273
+#, fuzzy
+msgid "Marker"
+msgstr "Marcas"
+
+#: gtk_ardour/meter_bridge.cc:74
+msgid "ardour: meter bridge"
+msgstr "ardour: VUímetro"
+
+#: gtk_ardour/meter_bridge.cc:75
+msgid "ardour_meter_bridge"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93
+#, c-format
+msgid "# of %u-sample overs"
+msgstr "# de %u-quadros"
+
+#: gtk_ardour/meter_bridge_strip.cc:219
+msgid "New name for meter:"
+msgstr "Novo nome para o VUímetro:"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507
+#: gtk_ardour/region_editor.cc:45
+msgid "mute"
+msgstr "mudo"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508
+msgid "solo"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506
+msgid "RECORD"
+msgstr "GRAVAR"
+
+#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514
+msgid "polarity"
+msgstr "polaridade"
+
+#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509
+msgid "comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810
+msgid "INPUT"
+msgstr "ENTRADA"
+
+#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831
+msgid "OUTPUT"
+msgstr "SAÃDA"
+
+#: gtk_ardour/mixer_strip.cc:173
+msgid "Pan automation mode"
+msgstr "Modo de automatização de panorâmica"
+
+#: gtk_ardour/mixer_strip.cc:174
+msgid "Gain automation mode"
+msgstr "Modo de automatização de ganho"
+
+#: gtk_ardour/mixer_strip.cc:176
+msgid "Pan automation type"
+msgstr "Tipo de automatização de panorâmica"
+
+#: gtk_ardour/mixer_strip.cc:177
+msgid "Gain automation type"
+msgstr "Tipo de automatização de ganho"
+
+#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232
+#: gtk_ardour/mixer_strip.cc:979
+msgid "trim"
+msgstr "recorte"
+
+#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233
+#: gtk_ardour/mixer_strip.cc:983
+msgid "abs"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:240
+msgid "gain automation mode"
+msgstr "modo de automatização de ganho"
+
+#: gtk_ardour/mixer_strip.cc:241
+msgid "pan automation mode"
+msgstr "modo de automatização de panorâmica"
+
+#: gtk_ardour/mixer_strip.cc:242
+msgid "gain automation state"
+msgstr "ponto de automatização de ganho"
+
+#: gtk_ardour/mixer_strip.cc:243
+msgid "pan automation state"
+msgstr "ponto de automatização de panorâmica"
+
+#: gtk_ardour/mixer_strip.cc:259
+msgid "varispeed"
+msgstr "velocidade variável"
+
+#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174
+msgid "click to add/edit comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:463
+msgid "unknown strip width \"%1\" in XML GUI information"
+msgstr ""
+"largura desconhecida \"%1\" na informação XML para o interface gráfico (GUI)"
+
+#: gtk_ardour/mixer_strip.cc:522
+msgid "REC"
+msgstr "GRAV"
+
+#: gtk_ardour/mixer_strip.cc:525
+#, fuzzy
+msgid "cmt"
+msgstr "corte"
+
+#: gtk_ardour/mixer_strip.cc:530
+msgid "pol"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620
+#: gtk_ardour/redirect_box.cc:1180
+msgid "Not connected to JACK - no I/O changes are possible"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667
+msgid "could not register new ports required for that connection"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:813
+msgid "IN"
+msgstr "ENTRADA"
+
+#: gtk_ardour/mixer_strip.cc:834
+msgid "OUT"
+msgstr "SAÃDA"
+
+#: gtk_ardour/mixer_strip.cc:950
+msgid "aplay"
+msgstr "aRepr"
+
+#: gtk_ardour/mixer_strip.cc:956
+msgid "awrite"
+msgstr "aGrav"
+
+#: gtk_ardour/mixer_strip.cc:1134
+#, fuzzy
+msgid ": comment editor"
+msgstr "Não foi possível iniciar o painel principal de edição (editor)"
+
+#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224
+msgid "no group"
+msgstr "sem grupo"
+
+#: gtk_ardour/mixer_strip.cc:1227
+msgid "~G"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:52
+msgid "Strips"
+msgstr "Painéis"
+
+#: gtk_ardour/mixer_ui.cc:56
+msgid "Snapshots"
+msgstr "Capturas"
+
+#: gtk_ardour/mixer_ui.cc:61
+msgid "***"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17
+#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144
+#: gtk_ardour/tempo_dialog.cc:162
+msgid "Bar"
+msgstr "Compasso"
+
+#: gtk_ardour/mixer_ui.cc:121
+msgid "Mix Groups"
+msgstr "Grupos"
+
+#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373
+msgid "ardour: mixer"
+msgstr "ardour: misturador"
+
+#: gtk_ardour/mixer_ui.cc:192
+msgid "ardour_mixer"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:342
+msgid "ardour: mixer: "
+msgstr "ardour: misturador: "
+
+#: gtk_ardour/mixer_ui.cc:641
+msgid "signal"
+msgstr "sinal"
+
+#: gtk_ardour/mixer_ui.cc:672
+msgid "Show All AudioTrack MixerStrips"
+msgstr "Mostrar painéis de mistura de todas as faixas audio"
+
+#: gtk_ardour/mixer_ui.cc:673
+msgid "Hide All AudioTrack MixerStrips"
+msgstr "Esconder painéis de mistura de todas as faixas audio"
+
+#: gtk_ardour/mixer_ui.cc:674
+msgid "Show All AudioBus MixerStrips"
+msgstr "Mostrar painéis de mistura de todos os barramentos audio"
+
+#: gtk_ardour/mixer_ui.cc:675
+msgid "Hide All AudioBus MixerStrips"
+msgstr "Esconder painéis de mistura de todos os barramentos audio"
+
+#: gtk_ardour/mixer_ui.cc:687
+msgid "track display list item for renamed strip not found!"
+msgstr "não foi encontrada qualquer faixa para o painel de mistura"
+
+#: gtk_ardour/mixer_ui.cc:700
+msgid "Name for new mix group"
+msgstr "Nome para o novo grupo de mistura"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Session name:"
+msgstr "Nome de sessão:"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Create"
+msgstr "Criar"
+
+#: gtk_ardour/new_session_dialog.cc:40
+msgid "use control outs"
+msgstr "usar saídas de controlo"
+
+#: gtk_ardour/new_session_dialog.cc:41
+msgid "use master outs"
+msgstr "usar saídas principais"
+
+#: gtk_ardour/new_session_dialog.cc:42
+msgid "automatically connect track inputs to physical ports"
+msgstr "ligar entradas físicas automaticamente"
+
+#: gtk_ardour/new_session_dialog.cc:43
+msgid "automatically connect track outputs to master outs"
+msgstr "ligar saídas principais automaticamente"
+
+#: gtk_ardour/new_session_dialog.cc:44
+msgid "automatically connect track outputs to physical ports"
+msgstr "ligar saídas físicas automaticamente"
+
+#: gtk_ardour/new_session_dialog.cc:45
+msgid "manually connect track outputs"
+msgstr "ligar saídas manualmente"
+
+#: gtk_ardour/new_session_dialog.cc:50
+msgid "Advanced..."
+msgstr "Avançado..."
+
+#: gtk_ardour/new_session_dialog.cc:52
+msgid "show again"
+msgstr "mostrar este diálogo novamente"
+
+#: gtk_ardour/new_session_dialog.cc:55
+msgid "Hardware Inputs: use"
+msgstr "Entradas Físicas: usar"
+
+#: gtk_ardour/new_session_dialog.cc:56
+msgid "Hardware Outputs: use"
+msgstr "Saídas Físicas: usar"
+
+#: gtk_ardour/new_session_dialog.cc:62
+msgid "new session setup"
+msgstr "nova sessão"
+
+#: gtk_ardour/new_session_dialog.cc:63
+msgid "ardour_new_session"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:72
+msgid "This session will playback and record at %1 Hz"
+msgstr "Esta sessão irá reproduzir e gravar a %1 Hz"
+
+#: gtk_ardour/new_session_dialog.cc:74
+msgid ""
+"This rate is set by JACK and cannot be changed.\n"
+"If you want to use a different sample rate\n"
+"please exit and restart JACK"
+msgstr ""
+"Esta frequência de amostragem é pré-estabelecida\n"
+"pelo serviço JACK e não pode ser alterada.\n"
+"Se pretende usar uma frequência de amostragem diferente\n"
+"terá de sair e reiniciar o serviço JACK"
+
+#: gtk_ardour/new_session_dialog.cc:155
+#, fuzzy
+msgid "Session template"
+msgstr "Modelo de sessão"
+
+#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20
+#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146
+#: gtk_ardour/tempo_dialog.cc:164
+msgid "Location"
+msgstr "Localização"
+
+#: gtk_ardour/new_session_dialog.cc:178
+msgid "Configuration"
+msgstr "Configuração"
+
+#: gtk_ardour/new_session_dialog.cc:269
+msgid "blank"
+msgstr "vazio"
+
+#: gtk_ardour/new_session_dialog.cc:328
+msgid "No template - create tracks/busses manually"
+msgstr "Sem modelo - criar faixas/barramentos manualmente"
+
+#: gtk_ardour/new_session_dialog.cc:337
+msgid "No template"
+msgstr "Sem modelo"
+
+#: gtk_ardour/option_editor.cc:48
+msgid "Internal"
+msgstr "Interno"
+
+#: gtk_ardour/option_editor.cc:49
+msgid "Slave to MTC"
+msgstr "Escravo MTC"
+
+#: gtk_ardour/option_editor.cc:50
+msgid "Sync with JACK"
+msgstr "Sincronia JACK"
+
+#: gtk_ardour/option_editor.cc:51
+msgid "never used but stops crashes"
+msgstr "nunca usado mas evita problemas"
+
+#: gtk_ardour/option_editor.cc:56
+#, fuzzy
+msgid "Later regions are higher"
+msgstr "Descer a região em um nível"
+
+#: gtk_ardour/option_editor.cc:57
+msgid "Most recently added/moved/trimmed regions are higher"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:58
+#, fuzzy
+msgid "Most recently added regions are higher"
+msgstr "Descer a região em um nível"
+
+#: gtk_ardour/option_editor.cc:63
+#, fuzzy
+msgid "Span entire region overlap"
+msgstr "Elevar a região em um nível"
+
+#: gtk_ardour/option_editor.cc:64
+msgid "Short fades at the start of the overlap"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:82
+#, fuzzy
+msgid "Automatically create crossfades"
+msgstr "Desvanecimento cruzado automático em sobreposição"
+
+#: gtk_ardour/option_editor.cc:83
+msgid "New full-overlap crossfades are unmuted"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:84
+#, fuzzy
+msgid "Region layering mode"
+msgstr "Finais de região"
+
+#: gtk_ardour/option_editor.cc:85
+#, fuzzy
+msgid "Crossfade model"
+msgstr "Desvanecimento cruzado"
+
+#: gtk_ardour/option_editor.cc:90
+msgid "Latched solo"
+msgstr "Solo retido"
+
+#: gtk_ardour/option_editor.cc:91
+msgid "Solo via bus"
+msgstr "Solo por barramento"
+
+#: gtk_ardour/option_editor.cc:96
+msgid "Show waveforms while recording"
+msgstr "Mostrar formas de onda enquanto grava"
+
+#: gtk_ardour/option_editor.cc:97
+msgid "Narrow mixer strips"
+msgstr "Estreitar painéis de mistura"
+
+#: gtk_ardour/option_editor.cc:98
+msgid "Show measure lines"
+msgstr "Mostrar linhas de tempo"
+
+#: gtk_ardour/option_editor.cc:99
+msgid "Follow playhead"
+msgstr "Seguir o cursor de reprodução"
+
+#: gtk_ardour/option_editor.cc:103
+msgid "Send MTC"
+msgstr "Enviar MTC"
+
+#: gtk_ardour/option_editor.cc:104
+msgid "Send MMC"
+msgstr "Enviar MMC"
+
+#: gtk_ardour/option_editor.cc:105
+msgid "JACK time master"
+msgstr "Supervisor de tempo JACK"
+
+#: gtk_ardour/option_editor.cc:107
+#, fuzzy
+msgid "SMPTE offset is negative"
+msgstr "Deslocamento SMPTE"
+
+#: gtk_ardour/option_editor.cc:111
+#, fuzzy
+msgid "Send MIDI parameter feedback"
+msgstr "Enviar resposta a parametros MIDI"
+
+#: gtk_ardour/option_editor.cc:112
+#, fuzzy
+msgid "MIDI parameter control"
+msgstr "Receber controlo de parametros MIDI"
+
+#: gtk_ardour/option_editor.cc:113
+#, fuzzy
+msgid "MMC control"
+msgstr "Porta MMC"
+
+#: gtk_ardour/option_editor.cc:131
+#, fuzzy
+msgid "Auto-connect new track inputs to hardware"
+msgstr "Ligar novas faixas automaticamente"
+
+#: gtk_ardour/option_editor.cc:132
+#, fuzzy
+msgid "Auto-connect new track outputs to hardware"
+msgstr "Ligar novas faixas automaticamente"
+
+#: gtk_ardour/option_editor.cc:133
+#, fuzzy
+msgid "Auto-connect new track outputs to master bus"
+msgstr "ligar saídas principais automaticamente"
+
+#: gtk_ardour/option_editor.cc:134
+#, fuzzy
+msgid "Manually connect new track outputs"
+msgstr "ligar saídas manualmente"
+
+#: gtk_ardour/option_editor.cc:135
+msgid "Use Hardware Monitoring"
+msgstr "Usar monitorização física"
+
+#: gtk_ardour/option_editor.cc:136
+msgid "Use Software Monitoring"
+msgstr "Usar monitorização lógica"
+
+#: gtk_ardour/option_editor.cc:137
+msgid "Stop plugins with transport"
+msgstr "Suspender efeitos/plug-ins com transporte"
+
+#: gtk_ardour/option_editor.cc:138
+msgid "Run plugins while recording"
+msgstr "Executar efeitos/plug-ins durante a gravação"
+
+#: gtk_ardour/option_editor.cc:139
+#, fuzzy
+msgid "Verify remove last capture"
+msgstr "Remover a última captura"
+
+#: gtk_ardour/option_editor.cc:140
+msgid "Stop recording on xrun"
+msgstr "Suspender a gravação em caso de falha sincrónica (XRUN)"
+
+#: gtk_ardour/option_editor.cc:141
+msgid "Stop transport at end of session"
+msgstr "Suspender o transporte no final da sessão"
+
+#: gtk_ardour/option_editor.cc:142
+msgid "Debug keyboard events"
+msgstr "Depurar eventos programáticos de teclado"
+
+#: gtk_ardour/option_editor.cc:143
+msgid "-12dB gain reduction for ffwd/rew"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:152
+msgid "ardour: options editor"
+msgstr "ardour: opções"
+
+#: gtk_ardour/option_editor.cc:153
+msgid "ardour_option_editor"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:183
+msgid "Misc"
+msgstr "Miscelânea"
+
+#: gtk_ardour/option_editor.cc:184
+msgid "Sync"
+msgstr "Sincronia"
+
+#: gtk_ardour/option_editor.cc:185
+msgid "Paths/Files"
+msgstr "Directórios/Ficheiros"
+
+#: gtk_ardour/option_editor.cc:186
+msgid "Display"
+msgstr "Visualização"
+
+#: gtk_ardour/option_editor.cc:187
+msgid "Kbd/Mouse"
+msgstr "Teclado/Rato"
+
+#: gtk_ardour/option_editor.cc:188
+msgid "Click"
+msgstr "Metrónomo"
+
+#: gtk_ardour/option_editor.cc:190
+msgid "Layers & Fades"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:195
+msgid "MIDI"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:268
+msgid "24 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:270
+msgid "25 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:272
+msgid "30 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:278
+msgid "30 FPS drop"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379
+#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736
+#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800
+msgid "Medium"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738
+#: gtk_ardour/option_editor.cc:804
+#, fuzzy
+msgid "Faster"
+msgstr "Rápido"
+
+#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714
+#: gtk_ardour/option_editor.cc:776
+#, fuzzy
+msgid "Short"
+msgstr "porta"
+
+#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716
+#: gtk_ardour/option_editor.cc:780
+msgid "Long"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:396
+msgid "Broadcast WAVE/floating point"
+msgstr "WAVE/vírgula flutuante (Broadcast)"
+
+#: gtk_ardour/option_editor.cc:397
+msgid "WAVE/floating point"
+msgstr "WAVE/vírgula flutuante"
+
+#: gtk_ardour/option_editor.cc:417
+msgid "session RAID path"
+msgstr "directório RAID de sessão"
+
+#: gtk_ardour/option_editor.cc:422
+msgid "Native Format"
+msgstr "Formato Nativo"
+
+#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460
+#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409
+msgid "internal"
+msgstr "interno"
+
+#: gtk_ardour/option_editor.cc:537
+msgid "Short crossfade length (msecs)"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:710
+msgid "Meter Peak Hold"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:730
+msgid "Meter Falloff"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:847
+msgid "Positional Sync"
+msgstr "Sicronia de Posição"
+
+#: gtk_ardour/option_editor.cc:902
+msgid "SMPTE Frames/second"
+msgstr "Quadros SMPTE/segundo"
+
+#: gtk_ardour/option_editor.cc:903
+msgid "SMPTE Offset"
+msgstr "Deslocamento SMPTE"
+
+#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013
+#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211
+#, fuzzy
+msgid "online"
+msgstr "linear"
+
+#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014
+#: gtk_ardour/option_editor.cc:1208
+#, fuzzy
+msgid "offline"
+msgstr "linear"
+
+#: gtk_ardour/option_editor.cc:1319
+msgid "Use as click"
+msgstr "Usar como metrónomo"
+
+#: gtk_ardour/option_editor.cc:1344
+msgid "Use as click emphasis"
+msgstr "Usar como metrónomo acentuado"
+
+#: gtk_ardour/option_editor.cc:1478
+msgid "--unknown--"
+msgstr "--desconhecido--"
+
+#: gtk_ardour/option_editor.cc:1595
+msgid "Click audio file"
+msgstr "Ficheiro audio para metrónomo"
+
+#: gtk_ardour/option_editor.cc:1601
+msgid "Click emphasis audiofile"
+msgstr "Ficheiro audio para metrónomo acentuado"
+
+#: gtk_ardour/option_editor.cc:1638
+msgid ""
+"The auditioner is a dedicated mixer strip used\n"
+"for listening to specific regions outside the context\n"
+"of the overall mix. It can be connected just like any\n"
+"other mixer strip."
+msgstr ""
+"O auditor é um painel de mistura dedicado\n"
+"para a escuta de determinadas regiões fora do contexto\n"
+"da mistura geral. Pode ser inter-conectado tal como\n"
+"qualquer outro painel de mistura."
+
+#: gtk_ardour/option_editor.cc:1887
+msgid "Edit using"
+msgstr "Editar com"
+
+#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924
+msgid "+ button"
+msgstr "+ botão"
+
+#: gtk_ardour/option_editor.cc:1917
+msgid "Delete using"
+msgstr "Eliminar com"
+
+#: gtk_ardour/option_editor.cc:1947
+msgid "Ignore snap using"
+msgstr "Ignorar ajuste com"
+
+#: gtk_ardour/opts.cc:46
+msgid "Usage: "
+msgstr "Uso: "
+
+#: gtk_ardour/opts.cc:47
+msgid " -v, --version Show version information\n"
+msgstr " -v, --version Mostrar informação sobre versão\n"
+
+#: gtk_ardour/opts.cc:48
+msgid " -h, --help Print this message\n"
+msgstr " -h, --help Mostrar esta mesma mensagem\n"
+
+#: gtk_ardour/opts.cc:49
+msgid ""
+" -b, --bindings Print all possible keyboard binding "
+"names\n"
+msgstr ""
+" -b, --bindings Mostrar todas as associações de teclado "
+"possíveis\n"
+
+#: gtk_ardour/opts.cc:50
+#, fuzzy
+msgid " -n, --show-splash Show splash screen\n"
+msgstr ""
+" -n, --no-splash Não mostrar ecran de apresentação "
+"inicial\n"
+
+#: gtk_ardour/opts.cc:51
+#, fuzzy
+msgid ""
+" -c, --name name Use a specific jack client name, default "
+"is ardour\n"
+msgstr ""
+" -c, --jack-client-name name Empregar um nome de cliente JACK "
+"específico (ardour)\n"
+
+#: gtk_ardour/opts.cc:52
+#, fuzzy
+msgid ""
+" -N, --new session-name Create a new session from the command "
+"line\n"
+msgstr " [session-name] Nome de sessão a carregar\n"
+
+#: gtk_ardour/opts.cc:53
+msgid ""
+" -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:55
+#, fuzzy
+msgid " -V, --novst Do not use VST support\n"
+msgstr " -V, --novst Não usar suporte VST inicial\n"
+
+#: gtk_ardour/opts.cc:57
+msgid " [session-name] Name of session to load\n"
+msgstr " [session-name] Nome de sessão a carregar\n"
+
+#: gtk_ardour/opts.cc:58
+msgid " -C, --curvetest filename Curve algorithm debugger\n"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:58
+msgid "You can't graphically edit panning of more than stream"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:78
+#, fuzzy
+msgid "add pan automation event"
+msgstr "acrescentar evento de automatização a "
+
+#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441
+msgid "Bypass"
+msgstr "Ignorar"
+
+#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222
+#, fuzzy
+msgid "link"
+msgstr "entrada"
+
+#: gtk_ardour/panner_ui.cc:103
+msgid "panning link control"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:105
+msgid "panning link direction"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:232
+msgid "L"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:344
+#, c-format
+msgid "panner for channel %u"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:451
+#, fuzzy
+msgid "Reset all"
+msgstr "reiniciar"
+
+#: gtk_ardour/playlist_selector.cc:46
+msgid "Playlists grouped by track"
+msgstr ""
+
+#: gtk_ardour/playlist_selector.cc:53
+#, fuzzy
+msgid "close"
+msgstr "Fechar"
+
+#: gtk_ardour/playlist_selector.cc:59
+#, fuzzy
+msgid "ardour: playlists"
+msgstr "ardour: efeitos/plug-ins"
+
+#: gtk_ardour/playlist_selector.cc:104
+#, fuzzy
+msgid "ardour: playlist for "
+msgstr "ardour: efeitos/plug-ins"
+
+#: gtk_ardour/playlist_selector.cc:122
+#, fuzzy
+msgid "Other tracks"
+msgstr "retocar faixa"
+
+#: gtk_ardour/playlist_selector.cc:138
+msgid "unassigned"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:41
+msgid "Available LADSPA plugins"
+msgstr "Efeitos/plug-ins LADSPA disponíveis"
+
+#: gtk_ardour/plugin_selector.cc:42
+msgid "Type"
+msgstr "Tipo"
+
+#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51
+msgid "# Inputs"
+msgstr "No.Entradas"
+
+#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52
+msgid "# Outputs"
+msgstr "No.Saídas"
+
+#: gtk_ardour/plugin_selector.cc:50
+msgid "Available VST plugins"
+msgstr "Efeitos/plug-ins VST disponíveis"
+
+#: gtk_ardour/plugin_selector.cc:58
+msgid "To be added"
+msgstr "A serem acrescentados"
+
+#: gtk_ardour/plugin_selector.cc:72
+msgid "ardour: plugins"
+msgstr "ardour: efeitos/plug-ins"
+
+#: gtk_ardour/plugin_selector.cc:82
+msgid "Add a plugin to the effect list"
+msgstr "Acrescentar à lista de efeitos/plug-ins"
+
+#: gtk_ardour/plugin_selector.cc:84
+msgid "Remove a plugin from the effect list"
+msgstr "Remover à lista de efeitos/plug-ins"
+
+#: gtk_ardour/plugin_selector.cc:88
+msgid "Update"
+msgstr "Actualizar"
+
+#: gtk_ardour/plugin_selector.cc:89
+msgid "Update available plugins"
+msgstr "Actualizar efeitos/plug-ins disponíveis"
+
+#: gtk_ardour/plugin_selector.cc:110
+msgid "LADSPA"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:113
+msgid "VST"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:83
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this "
+"version of ardour)"
+msgstr ""
+"tipo desconhecido de editor de efeito/plug-in (nota: esta versão do ardour "
+"não suporta VST)"
+
+#: gtk_ardour/plugin_ui.cc:269
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr ""
+"Editor de efeitos/plug-ins: não foi possível criar elemento de controlo para "
+"%1"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "in"
+msgstr "entrada"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "ins"
+msgstr "entradas"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "out"
+msgstr "saída"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "outs"
+msgstr "saídas"
+
+#: gtk_ardour/plugin_ui.cc:382
+msgid "automation control"
+msgstr "controlo de automatização"
+
+#: gtk_ardour/plugin_ui.cc:869
+msgid "save"
+msgstr "guardar"
+
+#: gtk_ardour/plugin_ui.cc:870
+msgid "bypass"
+msgstr "ignorar"
+
+#: gtk_ardour/plugin_ui.cc:892
+msgid "Plugin preset %1 not found"
+msgstr "Parametrização de efeito/plug-in %1 inexistente"
+
+#: gtk_ardour/plugin_ui.cc:903
+msgid "Name for plugin settings:"
+msgstr "Nome para efeito/plug-in:"
+
+#: gtk_ardour/redirect_automation_line.cc:53
+msgid "redirect automation created for non-plugin"
+msgstr "automatização de re-encaminhamento criado para um não-efeito/plug-in"
+
+#: gtk_ardour/redirect_automation_time_axis.cc:92
+msgid "add automation event to "
+msgstr "acrescentar evento de automatização a "
+
+#: gtk_ardour/redirect_box.cc:213
+msgid "New send"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:214
+#, fuzzy
+msgid "Show send controls"
+msgstr "Controlo de velocidade"
+
+#: gtk_ardour/redirect_box.cc:360
+msgid "New Plugin ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:361
+#, fuzzy
+msgid "New Insert"
+msgstr "nova entrada"
+
+#: gtk_ardour/redirect_box.cc:362
+msgid "New Send ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:380
+#, fuzzy
+msgid "Select all"
+msgstr "Seleccionar tudo"
+
+#: gtk_ardour/redirect_box.cc:381
+#, fuzzy
+msgid "Deselect all"
+msgstr "Seleccionar tudo"
+
+#: gtk_ardour/redirect_box.cc:389
+#, fuzzy
+msgid "Inserts"
+msgstr "Inverter"
+
+#: gtk_ardour/redirect_box.cc:390
+#, fuzzy
+msgid "Sends"
+msgstr "Segundos"
+
+#: gtk_ardour/redirect_box.cc:393
+#, fuzzy
+msgid "Select all ..."
+msgstr "Seleccionar tudo"
+
+#: gtk_ardour/redirect_box.cc:406
+#, fuzzy
+msgid "Activate All"
+msgstr "Activar"
+
+#: gtk_ardour/redirect_box.cc:407
+#, fuzzy
+msgid "Deactivate All"
+msgstr "Desactivar"
+
+#: gtk_ardour/redirect_box.cc:488
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:500
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:513
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:616
+msgid "Pre-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:619
+msgid "Post-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:781
+msgid ""
+"You cannot reorder this set of redirects\n"
+"in that way because the inputs and\n"
+"outputs do not work correctly."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:903
+#, fuzzy
+msgid "ardour: rename redirect"
+msgstr "ardour: renomear região"
+
+#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043
+msgid ""
+"Copying the set of redirects on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:1064
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this track?\n"
+"(this cannot be undone)"
+msgstr ""
+"Deseja realmente remover o faixa \"%1\" ?\n"
+"(esta operação não pode ser desfeita)"
+
+#: gtk_ardour/redirect_box.cc:1067
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this bus?\n"
+"(this cannot be undone)"
+msgstr ""
+"Deseja realmente remover o faixa \"%1\" ?\n"
+"(esta operação não pode ser desfeita)"
+
+#: gtk_ardour/redirect_box.cc:1071
+#, fuzzy
+msgid "Yes, remove them all"
+msgstr "Sim, remover."
+
+#: gtk_ardour/redirect_box.cc:1114
+#, fuzzy
+msgid "ardour: %1"
+msgstr "ardour: misturador"
+
+#: gtk_ardour/redirect_box.cc:1156
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "ardour: misturador: "
+
+#: gtk_ardour/region_editor.cc:43
+msgid "NAME:"
+msgstr "NOME:"
+
+#: gtk_ardour/region_editor.cc:44
+msgid "lock"
+msgstr "bloquear"
+
+#: gtk_ardour/region_editor.cc:46
+msgid "opaque"
+msgstr "opaco"
+
+#: gtk_ardour/region_editor.cc:49
+msgid "Layer"
+msgstr "Nível"
+
+#: gtk_ardour/region_editor.cc:57
+msgid "ENVELOPE"
+msgstr "ENVOLVENTE"
+
+#: gtk_ardour/region_editor.cc:108
+msgid "mute this region"
+msgstr "emudecer esta região"
+
+#: gtk_ardour/region_editor.cc:109
+msgid "regions underneath this one cannot be heard"
+msgstr "regiões abaixo desta não serão ouvidas"
+
+#: gtk_ardour/region_editor.cc:110
+msgid "prevent any changes to this region"
+msgstr "evitar qualquer alteração nesta região"
+
+#: gtk_ardour/region_editor.cc:111
+msgid "use the gain envelope during playback"
+msgstr "usar a envolvente de ganho durante a reprodução"
+
+#: gtk_ardour/region_editor.cc:112
+msgid "show the gain envelope"
+msgstr "mostrar a curva de envolvente de ganho"
+
+#: gtk_ardour/region_editor.cc:113
+msgid "use fade in curve during playback"
+msgstr "usar curva de evanescimento durante a reprodução"
+
+#: gtk_ardour/region_editor.cc:114
+msgid "use fade out curve during playback"
+msgstr "usar curva de desvanecimento durante a reprodução"
+
+#: gtk_ardour/region_editor.cc:115
+msgid "audition this region"
+msgstr "ouvir esta região"
+
+#: gtk_ardour/region_editor.cc:148
+msgid "START:"
+msgstr "INÃCIO:"
+
+#: gtk_ardour/region_editor.cc:150
+msgid "END:"
+msgstr "FINAL:"
+
+#: gtk_ardour/region_editor.cc:152
+msgid "LENGTH:"
+msgstr "TAMANHO:"
+
+#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198
+#: gtk_ardour/region_editor.cc:234
+msgid "active"
+msgstr "activo"
+
+#: gtk_ardour/region_editor.cc:179
+msgid "visible"
+msgstr "visível"
+
+#: gtk_ardour/region_editor.cc:197
+msgid "FADE IN"
+msgstr "EVANESCER"
+
+#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235
+msgid "msecs"
+msgstr "msegs"
+
+#: gtk_ardour/region_editor.cc:233
+msgid "FADE OUT"
+msgstr "DESVANECER"
+
+#: gtk_ardour/region_editor.cc:276
+msgid "ardour: region "
+msgstr "ardour: região"
+
+#: gtk_ardour/region_editor.cc:410
+msgid "fade in edit"
+msgstr "alterar evanescimento"
+
+#: gtk_ardour/region_editor.cc:422
+msgid "fade out edit"
+msgstr "alterar desvanecimento"
+
+#: gtk_ardour/regionview.cc:1169
+#, fuzzy
+msgid "add gain control point"
+msgstr "remover ponto de controlo"
+
+#: gtk_ardour/route_params_ui.cc:58
+msgid "Tracks/Buses"
+msgstr "Faixas/Barramentos"
+
+#: gtk_ardour/route_params_ui.cc:59
+msgid "Pre Redirects"
+msgstr "Pré-encaminhamentos"
+
+#: gtk_ardour/route_params_ui.cc:60
+msgid "Post Redirects"
+msgstr "Pós-encaminhamentos"
+
+#: gtk_ardour/route_params_ui.cc:105
+#, fuzzy
+msgid "Pre-fader Redirects"
+msgstr "Pré-encaminhamentos"
+
+#: gtk_ardour/route_params_ui.cc:106
+#, fuzzy
+msgid "Post-fader Redirects"
+msgstr "Pós-encaminhamentos"
+
+#: gtk_ardour/route_params_ui.cc:138
+#, fuzzy
+msgid "ardour: track/bus inspector"
+msgstr "ardour: acrescentar faixa/barramento"
+
+#: gtk_ardour/route_params_ui.cc:139
+msgid "ardour_route_parameters"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:189
+msgid "route display list item for renamed route not found!"
+msgstr "não foi encontrado qualquer elemento de encaminhamento"
+
+#: gtk_ardour/route_params_ui.cc:448
+msgid "NO TRACK"
+msgstr "SEM FAIXA"
+
+#: gtk_ardour/route_params_ui.cc:669
+#, fuzzy
+msgid "ardour: track/bus inspector: "
+msgstr "ardour: acrescentar faixa/barramento"
+
+#: gtk_ardour/route_params_ui.cc:673
+msgid "No Route Selected"
+msgstr "Caminho Não Seleccionado"
+
+#: gtk_ardour/route_params_ui.cc:674
+#, fuzzy
+msgid "ardour: track/bus/inspector: no route selected"
+msgstr "ardour: parâmetros de encaminhamento: caminho não seleccionado"
+
+#: gtk_ardour/route_ui.cc:134
+msgid "mute change"
+msgstr "mudo alterado"
+
+#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220
+msgid "solo change"
+msgstr "solo alterado"
+
+#: gtk_ardour/route_ui.cc:284
+msgid "rec-enable change"
+msgstr "gravar alterado"
+
+#: gtk_ardour/route_ui.cc:423
+msgid "Solo-safe"
+msgstr "solo livre"
+
+#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474
+msgid "MIDI Bind"
+msgstr "Associação MIDI"
+
+#: gtk_ardour/route_ui.cc:445
+msgid "Pre Fader"
+msgstr "Pré-Atenuador"
+
+#: gtk_ardour/route_ui.cc:452
+msgid "Post Fader"
+msgstr "Pós-Atenuador"
+
+#: gtk_ardour/route_ui.cc:459
+msgid "Control Outs"
+msgstr "Saídas de Controlo"
+
+#: gtk_ardour/route_ui.cc:466
+msgid "Main Outs"
+msgstr "Saídas Principais"
+
+#: gtk_ardour/route_ui.cc:503
+msgid "mix group solo change"
+msgstr "grupo solo alterado"
+
+#: gtk_ardour/route_ui.cc:537
+msgid "mix group mute change"
+msgstr "grupo mudo alterado"
+
+#: gtk_ardour/route_ui.cc:553
+msgid "mix group rec-enable change"
+msgstr "grupo gravar alterado"
+
+#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258
+msgid "ardour: color selection"
+msgstr "ardor: selecção de cor"
+
+#: gtk_ardour/route_ui.cc:652
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"You may also lose the playlist used by this track.\n"
+"(cannot be undone)"
+msgstr ""
+"Deseja realmente remover o faixa \"%1\" ?\n"
+"A lista de reprodução em uso por esta faixa pode ficar perdida.\n"
+"(esta operação não pode ser desfeita)"
+
+#: gtk_ardour/route_ui.cc:654
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Deseja realmente remover o barramento \"%1\" ?\n"
+"(esta operação não pode ser desfeita)"
+
+#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299
+msgid "Yes, remove it."
+msgstr "Sim, remover."
+
+#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358
+msgid "new name: "
+msgstr "novo nome: "
+
+#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31
+msgid "Beats per minute"
+msgstr "Batimentos por minuto"
+
+#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35
+#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163
+msgid "Beat"
+msgstr "Batimento"
+
+#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158
+msgid "Meter denominator"
+msgstr "Denominador métrico"
+
+#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159
+msgid "Beats per bar"
+msgstr "Batimentos por compasso"
+
+#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189
+msgid "whole (1)"
+msgstr "toda (1)"
+
+#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191
+msgid "second (2)"
+msgstr "segunda (2)"
+
+#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193
+msgid "third (3)"
+msgstr "terça (3)"
+
+#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195
+#: gtk_ardour/tempo_dialog.cc:203
+msgid "quarter (4)"
+msgstr "quarta (4)"
+
+#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197
+msgid "eighth (8)"
+msgstr "octogésima (8)"
+
+#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199
+msgid "sixteenth (16)"
+msgstr "hexodécima (16)"
+
+#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201
+msgid "thirty-second (32)"
+msgstr "trigésima-segunda (32)"
+
+#: gtk_ardour/tempo_dialog.cc:301
+msgid "garbaged note type entry (%1)"
+msgstr "tipo de nota desconhecido (%1)"
+
+#: gtk_ardour/tempo_dialog.cc:311
+msgid "incomprehensible note type entry (%1)"
+msgstr "tipo de nota imcompreensível (%1)"
+
+#: gtk_ardour/time_axis_view.cc:95
+msgid "gTortnam"
+msgstr ""
+
+#: gtk_ardour/time_axis_view.cc:446
+msgid "Largest"
+msgstr "Enorme"
+
+#: gtk_ardour/time_axis_view.cc:447
+msgid "Large"
+msgstr "Grande"
+
+#: gtk_ardour/time_axis_view.cc:448
+msgid "Larger"
+msgstr "Maior"
+
+#: gtk_ardour/time_axis_view.cc:450
+msgid "Smaller"
+msgstr "Menor"
+
+#: gtk_ardour/time_axis_view.cc:451
+msgid "Small"
+msgstr "Pequeno"
+
+#: gtk_ardour/time_axis_view.cc:785
+msgid "unknown track height name \"%1\" in XML GUI information"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:69
+msgid "TimeAxisViewItemName"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:258
+msgid "new duration %1 frames is out of bounds for %2"
+msgstr ""
+
+#: gtk_ardour/time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr ""
+
+#: gtk_ardour/utils.cc:57
+msgid ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+msgstr ""
+
+#: gtk_ardour/utils.cc:66
+msgid "aeiou"
+msgstr ""
+
+#: gtk_ardour/utils.cc:75
+msgid "AEIOU"
+msgstr ""
+
+#: gtk_ardour/utils.cc:84
+msgid "bcdfghjklmnpqrtvwxyz"
+msgstr ""
+
+#: gtk_ardour/utils.cc:93
+msgid "BCDFGHJKLMNPQRTVWXYZ"
+msgstr ""
+
+#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265
+msgid "bad XPM header %1"
+msgstr ""
+
+#: gtk_ardour/utils.cc:516
+msgid "missing RGBA style for \"%1\""
+msgstr ""
+
+#: gtk_ardour/visual_time_axis.cc:297
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Deseja realmente remover o faixa \"%1\" ?\n"
+"(esta operação não pode ser desfeita)"
+
+#: gtk_ardour/visual_time_axis.cc:385
+msgid "A track already exists with that name"
+msgstr "Já existe uma faixa com este nome"
+
+#~ msgid "Seamless Looping"
+#~ msgstr "Ciclos Imperceptíveis"
+
+#~ msgid "Export to CD"
+#~ msgstr "Exportar para CD"
+
+#~ msgid "Recieve MMC"
+#~ msgstr "Receber MMC"
+
+#~ msgid "Trace MIDI Input"
+#~ msgstr "Rastrear entradas MIDI"
+
+#~ msgid "Trace MIDI Output"
+#~ msgstr "Rastrear saídas MIDI"
+
+#~ msgid "MTC Port"
+#~ msgstr "Porta MTC"
+
+#~ msgid "MIDI Param Port"
+#~ msgstr "Porta Parameterização MIDI"
+
+#~ msgid "attempt to timestretch a non-audio track!"
+#~ msgstr "tentativa de alongamento temporal duma faixa não-audio"
+
+#~ msgid "move region(s) between tracks"
+#~ msgstr "Mover regiões entre faixas"
+
+#~ msgid "copy region(s) between tracks"
+#~ msgstr "Copiar regiões entre faixas"
+
+#~ msgid "ardour: tempo editor"
+#~ msgstr "ardour: edição de tempo"
+
+#~ msgid "apply"
+#~ msgstr "aplicar"
+
+#~ msgid "fade"
+#~ msgstr "desvanecimento"
+
+#~ msgid "Edit left"
+#~ msgstr "Editar à esquerda"
+
+#~ msgid "Edit right"
+#~ msgstr "Editar à direita"
+
+#~ msgid "Edit fade"
+#~ msgstr "Editar desvanecimento"
+
+#~ msgid "Export region"
+#~ msgstr "Exportar região"
+
+#, fuzzy
+#~ msgid "Bounce region"
+#~ msgstr "Rebater selecção"
+
+#~ msgid "Region"
+#~ msgstr "Região"
+
+#~ msgid "Play selected region"
+#~ msgstr "Reproduzir região seleccionada"
+
+#~ msgid "clear connections"
+#~ msgstr "apagar ligações"
+
+#~ msgid "add comments/notes here"
+#~ msgstr "acrescentar comentários/notas aqui"
+
+#~ msgid "Crossfades in use"
+#~ msgstr "Desvanecimentos cruzados automáticos em utilização"
+
+#~ msgid "outside this computer"
+#~ msgstr "fora deste computador"
+
+#~ msgid "inside this computer"
+#~ msgstr "dentro deste computador"
+
+#~ msgid "Recorded audio is generated"
+#~ msgstr "Gravação audio é gerada"
diff --git a/gtk2_ardour/po/ru_RU.po b/gtk2_ardour/po/ru_RU.po
new file mode 100644
index 0000000000..b4de6dcce9
--- /dev/null
+++ b/gtk2_ardour/po/ru_RU.po
@@ -0,0 +1,5178 @@
+# Copyright (C) 2004 Paul Davis
+# This file is distributed under the same license as the gtk-ardour package.
+# Igor Blinov pitstop@nm.ru, 2004.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gtk-ardour 0.413.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2005-09-19 18:09-0400\n"
+"PO-Revision-Date: 2004-03-31 00:45+0300\n"
+"Last-Translator: Igor Blinov pitstop@nm.ru\n"
+"Language-Team: Russian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gtk_ardour/about.cc:134
+msgid "Marcus Andersson"
+msgstr ""
+
+#: gtk_ardour/about.cc:135
+msgid "Jeremy Hall"
+msgstr ""
+
+#: gtk_ardour/about.cc:136
+msgid "Steve Harris"
+msgstr ""
+
+#: gtk_ardour/about.cc:137
+msgid "Tim Mayberry"
+msgstr ""
+
+#: gtk_ardour/about.cc:138
+msgid "Mark Stewart"
+msgstr ""
+
+#: gtk_ardour/about.cc:139
+msgid "Sam Chessman"
+msgstr ""
+
+#: gtk_ardour/about.cc:140
+msgid "Jack O'Quin"
+msgstr ""
+
+#: gtk_ardour/about.cc:141
+msgid "Matt Krai"
+msgstr ""
+
+#: gtk_ardour/about.cc:142
+msgid "Ben Bell"
+msgstr ""
+
+#: gtk_ardour/about.cc:143
+msgid "Gerard van Dongen"
+msgstr ""
+
+#: gtk_ardour/about.cc:144
+msgid "Thomas Charbonnel"
+msgstr ""
+
+#: gtk_ardour/about.cc:145
+msgid "Nick Mainsbridge"
+msgstr ""
+
+#: gtk_ardour/about.cc:146
+msgid "Colin Law"
+msgstr ""
+
+#: gtk_ardour/about.cc:147
+msgid "Sampo Savolainen"
+msgstr ""
+
+#: gtk_ardour/about.cc:148
+msgid "Joshua Leach"
+msgstr ""
+
+#: gtk_ardour/about.cc:149
+msgid "Rob Holland"
+msgstr ""
+
+#: gtk_ardour/about.cc:150
+msgid "Per Sigmond"
+msgstr ""
+
+#: gtk_ardour/about.cc:151
+msgid "Doug Mclain"
+msgstr ""
+
+#: gtk_ardour/about.cc:156
+msgid ""
+"French:\n"
+"\tAlain Fréhel <alain.frehel@free.fr>"
+msgstr ""
+
+#: gtk_ardour/about.cc:157
+msgid ""
+"German:\n"
+"\tKarsten Petersen <kapet@kapet.de>"
+msgstr ""
+
+#: gtk_ardour/about.cc:158
+msgid ""
+"Italian:\n"
+"\tFilippo Pappalardo <filippo@email.it>"
+msgstr ""
+
+#: gtk_ardour/about.cc:159
+msgid ""
+"Portuguese:\n"
+"\tRui Nuno Capela <rncbc@rncbc.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:160
+msgid ""
+"Brazilian Portuguese:\n"
+"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
+"\tChris Ross <chris@tebibyte.org>"
+msgstr ""
+
+#: gtk_ardour/about.cc:162
+msgid ""
+"Spanish:\n"
+"\t Alex Krohn <alexkrohn@fastmail.fm>"
+msgstr ""
+
+#: gtk_ardour/about.cc:163
+msgid ""
+"Russian:\n"
+"\t Igor Blinov <pitstop@nm.ru>"
+msgstr ""
+
+#: gtk_ardour/about.cc:181
+msgid ""
+"Copyright (C) 1999-2005 Paul Davis\n"
+"Ardour comes with ABSOLUTELY NO WARRANTY\n"
+"This is free software, and you are welcome to redistribute it\n"
+"under certain conditions; see the file COPYING for details.\n"
+msgstr ""
+
+#: gtk_ardour/about.cc:188
+msgid ""
+"Ardour: %1\n"
+"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+msgstr ""
+
+#: gtk_ardour/about.cc:206
+msgid ""
+"Primary author:\n"
+"\tPaul Davis\n"
+"\n"
+"Major developers:\n"
+"\tJesse Chappell\n"
+"\tTaybin Rutkin\n"
+"Contributors:\n"
+"\t"
+msgstr ""
+
+#: gtk_ardour/about.cc:243
+msgid "Authors"
+msgstr ""
+
+#: gtk_ardour/about.cc:244
+#, fuzzy
+msgid "Translators"
+msgstr "Triangular"
+
+#: gtk_ardour/about.cc:361
+msgid "cannot open splash image file \"%1\""
+msgstr "не удалоÑÑŒ отобразить заÑтавку (файл \"%1\")"
+
+#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33
+#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81
+#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977
+#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85
+#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777
+#: gtk_ardour/redirect_box.cc:900
+msgid "OK"
+msgstr "ОК"
+
+#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92
+#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046
+#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72
+#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982
+#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733
+#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000
+#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129
+#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785
+#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86
+#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072
+#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33
+#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161
+msgid "Cancel"
+msgstr "Отмена"
+
+#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94
+msgid "Tracks"
+msgstr "Треки"
+
+#: gtk_ardour/add_route_dialog.cc:43
+msgid "Busses"
+msgstr "Шины"
+
+#: gtk_ardour/add_route_dialog.cc:48
+msgid "ardour: add track/bus"
+msgstr "ardour: добавить трек/шину"
+
+#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81
+msgid "Add"
+msgstr "Добавить"
+
+#: gtk_ardour/add_route_dialog.cc:86
+msgid "Name (template)"
+msgstr "Ð˜Ð¼Ñ (шаблона)"
+
+#: gtk_ardour/ardour_ui.cc:798
+msgid ""
+"pre\n"
+"roll"
+msgstr "откат"
+
+#: gtk_ardour/ardour_ui.cc:799
+msgid ""
+"post\n"
+"roll"
+msgstr "накат"
+
+#: gtk_ardour/ardour_ui.cc:807
+msgid "% "
+msgstr "% "
+
+#: gtk_ardour/ardour_ui.cc:808
+msgid "spring"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:810
+msgid ""
+"punch\n"
+"in"
+msgstr ""
+"врезка\n"
+"до"
+
+#: gtk_ardour/ardour_ui.cc:811
+msgid ""
+"punch\n"
+"out"
+msgstr ""
+"врезка\n"
+"поÑле"
+
+#: gtk_ardour/ardour_ui.cc:812
+msgid ""
+"auto\n"
+"return"
+msgstr ""
+"авто\n"
+"возврат"
+
+#: gtk_ardour/ardour_ui.cc:813
+msgid ""
+"auto\n"
+"play"
+msgstr ""
+"авто\n"
+"воÑпр."
+
+#: gtk_ardour/ardour_ui.cc:814
+msgid ""
+"auto\n"
+"input"
+msgstr ""
+"авто\n"
+"вход"
+
+#: gtk_ardour/ardour_ui.cc:815
+msgid "click"
+msgstr "метроном"
+
+#: gtk_ardour/ardour_ui.cc:816
+msgid ""
+"follow\n"
+"PH"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:817
+msgid "AUDITIONING"
+msgstr "КОÐТРОЛЬ"
+
+#: gtk_ardour/ardour_ui.cc:818
+msgid "SOLO"
+msgstr "СОЛО"
+
+#: gtk_ardour/ardour_ui.cc:870
+msgid "Percentage"
+msgstr "Процентов"
+
+#: gtk_ardour/ardour_ui.cc:872
+msgid "Semitones"
+msgstr "Полутонов"
+
+#: gtk_ardour/ardour_ui.cc:875
+msgid "Sprung"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:877
+msgid "Wheel"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:902
+msgid ""
+"You cannot record-enable\n"
+"track %1\n"
+"because it has no input connections.\n"
+"You would be wasting space recording silence."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1073
+msgid "quit"
+msgstr "выйти"
+
+#: gtk_ardour/ardour_ui.cc:1082
+msgid ""
+"Ardour was unable to save your session.\n"
+"\n"
+"If you still wish to quit, please use the\n"
+"\n"
+"\"Just quit\" option."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1107
+msgid "Save and %1"
+msgstr "Сохранить и %1"
+
+#: gtk_ardour/ardour_ui.cc:1112
+msgid "Just %1"
+msgstr "Да, %1"
+
+#: gtk_ardour/ardour_ui.cc:1117
+msgid "Don't %1"
+msgstr "Отмена"
+
+#: gtk_ardour/ardour_ui.cc:1126
+#, fuzzy
+msgid "session"
+msgstr "СеÑÑиÑ"
+
+#: gtk_ardour/ardour_ui.cc:1128
+#, fuzzy
+msgid "snapshot"
+msgstr "Снимок"
+
+#: gtk_ardour/ardour_ui.cc:1130
+#, fuzzy
+msgid ""
+"The %1\n"
+"\"%2\"\n"
+"has not been saved.\n"
+"\n"
+"Any changes made this time\n"
+"will be lost unless you save it.\n"
+"\n"
+"What do you want to do?"
+msgstr ""
+"СеÑÑÐ¸Ñ \"%1\"\n"
+"не Ñохранена.\n"
+"\n"
+"Ð’Ñе Ñделанные изменениÑ\n"
+"будут потерÑны, еÑли не Ñохранить их.\n"
+"\n"
+"Что Ð’Ñ‹ хотите Ñделать?"
+
+#: gtk_ardour/ardour_ui.cc:1151
+msgid "Prompter"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1152
+msgid "ardour: save session?"
+msgstr "ardour: Ñохранить ÑеÑÑию?"
+
+#: gtk_ardour/ardour_ui.cc:1219
+#, fuzzy, c-format
+msgid "disconnected"
+msgstr "ОтÑоединить"
+
+#: gtk_ardour/ardour_ui.cc:1226
+#, fuzzy, c-format
+msgid "SR: %.1f kHz / %4.1f msecs"
+msgstr "SR: %.1f кГц"
+
+#: gtk_ardour/ardour_ui.cc:1230
+#, c-format
+msgid "SR: %u kHz / %4.1f msecs"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:1243
+#, c-format
+msgid "DSP Load: %.1f%%"
+msgstr "Загрузка DSP: %.1f%%"
+
+#: gtk_ardour/ardour_ui.cc:1253
+#, c-format
+msgid "Disk r:%5.1f w:%5.1f MB/s"
+msgstr "ДиÑк r:%5.1f w:%5.1f MB/Ñек"
+
+#: gtk_ardour/ardour_ui.cc:1267
+#, fuzzy, c-format
+msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
+msgstr "Буферы p:%5.0f%% c:%5.0f%%"
+
+#: gtk_ardour/ardour_ui.cc:1294
+msgid "space: 24hrs+"
+msgstr "меÑто на диÑке: 24 чаÑа +"
+
+#: gtk_ardour/ardour_ui.cc:1324
+#, c-format
+msgid "space: %02dh:%02dm:%02ds"
+msgstr "Ñвободное меÑто: %02dч:%02dмин:%02dÑек"
+
+#: gtk_ardour/ardour_ui.cc:1575
+msgid "programming error: impossible control method"
+msgstr "ошибка в программе: impossible control method"
+
+#: gtk_ardour/ardour_ui.cc:1800
+msgid "cancel"
+msgstr "отмена"
+
+#: gtk_ardour/ardour_ui.cc:1801
+msgid "rescan"
+msgstr "обновить"
+
+#: gtk_ardour/ardour_ui.cc:1842
+msgid "open session"
+msgstr "открыть ÑеÑÑию"
+
+#: gtk_ardour/ardour_ui.cc:1897
+msgid "Patience is a virtue.\n"
+msgstr "По нитке дойдёшь и до клубка.\n"
+
+#: gtk_ardour/ardour_ui.cc:1906
+msgid "You cannot add a track without a session already loaded."
+msgstr "Ð’Ñ‹ не можете добавить трек пока ÑеÑÑÐ¸Ñ Ð½Ðµ загружена."
+
+#: gtk_ardour/ardour_ui.cc:1913
+msgid "could not create new audio track"
+msgstr "не удалоÑÑŒ Ñоздать новый аудиотрек"
+
+#: gtk_ardour/ardour_ui.cc:1917
+msgid "could not create new audio bus"
+msgstr "не удалоÑÑŒ Ñоздать новую аудиошину"
+
+#: gtk_ardour/ardour_ui.cc:1936
+msgid ""
+"There are insufficient JACK ports available\n"
+"to create a new track or bus.\n"
+"You should save Ardour, exit and\n"
+"restart JACK with more ports."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2071
+msgid ""
+"Please create 1 or more track\n"
+"before trying to record.\n"
+"Check the Session menu."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2312
+#, fuzzy
+msgid ""
+"JACK has either been shutdown or it\n"
+"disconnected Ardour because Ardour\n"
+"was not fast enough. You can save the\n"
+"session and/or try to reconnect to JACK ."
+msgstr ""
+"Внимание! JACK завершил работу или\n"
+"потерÑл Ñинхронизацию Ñ Ardour и отÑоединил его.\n"
+"Ðеобходимо Ñохранить ÑеÑÑию и\n"
+"перезапуÑтить JACK и Ardour."
+
+#: gtk_ardour/ardour_ui.cc:2328
+msgid "Unable to create all required ports"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2336
+#, fuzzy
+msgid "Unable to start the session running"
+msgstr "Ð’ начало ÑеÑÑии"
+
+#: gtk_ardour/ardour_ui.cc:2472
+msgid "No Stream"
+msgstr "Ðет потока"
+
+#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518
+msgid "none"
+msgstr "нет"
+
+#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527
+#: gtk_ardour/automation_time_axis.cc:189
+#: gtk_ardour/automation_time_axis.cc:218
+#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211
+#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947
+#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659
+msgid "off"
+msgstr "выкл"
+
+#: gtk_ardour/ardour_ui.cc:2548
+msgid "Name for snapshot"
+msgstr "Ð˜Ð¼Ñ Ñнимка"
+
+#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294
+msgid "Name for mix template:"
+msgstr "Ð˜Ð¼Ñ mix-шаблона:"
+
+#: gtk_ardour/ardour_ui.cc:2717
+msgid "-template"
+msgstr "-шаблон"
+
+#: gtk_ardour/ardour_ui.cc:2760
+msgid "Session %1 already exists at %2"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2832
+msgid ""
+"You do not have write access to this session.\n"
+"This prevents the session from being loaded."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897
+msgid "Session \"%1 (snapshot %2)\" did not load successfully"
+msgstr "Ðе удалоÑÑŒ загрузить ÑеÑÑию \"%1 (Ñнимок %2)\""
+
+#: gtk_ardour/ardour_ui.cc:2966
+msgid ""
+"No audio files were ready for cleanup\n"
+"\n"
+"If this seems suprising, check for any existing\n"
+"snapshots. These may still include regions that\n"
+"require some unused files to continue to exist."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001
+msgid "files"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003
+msgid "file"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3026
+msgid "ardour: cleanup"
+msgstr "ardour: очиÑтка"
+
+#: gtk_ardour/ardour_ui.cc:3040
+msgid ""
+"Cleanup is a destructive operation.\n"
+"ALL undo/redo information will be lost if you cleanup.\n"
+"Unused audio files will be moved to a \"dead sounds\" location."
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3045
+msgid "Proceed with cleanup"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3061
+#, fuzzy
+msgid "CleanupDialog"
+msgstr "ОчиÑтка"
+
+#: gtk_ardour/ardour_ui.cc:3062
+#, fuzzy
+msgid "ardour cleanup"
+msgstr "ardour: очиÑтка"
+
+#: gtk_ardour/ardour_ui.cc:3063
+#, fuzzy
+msgid "ardour_cleanup"
+msgstr "ardour: очиÑтка"
+
+#: gtk_ardour/ardour_ui.cc:3086
+msgid "cleaned files"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3087
+#, fuzzy
+msgid ""
+"The following %1 %2 were not in use.\n"
+"The next time you flush the wastebasket\n"
+"it will release an additional %3 %4bytes\n"
+"of disk space"
+msgstr ""
+"Следующие %1 файлов не иÑпользуютÑÑ.\n"
+"ПоÑÐ»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð¾Ñ‡Ð¸Ñтка корзины оÑвободит\n"
+"%2 мегабайт меÑта на диÑке."
+
+#: gtk_ardour/ardour_ui.cc:3110
+#, fuzzy
+msgid "deleted file"
+msgstr "удалённые файлы"
+
+#: gtk_ardour/ardour_ui.cc:3111
+#, fuzzy
+msgid ""
+"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space"
+msgstr ""
+"Следующие %1 файлов были удалены, оÑвободив при Ñтом %2 Мб меÑта на диÑке"
+
+#: gtk_ardour/ardour_ui.cc:3226
+msgid "Recording was stopped because your system could not keep up."
+msgstr "ЗапиÑÑŒ оÑтановлена из-за недоÑтаточного быÑтродейÑÑ‚Ð²Ð¸Ñ ÑиÑтемы"
+
+#: gtk_ardour/ardour_ui.cc:3248
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to write data to disk\n"
+"quickly enough to keep up with recording.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3266
+msgid ""
+"The disk system on your computer\n"
+"was not able to keep up with Ardour.\n"
+"\n"
+"Specifically, it failed to read data from disk\n"
+"quickly enough to keep up with playback.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3291
+msgid "Recover from crash"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3292
+msgid "Ignore crash data"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3293
+msgid ""
+"This session appears to have been in\n"
+"middle of recording when ardour or\n"
+"the computer was shutdown.\n"
+"\n"
+"Ardour can recover any captured audio for\n"
+"you, or it can ignore it. Please decide\n"
+"what you would like to do.\n"
+msgstr ""
+
+#: gtk_ardour/ardour_ui.cc:3338
+#, fuzzy
+msgid "Could not disconnect from JACK"
+msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\""
+
+#: gtk_ardour/ardour_ui.cc:3351
+#, fuzzy
+msgid "Could not reconnect to JACK"
+msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\""
+
+#: gtk_ardour/ardour_ui2.cc:60
+msgid "UI: cannot setup editor"
+msgstr "ИнтерфейÑ: не удалоÑÑŒ инициализировать редактор"
+
+#: gtk_ardour/ardour_ui2.cc:65
+msgid "UI: cannot setup mixer"
+msgstr "ИнтерфейÑ: не удалоÑÑŒ инициализировать микшер"
+
+#: gtk_ardour/ardour_ui2.cc:70
+msgid "UI: cannot setup meter_bridge"
+msgstr "ИнтерфейÑ: не удалоÑÑŒ инициализировать индикаторы"
+
+#: gtk_ardour/ardour_ui2.cc:98
+msgid "MMC + Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:99
+msgid "MMC"
+msgstr "MMC"
+
+#: gtk_ardour/ardour_ui2.cc:100
+msgid "Local"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:117
+msgid "MMC ID"
+msgstr "MMC идентификатор"
+
+#: gtk_ardour/ardour_ui2.cc:215
+msgid "Play from playhead"
+msgstr "ВоÑпроизвеÑти от указателÑ"
+
+#: gtk_ardour/ardour_ui2.cc:216
+msgid "Stop playback"
+msgstr "Стоп"
+
+#: gtk_ardour/ardour_ui2.cc:217
+#, fuzzy
+msgid "Play range/selection"
+msgstr "ВоÑпроизвеÑти выделенное"
+
+#: gtk_ardour/ardour_ui2.cc:218
+msgid "Go to start of session"
+msgstr "Ð’ начало ÑеÑÑии"
+
+#: gtk_ardour/ardour_ui2.cc:219
+msgid "Go to end of session"
+msgstr "Ð’ конец ÑеÑÑии"
+
+#: gtk_ardour/ardour_ui2.cc:220
+msgid "Play loop range"
+msgstr "ВоÑпроизвеÑти \"кольцо\""
+
+#: gtk_ardour/ardour_ui2.cc:221
+msgid "Return to last playback start when stopped"
+msgstr "ВернутьÑÑ Ðº точке начала воÑпроизведениÑ"
+
+#: gtk_ardour/ardour_ui2.cc:222
+msgid "Start playback after any locate"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:223
+msgid "Be sensible about input monitoring"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:224
+msgid "Start recording at auto-punch start"
+msgstr "Ðачать запиÑÑŒ Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° \"авто-врезки\""
+
+#: gtk_ardour/ardour_ui2.cc:225
+msgid "Stop recording at auto-punch end"
+msgstr "ОÑтановить запиÑÑŒ в конце \"авто-врезки\""
+
+#: gtk_ardour/ardour_ui2.cc:226
+msgid "Enable/Disable audio click"
+msgstr "Вкл./Выкл. метроном"
+
+#: gtk_ardour/ardour_ui2.cc:227
+#, fuzzy
+msgid "Enable/Disable follow playhead"
+msgstr "Разрешить/запретить цикл"
+
+#: gtk_ardour/ardour_ui2.cc:228
+msgid "Shuttle speed control"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:229
+#, c-format
+msgid "Select semitones or %%-age for speed display"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:230
+msgid "Select sprung or wheel behaviour"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:231
+msgid "Current transport speed"
+msgstr "ТекщаÑÑ ÑкорÑÑ‚ÑŒ транÑпорта"
+
+#: gtk_ardour/ardour_ui2.cc:312
+msgid "Primary clock"
+msgstr "ОÑновной Ñчётчик"
+
+#: gtk_ardour/ardour_ui2.cc:313
+msgid "secondary clock"
+msgstr "дополнительный Ñчётчик"
+
+#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751
+#: gtk_ardour/ardour_ui2.cc:770
+msgid "stopped"
+msgstr "оÑтановлено"
+
+#: gtk_ardour/ardour_ui2.cc:431
+msgid "ardour: clock"
+msgstr "ardour: Ñчётчик"
+
+#: gtk_ardour/ardour_ui2.cc:721
+msgid "st"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:731
+msgid "sprung"
+msgstr ""
+
+#: gtk_ardour/ardour_ui2.cc:742
+msgid "wheel"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dependents.cc:74
+msgid "keyboard_target: error setting binding state: invalid node"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_dialogs.cc:158
+msgid "close session"
+msgstr "закрыть ÑеÑÑию"
+
+#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895
+msgid "New"
+msgstr "Ðовый"
+
+#: gtk_ardour/ardour_ui_ed.cc:76
+msgid "Open"
+msgstr "Открыть"
+
+#: gtk_ardour/ardour_ui_ed.cc:77
+msgid "Recent"
+msgstr "ПоÑледние"
+
+#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54
+#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784
+msgid "Close"
+msgstr "Закрыть"
+
+#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488
+msgid "Add Track/Bus"
+msgstr "Добавить Трек/Шину"
+
+#: gtk_ardour/ardour_ui_ed.cc:99
+msgid "Connect"
+msgstr "Соединить"
+
+#: gtk_ardour/ardour_ui_ed.cc:100
+msgid "Image Compositor"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:114
+msgid "Save"
+msgstr "Сохранить"
+
+#: gtk_ardour/ardour_ui_ed.cc:118
+msgid "Snapshot"
+msgstr "Снимок"
+
+#: gtk_ardour/ardour_ui_ed.cc:126
+msgid "Save Template..."
+msgstr "Сохранить шаблон..."
+
+#: gtk_ardour/ardour_ui_ed.cc:133
+msgid "Export session to audiofile..."
+msgstr "ЭкÑпорт ÑеÑÑии в аудиофайл..."
+
+#: gtk_ardour/ardour_ui_ed.cc:134
+#, fuzzy
+msgid "Export range to audiofile..."
+msgstr "ЭкÑпорт ÑеÑÑии в аудиофайл..."
+
+#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312
+#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118
+#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227
+msgid "Export"
+msgstr "ЭкÑпорт"
+
+#: gtk_ardour/ardour_ui_ed.cc:146
+msgid "Cleanup unused sources"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:147
+msgid "Flush wastebasket"
+msgstr "ОчиÑтить корзину"
+
+#: gtk_ardour/ardour_ui_ed.cc:149
+msgid "Cleanup"
+msgstr "ОчиÑтка"
+
+#: gtk_ardour/ardour_ui_ed.cc:154
+msgid "Quit"
+msgstr "Выйти"
+
+#: gtk_ardour/ardour_ui_ed.cc:156
+msgid "Session"
+msgstr "СеÑÑиÑ"
+
+#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287
+#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499
+#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570
+#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412
+msgid "Edit"
+msgstr "Правка"
+
+#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572
+#: gtk_ardour/mixer_strip.cc:631
+msgid "Disconnect"
+msgstr "ОтÑоединить"
+
+#: gtk_ardour/ardour_ui_ed.cc:174
+#, fuzzy
+msgid "Reconnect"
+msgstr "Соединить"
+
+#: gtk_ardour/ardour_ui_ed.cc:192
+msgid "Latency"
+msgstr ""
+
+#: gtk_ardour/ardour_ui_ed.cc:195
+msgid "JACK"
+msgstr "JACK"
+
+#: gtk_ardour/ardour_ui_ed.cc:205
+msgid "Editor"
+msgstr "Редактор"
+
+#: gtk_ardour/ardour_ui_ed.cc:206
+msgid "Mixer"
+msgstr "Микшер"
+
+#: gtk_ardour/ardour_ui_ed.cc:212
+msgid "Options Editor"
+msgstr "Редактор параметров"
+
+#: gtk_ardour/ardour_ui_ed.cc:219
+msgid "Audio Library"
+msgstr "Ðудио-библиотека"
+
+#: gtk_ardour/ardour_ui_ed.cc:225
+#, fuzzy
+msgid "Track/Bus Inspector"
+msgstr "Треки/Шины"
+
+#: gtk_ardour/ardour_ui_ed.cc:232
+msgid "Connections"
+msgstr "СоединениÑ"
+
+#: gtk_ardour/ardour_ui_ed.cc:240
+msgid "Meter Bridge"
+msgstr "Индикаторы"
+
+#: gtk_ardour/ardour_ui_ed.cc:248
+msgid "Locations"
+msgstr "Интервалы"
+
+#: gtk_ardour/ardour_ui_ed.cc:255
+msgid "Big Clock"
+msgstr "Большой Ñчётчик"
+
+#: gtk_ardour/ardour_ui_ed.cc:261
+msgid "About"
+msgstr "О программе"
+
+#: gtk_ardour/ardour_ui_ed.cc:264
+msgid "Windows"
+msgstr "Окна"
+
+#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203
+msgid "SMPTE"
+msgstr "SMPTE"
+
+#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202
+#: gtk_ardour/editor_rulers.cc:359
+msgid "Bars:Beats"
+msgstr "Такт:ДолÑ"
+
+#: gtk_ardour/audio_clock.cc:1642
+msgid "Minutes:Seconds"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/audio_clock.cc:1643
+msgid "Audio Frames"
+msgstr "Ðудио кадры"
+
+#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356
+#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713
+#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774
+#: gtk_ardour/option_editor.cc:794
+msgid "Off"
+msgstr "Выкл"
+
+#: gtk_ardour/audio_clock.cc:1646
+msgid "Mode"
+msgstr "Режим"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523
+msgid "m"
+msgstr "Ñ‚"
+
+#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524
+msgid "s"
+msgstr "Ñ"
+
+#: gtk_ardour/audio_time_axis.cc:104
+msgid "r"
+msgstr "з"
+
+#: gtk_ardour/audio_time_axis.cc:108
+msgid "g"
+msgstr "г"
+
+#: gtk_ardour/audio_time_axis.cc:109
+msgid "p"
+msgstr "Ñп"
+
+#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44
+#: gtk_ardour/visual_time_axis.cc:90
+msgid "h"
+msgstr "в"
+
+#: gtk_ardour/audio_time_axis.cc:111
+msgid "a"
+msgstr "а"
+
+#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89
+msgid "v"
+msgstr "п"
+
+#: gtk_ardour/audio_time_axis.cc:185
+msgid "Record"
+msgstr "ЗапиÑÑŒ"
+
+#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191
+msgid "Solo"
+msgstr "Соло"
+
+#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236
+#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433
+msgid "Mute"
+msgstr "Тихо"
+
+#: gtk_ardour/audio_time_axis.cc:188
+msgid "Edit Group"
+msgstr "Группы"
+
+#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110
+msgid "Display Height"
+msgstr "Ð’Ñ‹Ñота дорожки"
+
+#: gtk_ardour/audio_time_axis.cc:190
+msgid "Playlist"
+msgstr "СпиÑок"
+
+#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752
+msgid "Automation"
+msgstr "Ðвтомат"
+
+#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111
+msgid "Visual options"
+msgstr "Параметры отображениÑ"
+
+#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112
+msgid "Hide this track"
+msgstr "Скрыть трек"
+
+#: gtk_ardour/audio_time_axis.cc:349
+msgid "No group"
+msgstr "Ðет группы"
+
+#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447
+#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229
+msgid "Height"
+msgstr "Ð’Ñ‹Ñота"
+
+#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266
+#: gtk_ardour/marker_time_axis.cc:230
+msgid "Color"
+msgstr "Цвет"
+
+#: gtk_ardour/audio_time_axis.cc:720
+msgid "Hide all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:721
+msgid "Show all crossfades"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:729
+msgid "show all automation"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:732
+#, fuzzy
+msgid "show existing automation"
+msgstr "иÑпользовать имеющийÑÑ ÑˆÐ°Ð±Ð»Ð¾Ð½"
+
+#: gtk_ardour/audio_time_axis.cc:735
+msgid "hide all automation"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204
+#: gtk_ardour/editor.cc:234
+msgid "gain"
+msgstr "уÑил."
+
+#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244
+msgid "pan"
+msgstr "пан."
+
+#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388
+msgid "Plugins"
+msgstr "Модули (плагины)"
+
+#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95
+msgid "Show waveforms"
+msgstr "Отображать форму Ñигнала"
+
+#: gtk_ardour/audio_time_axis.cc:766
+msgid "Traditional"
+msgstr "ОбычнаÑ"
+
+#: gtk_ardour/audio_time_axis.cc:769
+msgid "Rectified"
+msgstr "УвеличеннаÑ"
+
+#: gtk_ardour/audio_time_axis.cc:772
+msgid "Waveform"
+msgstr "Форма Ñигнала"
+
+#: gtk_ardour/audio_time_axis.cc:782
+#, fuzzy
+msgid "align with existing material"
+msgstr "СущеÑтвующий материал"
+
+#: gtk_ardour/audio_time_axis.cc:787
+#, fuzzy
+msgid "align with capture time"
+msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи"
+
+#: gtk_ardour/audio_time_axis.cc:793
+#, fuzzy
+msgid "Alignment"
+msgstr "ВыровнÑÑ‚ÑŒ"
+
+#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288
+msgid "Active"
+msgstr "Ðктивен"
+
+#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386
+#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467
+#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269
+#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233
+#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83
+msgid "Remove"
+msgstr "Удалить"
+
+#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880
+#: gtk_ardour/audio_time_axis.cc:911
+#, fuzzy
+msgid "Name for playlist"
+msgstr "Ð˜Ð¼Ñ Ñнимка"
+
+#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433
+msgid "a track already exists with that name"
+msgstr "трек Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует"
+
+#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001
+#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539
+msgid "programming error: "
+msgstr "ошибка в программе: "
+
+#: gtk_ardour/audio_time_axis.cc:1889
+msgid "Current: %1"
+msgstr ""
+
+#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452
+#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226
+#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377
+msgid "Rename"
+msgstr "Переименовать"
+
+#: gtk_ardour/audio_time_axis.cc:1896
+msgid "New Copy"
+msgstr "ÐÐ¾Ð²Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ"
+
+#: gtk_ardour/audio_time_axis.cc:1898
+msgid "Clear Current"
+msgstr "ОчиÑтить текущий"
+
+#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472
+#: gtk_ardour/editor.cc:2557
+msgid "Select"
+msgstr "Выделеннное"
+
+#: gtk_ardour/automation_line.cc:904
+#, fuzzy
+msgid "automation event move"
+msgstr "автомат"
+
+#: gtk_ardour/automation_line.cc:906
+#, fuzzy
+msgid "automation range drag"
+msgstr "автомат"
+
+#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64
+#, fuzzy
+msgid "remove control point"
+msgstr "иÑпользовать контрольные выходы"
+
+#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010
+msgid "clear"
+msgstr "очиÑтить"
+
+#: gtk_ardour/automation_time_axis.cc:80
+msgid "track height"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:81
+#, fuzzy
+msgid "automation state"
+msgstr "автомат"
+
+#: gtk_ardour/automation_time_axis.cc:82
+#, fuzzy
+msgid "clear track"
+msgstr "Скрыть трек"
+
+#: gtk_ardour/automation_time_axis.cc:83
+#, fuzzy
+msgid "hide track"
+msgstr "Скрыть трек"
+
+#: gtk_ardour/automation_time_axis.cc:191
+#: gtk_ardour/automation_time_axis.cc:229
+#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213
+#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419
+#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50
+msgid "play"
+msgstr "воÑпроизвеÑти"
+
+#: gtk_ardour/automation_time_axis.cc:193
+#: gtk_ardour/automation_time_axis.cc:240
+#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215
+#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422
+#: gtk_ardour/plugin_ui.cc:663
+msgid "write"
+msgstr "запиÑÑŒ"
+
+#: gtk_ardour/automation_time_axis.cc:195
+#: gtk_ardour/automation_time_axis.cc:251
+#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217
+#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953
+#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665
+msgid "touch"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274
+#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428
+msgid "???"
+msgstr ""
+
+#: gtk_ardour/automation_time_axis.cc:276
+#, fuzzy
+msgid "clear automation"
+msgstr "очиÑтить интервалы"
+
+#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453
+#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398
+msgid "Hide"
+msgstr "Скрыть"
+
+#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52
+#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364
+msgid "Clear"
+msgstr "ОчиÑтить"
+
+#: gtk_ardour/automation_time_axis.cc:474
+#, fuzzy
+msgid "State"
+msgstr "Ðачало"
+
+#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49
+msgid "Input Connections"
+msgstr "Входные ÑоединениÑ"
+
+#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48
+msgid "Output Connections"
+msgstr "Выходные ÑоединениÑ"
+
+#: gtk_ardour/connection_editor.cc:49
+#, fuzzy
+msgid "New Input"
+msgstr "новый вход"
+
+#: gtk_ardour/connection_editor.cc:50
+#, fuzzy
+msgid "New Output"
+msgstr "новый выход"
+
+#: gtk_ardour/connection_editor.cc:51
+#, fuzzy
+msgid "Delete"
+msgstr "удалить"
+
+#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96
+#, fuzzy
+msgid "Add Port"
+msgstr "добавить порт"
+
+#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105
+#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786
+#, fuzzy
+msgid "Rescan"
+msgstr "обновить"
+
+#: gtk_ardour/connection_editor.cc:101
+msgid "Available Ports"
+msgstr "ДоÑтупные порты"
+
+#: gtk_ardour/connection_editor.cc:183
+msgid "ardour: connections"
+msgstr "ardour: ÑоединениÑ"
+
+#: gtk_ardour/connection_editor.cc:513
+#, c-format
+msgid "in %d"
+msgstr "в %d"
+
+#: gtk_ardour/connection_editor.cc:644
+msgid "Name for new connection:"
+msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ ÑоединениÑ:"
+
+#: gtk_ardour/crossfade_edit.cc:71
+#, fuzzy
+msgid "crossfade editor"
+msgstr "редактировать введение в уровень"
+
+#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449
+#, fuzzy
+msgid "Reset"
+msgstr "ОгромнаÑ"
+
+#: gtk_ardour/crossfade_edit.cc:78
+#, fuzzy
+msgid "Fade"
+msgstr "Затухание"
+
+#: gtk_ardour/crossfade_edit.cc:79
+#, fuzzy
+msgid "Out (dry)"
+msgstr "в %d"
+
+#: gtk_ardour/crossfade_edit.cc:80
+#, fuzzy
+msgid "Out"
+msgstr "Выходов"
+
+#: gtk_ardour/crossfade_edit.cc:81
+#, fuzzy
+msgid "In (dry)"
+msgstr "в %d"
+
+#: gtk_ardour/crossfade_edit.cc:82
+msgid "In"
+msgstr ""
+
+#: gtk_ardour/crossfade_edit.cc:84
+#, fuzzy
+msgid "With Pre-roll"
+msgstr "откат"
+
+#: gtk_ardour/crossfade_edit.cc:85
+#, fuzzy
+msgid "With Post-roll"
+msgstr "накат"
+
+#: gtk_ardour/crossfade_edit.cc:93
+#, fuzzy
+msgid "Fade In"
+msgstr "Затухание"
+
+#: gtk_ardour/crossfade_edit.cc:94
+#, fuzzy
+msgid "Fade Out"
+msgstr "Затухание"
+
+#: gtk_ardour/crossfade_edit.cc:98
+#, fuzzy
+msgid "ardour: x-fade edit"
+msgstr "ardour: редактор"
+
+#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311
+#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189
+msgid "Audition"
+msgstr "Ðудит"
+
+#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804
+msgid "Regions/name"
+msgstr "ОблаÑти/имÑ"
+
+#: gtk_ardour/editor.cc:108
+msgid "Chunks"
+msgstr "Фрагменты"
+
+#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079
+msgid "Slide"
+msgstr "Скольжение"
+
+#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077
+msgid "Splice"
+msgstr "Стыковка"
+
+#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136
+#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96
+#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977
+msgid "None"
+msgstr "Ðет"
+
+#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124
+#, fuzzy
+msgid "CD Frames"
+msgstr "Кадр"
+
+#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126
+#, fuzzy
+msgid "SMPTE Frames"
+msgstr "SMPTE Кадры/Секунды"
+
+#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128
+#, fuzzy
+msgid "SMPTE Seconds"
+msgstr "SMPTE Кадры/Секунды"
+
+#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130
+msgid "SMPTE Minutes"
+msgstr ""
+
+#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132
+#, fuzzy
+msgid "Seconds"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134
+#, fuzzy
+msgid "Minutes"
+msgstr "Главные выходы"
+
+#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106
+msgid "Beats/32"
+msgstr "долÑм/32"
+
+#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104
+msgid "Beats/16"
+msgstr "долÑм/16"
+
+#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102
+msgid "Beats/8"
+msgstr "долÑм/8"
+
+#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100
+msgid "Beats/4"
+msgstr "долÑм/4"
+
+#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098
+msgid "Beats/3"
+msgstr "долÑм/3"
+
+#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108
+msgid "Beats"
+msgstr "долÑм"
+
+#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110
+msgid "Bars"
+msgstr "тактам"
+
+#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112
+msgid "Marks"
+msgstr "маркерам"
+
+#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114
+#: gtk_ardour/editor.cc:4182
+msgid "Edit Cursor"
+msgstr "курÑору"
+
+#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116
+msgid "Region starts"
+msgstr "нач. облаÑтей"
+
+#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118
+msgid "Region ends"
+msgstr "оконч. облаÑтей"
+
+#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122
+msgid "Region syncs"
+msgstr ""
+
+#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120
+msgid "Region bounds"
+msgstr ""
+
+#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153
+#: gtk_ardour/time_axis_view.cc:449
+msgid "Normal"
+msgstr "Ðорм."
+
+#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155
+msgid "Magnetic"
+msgstr "Магн."
+
+#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174
+#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237
+msgid "Left"
+msgstr "лев. краю"
+
+#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176
+#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238
+msgid "Right"
+msgstr "прав. краю"
+
+#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178
+msgid "Center"
+msgstr "центру"
+
+#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180
+msgid "Playhead"
+msgstr "указателю"
+
+#: gtk_ardour/editor.cc:201
+msgid "Mins:Secs"
+msgstr "Мин:Сек"
+
+#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353
+msgid "Frames"
+msgstr "Кадр"
+
+#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373
+msgid "Tempo"
+msgstr "Темп"
+
+#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367
+msgid "Meter"
+msgstr "Размер"
+
+#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379
+msgid "Location Markers"
+msgstr "Маркеры интервалов"
+
+#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385
+msgid "Range Markers"
+msgstr ""
+
+#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391
+msgid "Loop/Punch Ranges"
+msgstr ""
+
+#: gtk_ardour/editor.cc:221
+msgid ""
+"editor\n"
+"mixer"
+msgstr ""
+"редактор\n"
+"микшер"
+
+#: gtk_ardour/editor.cc:232
+msgid "range"
+msgstr "выделÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:233
+msgid "object"
+msgstr "объект"
+
+#: gtk_ardour/editor.cc:235
+msgid "zoom"
+msgstr "маÑштаб"
+
+#: gtk_ardour/editor.cc:236
+msgid "timefx"
+msgstr "Ñффект"
+
+#: gtk_ardour/editor.cc:237
+msgid "listen"
+msgstr ""
+
+#: gtk_ardour/editor.cc:239
+msgid "mode"
+msgstr "режим"
+
+#: gtk_ardour/editor.cc:240
+msgid "automation"
+msgstr "автомат"
+
+#: gtk_ardour/editor.cc:242
+msgid "Edit Mode"
+msgstr "Режим редактированиÑ"
+
+#: gtk_ardour/editor.cc:243
+msgid "Snap To"
+msgstr "ПривÑзка к"
+
+#: gtk_ardour/editor.cc:244
+msgid "Snap Mode"
+msgstr "ПривÑзка к"
+
+#: gtk_ardour/editor.cc:245
+msgid "Zoom Focus"
+msgstr "МаÑштабировать к"
+
+#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364
+#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579
+msgid "Nudge"
+msgstr ""
+
+#: gtk_ardour/editor.cc:511
+msgid "Zoom in"
+msgstr "Увеличить"
+
+#: gtk_ardour/editor.cc:512
+msgid "Zoom out"
+msgstr "Уменьшить"
+
+#: gtk_ardour/editor.cc:517
+msgid "Zoom to session"
+msgstr "Показать вÑÑ‘"
+
+#: gtk_ardour/editor.cc:536
+msgid "Zoom Span"
+msgstr "ОблаÑÑ‚ÑŒ проÑмотра"
+
+#: gtk_ardour/editor.cc:566
+msgid "Edit Groups"
+msgstr ""
+"Ред.\n"
+"группы"
+
+#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142
+msgid "-all-"
+msgstr "-вÑе-"
+
+#: gtk_ardour/editor.cc:718
+msgid "Nudge region/selection forwards"
+msgstr ""
+
+#: gtk_ardour/editor.cc:719
+msgid "Nudge region/selection backwards"
+msgstr ""
+
+#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308
+msgid "ardour: editor"
+msgstr "ardour: редактор"
+
+#: gtk_ardour/editor.cc:729
+msgid "ardour_editor"
+msgstr "ardour_редактор"
+
+#: gtk_ardour/editor.cc:846
+msgid "VerboseCanvasCursor"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1405
+msgid "FirstActionMessage"
+msgstr ""
+
+#: gtk_ardour/editor.cc:1407
+msgid "Start a new session\n"
+msgstr "Ðачать новую ÑеÑÑию\n"
+
+#: gtk_ardour/editor.cc:1408
+msgid "via Session menu"
+msgstr "в меню \"СеÑÑиÑ\""
+
+#: gtk_ardour/editor.cc:1703
+msgid "ardour: editor: "
+msgstr "ardour: редактор: "
+
+#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796
+#: gtk_ardour/editor_markers.cc:797
+msgid "Loop"
+msgstr "Кольцо"
+
+#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810
+#: gtk_ardour/editor_markers.cc:823
+msgid "Punch"
+msgstr "Врезка"
+
+#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688
+#, fuzzy
+msgid "programming error: fade in canvas item has no regionview data pointer!"
+msgstr "ошибка в программе: line canvas item has no line pointer!"
+
+#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986
+#: gtk_ardour/redirect_box.cc:401
+msgid "Deactivate"
+msgstr "Деактивировать"
+
+#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988
+#: gtk_ardour/redirect_box.cc:398
+msgid "Activate"
+msgstr "Ðктивировать"
+
+#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993
+#, fuzzy
+msgid "Linear"
+msgstr "линейное"
+
+#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994
+#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734
+#: gtk_ardour/option_editor.cc:796
+#, fuzzy
+msgid "Slowest"
+msgstr "Меньше"
+
+#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995
+#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735
+#: gtk_ardour/option_editor.cc:798
+#, fuzzy
+msgid "Slow"
+msgstr "Соло"
+
+#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996
+#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737
+#: gtk_ardour/option_editor.cc:802
+#, fuzzy
+msgid "Fast"
+msgstr "Затухание"
+
+#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997
+#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739
+#: gtk_ardour/option_editor.cc:806
+#, fuzzy
+msgid "Fastest"
+msgstr "быÑтрое"
+
+#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113
+msgid "Freeze"
+msgstr "Заморозить"
+
+#: gtk_ardour/editor.cc:2109
+msgid "Unfreeze"
+msgstr "Разморозить"
+
+#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328
+#, fuzzy
+msgid "Unmute"
+msgstr "тихо"
+
+#: gtk_ardour/editor.cc:2247
+msgid "Convert to short"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2249
+msgid "Convert to full"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2260
+#, fuzzy
+msgid "Crossfade"
+msgstr "КроÑÑфейд"
+
+#: gtk_ardour/editor.cc:2303
+msgid "Popup region editor"
+msgstr "Открыть редактор облаÑти"
+
+#: gtk_ardour/editor.cc:2304
+#, fuzzy
+msgid "Raise to top layer"
+msgstr "ПоднÑÑ‚ÑŒ облаÑÑ‚ÑŒ в верхний Ñлой"
+
+#: gtk_ardour/editor.cc:2305
+#, fuzzy
+msgid "Lower to bottom layer"
+msgstr "ОпуÑтить облаÑÑ‚ÑŒ в нижний Ñлой"
+
+#: gtk_ardour/editor.cc:2307
+msgid "Define sync point"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2308
+msgid "Remove sync point"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2313
+#, fuzzy
+msgid "Bounce"
+msgstr "СвеÑти выделенное"
+
+#: gtk_ardour/editor.cc:2323
+msgid "Lock"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2324
+msgid "Unlock"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2334
+msgid "Original position"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2340
+msgid "Toggle envelope visibility"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2341
+msgid "Toggle envelope active"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2345
+#, fuzzy
+msgid "DeNormalize"
+msgstr "Ðорм."
+
+#: gtk_ardour/editor.cc:2347
+msgid "Normalize"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2350
+msgid "Reverse"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2359
+msgid "Nudge fwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2360
+msgid "Nudge bwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2361
+msgid "Nudge fwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2362
+msgid "Nudge bwd by capture offset"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2371
+msgid "Start to edit cursor"
+msgstr "От начала до курÑора"
+
+#: gtk_ardour/editor.cc:2372
+msgid "Edit cursor to end"
+msgstr "От курÑора до конца"
+
+#: gtk_ardour/editor.cc:2374
+msgid "Trim"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2377
+msgid "Split"
+msgstr "Склеить"
+
+#: gtk_ardour/editor.cc:2380
+msgid "Make mono regions"
+msgstr "Создать моно-облаÑти"
+
+#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428
+msgid "Duplicate"
+msgstr "Размножить"
+
+#: gtk_ardour/editor.cc:2384
+msgid "Fill Track"
+msgstr "Заполнить трек"
+
+#: gtk_ardour/editor.cc:2388
+msgid "Destroy"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2418
+#, fuzzy
+msgid "Play range"
+msgstr "ВоÑпроизвеÑти \"кольцо\""
+
+#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446
+msgid "Loop range"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2421
+#, fuzzy
+msgid "Create chunk from range"
+msgstr "Создать фрагмент из выделенного"
+
+#: gtk_ardour/editor.cc:2423
+msgid "Create Region"
+msgstr "Создать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2424
+msgid "Separate Region"
+msgstr "Разделить облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2425
+#, fuzzy
+msgid "Crop Region to range"
+msgstr "Обрезать облаÑÑ‚ÑŒ по выделенному"
+
+#: gtk_ardour/editor.cc:2426
+msgid "Bounce range"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2432
+#, fuzzy
+msgid "Fill range w/Region"
+msgstr "Создать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2434
+#, fuzzy
+msgid "Range"
+msgstr "выделÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538
+#, fuzzy
+msgid "Play from edit cursor"
+msgstr "ВоÑпроизвеÑти от курÑора"
+
+#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539
+msgid "Play from start"
+msgstr "ВоÑпроизвеÑти Ñ Ð½Ð°Ñ‡Ð°Ð»Ð°"
+
+#: gtk_ardour/editor.cc:2451
+#, fuzzy
+msgid "Play region"
+msgstr "ВоÑпроизвеÑти облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2453
+msgid "Loop Region"
+msgstr "\"Закольцевать\" облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540
+#: gtk_ardour/library_ui.cc:972
+msgid "Play"
+msgstr "ВоÑпроизвеÑти"
+
+#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548
+#, fuzzy
+msgid "Select All in track"
+msgstr "Выделить вÑÑ‘"
+
+#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549
+#, fuzzy
+msgid "Select All"
+msgstr "Выделить вÑÑ‘"
+
+#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550
+#, fuzzy
+msgid "Invert in track"
+msgstr "Скрыть трек"
+
+#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551
+#, fuzzy
+msgid "Invert"
+msgstr "Ðовый \"возврат\""
+
+#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553
+#, fuzzy
+msgid "Select loop range"
+msgstr "выбрать окно проÑмотра"
+
+#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554
+#, fuzzy
+msgid "Select punch range"
+msgstr "Выбрать текущий интервал"
+
+#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565
+#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369
+msgid "Cut"
+msgstr "Вырезать"
+
+#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566
+#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371
+msgid "Copy"
+msgstr "Копировать"
+
+#: gtk_ardour/editor.cc:2482
+#, fuzzy
+msgid "Paste at edit cursor"
+msgstr "От начала до курÑора"
+
+#: gtk_ardour/editor.cc:2483
+#, fuzzy
+msgid "Paste at mouse"
+msgstr "иÑпользовать маÑтер-выходы"
+
+#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923
+msgid "Align"
+msgstr "ВыровнÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925
+msgid "Align Relative"
+msgstr "ВыровнÑÑ‚ÑŒ отноÑительно"
+
+#: gtk_ardour/editor.cc:2492
+msgid "Insert chunk"
+msgstr "Ð’Ñтавить фрагмент"
+
+#: gtk_ardour/editor.cc:2496
+#, fuzzy
+msgid "New Region from range"
+msgstr "Создать облаÑÑ‚ÑŒ из выделенного"
+
+#: gtk_ardour/editor.cc:2497
+#, fuzzy
+msgid "Separate Range"
+msgstr "Разделить облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2507
+msgid "Insert Region"
+msgstr "Ð’Ñтавить облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:2508
+msgid "Insert external sndfile"
+msgstr "Ð’Ñтавить внешний аудиофайл"
+
+#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438
+msgid "Import"
+msgstr "Импорт"
+
+#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574
+msgid "Nudge entire track fwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575
+msgid "Nudge track after edit cursor fwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576
+msgid "Nudge entire track bwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577
+msgid "Nudge track after edit cursor bwd"
+msgstr ""
+
+#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920
+#: gtk_ardour/redirect_box.cc:373
+msgid "Paste"
+msgstr "Ð’Ñтавить"
+
+#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645
+#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799
+msgid "add marker"
+msgstr "добавить маркер"
+
+#: gtk_ardour/editor.cc:3084
+msgid "select/move objects"
+msgstr "выбирать/двигать объекты"
+
+#: gtk_ardour/editor.cc:3085
+msgid "select/move ranges"
+msgstr "выбирать/двигать диапазоны"
+
+#: gtk_ardour/editor.cc:3086
+msgid "draw gain automation"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3087
+msgid "select zoom range"
+msgstr "выбрать окно проÑмотра"
+
+#: gtk_ardour/editor.cc:3088
+msgid "stretch/shrink regions"
+msgstr "раÑÑ‚Ñнуть/Ñжать облаÑти"
+
+#: gtk_ardour/editor.cc:3089
+#, fuzzy
+msgid "listen to specific regions"
+msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:3213
+msgid "Start:"
+msgstr "Ðачало:"
+
+#: gtk_ardour/editor.cc:3214
+msgid "End:"
+msgstr "Конец:"
+
+#: gtk_ardour/editor.cc:3215
+msgid "Edit:"
+msgstr "Редактировать:"
+
+#: gtk_ardour/editor.cc:3429
+msgid "incorrectly formatted URI list, ignored"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3611
+#, fuzzy
+msgid "set selected trackview"
+msgstr "Ð’Ñтавить выбранное"
+
+#: gtk_ardour/editor.cc:3647
+#, fuzzy
+msgid "set selected control point"
+msgstr "иÑпользовать контрольные выходы"
+
+#: gtk_ardour/editor.cc:3719
+#, fuzzy
+msgid "set selected regionview"
+msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835
+#, fuzzy
+msgid "set selected regions"
+msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:3891
+msgid "Undo"
+msgstr "Отменить"
+
+#: gtk_ardour/editor.cc:3893
+msgid "Undo (%1)"
+msgstr "Отменить (%1)"
+
+#: gtk_ardour/editor.cc:3903
+msgid "Redo"
+msgstr "Вернуть"
+
+#: gtk_ardour/editor.cc:3905
+msgid "Redo (%1)"
+msgstr "Вернуть (%1)"
+
+#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946
+msgid "... as new track"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947
+#, fuzzy
+msgid "... as new region"
+msgstr "проÑлушать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452
+msgid "Import audio (copy)"
+msgstr "Импортировать аудио (копировать)"
+
+#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457
+msgid "Embed audio (link)"
+msgstr ""
+
+#: gtk_ardour/editor.cc:3953
+msgid "Remove last capture"
+msgstr "Удалить поÑледнюю запиÑÑŒ"
+
+#: gtk_ardour/editor.cc:3974
+msgid "Duplicate how many times?"
+msgstr "КоличеÑтво повторов?"
+
+#: gtk_ardour/editor.cc:4550
+msgid ""
+"Playlist %1 is currently unused.\n"
+"If left alone, no audio files used by it will be cleaned.\n"
+"If deleted, audio files used by it alone by will cleaned."
+msgstr ""
+
+#: gtk_ardour/editor.cc:4555
+#, fuzzy
+msgid "Delete playlist"
+msgstr "Ð˜Ð¼Ñ Ñнимка"
+
+#: gtk_ardour/editor.cc:4556
+#, fuzzy
+msgid "Keep playlist"
+msgstr "Ð˜Ð¼Ñ Ñнимка"
+
+#: gtk_ardour/editor.cc:4557
+#, fuzzy
+msgid "Cancel cleanup"
+msgstr "ОчиÑтка"
+
+#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258
+#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290
+msgid ""
+"programming error: control point canvas item has no control point object "
+"pointer!"
+msgstr ""
+"ошибка в программе: control point canvas item has no control point object "
+"pointer!"
+
+#: gtk_ardour/editor_canvas_events.cc:717
+msgid "programming error: line canvas item has no line object pointer!"
+msgstr "ошибка в программе: line canvas item has no line object pointer!"
+
+#: gtk_ardour/editor_canvas_events.cc:744
+#: gtk_ardour/editor_canvas_events.cc:784
+#: gtk_ardour/editor_canvas_events.cc:823
+msgid "programming error: no \"rect\" pointer associated with selection item"
+msgstr "ошибка в программе: no \"rect\" pointer associated with selection item"
+
+#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298
+#: gtk_ardour/mixer_ui.cc:670
+msgid "Show All"
+msgstr "Показать вÑÑ‘"
+
+#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299
+#: gtk_ardour/mixer_ui.cc:671
+msgid "Hide All"
+msgstr "Скрыть вÑÑ‘"
+
+#: gtk_ardour/editor_edit_groups.cc:98
+msgid "Name for new edit group"
+msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð¹ группы"
+
+#: gtk_ardour/editor_export_audio.cc:60
+msgid ""
+"There is no range to export.\n"
+"\n"
+"Select a range using the range mouse mode"
+msgstr ""
+
+#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707
+msgid "programming error: no ImageFrameView selected"
+msgstr "ошибка в программе: no ImageFrameView selected"
+
+#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930
+msgid "programming error: no MarkerView selected"
+msgstr "ошибка в программе: no MarkerView selected"
+
+#: gtk_ardour/editor_keys.cc:187
+#, fuzzy
+msgid "keyboard selection"
+msgstr "Выделить по интервалу"
+
+#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376
+#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526
+#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584
+#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650
+#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700
+#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960
+#: gtk_ardour/editor_mouse.cc:4075
+msgid "programming error: marker canvas item has no marker object pointer!"
+msgstr "ошибка в программе: marker canvas item has no marker object pointer!"
+
+#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681
+msgid "remove marker"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494
+msgid "Locate to"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495
+msgid "Play from"
+msgstr "ВоÑпроизвеÑти от"
+
+#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496
+#, fuzzy
+msgid "Set from playhead"
+msgstr "ВоÑпроизвеÑти от указателÑ"
+
+#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497
+#, fuzzy
+msgid "Set from range"
+msgstr "выбрать окно проÑмотра"
+
+#: gtk_ardour/editor_markers.cc:479
+msgid "Set Loop Range"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:480
+msgid "Set Punch Range"
+msgstr ""
+
+#: gtk_ardour/editor_markers.cc:736
+msgid "ardour: rename mark"
+msgstr "ardour: переименовать маркер"
+
+#: gtk_ardour/editor_markers.cc:738
+#, fuzzy
+msgid "ardour: rename range"
+msgstr "ardour: переименовать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_markers.cc:792
+#, fuzzy
+msgid "set loop range"
+msgstr "выбрать окно проÑмотра"
+
+#: gtk_ardour/editor_markers.cc:818
+#, fuzzy
+msgid "set punch range"
+msgstr "Выбрать текущий интервал"
+
+#: gtk_ardour/editor_mouse.cc:99
+msgid "Editor::event_frame() used on unhandled event type %1"
+msgstr "Editor::event_frame() used on unhandled event type %1"
+
+#: gtk_ardour/editor_mouse.cc:1555
+msgid "programming error: start_grab called without drag item"
+msgstr "ошибка в программе: start_grab called without drag item"
+
+#: gtk_ardour/editor_mouse.cc:1760
+#, fuzzy
+msgid "change fade in length"
+msgstr "редактировать введение в уровень"
+
+#: gtk_ardour/editor_mouse.cc:1778
+#, fuzzy
+msgid "programming error: fade out canvas item has no regionview data pointer!"
+msgstr "ошибка в программе: cursor canvas item has no cursor data pointer!"
+
+#: gtk_ardour/editor_mouse.cc:1852
+#, fuzzy
+msgid "change fade out length"
+msgstr "редактировать Ñведение в ноль"
+
+#: gtk_ardour/editor_mouse.cc:1871
+msgid "programming error: cursor canvas item has no cursor data pointer!"
+msgstr "ошибка в программе: cursor canvas item has no cursor data pointer!"
+
+#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470
+msgid ""
+"programming error: meter marker canvas item has no marker object pointer!"
+msgstr ""
+"ошибка в программе: meter marker canvas item has no marker object pointer!"
+
+#: gtk_ardour/editor_mouse.cc:2163
+msgid "move meter mark"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335
+#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439
+msgid ""
+"programming error: tempo marker canvas item has no marker object pointer!"
+msgstr ""
+"ошибка в программе: tempo marker canvas item has no marker object pointer!"
+
+#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340
+#: gtk_ardour/editor_tempodisplay.cc:425
+msgid "programming error: marker for tempo is not a tempo marker!"
+msgstr "ошибка в программе: marker for tempo is not a tempo marker!"
+
+#: gtk_ardour/editor_mouse.cc:2245
+msgid "move tempo mark"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2388
+msgid "programming error: line canvas item has no line pointer!"
+msgstr "ошибка в программе: line canvas item has no line pointer!"
+
+#: gtk_ardour/editor_mouse.cc:2497
+#, fuzzy
+msgid "move region(s)"
+msgstr "Создать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_mouse.cc:2509
+msgid "Drag region copy"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:2579
+#, fuzzy
+msgid "copy region(s)"
+msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_mouse.cc:2612
+#, fuzzy
+msgid "Drag region brush"
+msgstr "проÑлушать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_mouse.cc:3425
+#, fuzzy
+msgid "selection grab"
+msgstr "Выделенное"
+
+#: gtk_ardour/editor_mouse.cc:3571
+#, fuzzy
+msgid "range selection"
+msgstr "ВоÑпроизвеÑти выделенное"
+
+#: gtk_ardour/editor_mouse.cc:3587
+#, fuzzy
+msgid "trim selection start"
+msgstr "Выделить по интервалу"
+
+#: gtk_ardour/editor_mouse.cc:3603
+#, fuzzy
+msgid "trim selection end"
+msgstr "Выделить по интервалу"
+
+#: gtk_ardour/editor_mouse.cc:3620
+#, fuzzy
+msgid "move selection"
+msgstr "СвеÑти выделенное"
+
+#: gtk_ardour/editor_mouse.cc:3995
+#, fuzzy
+msgid "Start point trim"
+msgstr "От начала до курÑора"
+
+#: gtk_ardour/editor_mouse.cc:4023
+msgid "End point trim"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:4062
+msgid "trimmed region"
+msgstr ""
+
+#: gtk_ardour/editor_mouse.cc:4203
+#, fuzzy
+msgid "new range marker"
+msgstr "Маркеры интервалов"
+
+#: gtk_ardour/editor_mouse.cc:4422
+#, fuzzy
+msgid "select regions"
+msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_mouse.cc:4451
+msgid "Name for region:"
+msgstr "Ð˜Ð¼Ñ Ð¾Ð±Ð»Ð°Ñти: "
+
+#: gtk_ardour/editor_mouse.cc:4517
+#, fuzzy
+msgid "timestretch"
+msgstr "ardour: Ñффект timestretch"
+
+#: gtk_ardour/editor_ops.cc:117
+#, fuzzy
+msgid "split"
+msgstr "Склеить"
+
+#: gtk_ardour/editor_ops.cc:153
+#, fuzzy
+msgid "remove region"
+msgstr "Создать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:172
+msgid ""
+" This is destructive, will possibly delete audio files\n"
+"It cannot be undone\n"
+"Do you really want to destroy %1 ?"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "these regions"
+msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:176
+#, fuzzy
+msgid "this region"
+msgstr "отключить воÑпроизведение Ñтой облаÑти"
+
+#: gtk_ardour/editor_ops.cc:179
+#, fuzzy
+msgid "Yes, destroy them."
+msgstr "Да"
+
+#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434
+msgid "Yes, destroy it."
+msgstr "Да"
+
+#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435
+#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300
+msgid "No, do nothing."
+msgstr "Ðет"
+
+#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307
+#, fuzzy
+msgid "extend selection"
+msgstr "Выделить по интервалу"
+
+#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357
+#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427
+msgid "nudge forward"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:491
+msgid "build_region_boundary_cache called with snap_type = %1"
+msgstr "build_region_boundary_cache called with snap_type = %1"
+
+#: gtk_ardour/editor_ops.cc:1305
+#, fuzzy
+msgid "set selection from range"
+msgstr "Создать облаÑÑ‚ÑŒ из выделенного"
+
+#: gtk_ardour/editor_ops.cc:1421
+msgid "clear markers"
+msgstr "очиÑтить маркеры"
+
+#: gtk_ardour/editor_ops.cc:1433
+msgid "clear ranges"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1452
+msgid "clear locations"
+msgstr "очиÑтить интервалы"
+
+#: gtk_ardour/editor_ops.cc:1503
+#, fuzzy
+msgid "insert dragged region"
+msgstr "Ð’Ñтавить облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:1538
+#, fuzzy
+msgid "insert region"
+msgstr "Ð’Ñтавить облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:1744
+msgid "ardour: rename region"
+msgstr "ardour: переименовать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:1891
+msgid "You can't import an audiofile until you have a session loaded."
+msgstr "Ð’Ñ‹ не можете импортировать аудиофайл пока ÑеÑÑÐ¸Ñ Ð½Ðµ загружена."
+
+#: gtk_ardour/editor_ops.cc:1901
+#, fuzzy
+msgid "Import selected as tracks"
+msgstr ""
+"Импортировать\n"
+"выбранное"
+
+#: gtk_ardour/editor_ops.cc:1904
+#, fuzzy
+msgid "Import selected to region list"
+msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:1933
+msgid "ardour: audio import in progress"
+msgstr "ardour: ... идёт импорт аудио"
+
+#: gtk_ardour/editor_ops.cc:1937
+msgid "Cancel Import"
+msgstr "Отменить импорт"
+
+#: gtk_ardour/editor_ops.cc:1944
+#, fuzzy
+msgid "ardour: importing %1"
+msgstr "ardour: ÑкÑпорт"
+
+#: gtk_ardour/editor_ops.cc:1990
+msgid "%1 it anyway"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1996
+#, fuzzy
+msgid "Don't %1 it"
+msgstr "Отмена"
+
+#: gtk_ardour/editor_ops.cc:1997
+msgid "%1 all without questions"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:1998
+#, fuzzy
+msgid "Cancel entire import"
+msgstr "Отменить импорт"
+
+#: gtk_ardour/editor_ops.cc:2004
+#, fuzzy
+msgid ""
+"%1\n"
+"This audiofile's sample rate doesn't match the session sample rate!"
+msgstr ""
+"Выбранный аудиофайл имеет чаÑтоту диÑкретизации данных\n"
+"отличную от текущей ÑеÑÑии!"
+
+#: gtk_ardour/editor_ops.cc:2032
+msgid "You can't embed an audiofile until you have a session loaded."
+msgstr "Ð’Ñ‹ не можете импортировать аудиофайл пока ÑеÑÑÐ¸Ñ Ð½Ðµ загружена."
+
+#: gtk_ardour/editor_ops.cc:2039
+msgid "Add to External Region list"
+msgstr "Добавить во внешний ÑпиÑок облаÑтей"
+
+#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210
+#: gtk_ardour/editor_ops.cc:2286
+msgid "Editor: cannot open file \"%1\" (%2)"
+msgstr "Редактор: не удалоÑÑŒ открыть файл \"%1\" (%2)"
+
+#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312
+msgid "could not open %1"
+msgstr "не удалоÑÑŒ открыть %1"
+
+#: gtk_ardour/editor_ops.cc:2171
+#, fuzzy
+msgid "Insert selected as new tracks"
+msgstr "Ð’Ñтавить выбранное"
+
+#: gtk_ardour/editor_ops.cc:2186
+msgid "Insert selected"
+msgstr "Ð’Ñтавить выбранное"
+
+#: gtk_ardour/editor_ops.cc:2327
+#, fuzzy
+msgid "insert sndfile"
+msgstr "Ð’Ñтавить внешний аудиофайл"
+
+#: gtk_ardour/editor_ops.cc:2464
+#, fuzzy
+msgid "separate"
+msgstr "Разделить облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:2528
+#, fuzzy
+msgid "trim to selection"
+msgstr "Выделить по интервалу"
+
+#: gtk_ardour/editor_ops.cc:2568
+msgid "region fill"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2626
+#, fuzzy
+msgid "fill selection"
+msgstr "Закольцевать выделенное"
+
+#: gtk_ardour/editor_ops.cc:2650
+msgid "Place the edit cursor at the desired sync point"
+msgstr "ПомеÑтите курÑор на точку Ñинхронизации"
+
+#: gtk_ardour/editor_ops.cc:2656
+#, fuzzy
+msgid "set sync from edit cursor"
+msgstr "ВоÑпроизвеÑти от курÑора"
+
+#: gtk_ardour/editor_ops.cc:2668
+msgid "remove sync"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2682
+msgid "naturalize"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:2746
+#, fuzzy
+msgid "align selection (relative)"
+msgstr "ВыровнÑÑ‚ÑŒ отноÑительно"
+
+#: gtk_ardour/editor_ops.cc:2774
+#, fuzzy
+msgid "align selection"
+msgstr "СвеÑти выделенное"
+
+#: gtk_ardour/editor_ops.cc:2786
+#, fuzzy
+msgid "align region"
+msgstr "проÑлушать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858
+#, fuzzy
+msgid "trim to edit"
+msgstr "От начала до курÑора"
+
+#: gtk_ardour/editor_ops.cc:2909
+#, fuzzy
+msgid "ardour: freeze"
+msgstr "ardour: "
+
+#: gtk_ardour/editor_ops.cc:2914
+#, fuzzy
+msgid "Cancel Freeze"
+msgstr "Отмена"
+
+#: gtk_ardour/editor_ops.cc:2951
+#, fuzzy
+msgid "bounce range"
+msgstr "Выбрать текущий интервал"
+
+#: gtk_ardour/editor_ops.cc:3004
+msgid "cut"
+msgstr "вырезать"
+
+#: gtk_ardour/editor_ops.cc:3007
+msgid "copy"
+msgstr "копировать"
+
+#: gtk_ardour/editor_ops.cc:3020
+msgid " objects"
+msgstr "объекты"
+
+#: gtk_ardour/editor_ops.cc:3046
+msgid " range"
+msgstr ""
+
+#: gtk_ardour/editor_ops.cc:3201
+#, fuzzy
+msgid "paste"
+msgstr "Ð’Ñтавить"
+
+#: gtk_ardour/editor_ops.cc:3236
+#, fuzzy
+msgid "paste chunk"
+msgstr "Создать фрагмент"
+
+#: gtk_ardour/editor_ops.cc:3276
+#, fuzzy
+msgid "duplicate region"
+msgstr "Разделить облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/editor_ops.cc:3309
+#, fuzzy
+msgid "duplicate selection"
+msgstr "СвеÑти выделенное"
+
+#: gtk_ardour/editor_ops.cc:3349
+#, fuzzy
+msgid "clear playlist"
+msgstr "Ð˜Ð¼Ñ Ñнимка"
+
+#: gtk_ardour/editor_ops.cc:3378
+#, fuzzy
+msgid "nudge track"
+msgstr "Скрыть трек"
+
+#: gtk_ardour/editor_ops.cc:3431
+msgid ""
+"Do you really want to destroy the last capture?\n"
+"(This is destructive and cannot be undone)"
+msgstr ""
+"ПоÑледнюю запиÑÑŒ будет удалена. Ð’Ñ‹ уверены?\n"
+"(отмена операции невозможна)"
+
+#: gtk_ardour/editor_ops.cc:3463
+#, fuzzy
+msgid "normalize"
+msgstr "Ðорм."
+
+#: gtk_ardour/editor_ops.cc:3510
+msgid "reverse regions"
+msgstr ""
+
+#: gtk_ardour/editor_region_list.cc:223
+#, fuzzy
+msgid "hidden"
+msgstr "Скрытый"
+
+#: gtk_ardour/editor_region_list.cc:408
+msgid "Show all"
+msgstr "Показать вÑÑ‘"
+
+#: gtk_ardour/editor_region_list.cc:417
+msgid "Ascending"
+msgstr "по возраÑтанию"
+
+#: gtk_ardour/editor_region_list.cc:419
+msgid "Descending"
+msgstr "по убыванию"
+
+#: gtk_ardour/editor_region_list.cc:423
+msgid "By Region Name"
+msgstr "по имени облаÑти"
+
+#: gtk_ardour/editor_region_list.cc:425
+msgid "By Region Length"
+msgstr "по длине облаÑти"
+
+#: gtk_ardour/editor_region_list.cc:427
+msgid "By Region Position"
+msgstr "по раÑположению облаÑти"
+
+#: gtk_ardour/editor_region_list.cc:429
+msgid "By Region Timestamp"
+msgstr "по времени ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±Ð»Ð°Ñти"
+
+#: gtk_ardour/editor_region_list.cc:431
+msgid "By Region Start in File"
+msgstr "по началу облаÑти в файле"
+
+#: gtk_ardour/editor_region_list.cc:433
+msgid "By Region End in File"
+msgstr "по концу облаÑти в файле"
+
+#: gtk_ardour/editor_region_list.cc:435
+msgid "By Source File Name"
+msgstr "по имени файла"
+
+#: gtk_ardour/editor_region_list.cc:437
+msgid "By Source File Length"
+msgstr "по размеру файла"
+
+#: gtk_ardour/editor_region_list.cc:439
+msgid "By Source File Creation Date"
+msgstr "по дате ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸Ñходного файла"
+
+#: gtk_ardour/editor_region_list.cc:441
+msgid "By Source Filesystem"
+msgstr "по раÑположению файла"
+
+#: gtk_ardour/editor_region_list.cc:444
+msgid "Sorting"
+msgstr "Сортировка"
+
+#: gtk_ardour/editor_region_list.cc:808
+msgid "Regions/length"
+msgstr "ОблаÑти/длина"
+
+#: gtk_ardour/editor_region_list.cc:812
+msgid "Regions/position"
+msgstr "ОблаÑти/положение"
+
+#: gtk_ardour/editor_region_list.cc:816
+msgid "Regions/creation"
+msgstr "ОблаÑти/Ñоздание"
+
+#: gtk_ardour/editor_region_list.cc:820
+msgid "Regions/start"
+msgstr "ОблаÑти/начало"
+
+#: gtk_ardour/editor_region_list.cc:824
+msgid "Regions/end"
+msgstr "ОблаÑти/конец"
+
+#: gtk_ardour/editor_region_list.cc:828
+msgid "Regions/file name"
+msgstr "ОблаÑти/Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°"
+
+#: gtk_ardour/editor_region_list.cc:832
+msgid "Regions/file size"
+msgstr "ОблаÑти/размер файла"
+
+#: gtk_ardour/editor_region_list.cc:836
+msgid "Regions/file date"
+msgstr "ОблаÑти/дата файла"
+
+#: gtk_ardour/editor_region_list.cc:840
+msgid "Regions/file system"
+msgstr "ОблаÑти/Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема"
+
+#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73
+#: gtk_ardour/editor_route_list.cc:231
+msgid "editor"
+msgstr "редактор"
+
+#: gtk_ardour/editor_route_list.cc:300
+msgid "Show All AbstractTracks"
+msgstr "Показать вÑе треки"
+
+#: gtk_ardour/editor_route_list.cc:301
+msgid "Hide All AbstractTracks"
+msgstr "Скрыть вÑе треки"
+
+#: gtk_ardour/editor_route_list.cc:302
+msgid "Show All AudioBus"
+msgstr "Показать вÑе аудиошины"
+
+#: gtk_ardour/editor_route_list.cc:303
+msgid "Hide All AudioBus"
+msgstr "Скрыть вÑе аудиошины"
+
+#: gtk_ardour/editor_rulers.cc:311
+#, fuzzy
+msgid "New location marker"
+msgstr "Маркеры интервалов"
+
+#: gtk_ardour/editor_rulers.cc:312
+#, fuzzy
+msgid "Clear all locations"
+msgstr "очиÑтить интервалы"
+
+#: gtk_ardour/editor_rulers.cc:317
+#, fuzzy
+msgid "Clear all ranges"
+msgstr "ВоÑпроизвеÑти \"кольцо\""
+
+#: gtk_ardour/editor_rulers.cc:326
+#, fuzzy
+msgid "New Tempo"
+msgstr "Ðовый темп"
+
+#: gtk_ardour/editor_rulers.cc:327
+#, fuzzy
+msgid "Clear tempo"
+msgstr "Ðовый темп"
+
+#: gtk_ardour/editor_rulers.cc:332
+#, fuzzy
+msgid "New Meter"
+msgstr "Размер"
+
+#: gtk_ardour/editor_rulers.cc:333
+#, fuzzy
+msgid "Clear meter"
+msgstr "очиÑтить маркеры"
+
+#: gtk_ardour/editor_rulers.cc:341
+#, fuzzy
+msgid "Min:Secs"
+msgstr "Мин:Сек"
+
+#: gtk_ardour/editor_selection_list.cc:117
+msgid "name for chunk:"
+msgstr "Ð¸Ð¼Ñ Ñ„Ñ€Ð°Ð³Ð¼ÐµÐ½Ñ‚Ð°:"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Create chunk"
+msgstr "Создать фрагмент"
+
+#: gtk_ardour/editor_selection_list.cc:119
+msgid "Forget it"
+msgstr "Забыть"
+
+#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295
+msgid "add"
+msgstr "добавить"
+
+#: gtk_ardour/editor_tempodisplay.cc:276
+#, fuzzy
+msgid "add tempo mark"
+msgstr "добавить маркер"
+
+#: gtk_ardour/editor_tempodisplay.cc:318
+#, fuzzy
+msgid "add meter mark"
+msgstr "добавить маркер"
+
+#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383
+msgid "done"
+msgstr "готово"
+
+#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404
+msgid "replace tempo mark"
+msgstr ""
+
+#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475
+msgid "programming error: marker for meter is not a meter marker!"
+msgstr "ошибка в программе: marker for meter is not a meter marker!"
+
+#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487
+#, fuzzy
+msgid "remove tempo mark"
+msgstr "Да, удалить вÑÑ‘"
+
+#: gtk_ardour/editor_timefx.cc:50
+msgid "Quick but Ugly"
+msgstr "БыÑтро и грубо"
+
+#: gtk_ardour/editor_timefx.cc:51
+msgid "Skip Anti-aliasing"
+msgstr "Без фильтрации"
+
+#: gtk_ardour/editor_timefx.cc:53
+msgid "Stretch/Shrink it"
+msgstr "РаÑÑ‚Ñнуть/Сжать"
+
+#: gtk_ardour/editor_timefx.cc:57
+msgid "ardour: timestretch"
+msgstr "ardour: Ñффект timestretch"
+
+#: gtk_ardour/editor_timefx.cc:58
+msgid "TimeStretchDialog"
+msgstr "TimeStretchDialog"
+
+#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83
+#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85
+msgid "TimeStretchButton"
+msgstr "TimeStretchButton"
+
+#: gtk_ardour/editor_timefx.cc:86
+msgid "TimeStretchProgress"
+msgstr "TimeStretchProgress"
+
+#: gtk_ardour/editor_timefx.cc:151
+msgid "timestretch cannot be started - thread creation error"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410
+#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189
+msgid "22.05kHz"
+msgstr "22.05кГц"
+
+#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413
+#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949
+#: gtk_ardour/export_dialog.cc:1191
+msgid "44.1kHz"
+msgstr "44.1кГц"
+
+#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416
+#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193
+msgid "48kHz"
+msgstr "48кГц"
+
+#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419
+#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195
+msgid "88.2kHz"
+msgstr "88.2кГц"
+
+#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422
+#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197
+msgid "96kHz"
+msgstr "96кГц"
+
+#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425
+#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199
+msgid "192kHz"
+msgstr "192кГц"
+
+#: gtk_ardour/export_dialog.cc:73
+msgid "best"
+msgstr "выÑокое"
+
+#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964
+msgid "fastest"
+msgstr "быÑтрое"
+
+#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966
+msgid "linear"
+msgstr "линейное"
+
+#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968
+msgid "better"
+msgstr "нормальное"
+
+#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970
+msgid "intermediate"
+msgstr "Ñреднее"
+
+#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979
+msgid "Rectangular"
+msgstr "Rectangular"
+
+#: gtk_ardour/export_dialog.cc:84
+msgid "Shaped Noise"
+msgstr "Shaped Noise"
+
+#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981
+msgid "Triangular"
+msgstr "Triangular"
+
+#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336
+msgid "stereo"
+msgstr "Ñтерео"
+
+#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497
+#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219
+#: gtk_ardour/utils.cc:334
+msgid "mono"
+msgstr "моно"
+
+#: gtk_ardour/export_dialog.cc:97
+msgid "CUE"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:98
+msgid "TOC"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:106
+msgid "FORMAT"
+msgstr "ФОРМÐТ"
+
+#: gtk_ardour/export_dialog.cc:107
+msgid "SAMPLE RATE"
+msgstr "ЧÐСТОТРДИСКРЕТИЗÐЦИИ"
+
+#: gtk_ardour/export_dialog.cc:108
+msgid "CONVERSION QUALITY"
+msgstr "КÐЧЕСТВО ПРЕОБРÐЗОВÐÐИЯ"
+
+#: gtk_ardour/export_dialog.cc:109
+msgid "DITHER TYPE"
+msgstr "ТИП ПОДМЕШИВÐЕМОГО ШУМÐ"
+
+#: gtk_ardour/export_dialog.cc:110
+#, fuzzy
+msgid "CD MARKER FILE TYPE"
+msgstr "ТИП ФÐЙЛÐ"
+
+#: gtk_ardour/export_dialog.cc:111
+msgid "CHANNELS"
+msgstr "КÐÐÐЛЫ"
+
+#: gtk_ardour/export_dialog.cc:112
+msgid "FILE TYPE"
+msgstr "ТИП ФÐЙЛÐ"
+
+#: gtk_ardour/export_dialog.cc:113
+msgid "SAMPLE FORMAT"
+msgstr "РÐЗРЯДÐОСТЬ"
+
+#: gtk_ardour/export_dialog.cc:114
+msgid "SAMPLE ENDIANNESS"
+msgstr "СВОЙСТВÐ"
+
+#: gtk_ardour/export_dialog.cc:115
+#, fuzzy
+msgid "EXPORT CD MARKER FILE ONLY"
+msgstr "ТИП ФÐЙЛÐ"
+
+#: gtk_ardour/export_dialog.cc:116
+msgid "EXPORT TO FILE"
+msgstr "ЭКСПОРТ Ð’ ФÐЙЛ"
+
+#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118
+#: gtk_ardour/option_editor.cc:119
+msgid "Browse"
+msgstr "Обзор"
+
+#: gtk_ardour/export_dialog.cc:119
+msgid "Specific tracks ..."
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:131
+msgid "ardour: export"
+msgstr "ardour: ÑкÑпорт"
+
+#: gtk_ardour/export_dialog.cc:132
+msgid "ardour_export"
+msgstr "ardour_ÑкÑпорт"
+
+#: gtk_ardour/export_dialog.cc:156
+#, fuzzy
+msgid "Output"
+msgstr "Выходов"
+
+#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626
+msgid "Track"
+msgstr "Трек"
+
+#: gtk_ardour/export_dialog.cc:287
+msgid "slereg"
+msgstr "slereg"
+
+#: gtk_ardour/export_dialog.cc:658
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD toc file"
+msgstr ""
+"Редакор: не могу открыть \"%1\" как файл ÑкÑпорта маркеров Ð´Ð»Ñ CD-треков"
+
+#: gtk_ardour/export_dialog.cc:780
+#, fuzzy
+msgid "Editor: cannot open \"%1\" as export file for CD cue file"
+msgstr ""
+"Редакор: не могу открыть \"%1\" как файл ÑкÑпорта маркеров Ð´Ð»Ñ CD-треков"
+
+#: gtk_ardour/export_dialog.cc:799
+msgid "WAV"
+msgstr ""
+
+#: gtk_ardour/export_dialog.cc:1051
+msgid "Stop Export"
+msgstr "ОÑтановить ÑкÑпорт"
+
+#: gtk_ardour/gain_automation_time_axis.cc:60
+#, fuzzy
+msgid "add gain automation event"
+msgstr "автомат"
+
+#: gtk_ardour/gain_meter.cc:68
+msgid "Cannot create slider pixmaps"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:83
+msgid "dbFS"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134
+#: gtk_ardour/gain_meter.cc:728
+msgid "pre"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724
+#, fuzzy
+msgid "input"
+msgstr "%1 вход"
+
+#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732
+#, fuzzy
+msgid "post"
+msgstr "порт"
+
+#: gtk_ardour/gain_meter.cc:146
+msgid "tupni"
+msgstr ""
+
+#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470
+#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537
+#, fuzzy
+msgid "-inf"
+msgstr "в"
+
+#: gtk_ardour/imageframe_socket_handler.cc:127
+msgid "Image Compositor Socket has been shutdown/closed"
+msgstr ""
+
+#: gtk_ardour/imageframe_time_axis.cc:295
+#, fuzzy
+msgid "0.5 seconds"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259
+#, fuzzy
+msgid "1 seconds"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260
+#, fuzzy
+msgid "1.5 seconds"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261
+#, fuzzy
+msgid "2 seconds"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262
+#, fuzzy
+msgid "2.5 seconds"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263
+#, fuzzy
+msgid "3 seconds"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268
+msgid "Duration (sec)"
+msgstr ""
+
+#: gtk_ardour/imageframe_time_axis.cc:310
+#, fuzzy
+msgid "Remove Frame"
+msgstr "Удалить поле"
+
+#: gtk_ardour/imageframe_time_axis.cc:313
+#, fuzzy
+msgid "Image Frame"
+msgstr "Кадр"
+
+#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274
+#, fuzzy
+msgid "Rename Track"
+msgstr "Переименовать"
+
+#: gtk_ardour/io_selector.cc:64
+msgid "%1 input"
+msgstr "%1 вход"
+
+#: gtk_ardour/io_selector.cc:66
+msgid "%1 output"
+msgstr "%1 выход"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103
+msgid "Inputs"
+msgstr "Входов"
+
+#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104
+msgid "Outputs"
+msgstr "Выходов"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Input"
+msgstr "добавить вход"
+
+#: gtk_ardour/io_selector.cc:142
+#, fuzzy
+msgid "Add Output"
+msgstr "добавить выход"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Input"
+msgstr "Удалить"
+
+#: gtk_ardour/io_selector.cc:143
+#, fuzzy
+msgid "Remove Output"
+msgstr "# Выходов"
+
+#: gtk_ardour/io_selector.cc:144
+#, fuzzy
+msgid "Disconnect All"
+msgstr "ОтÑоединить"
+
+#: gtk_ardour/io_selector.cc:158
+msgid "Available connections"
+msgstr "ДоÑтупные ÑоединениÑ"
+
+#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636
+#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724
+msgid "port"
+msgstr "порт"
+
+#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587
+msgid "There are no more JACK ports available."
+msgstr ""
+
+#: gtk_ardour/io_selector.cc:790
+msgid "ardour: "
+msgstr "ardour: "
+
+#: gtk_ardour/keyboard.cc:419
+msgid "KeyboardTarget: keyname \"%1\" is unknown."
+msgstr "KeyboardTarget: \"%1\" - неизвеÑтное имÑ."
+
+#: gtk_ardour/keyboard.cc:645
+msgid ""
+"Your system is completely broken - NumLock uses \"%1\"as its modifier. This "
+"is madness - see the man page for xmodmap to find out how to fix this."
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:653
+msgid ""
+"Your system generates \"%1\" when the NumLock key is pressed. This can cause "
+"problems when editing so Ardour will use %2 to mean Meta rather than %1"
+msgstr ""
+
+#: gtk_ardour/keyboard.cc:714
+msgid "You have %1 keys bound to \"mod1\""
+msgstr "Ð”Ð»Ñ \"mod1\" назначено кнопок: %1"
+
+#: gtk_ardour/keyboard.cc:729
+msgid "You have %1 keys bound to \"mod2\""
+msgstr "Ð”Ð»Ñ \"mod2\" назначено кнопок: %1"
+
+#: gtk_ardour/keyboard.cc:744
+msgid "You have %1 keys bound to \"mod3\""
+msgstr "Ð”Ð»Ñ \"mod3\" назначено кнопок: %1"
+
+#: gtk_ardour/keyboard.cc:759
+msgid "You have %1 keys bound to \"mod4\""
+msgstr "Ð”Ð»Ñ \"mod4\" назначено кнопок: %1"
+
+#: gtk_ardour/keyboard.cc:774
+msgid "You have %1 keys bound to \"mod5\""
+msgstr "Ð”Ð»Ñ \"mod5\" назначено кнопок: %1"
+
+#: gtk_ardour/keyboard_target.cc:72
+msgid "KeyboardTarget: empty string passed to add_binding."
+msgstr ""
+
+#: gtk_ardour/keyboard_target.cc:78
+msgid "KeyboardTarget: no translation found for \"%1\""
+msgstr "KeyboardTarget: Ð´Ð»Ñ \"%1\" ÑопоÑтавление не найдено"
+
+#: gtk_ardour/keyboard_target.cc:83
+msgid "KeyboardTarget: unknown action \"%1\""
+msgstr "KeyboardTarget: \"%1\" - неизвеÑтное Ñобытие"
+
+#: gtk_ardour/keyboard_target.cc:248
+msgid "misformed binding node - ignored"
+msgstr "неверное определение ÑвÑзи - пропущено"
+
+#: gtk_ardour/library_ui.cc:62
+msgid "Soundfile Library"
+msgstr "Ðудио-библиотека"
+
+#: gtk_ardour/library_ui.cc:63
+msgid "Filesystem"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:66
+msgid "Split Channels"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:69
+msgid "ardour: soundfile selector"
+msgstr "ardour: выбор файлов"
+
+#: gtk_ardour/library_ui.cc:430
+msgid "Add to Library..."
+msgstr ""
+"Добавить\n"
+"в библиотеку..."
+
+#: gtk_ardour/library_ui.cc:431
+msgid "Remove..."
+msgstr "Удалить..."
+
+#: gtk_ardour/library_ui.cc:432
+msgid "Find..."
+msgstr "Ðайти..."
+
+#: gtk_ardour/library_ui.cc:433
+msgid "Add Folder"
+msgstr ""
+"Создать\n"
+"папку"
+
+#: gtk_ardour/library_ui.cc:434
+msgid "Add audio file or directory"
+msgstr "Добавить аудиофайл или каталог"
+
+#: gtk_ardour/library_ui.cc:713
+msgid "Importing"
+msgstr "Импорт"
+
+#: gtk_ardour/library_ui.cc:748
+msgid "%1 not added to database"
+msgstr "%1 не добавлен в базу"
+
+#: gtk_ardour/library_ui.cc:767
+msgid "Folder name:"
+msgstr "Ð˜Ð¼Ñ Ð¿Ð°Ð¿ÐºÐ¸:"
+
+#: gtk_ardour/library_ui.cc:838
+msgid "Should not be reached"
+msgstr "Станет недоÑтупен"
+
+#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096
+msgid "file \"%1\" could not be opened"
+msgstr "не удалоÑÑŒ открыть файл \"%1\" !"
+
+#: gtk_ardour/library_ui.cc:956
+msgid "Field"
+msgstr "Критерий"
+
+#: gtk_ardour/library_ui.cc:957
+msgid "Value"
+msgstr "Значение"
+
+#: gtk_ardour/library_ui.cc:973
+msgid "Stop"
+msgstr "Стоп"
+
+#: gtk_ardour/library_ui.cc:974
+msgid "Add Field..."
+msgstr "Добавить поле..."
+
+#: gtk_ardour/library_ui.cc:975
+msgid "Remove Field"
+msgstr "Удалить поле"
+
+#: gtk_ardour/library_ui.cc:979
+msgid "Soundfile Info"
+msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ файле"
+
+#: gtk_ardour/library_ui.cc:1106
+msgid "file \"%1\" appears not to be an audio file"
+msgstr ""
+
+#: gtk_ardour/library_ui.cc:1159
+#, fuzzy
+msgid "Could not read file: %1 (%2)."
+msgstr "Редактор: не удалоÑÑŒ открыть файл \"%1\" (%2)"
+
+#: gtk_ardour/library_ui.cc:1177
+msgid "Could not access soundfile: "
+msgstr "Файл недоÑтупен: "
+
+#: gtk_ardour/library_ui.cc:1222
+msgid "Field name:"
+msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»Ñ:"
+
+#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367
+msgid "Field value:"
+msgstr "Значение полÑ:"
+
+#: gtk_ardour/library_ui.cc:1295
+msgid "Find"
+msgstr "Ðайти"
+
+#: gtk_ardour/library_ui.cc:1296
+msgid "AND"
+msgstr "И"
+
+#: gtk_ardour/library_ui.cc:1297
+msgid "OR"
+msgstr "ИЛИ"
+
+#: gtk_ardour/library_ui.cc:1300
+msgid "ardour: locate soundfiles"
+msgstr "ardour: раÑположение звуковых файлов"
+
+#: gtk_ardour/library_ui.cc:1426
+msgid "Results"
+msgstr "Результаты"
+
+#: gtk_ardour/library_ui.cc:1427
+msgid "Uris"
+msgstr "Uris"
+
+#: gtk_ardour/library_ui.cc:1439
+msgid "Create multi-channel region"
+msgstr ""
+"Создать\n"
+"многоканальный"
+
+#: gtk_ardour/library_ui.cc:1442
+msgid "Ardour: Search Results"
+msgstr "Ardour: ПоиÑк результатов"
+
+#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50
+msgid "Set"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51
+msgid "Go"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:54
+msgid "CD"
+msgstr "CD"
+
+#: gtk_ardour/location_ui.cc:55
+msgid "Hidden"
+msgstr "Скрытый"
+
+#: gtk_ardour/location_ui.cc:57
+msgid "SCMS"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:58
+msgid "Pre-Emphasis"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:592
+msgid "Add New Location"
+msgstr "Добавить новый интервал"
+
+#: gtk_ardour/location_ui.cc:593
+msgid "Add New Range"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:597
+msgid "ardour: locations"
+msgstr "ardour: интервалы"
+
+#: gtk_ardour/location_ui.cc:598
+msgid "ardour_locations"
+msgstr "ardour_интервалы"
+
+#: gtk_ardour/location_ui.cc:629
+#, fuzzy
+msgid "Location (CD Index) Markers"
+msgstr "Маркеры интервалов"
+
+#: gtk_ardour/location_ui.cc:649
+msgid "Range (CD Track) Markers"
+msgstr ""
+
+#: gtk_ardour/location_ui.cc:814
+msgid "add range marker"
+msgstr ""
+
+#: gtk_ardour/main.cc:76
+msgid "ardour is killing itself for a clean exit\n"
+msgstr "ardour: принудительное завершение работы\n"
+
+#: gtk_ardour/main.cc:85
+msgid "stopping user interface\n"
+msgstr "завершение работы...\n"
+
+#: gtk_ardour/main.cc:104
+#, fuzzy, c-format
+msgid "%d(%d): received signal %d\n"
+msgstr "%d: принÑÑ‚ Ñигнал %d\n"
+
+#: gtk_ardour/main.cc:190
+msgid "cannot become new process group leader (%1)"
+msgstr ""
+
+#: gtk_ardour/main.cc:217
+msgid "cannot setup signal handling for %1"
+msgstr "cannot setup signal handling for %1"
+
+#: gtk_ardour/main.cc:228
+msgid "cannot set default signal mask (%1)"
+msgstr "cannot set default signal mask (%1)"
+
+#: gtk_ardour/main.cc:253
+#, fuzzy
+msgid ""
+"Without a UI style file, ardour will look strange.\n"
+" Please set ARDOUR_UI_RC to point to a valid UI style file"
+msgstr ""
+"ГрафичеÑий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ardour будет выглÑдеть необычно\n"
+"без файла определÑющего Ñтиль отображениÑ.\n"
+"ПожалуйÑта, укажите его (файл) в переменной Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ ARDOUR_UI_RC"
+
+#: gtk_ardour/main.cc:292
+msgid ""
+"Ardour could not connect to JACK.\n"
+"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 ""
+"Ardour не удаётÑÑ ÑƒÑтановить Ñоединение Ñ Ñервером JACK.\n"
+"СущеÑтвует неÑколько возможных причин:\n"
+"\n"
+"1) Сервер JACK не запущен.\n"
+"2) Сервер JACK запущен Ñ Ð¿Ñ€Ð°Ð²Ð°Ð¼Ð¸ другого пользователÑ, возможно root.\n"
+"3) Уже ÑущеÑтвует клиент Ñервера JACK Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ \"ardour\".\n"
+"\n"
+"ПожалуйÑта, проверьте вÑе варианты, возможно потребуетÑÑ (пере)запуÑк JACK."
+
+#: gtk_ardour/main.cc:305
+msgid "ardour: unplugged"
+msgstr "ardour: нет ÑоединениÑ"
+
+#: gtk_ardour/main.cc:363
+msgid "Ardour/GTK "
+msgstr "Ardour/GTK "
+
+#: gtk_ardour/main.cc:365
+msgid ""
+"\n"
+" (built using "
+msgstr ""
+
+#: gtk_ardour/main.cc:369
+#, fuzzy
+msgid " with libardour "
+msgstr " работает Ñ libardour "
+
+#: gtk_ardour/main.cc:374
+msgid " and GCC version "
+msgstr ""
+
+#: gtk_ardour/main.cc:384
+#, fuzzy
+msgid "Copyright (C) 1999-2005 Paul Davis"
+msgstr "ÐвторÑкое право 1999-2004 Paul Davis"
+
+#: gtk_ardour/main.cc:385
+msgid ""
+"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
+msgstr ""
+
+#: gtk_ardour/main.cc:387
+msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
+msgstr "Ardour раÑпроÑтранÑетÑÑ Ð‘Ð•Ð— ВСЯКИХ ГÐРÐÐТИЙ"
+
+#: gtk_ardour/main.cc:388
+msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+msgstr ""
+
+#: gtk_ardour/main.cc:389
+msgid "This is free software, and you are welcome to redistribute it "
+msgstr "Это Ñвободное программное обеÑпечение, Ð’Ñ‹ можете раÑпроÑтранÑÑ‚ÑŒ его"
+
+#: gtk_ardour/main.cc:390
+#, fuzzy
+msgid "under certain conditions; see the source for copying conditions."
+msgstr "на определённых уÑловиÑÑ…; подробнее об Ñтом читайте в файле COPYING."
+
+#: gtk_ardour/main.cc:399
+msgid "could not create ARDOUR GUI"
+msgstr "не удалоÑÑŒ Ñоздать графичеÑкий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ ARDOUR"
+
+#: gtk_ardour/main.cc:419
+msgid "Could not connect to JACK server as \"%1\""
+msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\""
+
+#: gtk_ardour/main.cc:424
+msgid "could not initialize Ardour."
+msgstr "не удалоÑÑŒ запуÑтить Ardour."
+
+#: gtk_ardour/main.cc:435
+msgid "could not load command line session \"%1\""
+msgstr "не удалоÑÑŒ загрузить ÑеÑÑию \"%1\", указанную в командной Ñтроке"
+
+#: gtk_ardour/main.cc:455
+msgid ""
+"\n"
+"\n"
+"A session named \"%1\" already exists.\n"
+"To avoid this message, start ardour as \"ardour %1"
+msgstr ""
+
+#: gtk_ardour/main.cc:466
+msgid ""
+"\n"
+"\n"
+"No session named \"%1\" exists.\n"
+"To create it from the command line, start ardour as \"ardour --new %1"
+msgstr ""
+
+#: gtk_ardour/marker.cc:354
+#, fuzzy
+msgid "MarkerText"
+msgstr "маркерам"
+
+#: gtk_ardour/marker_time_axis.cc:271
+#, fuzzy
+msgid "Remove Marker"
+msgstr "Удалить поле"
+
+#: gtk_ardour/marker_time_axis.cc:273
+#, fuzzy
+msgid "Marker"
+msgstr "маркерам"
+
+#: gtk_ardour/meter_bridge.cc:74
+msgid "ardour: meter bridge"
+msgstr "ardour: индикатор уровнÑ"
+
+#: gtk_ardour/meter_bridge.cc:75
+msgid "ardour_meter_bridge"
+msgstr "ardour_индикатор_уровнÑ"
+
+#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93
+#, c-format
+msgid "# of %u-sample overs"
+msgstr ""
+
+#: gtk_ardour/meter_bridge_strip.cc:219
+msgid "New name for meter:"
+msgstr "Ðовое Ð¸Ð¼Ñ Ð¸Ð½Ð´Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð°:"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507
+#: gtk_ardour/region_editor.cc:45
+msgid "mute"
+msgstr "тихо"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508
+msgid "solo"
+msgstr "Ñоло"
+
+#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506
+msgid "RECORD"
+msgstr "ЗÐПИСЬ"
+
+#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514
+msgid "polarity"
+msgstr "полÑрноÑÑ‚ÑŒ"
+
+#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509
+msgid "comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810
+msgid "INPUT"
+msgstr "ВХОД"
+
+#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831
+msgid "OUTPUT"
+msgstr "ВЫХОД"
+
+#: gtk_ardour/mixer_strip.cc:173
+#, fuzzy
+msgid "Pan automation mode"
+msgstr "автомат"
+
+#: gtk_ardour/mixer_strip.cc:174
+#, fuzzy
+msgid "Gain automation mode"
+msgstr "автомат"
+
+#: gtk_ardour/mixer_strip.cc:176
+#, fuzzy
+msgid "Pan automation type"
+msgstr "автомат"
+
+#: gtk_ardour/mixer_strip.cc:177
+#, fuzzy
+msgid "Gain automation type"
+msgstr "автомат"
+
+#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232
+#: gtk_ardour/mixer_strip.cc:979
+msgid "trim"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233
+#: gtk_ardour/mixer_strip.cc:983
+msgid "abs"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:240
+#, fuzzy
+msgid "gain automation mode"
+msgstr "автомат"
+
+#: gtk_ardour/mixer_strip.cc:241
+#, fuzzy
+msgid "pan automation mode"
+msgstr "автомат"
+
+#: gtk_ardour/mixer_strip.cc:242
+#, fuzzy
+msgid "gain automation state"
+msgstr "автомат"
+
+#: gtk_ardour/mixer_strip.cc:243
+#, fuzzy
+msgid "pan automation state"
+msgstr "автомат"
+
+#: gtk_ardour/mixer_strip.cc:259
+msgid "varispeed"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174
+msgid "click to add/edit comments"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:463
+msgid "unknown strip width \"%1\" in XML GUI information"
+msgstr "неизвеÑÑ‚Ð½Ð°Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ð° трека \"%1\" в XML опиÑании"
+
+#: gtk_ardour/mixer_strip.cc:522
+msgid "REC"
+msgstr "ЗÐП"
+
+#: gtk_ardour/mixer_strip.cc:525
+#, fuzzy
+msgid "cmt"
+msgstr "вырезать"
+
+#: gtk_ardour/mixer_strip.cc:530
+msgid "pol"
+msgstr "пол"
+
+#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620
+#: gtk_ardour/redirect_box.cc:1180
+msgid "Not connected to JACK - no I/O changes are possible"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667
+msgid "could not register new ports required for that connection"
+msgstr ""
+
+#: gtk_ardour/mixer_strip.cc:813
+msgid "IN"
+msgstr "Ð’Ð¥"
+
+#: gtk_ardour/mixer_strip.cc:834
+msgid "OUT"
+msgstr "ВЫХ"
+
+#: gtk_ardour/mixer_strip.cc:950
+msgid "aplay"
+msgstr "авоÑпр"
+
+#: gtk_ardour/mixer_strip.cc:956
+#, fuzzy
+msgid "awrite"
+msgstr "запиÑÑŒ"
+
+#: gtk_ardour/mixer_strip.cc:1134
+#, fuzzy
+msgid ": comment editor"
+msgstr "ИнтерфейÑ: не удалоÑÑŒ инициализировать редактор"
+
+#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224
+msgid "no group"
+msgstr "нет группы"
+
+#: gtk_ardour/mixer_strip.cc:1227
+msgid "~G"
+msgstr "нГр"
+
+#: gtk_ardour/mixer_ui.cc:52
+msgid "Strips"
+msgstr "Каналы"
+
+#: gtk_ardour/mixer_ui.cc:56
+msgid "Snapshots"
+msgstr "Снимки"
+
+#: gtk_ardour/mixer_ui.cc:61
+msgid "***"
+msgstr "***"
+
+#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17
+#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144
+#: gtk_ardour/tempo_dialog.cc:162
+msgid "Bar"
+msgstr "Такт"
+
+#: gtk_ardour/mixer_ui.cc:121
+msgid "Mix Groups"
+msgstr "Mix группы"
+
+#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373
+msgid "ardour: mixer"
+msgstr "ardour: микшер"
+
+#: gtk_ardour/mixer_ui.cc:192
+msgid "ardour_mixer"
+msgstr "ardour_микшер"
+
+#: gtk_ardour/mixer_ui.cc:342
+msgid "ardour: mixer: "
+msgstr "ardour: микшер: "
+
+#: gtk_ardour/mixer_ui.cc:641
+msgid "signal"
+msgstr "Ñигнал"
+
+#: gtk_ardour/mixer_ui.cc:672
+msgid "Show All AudioTrack MixerStrips"
+msgstr "Показать вÑе каналы аудиотреков"
+
+#: gtk_ardour/mixer_ui.cc:673
+msgid "Hide All AudioTrack MixerStrips"
+msgstr "Скрыть вÑе каналы аудиотреков"
+
+#: gtk_ardour/mixer_ui.cc:674
+msgid "Show All AudioBus MixerStrips"
+msgstr "Показать вÑе каналы аудиошин"
+
+#: gtk_ardour/mixer_ui.cc:675
+msgid "Hide All AudioBus MixerStrips"
+msgstr "Скрыть вÑе каналы аудиошин"
+
+#: gtk_ardour/mixer_ui.cc:687
+msgid "track display list item for renamed strip not found!"
+msgstr ""
+
+#: gtk_ardour/mixer_ui.cc:700
+msgid "Name for new mix group"
+msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð¹ mix группы"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Session name:"
+msgstr "Ð˜Ð¼Ñ ÑеÑÑии:"
+
+#: gtk_ardour/new_session_dialog.cc:39
+msgid "Create"
+msgstr "Создать"
+
+#: gtk_ardour/new_session_dialog.cc:40
+msgid "use control outs"
+msgstr "иÑпользовать контрольные выходы"
+
+#: gtk_ardour/new_session_dialog.cc:41
+msgid "use master outs"
+msgstr "иÑпользовать маÑтер-выходы"
+
+#: gtk_ardour/new_session_dialog.cc:42
+#, fuzzy
+msgid "automatically connect track inputs to physical ports"
+msgstr "автоматичеÑкое подключение треков ко входам"
+
+#: gtk_ardour/new_session_dialog.cc:43
+#, fuzzy
+msgid "automatically connect track outputs to master outs"
+msgstr "автоматичеÑкое подключение треков к маÑтер-выходам"
+
+#: gtk_ardour/new_session_dialog.cc:44
+#, fuzzy
+msgid "automatically connect track outputs to physical ports"
+msgstr "автоматичеÑкое подключение треков к выходам"
+
+#: gtk_ardour/new_session_dialog.cc:45
+msgid "manually connect track outputs"
+msgstr "ручное подключение треков к выходам"
+
+#: gtk_ardour/new_session_dialog.cc:50
+msgid "Advanced..."
+msgstr "Дополнительно..."
+
+#: gtk_ardour/new_session_dialog.cc:52
+msgid "show again"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:55
+msgid "Hardware Inputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:56
+msgid "Hardware Outputs: use"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:62
+msgid "new session setup"
+msgstr "наÑтройки новой ÑеÑÑии"
+
+#: gtk_ardour/new_session_dialog.cc:63
+msgid "ardour_new_session"
+msgstr "ardour_новаÑ_ÑеÑÑиÑ"
+
+#: gtk_ardour/new_session_dialog.cc:72
+msgid "This session will playback and record at %1 Hz"
+msgstr ""
+"Эта ÑеÑÑÐ¸Ñ Ð±ÑƒÐ´ÐµÑ‚ запиÑыватьÑÑ Ð¸ воÑпроизводитьÑÑ\n"
+"Ñ Ñ‡Ð°Ñтотой диÑкретизации %1 Гц"
+
+#: gtk_ardour/new_session_dialog.cc:74
+msgid ""
+"This rate is set by JACK and cannot be changed.\n"
+"If you want to use a different sample rate\n"
+"please exit and restart JACK"
+msgstr ""
+"Этот параметр уÑтанавливаетÑÑ Ñервером JACK и не может быть изменён.\n"
+"ЕÑли вы хотите иÑпользовать другую чаÑтоту диÑкретизации,\n"
+"вам необходимо закрыть Ardour и перезапуÑтить JACK"
+
+#: gtk_ardour/new_session_dialog.cc:155
+#, fuzzy
+msgid "Session template"
+msgstr "иÑпользовать имеющийÑÑ ÑˆÐ°Ð±Ð»Ð¾Ð½"
+
+#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20
+#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146
+#: gtk_ardour/tempo_dialog.cc:164
+msgid "Location"
+msgstr "РаÑположение"
+
+#: gtk_ardour/new_session_dialog.cc:178
+msgid "Configuration"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:269
+msgid "blank"
+msgstr "пуÑтой"
+
+#: gtk_ardour/new_session_dialog.cc:328
+msgid "No template - create tracks/busses manually"
+msgstr ""
+
+#: gtk_ardour/new_session_dialog.cc:337
+#, fuzzy
+msgid "No template"
+msgstr "-шаблон"
+
+#: gtk_ardour/option_editor.cc:48
+#, fuzzy
+msgid "Internal"
+msgstr "внутренний"
+
+#: gtk_ardour/option_editor.cc:49
+#, fuzzy
+msgid "Slave to MTC"
+msgstr "Передача MTC"
+
+#: gtk_ardour/option_editor.cc:50
+msgid "Sync with JACK"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:51
+msgid "never used but stops crashes"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:56
+#, fuzzy
+msgid "Later regions are higher"
+msgstr "ОпуÑтить облаÑÑ‚ÑŒ на один Ñлой"
+
+#: gtk_ardour/option_editor.cc:57
+msgid "Most recently added/moved/trimmed regions are higher"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:58
+#, fuzzy
+msgid "Most recently added regions are higher"
+msgstr "ОпуÑтить облаÑÑ‚ÑŒ на один Ñлой"
+
+#: gtk_ardour/option_editor.cc:63
+#, fuzzy
+msgid "Span entire region overlap"
+msgstr "ПоднÑÑ‚ÑŒ облаÑÑ‚ÑŒ на один Ñлой"
+
+#: gtk_ardour/option_editor.cc:64
+msgid "Short fades at the start of the overlap"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:82
+#, fuzzy
+msgid "Automatically create crossfades"
+msgstr "ÐвтоматичеÑкий кроÑÑфейд на перекрытии"
+
+#: gtk_ardour/option_editor.cc:83
+msgid "New full-overlap crossfades are unmuted"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:84
+#, fuzzy
+msgid "Region layering mode"
+msgstr "оконч. облаÑтей"
+
+#: gtk_ardour/option_editor.cc:85
+#, fuzzy
+msgid "Crossfade model"
+msgstr "КроÑÑфейд"
+
+#: gtk_ardour/option_editor.cc:90
+msgid "Latched solo"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:91
+msgid "Solo via bus"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:96
+#, fuzzy
+msgid "Show waveforms while recording"
+msgstr "Отображать форму Ñигнала"
+
+#: gtk_ardour/option_editor.cc:97
+msgid "Narrow mixer strips"
+msgstr "Узкие каналы микшера"
+
+#: gtk_ardour/option_editor.cc:98
+msgid "Show measure lines"
+msgstr "Показывать линии тактов"
+
+#: gtk_ardour/option_editor.cc:99
+msgid "Follow playhead"
+msgstr "Следовать за указателем"
+
+#: gtk_ardour/option_editor.cc:103
+msgid "Send MTC"
+msgstr "Передача MTC"
+
+#: gtk_ardour/option_editor.cc:104
+msgid "Send MMC"
+msgstr "Передача MMC"
+
+#: gtk_ardour/option_editor.cc:105
+msgid "JACK time master"
+msgstr "JACK-Ñчётчик - маÑтер"
+
+#: gtk_ardour/option_editor.cc:107
+#, fuzzy
+msgid "SMPTE offset is negative"
+msgstr "Смещение SMPTE"
+
+#: gtk_ardour/option_editor.cc:111
+msgid "Send MIDI parameter feedback"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:112
+msgid "MIDI parameter control"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:113
+#, fuzzy
+msgid "MMC control"
+msgstr "MMC порт"
+
+#: gtk_ardour/option_editor.cc:131
+#, fuzzy
+msgid "Auto-connect new track inputs to hardware"
+msgstr "ÐвтоподÑоединение новых треков"
+
+#: gtk_ardour/option_editor.cc:132
+#, fuzzy
+msgid "Auto-connect new track outputs to hardware"
+msgstr "ÐвтоподÑоединение новых треков"
+
+#: gtk_ardour/option_editor.cc:133
+#, fuzzy
+msgid "Auto-connect new track outputs to master bus"
+msgstr "автоматичеÑкое подключение треков к маÑтер-выходам"
+
+#: gtk_ardour/option_editor.cc:134
+#, fuzzy
+msgid "Manually connect new track outputs"
+msgstr "ручное подключение треков к выходам"
+
+#: gtk_ardour/option_editor.cc:135
+msgid "Use Hardware Monitoring"
+msgstr "Ðппаратный контроль"
+
+#: gtk_ardour/option_editor.cc:136
+msgid "Use Software Monitoring"
+msgstr "ИÑпользовать программный контроль"
+
+#: gtk_ardour/option_editor.cc:137
+msgid "Stop plugins with transport"
+msgstr "ОÑтанавливать модули (plugins) вмеÑте Ñ Ñ‚Ñ€Ð°Ð½Ñпортом"
+
+#: gtk_ardour/option_editor.cc:138
+msgid "Run plugins while recording"
+msgstr "ИÑпользовать модули (plugins) во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи"
+
+#: gtk_ardour/option_editor.cc:139
+#, fuzzy
+msgid "Verify remove last capture"
+msgstr "Удалить поÑледнюю запиÑÑŒ"
+
+#: gtk_ardour/option_editor.cc:140
+msgid "Stop recording on xrun"
+msgstr "ОÑтановить запиÑÑŒ при потере отÑчётов"
+
+#: gtk_ardour/option_editor.cc:141
+msgid "Stop transport at end of session"
+msgstr "ОÑтанавливать транÑпорт в конце ÑеÑÑии"
+
+#: gtk_ardour/option_editor.cc:142
+msgid "Debug keyboard events"
+msgstr "Отладка наÑтроек клавиатуры"
+
+#: gtk_ardour/option_editor.cc:143
+msgid "-12dB gain reduction for ffwd/rew"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:152
+msgid "ardour: options editor"
+msgstr "adour: редактор параметров"
+
+#: gtk_ardour/option_editor.cc:153
+msgid "ardour_option_editor"
+msgstr "adour_редактор_параметров"
+
+#: gtk_ardour/option_editor.cc:183
+msgid "Misc"
+msgstr "Прочее"
+
+#: gtk_ardour/option_editor.cc:184
+msgid "Sync"
+msgstr "Синхр."
+
+#: gtk_ardour/option_editor.cc:185
+msgid "Paths/Files"
+msgstr "Пути/Файлы"
+
+#: gtk_ardour/option_editor.cc:186
+msgid "Display"
+msgstr "Экран"
+
+#: gtk_ardour/option_editor.cc:187
+msgid "Kbd/Mouse"
+msgstr "Клавиатура/Мышь"
+
+#: gtk_ardour/option_editor.cc:188
+msgid "Click"
+msgstr "Метроном"
+
+#: gtk_ardour/option_editor.cc:190
+msgid "Layers & Fades"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:195
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gtk_ardour/option_editor.cc:268
+msgid "24 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:270
+msgid "25 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:272
+msgid "30 FPS"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:278
+msgid "30 FPS drop"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379
+#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736
+#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800
+msgid "Medium"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738
+#: gtk_ardour/option_editor.cc:804
+#, fuzzy
+msgid "Faster"
+msgstr "Затухание"
+
+#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714
+#: gtk_ardour/option_editor.cc:776
+#, fuzzy
+msgid "Short"
+msgstr "порт"
+
+#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716
+#: gtk_ardour/option_editor.cc:780
+msgid "Long"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:396
+msgid "Broadcast WAVE/floating point"
+msgstr "Broadcast WAVE/Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰Ð°Ñ Ñ‚Ð¾Ñ‡ÐºÐ°"
+
+#: gtk_ardour/option_editor.cc:397
+msgid "WAVE/floating point"
+msgstr "WAVE/Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰Ð°Ñ Ñ‚Ð¾Ñ‡ÐºÐ°"
+
+#: gtk_ardour/option_editor.cc:417
+msgid "session RAID path"
+msgstr "путь к файлам RAID ÑеÑÑий"
+
+#: gtk_ardour/option_editor.cc:422
+msgid "Native Format"
+msgstr "Внутренний формат"
+
+#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460
+#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409
+msgid "internal"
+msgstr "внутренний"
+
+#: gtk_ardour/option_editor.cc:537
+msgid "Short crossfade length (msecs)"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:710
+msgid "Meter Peak Hold"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:730
+msgid "Meter Falloff"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:847
+msgid "Positional Sync"
+msgstr ""
+
+#: gtk_ardour/option_editor.cc:902
+msgid "SMPTE Frames/second"
+msgstr "SMPTE Кадры/Секунды"
+
+#: gtk_ardour/option_editor.cc:903
+msgid "SMPTE Offset"
+msgstr "Смещение SMPTE"
+
+#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013
+#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211
+#, fuzzy
+msgid "online"
+msgstr "линейное"
+
+#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014
+#: gtk_ardour/option_editor.cc:1208
+#, fuzzy
+msgid "offline"
+msgstr "линейное"
+
+#: gtk_ardour/option_editor.cc:1319
+msgid "Use as click"
+msgstr "ИÑпользовать как щелчок метронома"
+
+#: gtk_ardour/option_editor.cc:1344
+msgid "Use as click emphasis"
+msgstr "ИÑпользовать как акцентирующий щелчок метронома"
+
+#: gtk_ardour/option_editor.cc:1478
+msgid "--unknown--"
+msgstr "--неизвеÑтный--"
+
+#: gtk_ardour/option_editor.cc:1595
+msgid "Click audio file"
+msgstr "Файл щелчков метронома"
+
+#: gtk_ardour/option_editor.cc:1601
+msgid "Click emphasis audiofile"
+msgstr "Файл акцентирующих щелчков метронома"
+
+#: gtk_ardour/option_editor.cc:1638
+msgid ""
+"The auditioner is a dedicated mixer strip used\n"
+"for listening to specific regions outside the context\n"
+"of the overall mix. It can be connected just like any\n"
+"other mixer strip."
+msgstr ""
+"Контрольный канал - Ñто Ñпециальный канал микшера\n"
+"предназначенный Ð´Ð»Ñ Ð¿Ñ€Ð¾ÑÐ»ÑƒÑˆÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ‘Ð½Ð½Ñ‹Ñ… облаÑтей\n"
+"вне общего контекÑта микÑа. Его можно Ñоединить как любой\n"
+"другой канал микшера."
+
+#: gtk_ardour/option_editor.cc:1887
+msgid "Edit using"
+msgstr "Редактировать Ñочетание"
+
+#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924
+msgid "+ button"
+msgstr "+ клавиша"
+
+#: gtk_ardour/option_editor.cc:1917
+msgid "Delete using"
+msgstr "Удалить Ñочетание"
+
+#: gtk_ardour/option_editor.cc:1947
+msgid "Ignore snap using"
+msgstr "Ðе иÑпользовать \"Ñнимки\""
+
+#: gtk_ardour/opts.cc:46
+msgid "Usage: "
+msgstr "ИÑпользование: "
+
+#: gtk_ardour/opts.cc:47
+msgid " -v, --version Show version information\n"
+msgstr " -v, --version Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ верÑии программы\n"
+
+#: gtk_ardour/opts.cc:48
+msgid " -h, --help Print this message\n"
+msgstr " -h, --help Показать Ñто Ñообщение\n"
+
+#: gtk_ardour/opts.cc:49
+msgid ""
+" -b, --bindings Print all possible keyboard binding "
+"names\n"
+msgstr ""
+" -b, --bindings Показать вÑе доÑтупные \"горÑчие\" "
+"клавиши\n"
+
+#: gtk_ardour/opts.cc:50
+#, fuzzy
+msgid " -n, --show-splash Show splash screen\n"
+msgstr " -n, --no-splash Ðе показывать заÑтавку\n"
+
+#: gtk_ardour/opts.cc:51
+#, fuzzy
+msgid ""
+" -c, --name name Use a specific jack client name, default "
+"is ardour\n"
+msgstr ""
+" -c, --jack-client-name Ð¸Ð¼Ñ Ð˜Ñпользовать другое Ð¸Ð¼Ñ jack-клиента, "
+"ardour по умолчанию\n"
+
+#: gtk_ardour/opts.cc:52
+#, fuzzy
+msgid ""
+" -N, --new session-name Create a new session from the command "
+"line\n"
+msgstr ""
+" [имÑ-ÑеÑÑии] Загрузить ÑеÑÑию Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ именем\n"
+
+#: gtk_ardour/opts.cc:53
+msgid ""
+" -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+msgstr ""
+
+#: gtk_ardour/opts.cc:55
+#, fuzzy
+msgid " -V, --novst Do not use VST support\n"
+msgstr " -n, --no-splash Ðе показывать заÑтавку\n"
+
+#: gtk_ardour/opts.cc:57
+msgid " [session-name] Name of session to load\n"
+msgstr ""
+" [имÑ-ÑеÑÑии] Загрузить ÑеÑÑию Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ именем\n"
+
+#: gtk_ardour/opts.cc:58
+msgid " -C, --curvetest filename Curve algorithm debugger\n"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:58
+msgid "You can't graphically edit panning of more than stream"
+msgstr ""
+
+#: gtk_ardour/pan_automation_time_axis.cc:78
+#, fuzzy
+msgid "add pan automation event"
+msgstr "автомат"
+
+#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441
+#, fuzzy
+msgid "Bypass"
+msgstr "обход"
+
+#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222
+#, fuzzy
+msgid "link"
+msgstr "в"
+
+#: gtk_ardour/panner_ui.cc:103
+msgid "panning link control"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:105
+msgid "panning link direction"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:232
+msgid "L"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:344
+#, c-format
+msgid "panner for channel %u"
+msgstr ""
+
+#: gtk_ardour/panner_ui.cc:451
+#, fuzzy
+msgid "Reset all"
+msgstr "ОгромнаÑ"
+
+#: gtk_ardour/playlist_selector.cc:46
+msgid "Playlists grouped by track"
+msgstr ""
+
+#: gtk_ardour/playlist_selector.cc:53
+#, fuzzy
+msgid "close"
+msgstr "Закрыть"
+
+#: gtk_ardour/playlist_selector.cc:59
+#, fuzzy
+msgid "ardour: playlists"
+msgstr "ardour: модули (plugins)"
+
+#: gtk_ardour/playlist_selector.cc:104
+#, fuzzy
+msgid "ardour: playlist for "
+msgstr "ardour: редактор: "
+
+#: gtk_ardour/playlist_selector.cc:122
+#, fuzzy
+msgid "Other tracks"
+msgstr "Скрыть трек"
+
+#: gtk_ardour/playlist_selector.cc:138
+msgid "unassigned"
+msgstr ""
+
+#: gtk_ardour/plugin_selector.cc:41
+msgid "Available LADSPA plugins"
+msgstr "ДоÑтупные LADSPA модули"
+
+#: gtk_ardour/plugin_selector.cc:42
+msgid "Type"
+msgstr "Тип"
+
+#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51
+msgid "# Inputs"
+msgstr "# Входов"
+
+#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52
+msgid "# Outputs"
+msgstr "# Выходов"
+
+#: gtk_ardour/plugin_selector.cc:50
+#, fuzzy
+msgid "Available VST plugins"
+msgstr "ДоÑтупные LADSPA модули"
+
+#: gtk_ardour/plugin_selector.cc:58
+msgid "To be added"
+msgstr "Добавлено"
+
+#: gtk_ardour/plugin_selector.cc:72
+msgid "ardour: plugins"
+msgstr "ardour: модули (plugins)"
+
+#: gtk_ardour/plugin_selector.cc:82
+msgid "Add a plugin to the effect list"
+msgstr "Добавить модуль в ÑпиÑок Ñффектов"
+
+#: gtk_ardour/plugin_selector.cc:84
+msgid "Remove a plugin from the effect list"
+msgstr "Удалить модуль из ÑпиÑка Ñффектов"
+
+#: gtk_ardour/plugin_selector.cc:88
+msgid "Update"
+msgstr "Обновить"
+
+#: gtk_ardour/plugin_selector.cc:89
+msgid "Update available plugins"
+msgstr "Обновить доÑтупные модули"
+
+#: gtk_ardour/plugin_selector.cc:110
+#, fuzzy
+msgid "LADSPA"
+msgstr "ADAT"
+
+#: gtk_ardour/plugin_selector.cc:113
+#, fuzzy
+msgid "VST"
+msgstr "УСТÐÐОВИТЬ"
+
+#: gtk_ardour/plugin_ui.cc:83
+msgid ""
+"unknown type of editor-supplying plugin (note: no VST support in this "
+"version of ardour)"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:269
+msgid "Plugin Editor: could not build control element for port %1"
+msgstr "Редактор модулей: невозможно Ñоздать Ñффект Ð´Ð»Ñ Ð¿Ð¾Ñ€Ñ‚Ð° %1"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "in"
+msgstr "в"
+
+#: gtk_ardour/plugin_ui.cc:367
+msgid "ins"
+msgstr "вÑÑ‚"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "out"
+msgstr "выход"
+
+#: gtk_ardour/plugin_ui.cc:368
+msgid "outs"
+msgstr "выходы"
+
+#: gtk_ardour/plugin_ui.cc:382
+#, fuzzy
+msgid "automation control"
+msgstr "автомат"
+
+#: gtk_ardour/plugin_ui.cc:869
+#, fuzzy
+msgid "save"
+msgstr "Сохранить"
+
+#: gtk_ardour/plugin_ui.cc:870
+msgid "bypass"
+msgstr "обход"
+
+#: gtk_ardour/plugin_ui.cc:892
+msgid "Plugin preset %1 not found"
+msgstr ""
+
+#: gtk_ardour/plugin_ui.cc:903
+msgid "Name for plugin settings:"
+msgstr "Ð˜Ð¼Ñ Ð½Ð°Ñтроек модулей:"
+
+#: gtk_ardour/redirect_automation_line.cc:53
+msgid "redirect automation created for non-plugin"
+msgstr ""
+
+#: gtk_ardour/redirect_automation_time_axis.cc:92
+msgid "add automation event to "
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:213
+msgid "New send"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:214
+#, fuzzy
+msgid "Show send controls"
+msgstr "иÑпользовать контрольные выходы"
+
+#: gtk_ardour/redirect_box.cc:360
+msgid "New Plugin ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:361
+#, fuzzy
+msgid "New Insert"
+msgstr "новый вход"
+
+#: gtk_ardour/redirect_box.cc:362
+msgid "New Send ..."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:380
+#, fuzzy
+msgid "Select all"
+msgstr "Выделить вÑÑ‘"
+
+#: gtk_ardour/redirect_box.cc:381
+#, fuzzy
+msgid "Deselect all"
+msgstr "Выделить вÑÑ‘"
+
+#: gtk_ardour/redirect_box.cc:389
+#, fuzzy
+msgid "Inserts"
+msgstr "Ðовый \"возврат\""
+
+#: gtk_ardour/redirect_box.cc:390
+#, fuzzy
+msgid "Sends"
+msgstr "Минуты:Секунды"
+
+#: gtk_ardour/redirect_box.cc:393
+#, fuzzy
+msgid "Select all ..."
+msgstr "Выделить вÑÑ‘"
+
+#: gtk_ardour/redirect_box.cc:406
+#, fuzzy
+msgid "Activate All"
+msgstr "Ðктивировать"
+
+#: gtk_ardour/redirect_box.cc:407
+#, fuzzy
+msgid "Deactivate All"
+msgstr "Деактивировать"
+
+#: gtk_ardour/redirect_box.cc:488
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:500
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:513
+msgid ""
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:616
+msgid "Pre-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:619
+msgid "Post-fader inserts, sends & plugins:"
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:781
+msgid ""
+"You cannot reorder this set of redirects\n"
+"in that way because the inputs and\n"
+"outputs do not work correctly."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:903
+#, fuzzy
+msgid "ardour: rename redirect"
+msgstr "ardour: переименовать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043
+msgid ""
+"Copying the set of redirects on the clipboard failed,\n"
+"probably because the I/O configuration of the plugins\n"
+"could not match the configuration of this track."
+msgstr ""
+
+#: gtk_ardour/redirect_box.cc:1064
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this track?\n"
+"(this cannot be undone)"
+msgstr ""
+"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n"
+"(отмена невозможна)"
+
+#: gtk_ardour/redirect_box.cc:1067
+#, fuzzy
+msgid ""
+"Do you really want to remove all redirects from this bus?\n"
+"(this cannot be undone)"
+msgstr ""
+"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n"
+"(отмена невозможна)"
+
+#: gtk_ardour/redirect_box.cc:1071
+#, fuzzy
+msgid "Yes, remove them all"
+msgstr "Да, удалить."
+
+#: gtk_ardour/redirect_box.cc:1114
+#, fuzzy
+msgid "ardour: %1"
+msgstr "ardour: "
+
+#: gtk_ardour/redirect_box.cc:1156
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "ardour: "
+
+#: gtk_ardour/region_editor.cc:43
+msgid "NAME:"
+msgstr "ИМЯ:"
+
+#: gtk_ardour/region_editor.cc:44
+msgid "lock"
+msgstr "фикÑ."
+
+#: gtk_ardour/region_editor.cc:46
+msgid "opaque"
+msgstr "затенить"
+
+#: gtk_ardour/region_editor.cc:49
+msgid "Layer"
+msgstr "Слой"
+
+#: gtk_ardour/region_editor.cc:57
+msgid "ENVELOPE"
+msgstr "ОГИБÐЮЩÐЯ"
+
+#: gtk_ardour/region_editor.cc:108
+msgid "mute this region"
+msgstr "отключить воÑпроизведение Ñтой облаÑти"
+
+#: gtk_ardour/region_editor.cc:109
+msgid "regions underneath this one cannot be heard"
+msgstr "облаÑти ниже Ñтой не могут быть проÑлушаны"
+
+#: gtk_ardour/region_editor.cc:110
+msgid "prevent any changes to this region"
+msgstr "запретить любые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñтой облаÑти"
+
+#: gtk_ardour/region_editor.cc:111
+msgid "use the gain envelope during playback"
+msgstr "иÑпользовать огибающую при воÑпроизведении"
+
+#: gtk_ardour/region_editor.cc:112
+msgid "show the gain envelope"
+msgstr "отображать огибающую"
+
+#: gtk_ardour/region_editor.cc:113
+msgid "use fade in curve during playback"
+msgstr "иÑпользовать вводную кривую при воÑпроизведении"
+
+#: gtk_ardour/region_editor.cc:114
+msgid "use fade out curve during playback"
+msgstr "иÑпользовать выводную кривую при воÑпроизведении"
+
+#: gtk_ardour/region_editor.cc:115
+msgid "audition this region"
+msgstr "проÑлушать облаÑÑ‚ÑŒ"
+
+#: gtk_ardour/region_editor.cc:148
+msgid "START:"
+msgstr "ÐÐЧÐЛО:"
+
+#: gtk_ardour/region_editor.cc:150
+msgid "END:"
+msgstr "КОÐЕЦ:"
+
+#: gtk_ardour/region_editor.cc:152
+msgid "LENGTH:"
+msgstr "ДЛИÐÐ:"
+
+#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198
+#: gtk_ardour/region_editor.cc:234
+msgid "active"
+msgstr "активно"
+
+#: gtk_ardour/region_editor.cc:179
+msgid "visible"
+msgstr "отображать"
+
+#: gtk_ardour/region_editor.cc:197
+msgid "FADE IN"
+msgstr "ВВЕДЕÐИЕ Ð’ УРОВЕÐЬ"
+
+#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235
+msgid "msecs"
+msgstr "мÑек"
+
+#: gtk_ardour/region_editor.cc:233
+msgid "FADE OUT"
+msgstr "СВЕДЕÐИЕ Ð’ ÐОЛЬ"
+
+#: gtk_ardour/region_editor.cc:276
+msgid "ardour: region "
+msgstr "ardour: облаÑÑ‚ÑŒ "
+
+#: gtk_ardour/region_editor.cc:410
+msgid "fade in edit"
+msgstr "редактировать введение в уровень"
+
+#: gtk_ardour/region_editor.cc:422
+msgid "fade out edit"
+msgstr "редактировать Ñведение в ноль"
+
+#: gtk_ardour/regionview.cc:1169
+#, fuzzy
+msgid "add gain control point"
+msgstr "иÑпользовать контрольные выходы"
+
+#: gtk_ardour/route_params_ui.cc:58
+msgid "Tracks/Buses"
+msgstr "Треки/Шины"
+
+#: gtk_ardour/route_params_ui.cc:59
+msgid "Pre Redirects"
+msgstr "Предобработка"
+
+#: gtk_ardour/route_params_ui.cc:60
+msgid "Post Redirects"
+msgstr "ПоÑтобработка"
+
+#: gtk_ardour/route_params_ui.cc:105
+#, fuzzy
+msgid "Pre-fader Redirects"
+msgstr "Предобработка"
+
+#: gtk_ardour/route_params_ui.cc:106
+#, fuzzy
+msgid "Post-fader Redirects"
+msgstr "ПоÑтобработка"
+
+#: gtk_ardour/route_params_ui.cc:138
+#, fuzzy
+msgid "ardour: track/bus inspector"
+msgstr "ardour: добавить трек/шину"
+
+#: gtk_ardour/route_params_ui.cc:139
+msgid "ardour_route_parameters"
+msgstr "ardour_параметры_маршрутов"
+
+#: gtk_ardour/route_params_ui.cc:189
+msgid "route display list item for renamed route not found!"
+msgstr ""
+
+#: gtk_ardour/route_params_ui.cc:448
+msgid "NO TRACK"
+msgstr "ÐЕТ ТРЕКОВ"
+
+#: gtk_ardour/route_params_ui.cc:669
+#, fuzzy
+msgid "ardour: track/bus inspector: "
+msgstr "ardour: добавить трек/шину"
+
+#: gtk_ardour/route_params_ui.cc:673
+msgid "No Route Selected"
+msgstr "Ðет выбранных маршрутов"
+
+#: gtk_ardour/route_params_ui.cc:674
+#, fuzzy
+msgid "ardour: track/bus/inspector: no route selected"
+msgstr "ardour: параметры маршрутов: нет выбранных маршрутов"
+
+#: gtk_ardour/route_ui.cc:134
+msgid "mute change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220
+msgid "solo change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:284
+msgid "rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:423
+#, fuzzy
+msgid "Solo-safe"
+msgstr "Соло"
+
+#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474
+#, fuzzy
+msgid "MIDI Bind"
+msgstr "MIDI"
+
+#: gtk_ardour/route_ui.cc:445
+msgid "Pre Fader"
+msgstr "Пред фейдер"
+
+#: gtk_ardour/route_ui.cc:452
+msgid "Post Fader"
+msgstr "ПоÑÑ‚ фейдер"
+
+#: gtk_ardour/route_ui.cc:459
+msgid "Control Outs"
+msgstr "Контрольные выходы"
+
+#: gtk_ardour/route_ui.cc:466
+msgid "Main Outs"
+msgstr "Главные выходы"
+
+#: gtk_ardour/route_ui.cc:503
+msgid "mix group solo change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:537
+msgid "mix group mute change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:553
+msgid "mix group rec-enable change"
+msgstr ""
+
+#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258
+msgid "ardour: color selection"
+msgstr "ardour: выбор цвета"
+
+#: gtk_ardour/route_ui.cc:652
+#, fuzzy
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"You may also lose the playlist used by this track.\n"
+"(cannot be undone)"
+msgstr ""
+"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n"
+"(отмена невозможна)"
+
+#: gtk_ardour/route_ui.cc:654
+msgid ""
+"Do you really want to remove bus \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Ð’Ñ‹ дейÑтвительно хотите удалить шину \"%1\" ?\n"
+"(отмена невозможна)"
+
+#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299
+msgid "Yes, remove it."
+msgstr "Да, удалить."
+
+#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358
+msgid "new name: "
+msgstr "новое имÑ: "
+
+#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31
+msgid "Beats per minute"
+msgstr "Ударов в минуту"
+
+#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35
+#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163
+msgid "Beat"
+msgstr "ДолÑ"
+
+#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158
+msgid "Meter denominator"
+msgstr "Знаменатель размера"
+
+#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159
+msgid "Beats per bar"
+msgstr "Долей на такт"
+
+#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189
+msgid "whole (1)"
+msgstr "целых (1)"
+
+#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191
+msgid "second (2)"
+msgstr "половины (2)"
+
+#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193
+msgid "third (3)"
+msgstr "трети (3)"
+
+#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195
+#: gtk_ardour/tempo_dialog.cc:203
+msgid "quarter (4)"
+msgstr "четверти (4)"
+
+#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197
+msgid "eighth (8)"
+msgstr "воÑьмых (8)"
+
+#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199
+msgid "sixteenth (16)"
+msgstr "шеÑтьнадцатых (16)"
+
+#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201
+msgid "thirty-second (32)"
+msgstr "тридцать-вторых (32)"
+
+#: gtk_ardour/tempo_dialog.cc:301
+msgid "garbaged note type entry (%1)"
+msgstr "неÑÑное определение ноты (%1)"
+
+#: gtk_ardour/tempo_dialog.cc:311
+msgid "incomprehensible note type entry (%1)"
+msgstr "некорректное определение ноты (%1)"
+
+#: gtk_ardour/time_axis_view.cc:95
+msgid "gTortnam"
+msgstr ""
+
+#: gtk_ardour/time_axis_view.cc:446
+msgid "Largest"
+msgstr "ОгромнаÑ"
+
+#: gtk_ardour/time_axis_view.cc:447
+msgid "Large"
+msgstr "БольшаÑ"
+
+#: gtk_ardour/time_axis_view.cc:448
+msgid "Larger"
+msgstr "Больше"
+
+#: gtk_ardour/time_axis_view.cc:450
+msgid "Smaller"
+msgstr "Меньше"
+
+#: gtk_ardour/time_axis_view.cc:451
+msgid "Small"
+msgstr "МаленькаÑ"
+
+#: gtk_ardour/time_axis_view.cc:785
+msgid "unknown track height name \"%1\" in XML GUI information"
+msgstr "неизвеÑтное Ð¸Ð¼Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ñ‹ трека \"%1\" в XML опиÑании"
+
+#: gtk_ardour/time_axis_view_item.cc:69
+msgid "TimeAxisViewItemName"
+msgstr ""
+
+#: gtk_ardour/time_axis_view_item.cc:258
+msgid "new duration %1 frames is out of bounds for %2"
+msgstr ""
+
+#: gtk_ardour/time_selection.cc:40
+msgid "programming error: request for non-existent audio range (%1)!"
+msgstr "ошибка в программе: request for non-existent audio range (%1)!"
+
+#: gtk_ardour/utils.cc:57
+msgid ""
+"\"\n"
+"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="
+msgstr ""
+
+#: gtk_ardour/utils.cc:66
+msgid "aeiou"
+msgstr ""
+
+#: gtk_ardour/utils.cc:75
+msgid "AEIOU"
+msgstr ""
+
+#: gtk_ardour/utils.cc:84
+msgid "bcdfghjklmnpqrtvwxyz"
+msgstr ""
+
+#: gtk_ardour/utils.cc:93
+msgid "BCDFGHJKLMNPQRTVWXYZ"
+msgstr ""
+
+#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265
+msgid "bad XPM header %1"
+msgstr "ошибка в XPM заголовке %1"
+
+#: gtk_ardour/utils.cc:516
+msgid "missing RGBA style for \"%1\""
+msgstr ""
+
+#: gtk_ardour/visual_time_axis.cc:297
+msgid ""
+"Do you really want to remove track \"%1\" ?\n"
+"(cannot be undone)"
+msgstr ""
+"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n"
+"(отмена невозможна)"
+
+#: gtk_ardour/visual_time_axis.cc:385
+msgid "A track already exists with that name"
+msgstr "Трек Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует"
+
+#~ msgid "Export to CD"
+#~ msgstr "ЭкÑпорт на CD"
+
+#~ msgid "programming error: location/marker map does not contain location!"
+#~ msgstr "ошибка в программе: location/marker map does not contain location!"
+
+#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$"
+#~ msgstr "Файлы изображений toggle-button-[0-9]*.xpm$ не найдены"
+
+#~ msgid ""
+#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$"
+#~ msgstr "Файлы изображений small-round-button-[0-9]*.xpm$ не найдены"
+
+#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$"
+#~ msgstr "Файлы изображений hslider[0-9]*.xpm$ не найдены"
+
+#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$"
+#~ msgstr "Файлы изображений vslider[0-9]*.xpm$ не найдены"
+
+#~ msgid "Trace MIDI Input"
+#~ msgstr "ТраÑÑировка входа MIDI"
+
+#~ msgid "Trace MIDI Output"
+#~ msgstr "ТраÑÑировка выхода MIDI"
+
+#~ msgid "MTC Port"
+#~ msgstr "MTC порт"
+
+#~ msgid "attempt to timestretch a non-audio track!"
+#~ msgstr "попытка применить timestretch-Ñффект к неаудиотреку"
+
+#~ msgid "cannot create timestretch thread - operation not carried out"
+#~ msgstr "cannot create timestretch thread - operation not carried out"
+
+#~ msgid "ardour: tempo editor"
+#~ msgstr "ardour: редактор ритма"
+
+#~ msgid "ardour_add_track_bus"
+#~ msgstr "ardour_add_track_bus"
+
+#~ msgid "ok"
+#~ msgstr "ок"
+
+#, fuzzy
+#~ msgid "apply"
+#~ msgstr "авоÑпр"
+
+#, fuzzy
+#~ msgid "fade"
+#~ msgstr "Затухание"
+
+#, fuzzy
+#~ msgid "Edit left"
+#~ msgstr "Режим редактированиÑ"
+
+#, fuzzy
+#~ msgid "Edit right"
+#~ msgstr "Редактировать Ñочетание"
+
+#, fuzzy
+#~ msgid "Edit fade"
+#~ msgstr "Режим редактированиÑ"
+
+#~ msgid "Export region"
+#~ msgstr "ЭкÑпорт облаÑти"
+
+#~ msgid "Region"
+#~ msgstr "ОблаÑÑ‚ÑŒ"
+
+#~ msgid "Play selected region"
+#~ msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+
+#~ msgid "clear connections"
+#~ msgstr "очиÑтить Ñоед."
+
+#, fuzzy
+#~ msgid "Crossfades in use"
+#~ msgstr "КроÑÑфейд"
+
+#, fuzzy
+#~ msgid "outside this computer"
+#~ msgstr "Скрыть трек"
+
+#, fuzzy
+#~ msgid "inside this computer"
+#~ msgstr "Скрыть трек"
diff --git a/gtk2_ardour/point_selection.h b/gtk2_ardour/point_selection.h
new file mode 100644
index 0000000000..d0ad08e602
--- /dev/null
+++ b/gtk2_ardour/point_selection.h
@@ -0,0 +1,12 @@
+#ifndef __ardour_gtk_point_selection_h__
+#define __ardour_gtk_point_selection_h__
+
+#include <list>
+
+#include "automation_selectable.h"
+
+struct PointSelection : public std::list<AutomationSelectable>
+{
+};
+
+#endif /* __ardour_gtk_point_selection_h__ */
diff --git a/gtk2_ardour/prompter.cc b/gtk2_ardour/prompter.cc
new file mode 100644
index 0000000000..7bbb9daea9
--- /dev/null
+++ b/gtk2_ardour/prompter.cc
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include "prompter.h"
+#include "ardour_ui.h"
+
+using namespace SigC;
+
+ArdourPrompter::ArdourPrompter (bool modal)
+ : Gtkmmext::Prompter (modal)
+{
+ the_entry().focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event));
+ the_entry().focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event));
+}
+
diff --git a/gtk2_ardour/prompter.h b/gtk2_ardour/prompter.h
new file mode 100644
index 0000000000..c2b78c770a
--- /dev/null
+++ b/gtk2_ardour/prompter.h
@@ -0,0 +1,32 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_prompter_h__
+#define __ardour_gtk_prompter_h__
+
+#include <gtkmmext/prompter.h>
+
+class ArdourPrompter : public Gtkmmext::Prompter
+{
+ public:
+ ArdourPrompter (bool modal = false);
+};
+
+#endif /* __ardour_gtk_prompter_h__ */
diff --git a/gtk2_ardour/public_editor.cc b/gtk2_ardour/public_editor.cc
new file mode 100644
index 0000000000..f14a216dcc
--- /dev/null
+++ b/gtk2_ardour/public_editor.cc
@@ -0,0 +1,144 @@
+#include "public_editor.h"
+#include "editor.h"
+
+PublicEditor* PublicEditor::_instance = 0;
+
+PublicEditor::PublicEditor ()
+ : Window (GTK_WINDOW_TOPLEVEL),
+ KeyboardTarget (*this, "editor")
+{
+}
+
+PublicEditor::~PublicEditor()
+{
+}
+
+gint
+PublicEditor::canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_fade_in_event (item, event, data);
+}
+gint
+PublicEditor::canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_fade_in_handle_event (item, event, data);
+}
+gint
+PublicEditor::canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_fade_out_event (item, event, data);
+}
+gint
+PublicEditor::canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_fade_out_handle_event (item, event, data);
+}
+gint
+PublicEditor::canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_crossfade_view_event (item, event, data);
+}
+gint
+PublicEditor::canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_region_view_event (item, event, data);
+}
+gint
+PublicEditor::canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_region_view_name_highlight_event (item, event, data);
+}
+gint
+PublicEditor::canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_region_view_name_event (item, event, data);
+}
+gint
+PublicEditor::canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_stream_view_event (item, event, data);
+}
+gint
+PublicEditor::canvas_automation_track_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_automation_track_event (item, event, data);
+}
+gint
+PublicEditor::canvas_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_marker_event (item, event, data);
+}
+gint
+PublicEditor::canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_zoom_rect_event (item, event, data);
+}
+gint
+PublicEditor::canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_selection_rect_event (item, event, data);
+}
+gint
+PublicEditor::canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_selection_start_trim_event (item, event, data);
+}
+gint
+PublicEditor::canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_selection_end_trim_event (item, event, data);
+}
+gint
+PublicEditor::canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_control_point_event (item, event, data);
+}
+gint
+PublicEditor::canvas_line_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_line_event (item, event, data);
+}
+gint
+PublicEditor::canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_tempo_marker_event (item, event, data);
+}
+gint
+PublicEditor::canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_meter_marker_event (item, event, data);
+}
+gint
+PublicEditor::canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_tempo_bar_event (item, event, data);
+}
+gint
+PublicEditor::canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_meter_bar_event (item, event, data);
+}
+gint
+PublicEditor::canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_marker_bar_event (item, event, data);
+}
+gint
+PublicEditor::canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_range_marker_bar_event (item, event, data);
+}
+gint
+PublicEditor::canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_transport_marker_bar_event (item, event, data);
+}
+
+gint
+PublicEditor::canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_imageframe_item_view_event(item, event, data);
+}
+gint
+PublicEditor::canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_imageframe_view_event(item, event, data);
+}
+gint
+PublicEditor::canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_imageframe_start_handle_event(item, event, data);
+}
+gint
+PublicEditor::canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_imageframe_end_handle_event(item, event, data);
+}
+gint
+PublicEditor::canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_marker_time_axis_view_event(item, event, data);
+}
+gint
+PublicEditor::canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_markerview_item_view_event(item, event, data);
+}
+gint
+PublicEditor::canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_markerview_start_handle_event(item, event, data);
+}
+gint
+PublicEditor::canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) {
+ return instance()->_canvas_markerview_end_handle_event(item, event, data);
+}
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
new file mode 100644
index 0000000000..e60f14f6b2
--- /dev/null
+++ b/gtk2_ardour/public_editor.h
@@ -0,0 +1,187 @@
+#ifndef __gtk_ardour_public_editor_h__
+#define __gtk_ardour_public_editor_h__
+
+#include <map>
+
+#include <string>
+#include <glib.h>
+#include <gdk/gdktypes.h>
+#include <gtk-canvas.h>
+#include <gtk--/window.h>
+#include <jack/types.h>
+#include <sigc++/signal_system.h>
+
+#include "editing.h"
+#include "keyboard_target.h"
+
+namespace ARDOUR {
+ class Session;
+ class AudioExportSpecification;
+ class AudioRegion;
+ class Playlist;
+ class RouteGroup;
+}
+
+namespace Gtk {
+ class Container;
+ class Menu;
+}
+
+class Editor;
+class TimeAxisViewItem;
+class TimeAxisView;
+class PluginSelector;
+class PlaylistSelector;
+class XMLNode;
+class Selection;
+
+class PublicEditor : public Gtk::Window, public Stateful, public KeyboardTarget {
+ public:
+ PublicEditor();
+ virtual ~PublicEditor();
+
+ typedef list<TimeAxisView *> TrackViewList;
+
+ static PublicEditor* instance() { return _instance; }
+
+ virtual void connect_to_session (ARDOUR::Session*) = 0;
+ virtual ARDOUR::Session* current_session() const = 0;
+ virtual void set_snap_to (Editing::SnapType) = 0;
+ virtual void set_snap_mode (Editing::SnapMode) = 0;
+ virtual void set_snap_threshold (double) = 0;
+ virtual void undo (uint32_t n = 1) = 0;
+ virtual void redo (uint32_t n = 1) = 0;
+ virtual void set_mouse_mode (Editing::MouseMode, bool force = false) = 0;
+ virtual void step_mouse_mode (bool next) = 0;
+ virtual Editing::MouseMode current_mouse_mode () = 0;
+ virtual void add_imageframe_time_axis(std::string track_name, void*) = 0;
+ virtual void add_imageframe_marker_time_axis(std::string track_name, TimeAxisView* marked_track, void*) = 0;
+ virtual void connect_to_image_compositor() = 0;
+ virtual void scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) = 0;
+ virtual TimeAxisView* get_named_time_axis(std::string name) = 0;
+ virtual bool consider_auditioning (ARDOUR::AudioRegion*) = 0;
+ virtual void set_show_waveforms (bool yn) = 0;
+ virtual bool show_waveforms() const = 0;
+ virtual void set_show_waveforms_recording (bool yn) = 0;
+ virtual bool show_waveforms_recording() const = 0;
+ virtual void new_region_from_selection () = 0;
+ virtual void separate_region_from_selection () = 0;
+ virtual void toggle_playback (bool with_abort) = 0;
+ virtual void set_edit_menu (Gtk::Menu&) = 0;
+ virtual jack_nframes_t unit_to_frame (double unit) = 0;
+ virtual double frame_to_unit (jack_nframes_t frame) = 0;
+ virtual double frame_to_unit (double frame) = 0;
+ virtual jack_nframes_t pixel_to_frame (double pixel) = 0;
+ virtual gulong frame_to_pixel (jack_nframes_t frame) = 0;
+ virtual Selection& get_selection() const = 0;
+ virtual Selection& get_cut_buffer() const = 0;
+ virtual void play_selection () = 0;
+ virtual void set_show_measures (bool yn) = 0;
+ virtual bool show_measures () const = 0;
+ virtual void export_session() = 0;
+ virtual void export_selection() = 0;
+ 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 void route_name_changed (TimeAxisView *) = 0;
+ virtual void clear_playlist (ARDOUR::Playlist&) = 0;
+ virtual void set_selected_mixer_strip (TimeAxisView&) = 0;
+ virtual void unselect_strip_in_display (TimeAxisView& tv) = 0;
+ virtual void set_follow_playhead (bool yn) = 0;
+ virtual void toggle_follow_playhead () = 0;
+ virtual bool follow_playhead() const = 0;
+ virtual void toggle_xfade_visibility () = 0;
+ virtual void set_xfade_visibility (bool yn) = 0;
+ virtual bool xfade_visibility() const = 0;
+ virtual void ensure_float (Gtk::Window&) = 0;
+ virtual void show_window () = 0;
+ virtual TrackViewList* get_valid_views (TimeAxisView*, ARDOUR::RouteGroup* grp = 0) = 0;
+ virtual jack_nframes_t leftmost_position() const = 0;
+ virtual jack_nframes_t current_page_frames() const = 0;
+ virtual void temporal_zoom_step (bool coarser) = 0;
+ virtual void scroll_tracks_down_line () = 0;
+ virtual void scroll_tracks_up_line () = 0;
+ virtual bool new_regionviews_display_gain () = 0;
+ virtual void prepare_for_cleanup () = 0;
+ virtual void reposition_x_origin (jack_nframes_t frame) = 0;
+ virtual void remove_last_capture () = 0;
+
+ SigC::Signal1<void,Editing::DisplayControl> DisplayControlChanged;
+ SigC::Signal0<void> ZoomFocusChanged;
+ SigC::Signal0<void> ZoomChanged;
+ SigC::Signal0<void> XOriginChanged;
+ SigC::Signal0<void> Resized;
+
+ static gint canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_line_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data);
+ static gint canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) ;
+ static gint canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) ;
+ static gint canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ static gint canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ static gint canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ static gint canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ static gint canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ static gint canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+ static gint canvas_automation_track_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ;
+
+ protected:
+ virtual gint _canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_line_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+ virtual gint _canvas_automation_track_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0;
+
+ static PublicEditor* _instance;
+};
+
+#endif // __gtk_ardour_public_editor_h__
diff --git a/gtk2_ardour/redirect_automation_line.cc b/gtk2_ardour/redirect_automation_line.cc
new file mode 100644
index 0000000000..138d376a65
--- /dev/null
+++ b/gtk2_ardour/redirect_automation_line.cc
@@ -0,0 +1,95 @@
+/*
+ Copyright (C) 2002-2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include "public_editor.h"
+#include "redirect_automation_line.h"
+#include "audio_time_axis.h"
+#include "utils.h"
+
+#include <ardour/session.h>
+#include <ardour/ladspa_plugin.h>
+#include <ardour/insert.h>
+#include <ardour/curve.h>
+
+#include "i18n.h"
+
+using namespace std;
+using namespace ARDOUR;
+
+RedirectAutomationLine::RedirectAutomationLine (string name, Redirect& rd, uint32_t port, Session& s,
+ TimeAxisView& tv, GtkCanvasItem* parent,
+ AutomationList& l,
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer))
+
+ : AutomationLine (name, tv, parent, l, point_callback, line_callback),
+ session (s),
+ _redirect (rd),
+ _port (port)
+{
+ set_verbose_cursor_uses_gain_mapping (false);
+
+ PluginInsert *pi;
+ Plugin::ParameterDescriptor desc;
+
+ if ((pi = dynamic_cast<PluginInsert*>(&_redirect)) == 0) {
+ fatal << _("redirect automation created for non-plugin") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ pi->plugin().get_parameter_descriptor (_port, desc);
+
+ upper = desc.upper;
+ lower = desc.lower;
+
+ if (desc.toggled) {
+ no_draw = true;
+ return;
+ }
+
+ no_draw = false;
+ range = upper - lower;
+
+ /* XXX set min/max for underlying curve ??? */
+}
+
+string
+RedirectAutomationLine::get_verbose_cursor_string (float fraction)
+{
+ char buf[32];
+
+ snprintf (buf, sizeof (buf), "%.2f", lower + (fraction * range));
+ return buf;
+}
+
+void
+RedirectAutomationLine::view_to_model_y (double& y)
+{
+ y = lower + (y * range);
+}
+
+void
+RedirectAutomationLine::model_to_view_y (double& y)
+{
+ y = (y - lower) / range;
+ y = max (0.0, y);
+ y = min (y, 1.0);
+}
+
diff --git a/gtk2_ardour/redirect_automation_line.h b/gtk2_ardour/redirect_automation_line.h
new file mode 100644
index 0000000000..1d5971fe58
--- /dev/null
+++ b/gtk2_ardour/redirect_automation_line.h
@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_redirect_automation_line_h__
+#define __ardour_gtk_redirect_automation_line_h__
+
+#include <ardour/ardour.h>
+#include <gtk-canvas.h>
+#include <gtk--.h>
+
+#include "automation_line.h"
+
+namespace ARDOUR {
+ class Session;
+ class Redirect;
+}
+
+class TimeAxisView;
+
+class RedirectAutomationLine : public AutomationLine
+{
+ public:
+ RedirectAutomationLine (string name, ARDOUR::Redirect&, uint32_t port, ARDOUR::Session&, TimeAxisView&, GtkCanvasItem* parent,
+ ARDOUR::AutomationList&,
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer));
+
+ uint32_t port() const { return _port; }
+ ARDOUR::Redirect& redirect() const { return _redirect; }
+
+ string get_verbose_cursor_string (float);
+
+ private:
+ ARDOUR::Session& session;
+ ARDOUR::Redirect& _redirect;
+ uint32_t _port;
+ float upper;
+ float lower;
+ float range;
+
+ void view_to_model_y (double&);
+ void model_to_view_y (double&);
+ void change_model (uint32_t, double x, double y);
+ void change_model_range (uint32_t, uint32_t, double delta);
+};
+
+#endif /* __ardour_gtk_region_gain_line_h__ */
diff --git a/gtk2_ardour/redirect_automation_time_axis.cc b/gtk2_ardour/redirect_automation_time_axis.cc
new file mode 100644
index 0000000000..5bbd7e290f
--- /dev/null
+++ b/gtk2_ardour/redirect_automation_time_axis.cc
@@ -0,0 +1,169 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/redirect.h>
+#include <ardour/session.h>
+#include <cstdlib>
+
+#include "redirect_automation_time_axis.h"
+#include "automation_line.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+
+RedirectAutomationTimeAxisView::RedirectAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, Widget* p, std::string n,
+ uint32_t prt, Redirect& rd, string state_name)
+
+ : AxisView (s),
+ AutomationTimeAxisView (s, r, e, parent, p, n, state_name, rd.name()),
+ redirect (rd),
+ port (prt)
+
+{
+ char buf[32];
+ xml_node = 0;
+ _marked_for_display = false;
+
+ ensure_xml_node ();
+
+ XMLNodeList kids;
+ XMLNodeConstIterator iter;
+
+ kids = xml_node->children ();
+
+ snprintf (buf, sizeof(buf), "Port_%" PRIu32, port);
+
+ for (iter = kids.begin(); iter != kids.end(); ++iter) {
+ if ((*iter)->name() == buf) {
+
+ XMLProperty *shown = (*iter)->property("shown_editor");
+
+ if (shown && shown->value() == "yes") {
+ _marked_for_display = true;
+ }
+ break;
+ }
+ }
+}
+
+RedirectAutomationTimeAxisView::~RedirectAutomationTimeAxisView ()
+{
+}
+
+void
+RedirectAutomationTimeAxisView::add_automation_event (GtkCanvasItem* item, GdkEvent* event, jack_nframes_t when, double y)
+{
+ double x = 0;
+
+ gtk_canvas_item_w2i (canvas_display, &x, &y);
+
+ /* compute vertical fractional position */
+
+ if (y < 0)
+ y = 0;
+ else if (y > height)
+ y = height;
+
+ y = 1.0 - (y / height);
+
+ /* map to model space */
+
+ if (!lines.empty()) {
+ AutomationList& alist (redirect.automation_list(port));
+ string description = _("add automation event to ");
+ description += redirect.describe_parameter (port);
+
+ lines.front()->view_to_model_y (y);
+
+ _session.begin_reversible_command (description);
+ _session.add_undo (alist.get_memento());
+ alist.add (when, y);
+ _session.add_redo_no_execute (alist.get_memento());
+ _session.commit_reversible_command ();
+ _session.set_dirty ();
+ }
+}
+
+void
+RedirectAutomationTimeAxisView::ensure_xml_node ()
+{
+ if (xml_node == 0) {
+ if ((xml_node = redirect.extra_xml ("GUI")) == 0) {
+ xml_node = new XMLNode ("GUI");
+ redirect.add_extra_xml (*xml_node);
+ }
+ }
+}
+
+guint32
+RedirectAutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
+{
+ ensure_xml_node ();
+ update_extra_xml_shown (true);
+
+ return TimeAxisView::show_at (y, nth, parent);
+}
+
+void
+RedirectAutomationTimeAxisView::hide ()
+{
+ ensure_xml_node ();
+ update_extra_xml_shown (false);
+
+ TimeAxisView::hide ();
+}
+
+
+void
+RedirectAutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
+{
+ char buf[32];
+
+ XMLNodeList nlist = xml_node->children ();
+ XMLNodeConstIterator i;
+ XMLNode * port_node = 0;
+
+ snprintf (buf, sizeof(buf), "Port_%" PRIu32, port);
+
+ for (i = nlist.begin(); i != nlist.end(); ++i) {
+ if ((*i)->name() == buf) {
+ port_node = (*i);
+ break;
+ }
+ }
+
+ if (!port_node) {
+ port_node = new XMLNode(buf);
+ xml_node->add_child_nocopy(*port_node);
+ }
+
+ port_node->add_property ("shown_editor", editor_shown ? "yes": "no");
+
+}
+
+void
+RedirectAutomationTimeAxisView::set_automation_state (AutoState state)
+{
+ if (!ignore_state_request) {
+ redirect.automation_list (port).set_automation_state (state);
+ }
+}
diff --git a/gtk2_ardour/redirect_automation_time_axis.h b/gtk2_ardour/redirect_automation_time_axis.h
new file mode 100644
index 0000000000..d4e7a46e71
--- /dev/null
+++ b/gtk2_ardour/redirect_automation_time_axis.h
@@ -0,0 +1,43 @@
+#ifndef __ardour_gtk_redirect_automation_time_axis_h__
+#define __ardour_gtk_redirect_automation_time_axis_h__
+
+#include <pbd/xml++.h>
+#include "automation_time_axis.h"
+
+namespace ARDOUR {
+ class Redirect;
+}
+
+class RedirectAutomationTimeAxisView : public AutomationTimeAxisView
+{
+ public:
+ RedirectAutomationTimeAxisView (ARDOUR::Session&,
+ ARDOUR::Route&,
+ PublicEditor&,
+ TimeAxisView& parent,
+ Gtk::Widget* parent,
+ std::string name,
+ uint32_t port,
+ ARDOUR::Redirect& rd,
+ std::string state_name);
+
+ ~RedirectAutomationTimeAxisView();
+
+ void add_automation_event (GtkCanvasItem *item, GdkEvent *event, jack_nframes_t, double);
+
+ guint32 show_at (double y, int& nth, Gtk::VBox *parent);
+ void hide ();
+
+
+ private:
+ ARDOUR::Redirect& redirect;
+ uint32_t port;
+
+ XMLNode *xml_node;
+ void ensure_xml_node();
+ void update_extra_xml_shown (bool editor_shown);
+
+ void set_automation_state (ARDOUR::AutoState);
+};
+
+#endif /* __ardour_gtk_redirect_automation_time_axis_h__ */
diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc
new file mode 100644
index 0000000000..66fc0cb347
--- /dev/null
+++ b/gtk2_ardour/redirect_box.cc
@@ -0,0 +1,1203 @@
+/*
+ Copyright (C) 2000-2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <glib.h>
+
+#include <sigc++/bind.h>
+
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/choice.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/doi.h>
+
+#include <ardour/ardour.h>
+#include <ardour/session.h>
+#include <ardour/audioengine.h>
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/diskstream.h>
+#include <ardour/send.h>
+#include <ardour/insert.h>
+#include <ardour/ladspa_plugin.h>
+#include <ardour/connection.h>
+#include <ardour/session_connection.h>
+
+#include "ardour_ui.h"
+#include "ardour_dialog.h"
+#include "ardour_message.h"
+#include "public_editor.h"
+#include "redirect_box.h"
+#include "keyboard.h"
+#include "plugin_selector.h"
+#include "route_redirect_selection.h"
+#include "mixer_ui.h"
+
+#include "plugin_ui.h"
+#include "send_ui.h"
+#include "io_selector.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace Gtkmmext;
+
+
+
+RedirectBox::RedirectBox (Placement pcmnt, Session& sess, Route& rt, PluginSelector &plugsel, RouteRedirectSelection & rsel, bool owner_is_mixer)
+ : _route(rt),
+ _session(sess),
+ _owner_is_mixer (owner_is_mixer),
+ _placement(pcmnt),
+ _plugin_selector(plugsel),
+ _rr_selection(rsel),
+ redirect_display (1)
+{
+ _width = Wide;
+ redirect_menu = 0;
+ send_action_menu = 0;
+ redirect_drag_in_progress = false;
+
+ redirect_display.set_name ("MixerRedirectSelector");
+ redirect_display.column_titles_active ();
+ redirect_display.set_reorderable (true);
+ redirect_display.set_button_actions (0, (GTK_BUTTON_SELECTS|GTK_BUTTON_DRAGS));
+ redirect_display.set_button_actions (1, 0);
+ redirect_display.set_button_actions (2, 0);
+ redirect_display.set_button_actions (3, 0);
+ redirect_display.drag_begin.connect (slot (*this, &RedirectBox::redirect_drag_begin));
+ redirect_display.drag_end.connect (slot (*this, &RedirectBox::redirect_drag_end));
+ redirect_display.set_usize (-1, 48);
+ redirect_display.set_selection_mode (GTK_SELECTION_MULTIPLE);
+ redirect_display.set_shadow_type (GTK_SHADOW_IN);
+ redirect_display.row_move.connect (slot (*this, &RedirectBox::redirects_reordered));
+
+ redirect_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ redirect_scroller.add (redirect_display);
+ redirect_eventbox.add (redirect_scroller);
+ pack_start (redirect_eventbox, true, true);
+
+ redirect_scroller.show ();
+ redirect_display.show ();
+ redirect_eventbox.show ();
+ show_all ();
+
+ _route.redirects_changed.connect (slot (*this, &RedirectBox::redirects_changed));
+
+ redirect_display.button_press_event.connect (slot (*this, &RedirectBox::redirect_button));
+ redirect_display.button_release_event.connect (slot (*this, &RedirectBox::redirect_button));
+
+ redirect_display.button_release_event.connect_after (slot (do_not_propagate));
+ _plugin_selector.hide.connect(slot(*this,&RedirectBox::disconnect_newplug));
+
+ redirect_display.click_column.connect (slot (*this, &RedirectBox::show_redirect_menu));
+
+ set_stuff_from_route ();
+
+ /* start off as a passthru strip. we'll correct this, if necessary,
+ in update_diskstream_display().
+ */
+
+ //set_name ("AudioTrackStripBase");
+
+ /* now force an update of all the various elements */
+
+ redirects_changed (0);
+
+ //add_events (GDK_BUTTON_RELEASE_MASK);
+}
+
+RedirectBox::~RedirectBox ()
+{
+// GoingAway(); /* EMIT_SIGNAL */
+
+}
+
+void
+RedirectBox::set_stuff_from_route ()
+{
+}
+
+void
+RedirectBox::set_title (const std::string & title)
+{
+ redirect_display.column(0).set_title (title);
+}
+
+void
+RedirectBox::set_title_shown (bool flag)
+{
+ if (flag) {
+ redirect_display.column_titles_show();
+ } else {
+ redirect_display.column_titles_hide();
+ }
+}
+
+
+void
+RedirectBox::update()
+{
+ redirects_changed(0);
+}
+
+
+void
+RedirectBox::set_width (Width w)
+{
+ if (_width == w) {
+ return;
+ }
+ _width = w;
+
+ redirects_changed(0);
+}
+
+
+void
+RedirectBox::remove_redirect_gui (Redirect *redirect)
+{
+ Insert *insert = 0;
+ Send *send = 0;
+ PortInsert *port_insert = 0;
+
+ if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
+
+ if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
+ PortInsertUI *io_selector = reinterpret_cast<PortInsertUI *> (port_insert->get_gui());
+ port_insert->set_gui (0);
+ delete io_selector;
+ }
+
+ } else if ((send = dynamic_cast<Send *> (insert)) != 0) {
+ SendUIWindow *sui = reinterpret_cast<SendUIWindow*> (send->get_gui());
+ send->set_gui (0);
+ delete sui;
+ }
+}
+
+void
+RedirectBox::build_send_action_menu ()
+
+{
+ using namespace Menu_Helpers;
+
+ send_action_menu = new Menu;
+ send_action_menu->set_name ("ArdourContextMenu");
+ MenuList& items = send_action_menu->items();
+
+ items.push_back (MenuElem (_("New send"), slot (*this, &RedirectBox::new_send)));
+ items.push_back (MenuElem (_("Show send controls"), slot (*this, &RedirectBox::show_send_controls)));
+}
+
+void
+RedirectBox::show_send_controls ()
+
+{
+}
+
+void
+RedirectBox::new_send ()
+
+{
+}
+
+void
+RedirectBox::show_redirect_menu (gint arg)
+{
+ if (redirect_menu == 0) {
+ redirect_menu = build_redirect_menu (redirect_display);
+ }
+
+ redirect_menu->popup (1, 0);
+}
+
+void
+RedirectBox::redirect_drag_begin (GdkDragContext *context)
+{
+ redirect_drag_in_progress = true;
+}
+
+void
+RedirectBox::redirect_drag_end (GdkDragContext *context)
+{
+ redirect_drag_in_progress = false;
+}
+
+gint
+RedirectBox::redirect_button (GdkEventButton *ev)
+{
+ gint row=-1, col=-1;
+ Redirect *redirect;
+ CList *clist = &redirect_display;
+
+ if (clist->get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 1) {
+ redirect = 0;
+ } else {
+ redirect = reinterpret_cast<Redirect *> (clist->row (row).get_data ());
+ }
+
+ switch (ev->type) {
+ case GDK_BUTTON_PRESS:
+ return FALSE;
+
+ case GDK_2BUTTON_PRESS:
+ if (ev->state != 0) {
+ return FALSE;
+ }
+ /* might be edit event, see below */
+ break;
+
+ case GDK_BUTTON_RELEASE:
+ if (redirect_drag_in_progress) {
+ // drag-n-drop reordering
+ return stop_signal (*clist, "button-release-event");
+ }
+ /* continue on */
+ break;
+
+ default:
+ /* shouldn't be here, but gcc complains */
+ return FALSE;
+ }
+
+ if (redirect && Keyboard::is_delete_event (ev)) {
+
+ Gtk::Main::idle.connect (bind (slot (*this, &RedirectBox::idle_delete_redirect), redirect));
+ return TRUE;
+
+ } else if (redirect && (Keyboard::is_edit_event (ev) || ev->type == GDK_2BUTTON_PRESS)) {
+
+ if (_session.engine().connected()) {
+ /* XXX giving an error message here is hard, because we may be in the midst of a button press */
+ edit_redirect (redirect);
+ }
+ return TRUE;
+
+ } else if (Keyboard::is_context_menu_event (ev)) {
+ show_redirect_menu(0);
+ return stop_signal (*clist, "button-release-event");
+
+ } else {
+ switch (ev->button) {
+ case 1:
+ if (redirect) {
+ using namespace CList_Helpers;
+ SelectionList& sel (redirect_display.selection());
+ bool selecting = true;
+
+ for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) {
+ if ((*i).get_row_num() == row) {
+ // clicked row is not selected yet, so it is
+ // becoming selected now
+ selecting = false;
+ break;
+ }
+ }
+
+ if (selecting) {
+ RedirectSelected (redirect); // emit
+ }
+ else {
+ RedirectUnselected (redirect); // emit
+ }
+ }
+ return FALSE;
+ break;
+
+ case 2:
+ if (redirect) {
+ redirect->set_active (!redirect->active(), this);
+ }
+ break;
+
+ case 3:
+ break;
+
+ default:
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+Menu *
+RedirectBox::build_redirect_menu (CList& clist)
+{
+ using namespace Menu_Helpers;
+ Menu * menu = new Menu;
+ menu->set_name ("ArdourContextMenu");
+ MenuList& items = menu->items();
+ menu->set_name ("ArdourContextMenu");
+
+ /* new stuff */
+
+ items.push_back (MenuElem (_("New Plugin ..."), slot (*this, &RedirectBox::choose_plugin)));
+ items.push_back (MenuElem (_("New Insert"), slot (*this, &RedirectBox::choose_insert)));
+ items.push_back (MenuElem (_("New Send ..."), slot (*this, &RedirectBox::choose_send)));
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Clear"), slot (*this, &RedirectBox::clear_redirects)));
+ items.push_back (SeparatorElem());
+
+ /* standard editing stuff */
+
+ items.push_back (MenuElem (_("Cut"), slot (*this, &RedirectBox::cut_redirects)));
+ selection_dependent_items.push_back (items.back());
+ items.push_back (MenuElem (_("Copy"), slot (*this, &RedirectBox::copy_redirects)));
+ selection_dependent_items.push_back (items.back());
+ items.push_back (MenuElem (_("Paste"), slot (*this, &RedirectBox::paste_redirects)));
+ redirect_paste_item = items.back();
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Rename"), slot (*this, &RedirectBox::rename_redirects)));
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Select all"), slot (*this, &RedirectBox::select_all_redirects)));
+ items.push_back (MenuElem (_("Deselect all"), slot (*this, &RedirectBox::deselect_all_redirects)));
+
+#if LATER
+ Menu *select_sub_menu = manage (new Menu);
+ MenuList& sitems = select_sub_menu->items();
+ select_sub_menu->set_name ("ArdourContextMenu");
+
+ sitems.push_back (MenuElem (_("Plugins")));
+ sitems.push_back (MenuElem (_("Inserts")));
+ sitems.push_back (MenuElem (_("Sends")));
+ sitems.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Select all ..."), *select_sub_menu));
+#endif
+ /* activation */
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Activate"), bind (slot (*this, &RedirectBox::for_selected_redirects),
+ &RedirectBox::activate_redirect)));
+ selection_dependent_items.push_back (items.back());
+ items.push_back (MenuElem (_("Deactivate"), bind (slot (*this, &RedirectBox::for_selected_redirects),
+ &RedirectBox::deactivate_redirect)));
+ selection_dependent_items.push_back (items.back());
+ items.push_back (SeparatorElem());
+
+ items.push_back (MenuElem (_("Activate All"), bind (slot (*this, &RedirectBox::all_redirects_active), true)));
+ items.push_back (MenuElem (_("Deactivate All"), bind (slot (*this, &RedirectBox::all_redirects_active), false)));
+
+ /* show editors */
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Edit"), bind (slot (*this, &RedirectBox::for_selected_redirects),
+ &RedirectBox::edit_redirect)));
+ selection_dependent_items.push_back (items.back());
+
+ menu->map_event.connect (slot (*this, &RedirectBox::redirect_menu_map_handler));
+
+ return menu;
+}
+
+gint
+RedirectBox::redirect_menu_map_handler (GdkEventAny *ev)
+{
+ using namespace Menu_Helpers;
+ using namespace CList_Helpers;
+
+ Gtk::CList* clist = &redirect_display;
+
+ bool sensitive = !clist->selection().empty();
+
+ for (vector<MenuItem*>::iterator i = selection_dependent_items.begin(); i != selection_dependent_items.end(); ++i) {
+ (*i)->set_sensitive (sensitive);
+ }
+
+ redirect_paste_item->set_sensitive (!_rr_selection.redirects.empty());
+ return FALSE;
+}
+
+void
+RedirectBox::select_all_redirects ()
+{
+ redirect_display.selection().all();
+}
+
+void
+RedirectBox::deselect_all_redirects ()
+{
+ redirect_display.selection().clear ();
+}
+
+void
+RedirectBox::choose_plugin ()
+{
+ show_plugin_selector();
+}
+
+void
+RedirectBox::insert_plugin_chosen (Plugin *plugin)
+{
+ if (plugin) {
+
+ Redirect *redirect = new PluginInsert (_session, *plugin, _placement);
+
+ redirect->active_changed.connect (slot (*this, &RedirectBox::show_redirect_active));
+
+ uint32_t err_streams;
+
+ if (_route.add_redirect (redirect, this, &err_streams)) {
+ wierd_plugin_dialog (*plugin, err_streams, _route);
+ delete redirect;
+ }
+ }
+}
+
+void
+RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, IO& io)
+{
+ ArdourDialog dialog ("wierd plugin dialog");
+ Label label;
+ Button button (_("OK"));
+ VBox vpacker;
+ HBox button_box;
+
+ /* i hate this kind of code */
+
+ if (streams > p.get_info().n_inputs) {
+ label.set_text (compose (_(
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point, there are\n"
+"%3 active signal streams.\n"
+"\n"
+"This makes no sense - you are throwing away\n"
+"part of the signal."),
+ p.name(),
+ p.get_info().n_inputs,
+ streams));
+ } else if (streams < p.get_info().n_inputs) {
+ label.set_text (compose (_(
+"You attempted to add a plugin (%1).\n"
+"The plugin has %2 inputs\n"
+"but at the insertion point there are\n"
+"only %3 active signal streams.\n"
+"\n"
+"This makes no sense - unless the plugin supports\n"
+"side-chain inputs. A future version of Ardour will\n"
+"support this type of configuration."),
+ p.name(),
+ p.get_info().n_inputs,
+ streams));
+ } else {
+ label.set_text (compose (_(
+"You attempted to add a plugin (%1).\n"
+"\n"
+"The I/O configuration doesn't make sense:\n"
+"\n"
+"The plugin has %2 inputs and %3 outputs.\n"
+"The track/bus has %4 inputs and %5 outputs.\n"
+"The insertion point, has %6 active signals.\n"
+"\n"
+"Ardour does not understand what to do in such situations.\n"),
+ p.name(),
+ p.get_info().n_inputs,
+ p.get_info().n_outputs,
+ io.n_inputs(),
+ io.n_outputs(),
+ streams));
+ }
+
+ button_box.pack_start (button, false, true);
+
+ vpacker.set_spacing (12);
+ vpacker.set_border_width (12);
+ vpacker.pack_start (label);
+ vpacker.pack_start (button_box);
+
+ button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 0));
+
+ dialog.add (vpacker);
+ dialog.set_name (X_("PluginIODialog"));
+ dialog.set_position (GTK_WIN_POS_MOUSE);
+ dialog.set_modal (true);
+ dialog.show_all ();
+
+ dialog.realize();
+ dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ dialog.run ();
+}
+
+void
+RedirectBox::choose_insert ()
+{
+ Redirect *redirect = new PortInsert (_session, _placement);
+ redirect->active_changed.connect (slot (*this, &RedirectBox::show_redirect_active));
+ _route.add_redirect (redirect, this);
+}
+
+void
+RedirectBox::choose_send ()
+{
+ Send *send = new Send (_session, _placement);
+
+ /* XXX need redirect lock on route */
+
+ send->ensure_io (0, _route.max_redirect_outs(), false, this);
+
+ IOSelectorWindow *ios = new IOSelectorWindow (_session, *send, false, true);
+
+ ios->show_all ();
+ ios->selector().Finished.connect (bind (slot (*this, &RedirectBox::send_io_finished), static_cast<Redirect*>(send), ios));
+}
+
+void
+RedirectBox::send_io_finished (IOSelector::Result r, Redirect* redirect, IOSelectorWindow* ios)
+{
+ switch (r) {
+ case IOSelector::Cancelled:
+ delete redirect;
+ break;
+
+ case IOSelector::Accepted:
+ _route.add_redirect (redirect, this);
+ break;
+ }
+
+ delete_when_idle (ios);
+}
+
+void
+RedirectBox::disconnect_newplug ()
+{
+ newplug_connection.disconnect();
+}
+void
+RedirectBox::show_plugin_selector ()
+{
+ newplug_connection = _plugin_selector.PluginCreated.connect (slot (*this,&RedirectBox::insert_plugin_chosen));
+ _plugin_selector.show_all ();
+}
+
+void
+RedirectBox::redirects_changed (void *src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RedirectBox::redirects_changed), src));
+
+ redirect_display.freeze ();
+ redirect_display.clear ();
+ redirect_active_connections.clear ();
+ redirect_name_connections.clear ();
+
+ _route.foreach_redirect (this, &RedirectBox::add_redirect_to_display);
+
+ switch (_placement) {
+ case PreFader:
+ build_redirect_tooltip(redirect_display, redirect_eventbox, _("Pre-fader inserts, sends & plugins:"));
+ break;
+ case PostFader:
+ build_redirect_tooltip(redirect_display, redirect_eventbox, _("Post-fader inserts, sends & plugins:"));
+ break;
+ }
+ redirect_display.thaw ();
+}
+
+void
+RedirectBox::add_redirect_to_display (Redirect *redirect)
+{
+ const gchar *rowdata[1];
+ gint row;
+ CList *clist = 0;
+
+ if (redirect->placement() != _placement) {
+ return;
+ }
+
+ clist = &redirect_display;
+
+ string rname = redirect_name (*redirect);
+ rowdata[0] = rname.c_str();
+ clist->rows().push_back (rowdata);
+ row = clist->rows().size() - 1;
+ clist->row (row).set_data (redirect);
+
+ show_redirect_active (redirect, this);
+
+ redirect_active_connections.push_back
+ (redirect->active_changed.connect (slot (*this, &RedirectBox::show_redirect_active)));
+ redirect_name_connections.push_back
+ (redirect->name_changed.connect (bind (slot (*this, &RedirectBox::show_redirect_name), redirect)));
+}
+
+string
+RedirectBox::redirect_name (Redirect& redirect)
+{
+ Send *send;
+ string name_display;
+
+ if (!redirect.active()) {
+ name_display = " (";
+ }
+
+ if ((send = dynamic_cast<Send *> (&redirect)) != 0) {
+
+ name_display += '>';
+
+ /* grab the send name out of its overall name */
+
+ string::size_type lbracket, rbracket;
+ lbracket = send->name().find ('[');
+ rbracket = send->name().find (']');
+
+ switch (_width) {
+ case Wide:
+ name_display += send->name().substr (lbracket+1, lbracket-rbracket-1);
+ break;
+ case Narrow:
+ name_display += short_version (send->name().substr (lbracket+1, lbracket-rbracket-1), 4);
+ break;
+ }
+
+ } else {
+
+ switch (_width) {
+ case Wide:
+ name_display += redirect.name();
+ break;
+ case Narrow:
+ name_display += short_version (redirect.name(), 5);
+ break;
+ }
+
+ }
+
+ if (!redirect.active()) {
+ name_display += ')';
+ }
+
+ return name_display;
+}
+
+void
+RedirectBox::build_redirect_tooltip (CList& clist, EventBox& box, string start)
+{
+ CList_Helpers::RowIterator ri;
+ string tip(start);
+
+ for (ri = clist.rows().begin(); ri != clist.rows().end(); ++ri) {
+ tip += '\n';
+ tip += clist.cell(ri->get_row_num(), 0).get_text();
+ }
+ ARDOUR_UI::instance()->tooltips().set_tip (box, tip);
+}
+
+void
+RedirectBox::show_redirect_name (void* src, Redirect *redirect)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RedirectBox::show_redirect_name), src, redirect));
+
+ show_redirect_active (redirect, src);
+}
+
+void
+RedirectBox::show_redirect_active (Redirect *redirect, void *src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RedirectBox::show_redirect_active), redirect, src));
+
+ CList_Helpers::RowIterator ri;
+ CList *clist;
+
+ if ((ri = redirect_display.rows().find_data (redirect)) == redirect_display.rows().end()) {
+ return;
+ }
+
+ clist = &redirect_display;
+
+ clist->cell(ri->get_row_num(), 0).set_text (redirect_name (*redirect));
+
+ if (redirect->active()) {
+ // ri->select ();
+ } else {
+ // ri->unselect ();
+ }
+}
+
+void
+RedirectBox::redirects_reordered (gint src, gint dst)
+{
+ /* this is called before the reorder has been done, so just queue
+ something for idle time.
+ */
+
+ Gtk::Main::idle.connect (slot (*this, &RedirectBox::compute_redirect_sort_keys));
+}
+
+gint
+RedirectBox::compute_redirect_sort_keys ()
+{
+ CList_Helpers::RowList::iterator i;
+ uint32_t sort_key;
+
+ sort_key = 0;
+
+ for (i = redirect_display.rows().begin(); i != redirect_display.rows().end(); ++i) {
+ Redirect *redirect = reinterpret_cast<Redirect*> (i->get_data());
+ redirect->set_sort_key (sort_key, this);
+ sort_key++;
+ }
+
+ if (_route.sort_redirects ()) {
+
+ redirects_changed (0);
+
+ /* now tell them about the problem */
+
+ ArdourDialog dialog ("wierd plugin dialog");
+ Label label;
+ Button button (_("OK"));
+ VBox vpacker;
+ HBox button_box;
+
+ label.set_text (_("\
+You cannot reorder this set of redirects\n\
+in that way because the inputs and\n\
+outputs do not work correctly."));
+
+ button_box.pack_start (button, false, true);
+
+ vpacker.set_spacing (12);
+ vpacker.set_border_width (12);
+ vpacker.pack_start (label);
+ vpacker.pack_start (button_box);
+
+ button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 0));
+
+ dialog.add (vpacker);
+ dialog.set_name (X_("PluginIODialog"));
+ dialog.set_position (GTK_WIN_POS_MOUSE);
+ dialog.set_modal (true);
+ dialog.show_all ();
+
+ dialog.realize();
+ dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
+
+ dialog.run ();
+ }
+
+ return FALSE;
+}
+
+void
+RedirectBox::rename_redirects ()
+{
+ vector<Redirect*> to_be_renamed;
+
+ get_selected_redirects (to_be_renamed);
+
+ if (to_be_renamed.empty()) {
+ return;
+ }
+
+ for (vector<Redirect*>::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
+ rename_redirect (*i);
+ }
+}
+
+void
+RedirectBox::cut_redirects ()
+{
+ vector<Redirect*> to_be_removed;
+
+ get_selected_redirects (to_be_removed);
+
+ if (to_be_removed.empty()) {
+ return;
+ }
+
+ /* this essentially transfers ownership of the redirect
+ of the redirect from the route to the mixer
+ selection.
+ */
+
+ _rr_selection.set (to_be_removed);
+
+ for (vector<Redirect*>::iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
+
+ void* gui = (*i)->get_gui ();
+
+ if (gui) {
+ static_cast<Gtk::Widget*>(gui)->hide ();
+ }
+
+ if (_route.remove_redirect (*i, this)) {
+ /* removal failed */
+ _rr_selection.remove (*i);
+ }
+
+ }
+}
+
+void
+RedirectBox::copy_redirects ()
+{
+ vector<Redirect*> to_be_copied;
+ vector<Redirect*> copies;
+
+ get_selected_redirects (to_be_copied);
+
+ if (to_be_copied.empty()) {
+ return;
+ }
+
+ for (vector<Redirect*>::iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
+ copies.push_back (Redirect::clone (**i));
+ }
+
+ _rr_selection.set (copies);
+}
+
+gint
+RedirectBox::idle_delete_redirect (Redirect *redirect)
+{
+ /* NOT copied to _mixer.selection() */
+
+ if (_route.remove_redirect (redirect, this)) {
+ /* removal failed */
+ return FALSE;
+ }
+
+ delete redirect;
+ return FALSE;
+}
+
+void
+RedirectBox::rename_redirect (Redirect* redirect)
+{
+ ArdourDialog dialog ("rename redirect dialog");
+ Entry entry;
+ VBox vbox;
+ HBox hbox;
+ Button ok_button (_("OK"));
+ Button cancel_button (_("Cancel"));
+
+ dialog.set_title (_("ardour: rename redirect"));
+ dialog.set_name ("RedirectRenameWindow");
+ dialog.set_usize (300, -1);
+ dialog.set_position (GTK_WIN_POS_MOUSE);
+ dialog.set_modal (true);
+
+ vbox.set_border_width (12);
+ vbox.set_spacing (12);
+ vbox.pack_start (entry, false, false);
+ vbox.pack_start (hbox, false, false);
+ hbox.pack_start (ok_button);
+ hbox.pack_start (cancel_button);
+
+ dialog.add (vbox);
+
+ entry.set_name ("RedirectNameDisplay");
+ entry.set_text (redirect->name());
+ entry.select_region (0, -1);
+ entry.grab_focus ();
+
+ ok_button.set_name ("EditorGTKButton");
+ cancel_button.set_name ("EditorGTKButton");
+
+ entry.activate.connect (bind (slot (dialog, &ArdourDialog::stop), 1));
+ cancel_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), -1));
+ ok_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 1));
+
+ /* recurse */
+
+ dialog.set_keyboard_input (true);
+ dialog.run ();
+
+ if (dialog.run_status() == 1) {
+ redirect->set_name (entry.get_text(), this);
+ }
+}
+
+void
+RedirectBox::cut_redirect (Redirect *redirect)
+{
+ /* this essentially transfers ownership of the redirect
+ of the redirect from the route to the mixer
+ selection.
+ */
+
+ _rr_selection.add (redirect);
+
+ void* gui = redirect->get_gui ();
+
+ if (gui) {
+ static_cast<Gtk::Widget*>(gui)->hide ();
+ }
+
+ if (_route.remove_redirect (redirect, this)) {
+ _rr_selection.remove (redirect);
+ }
+}
+
+void
+RedirectBox::copy_redirect (Redirect *redirect)
+{
+ Redirect* copy = Redirect::clone (*redirect);
+ _rr_selection.add (copy);
+}
+
+void
+RedirectBox::paste_redirects ()
+{
+ if (_rr_selection.redirects.empty()) {
+ return;
+ }
+
+ RedirectSelection& sel (_rr_selection.redirects);
+ list<Redirect*> others;
+
+ for (list<Redirect*>::iterator i = sel.begin(); i != sel.end(); ++i) {
+
+ Redirect* copy = Redirect::clone (**i);
+
+ copy->set_placement (_placement, this);
+ others.push_back (copy);
+ }
+
+ if (_route.add_redirects (others, this)) {
+ for (list<Redirect*>::iterator i = others.begin(); i != others.end(); ++i) {
+ delete *i;
+ }
+
+ string msg = _(
+ "Copying the set of redirects on the clipboard failed,\n\
+probably because the I/O configuration of the plugins\n\
+could not match the configuration of this track.");
+ ArdourMessage am (0, X_("bad redirect copy dialog"), msg);
+ }
+}
+
+void
+RedirectBox::activate_redirect (Redirect *r)
+{
+ r->set_active (true, 0);
+}
+
+void
+RedirectBox::deactivate_redirect (Redirect *r)
+{
+ r->set_active (false, 0);
+}
+
+void
+RedirectBox::get_selected_redirects (vector<Redirect*>& redirects)
+{
+ using namespace CList_Helpers;
+ SelectionList& sel (redirect_display.selection());
+
+ for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) {
+ Redirect* redirect = reinterpret_cast<Redirect *> ((*i).get_data ());
+ redirects.push_back (redirect);
+ }
+}
+
+void
+RedirectBox::for_selected_redirects (void (RedirectBox::*pmf)(Redirect*))
+{
+ using namespace CList_Helpers;
+ SelectionList& sel (redirect_display.selection());
+
+ for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) {
+ Redirect* redirect = reinterpret_cast<Redirect *> ((*i).get_data ());
+ (this->*pmf)(redirect);
+ }
+}
+
+void
+RedirectBox::clone_redirects ()
+{
+ RouteSelection& routes (_rr_selection.routes);
+
+ if (!routes.empty()) {
+ if (_route.copy_redirects (*routes.front(), _placement)) {
+ string msg = _(
+"Copying the set of redirects on the clipboard failed,\n\
+probably because the I/O configuration of the plugins\n\
+could not match the configuration of this track.");
+ ArdourMessage am (0, X_("bad redirect copy dialog"), msg);
+ }
+ }
+}
+
+void
+RedirectBox::all_redirects_active (bool state)
+{
+ _route.all_redirects_active (state);
+}
+
+void
+RedirectBox::clear_redirects()
+{
+ string prompt;
+ vector<string> choices;
+
+ if (dynamic_cast<AudioTrack*>(&_route) != 0) {
+ prompt = _("Do you really want to remove all redirects from this track?\n"
+ "(this cannot be undone)");
+ } else {
+ prompt = _("Do you really want to remove all redirects from this bus?\n"
+ "(this cannot be undone)");
+ }
+
+ choices.push_back (_("Yes, remove them all"));
+ choices.push_back (_("Cancel"));
+
+ Gtkmmext::Choice prompter (prompt, choices);
+
+ prompter.chosen.connect (Gtk::Main::quit.slot());
+ prompter.show_all ();
+
+ Gtk::Main::run ();
+
+ if (prompter.get_choice() == 0) {
+ _route.clear_redirects (this);
+ }
+}
+
+
+void
+RedirectBox::edit_redirect (Redirect* redirect)
+{
+ Insert *insert;
+
+ if (dynamic_cast<AudioTrack*>(&_route) != 0) {
+
+ if (dynamic_cast<AudioTrack*> (&_route)->freeze_state() == AudioTrack::Frozen) {
+ return;
+ }
+ }
+
+ if ((insert = dynamic_cast<Insert *> (redirect)) == 0) {
+
+ /* its a send */
+
+ if (!_session.engine().connected()) {
+ return;
+ }
+
+ Send *send = dynamic_cast<Send*> (redirect);
+
+ SendUIWindow *send_ui;
+
+ if (send->get_gui() == 0) {
+
+ string title;
+ title = compose(_("ardour: %1"), send->name());
+
+ send_ui = new SendUIWindow (*send, _session);
+ send_ui->set_title (title);
+ send->set_gui (send_ui);
+
+ } else {
+ send_ui = reinterpret_cast<SendUIWindow *> (send->get_gui());
+ }
+
+ if (send_ui->is_visible()) {
+ send_ui->get_window().raise ();
+ } else {
+ send_ui->show_all ();
+ }
+
+ } else {
+
+ /* its an insert */
+
+ PluginInsert *plugin_insert;
+ PortInsert *port_insert;
+
+ if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
+
+ PluginUIWindow *plugin_ui;
+
+ if (plugin_insert->get_gui() == 0) {
+
+ string title;
+ string maker = plugin_insert->plugin().maker();
+ string::size_type email_pos;
+
+ if ((email_pos = maker.find_first_of ('<')) != string::npos) {
+ maker = maker.substr (0, email_pos - 1);
+ }
+
+ if (maker.length() > 32) {
+ maker = maker.substr (0, 32);
+ maker += " ...";
+ }
+
+ title = compose(_("ardour: %1: %2 (by %3)"), _route.name(), plugin_insert->name(), maker);
+
+ plugin_ui = new PluginUIWindow (_session.engine(), *plugin_insert);
+ if (_owner_is_mixer) {
+ ARDOUR_UI::instance()->the_mixer()->ensure_float (*plugin_ui);
+ } else {
+ ARDOUR_UI::instance()->the_editor().ensure_float (*plugin_ui);
+ }
+ plugin_ui->set_title (title);
+ plugin_insert->set_gui (plugin_ui);
+
+ } else {
+ plugin_ui = reinterpret_cast<PluginUIWindow *> (plugin_insert->get_gui());
+ }
+
+ if (plugin_ui->is_visible()) {
+ plugin_ui->get_window().raise ();
+ } else {
+ plugin_ui->show_all ();
+ }
+
+ } else if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
+
+ if (!_session.engine().connected()) {
+ ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
+ return;
+ }
+
+ PortInsertWindow *io_selector;
+
+ if (port_insert->get_gui() == 0) {
+ io_selector = new PortInsertWindow (_session, *port_insert);
+ port_insert->set_gui (io_selector);
+
+ } else {
+ io_selector = reinterpret_cast<PortInsertWindow *> (port_insert->get_gui());
+ }
+
+ if (io_selector->is_visible()) {
+ io_selector->get_window().raise ();
+ } else {
+ io_selector->show_all ();
+ }
+ }
+ }
+}
+
+
diff --git a/gtk2_ardour/redirect_box.h b/gtk2_ardour/redirect_box.h
new file mode 100644
index 0000000000..8a8c58f717
--- /dev/null
+++ b/gtk2_ardour/redirect_box.h
@@ -0,0 +1,175 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_redirect_box__
+#define __ardour_gtk_redirect_box__
+
+#include <vector>
+
+#include <cmath>
+#include <gtk--.h>
+#include <gtkmmext/auto_spin.h>
+#include <gtkmmext/click_box.h>
+
+#include <ardour/types.h>
+#include <ardour/ardour.h>
+#include <ardour/io.h>
+#include <ardour/insert.h>
+#include <ardour/stateful.h>
+#include <ardour/redirect.h>
+
+#include <pbd/fastlog.h>
+
+#include "route_ui.h"
+#include "io_selector.h"
+#include "enums.h"
+
+class MotionController;
+class PluginSelector;
+class RouteRedirectSelection;
+
+namespace ARDOUR {
+ class Route;
+ class Send;
+ class Insert;
+ class Session;
+ class PortInsert;
+ class Connection;
+ class Plugin;
+}
+
+
+class RedirectBox : public Gtk::HBox
+{
+ public:
+ RedirectBox (ARDOUR::Placement, ARDOUR::Session&, ARDOUR::Route &, PluginSelector &, RouteRedirectSelection &, bool owner_is_mixer = false);
+ ~RedirectBox ();
+
+ void set_width (Width);
+
+ void set_title (const std::string & title);
+ void set_title_shown (bool flag);
+
+ void update();
+
+ void select_all_redirects ();
+ void deselect_all_redirects ();
+ void select_all_plugins ();
+ void select_all_inserts ();
+ void select_all_sends ();
+
+ SigC::Signal1<void,ARDOUR::Redirect *> RedirectSelected;
+ SigC::Signal1<void,ARDOUR::Redirect *> RedirectUnselected;
+
+ protected:
+ void set_stuff_from_route ();
+
+ private:
+ ARDOUR::Route & _route;
+ ARDOUR::Session & _session;
+ bool _owner_is_mixer;
+
+ ARDOUR::Placement _placement;
+
+ PluginSelector & _plugin_selector;
+ RouteRedirectSelection & _rr_selection;
+
+
+ Gtk::EventBox redirect_eventbox;
+ Gtk::HBox redirect_hpacker;
+ Gtk::CList redirect_display;
+ Gtk::ScrolledWindow redirect_scroller;
+
+ Width _width;
+
+ SigC::Connection newplug_connection;
+
+ Gtk::Menu *send_action_menu;
+ void build_send_action_menu ();
+
+ void new_send ();
+ void show_send_controls ();
+
+ Gtk::Menu *redirect_menu;
+ vector<Gtk::MenuItem*> selection_dependent_items;
+ Gtk::MenuItem* redirect_paste_item;
+ gint redirect_menu_map_handler (GdkEventAny *ev);
+ Gtk::Menu * build_redirect_menu (Gtk::CList&);
+ void build_redirect_tooltip (Gtk::CList&, Gtk::EventBox&, string);
+ void show_redirect_menu (gint arg);
+
+ void choose_send ();
+ void send_io_finished (IOSelector::Result, ARDOUR::Redirect*, IOSelectorWindow*);
+ void choose_insert ();
+ void choose_plugin ();
+ void insert_plugin_chosen (ARDOUR::Plugin *);
+
+ gint redirect_button (GdkEventButton *);
+ void redirects_changed (void *);
+ void show_redirect_active (ARDOUR::Redirect *, void *);
+ void show_redirect_name (void*, ARDOUR::Redirect *);
+ void add_redirect_to_display (ARDOUR::Redirect *);
+
+ void show_plugin_selector ();
+
+
+ string redirect_name (ARDOUR::Redirect&);
+
+
+ void remove_redirect_gui (ARDOUR::Redirect *);
+
+ void disconnect_newplug();
+
+ void redirects_reordered (gint, gint);
+ gint compute_redirect_sort_keys ();
+ vector<SigC::Connection> redirect_active_connections;
+ vector<SigC::Connection> redirect_name_connections;
+
+ bool redirect_drag_in_progress;
+ void redirect_drag_begin (GdkDragContext*);
+ void redirect_drag_end (GdkDragContext*);
+ void all_redirects_active(bool state);
+
+ void cut_redirects ();
+ void copy_redirects ();
+ void paste_redirects ();
+ void clear_redirects ();
+ void clone_redirects ();
+ void rename_redirects ();
+
+ void for_selected_redirects (void (RedirectBox::*pmf)(ARDOUR::Redirect*));
+ void get_selected_redirects (vector<ARDOUR::Redirect*>&);
+
+
+ void activate_redirect (ARDOUR::Redirect*);
+ void deactivate_redirect (ARDOUR::Redirect*);
+ void cut_redirect (ARDOUR::Redirect*);
+ void copy_redirect (ARDOUR::Redirect*);
+ void edit_redirect (ARDOUR::Redirect*);
+ void hide_redirect_editor (ARDOUR::Redirect*);
+ void rename_redirect (ARDOUR::Redirect*);
+
+ gint idle_delete_redirect (ARDOUR::Redirect *);
+
+ void wierd_plugin_dialog (ARDOUR::Plugin& p, uint32_t streams, ARDOUR::IO& io);
+
+};
+
+#endif /* __ardour_gtk_redirect_box__ */
diff --git a/gtk2_ardour/redirect_selection.h b/gtk2_ardour/redirect_selection.h
new file mode 100644
index 0000000000..3695f85c60
--- /dev/null
+++ b/gtk2_ardour/redirect_selection.h
@@ -0,0 +1,12 @@
+#ifndef __ardour_gtk_redirect_selection_h__
+#define __ardour_gtk_redirect_selection_h__
+
+#include <list>
+
+namespace ARDOUR {
+ class Redirect;
+}
+
+struct RedirectSelection : list<ARDOUR::Redirect*> {};
+
+#endif /* __ardour_gtk_redirect_selection_h__ */
diff --git a/gtk2_ardour/region_editor.cc b/gtk2_ardour/region_editor.cc
new file mode 100644
index 0000000000..1cd6447362
--- /dev/null
+++ b/gtk2_ardour/region_editor.cc
@@ -0,0 +1,739 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/audioregion.h>
+#include <ardour/utils.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/stop_signal.h>
+#include <cmath>
+
+#include "region_editor.h"
+#include "regionview.h"
+#include "ardour_ui.h"
+#include "utils.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+using namespace std;
+
+AudioRegionEditor::AudioRegionEditor (Session&s, AudioRegion& r, AudioRegionView& rv)
+ : ArdourDialog ("audio region editor"),
+ _session (s),
+ _region (r),
+ _region_view (rv),
+ name_label (_("NAME:")),
+ lock_button (_("lock")),
+ mute_button (_("mute")),
+ opaque_button (_("opaque")),
+ raise_arrow (GTK_ARROW_UP, GTK_SHADOW_OUT),
+ lower_arrow (GTK_ARROW_DOWN, GTK_SHADOW_OUT),
+ layer_label (_("Layer")),
+ audition_label (_("play")),
+ time_table (3, 2),
+ start_clock ("AudioRegionEditorClock", true),
+ end_clock ("AudioRegionEditorClock", true),
+ length_clock ("AudioRegionEditorClock", true, true),
+ sync_offset_clock ("AudioRegionEditorClock", true, true),
+ envelope_loop_table (1, 3),
+ envelope_label (_("ENVELOPE")),
+ fade_in_table (4, 3),
+ fade_in_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
+ fade_in_length_spinner (fade_in_length_adjustment, 10),
+ fade_out_table (4, 3),
+ fade_out_length_adjustment (5.0, 0.0, 10000, 0.05, 1),
+ fade_out_length_spinner (fade_out_length_adjustment, 10)
+
+{
+ start_clock.set_session (&_session);
+ end_clock.set_session (&_session);
+ length_clock.set_session (&_session);
+
+ name_entry.set_name ("AudioRegionEditorEntry");
+ name_label.set_name ("AudioRegionEditorLabel");
+
+ name_entry.focus_in_event.connect (slot (*this, &AudioRegionEditor::focus_change));
+ name_entry.focus_out_event.connect (slot (*this, &AudioRegionEditor::focus_change));
+
+ name_hbox.set_spacing (5);
+ name_hbox.pack_start (name_label, false, false);
+ name_hbox.pack_start (name_entry, false, false);
+
+ raise_button.add (raise_arrow);
+ lower_button.add (lower_arrow);
+ layer_frame.set_name ("BaseFrame");
+ layer_frame.set_shadow_type (GTK_SHADOW_IN);
+ layer_frame.add (layer_value_label);
+ layer_label.set_name ("AudioRegionEditorLabel");
+ layer_value_label.set_name ("AudioRegionEditorLabel");
+ Gtkmmext::set_usize_to_display_given_text (layer_value_label, "99", 5, 2);
+
+ layer_hbox.set_spacing (5);
+ layer_hbox.pack_start (layer_label, false, false);
+ layer_hbox.pack_start (layer_frame, false, false);
+#if 0
+ layer_hbox.pack_start (raise_button, false, false);
+ layer_hbox.pack_start (lower_button, false, false);
+#endif
+
+ audition_button.add (audition_label);
+
+ mute_button.set_name ("AudioRegionEditorToggleButton");
+ opaque_button.set_name ("AudioRegionEditorToggleButton");
+ lock_button.set_name ("AudioRegionEditorToggleButton");
+ envelope_active_button.set_name ("AudioRegionEditorToggleButton");
+ envelope_view_button.set_name ("AudioRegionEditorToggleButton");
+ fade_in_active_button.set_name ("AudioRegionEditorToggleButton");
+ fade_out_active_button.set_name ("AudioRegionEditorToggleButton");
+ audition_button.set_name ("AudioRegionEditorToggleButton");
+
+ ARDOUR_UI::instance()->tooltips().set_tip (mute_button, _("mute this region"));
+ ARDOUR_UI::instance()->tooltips().set_tip (opaque_button, _("regions underneath this one cannot be heard"));
+ ARDOUR_UI::instance()->tooltips().set_tip (lock_button, _("prevent any changes to this region"));
+ ARDOUR_UI::instance()->tooltips().set_tip (envelope_active_button, _("use the gain envelope during playback"));
+ ARDOUR_UI::instance()->tooltips().set_tip (envelope_view_button, _("show the gain envelope"));
+ ARDOUR_UI::instance()->tooltips().set_tip (fade_in_active_button, _("use fade in curve during playback"));
+ ARDOUR_UI::instance()->tooltips().set_tip (fade_out_active_button, _("use fade out curve during playback"));
+ ARDOUR_UI::instance()->tooltips().set_tip (audition_button, _("audition this region"));
+
+ mute_button.unset_flags (GTK_CAN_FOCUS);
+ opaque_button.unset_flags (GTK_CAN_FOCUS);
+ lock_button.unset_flags (GTK_CAN_FOCUS);
+ envelope_active_button.unset_flags (GTK_CAN_FOCUS);
+ envelope_view_button.unset_flags (GTK_CAN_FOCUS);
+ fade_in_active_button.unset_flags (GTK_CAN_FOCUS);
+ fade_out_active_button.unset_flags (GTK_CAN_FOCUS);
+ audition_button.unset_flags (GTK_CAN_FOCUS);
+
+ mute_button.set_events (mute_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ opaque_button.set_events (opaque_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ lock_button.set_events (lock_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ envelope_active_button.set_events (envelope_active_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ envelope_view_button.set_events (envelope_view_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ fade_in_active_button.set_events (fade_in_active_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ fade_out_active_button.set_events (fade_out_active_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+ audition_button.set_events (audition_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK));
+
+ top_row_button_hbox.set_border_width (5);
+ top_row_button_hbox.set_spacing (5);
+ top_row_button_hbox.set_homogeneous (false);
+ top_row_button_hbox.pack_start (mute_button, false, false);
+ top_row_button_hbox.pack_start (opaque_button, false, false);
+ top_row_button_hbox.pack_start (lock_button, false, false);
+ top_row_button_hbox.pack_start (layer_hbox, false, false, 5);
+ top_row_button_hbox.pack_end (audition_button, false, false);
+
+ top_row_hbox.pack_start (name_hbox, true, true);
+ top_row_hbox.pack_end (top_row_button_hbox, true, true);
+
+ start_label.set_name ("AudioRegionEditorLabel");
+ start_label.set_text (_("START:"));
+ end_label.set_name ("AudioRegionEditorLabel");
+ end_label.set_text (_("END:"));
+ length_label.set_name ("AudioRegionEditorLabel");
+ length_label.set_text (_("LENGTH:"));
+
+ time_table.set_col_spacings (2);
+ time_table.set_row_spacings (5);
+ time_table.set_border_width (5);
+
+ start_alignment.set (1.0, 0.5);
+ end_alignment.set (1.0, 0.5);
+ length_alignment.set (1.0, 0.5);
+
+ start_alignment.add (start_label);
+ end_alignment.add (end_label);
+ length_alignment.add (length_label);
+
+ time_table.attach (start_alignment, 0, 1, 0, 1);
+ time_table.attach (start_clock, 1, 2, 0, 1, 0, 0);
+
+ time_table.attach (end_alignment, 0, 1, 1, 2);
+ time_table.attach (end_clock, 1, 2, 1, 2, 0, 0);
+
+ time_table.attach (length_alignment, 0, 1, 2, 3);
+ time_table.attach (length_clock, 1, 2, 2, 3, 0, 0);
+
+ envelope_label.set_name ("AudioRegionEditorLabel");
+
+ envelope_active_button_label.set_text (_("active"));
+ envelope_active_button.add (envelope_active_button_label);
+ envelope_view_button_label.set_text (_("visible"));
+ envelope_view_button.add (envelope_view_button_label);
+
+ envelope_loop_table.set_border_width (5);
+ envelope_loop_table.set_row_spacings (2);
+ envelope_loop_table.attach (envelope_label, 0, 1, 0, 1, 0, 0);
+ envelope_loop_table.attach (envelope_active_button, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, 0);
+ envelope_loop_table.attach (envelope_view_button, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, 0);
+
+ /* fade in */
+
+ fade_in_table.set_border_width (5);
+ fade_in_table.set_homogeneous (false);
+
+ fade_in_label.set_name ("AudioRegionEditorLabel");
+ fade_in_active_button_label.set_name ("AudioRegionEditorSmallLabel");
+ fade_in_length_label.set_name ("AudioRegionEditorSmallLabel");
+
+ fade_in_label.set_text (_("FADE IN"));
+ fade_in_active_button_label.set_text (_("active"));
+ fade_in_length_label.set_text (_("msecs"));
+
+ fade_in_active_button.add (fade_in_active_button_label);
+
+ fade_in_length_spinner.set_name("GenericSpinner");
+
+ fade_in_length_spinner.set_digits (3);
+
+ fade_in_length_spinner.focus_in_event.connect (slot (*this, &AudioRegionEditor::focus_change));
+ fade_in_length_spinner.focus_out_event.connect (slot (*this, &AudioRegionEditor::focus_change));
+ fade_in_length_spinner.activate.connect (slot (*this, &AudioRegionEditor::activation));
+
+ Gtkmmext::set_usize_to_display_given_text (fade_in_length_spinner, "500g", 20, -1);
+
+ fade_in_label_align.add (fade_in_label);
+ fade_in_label_align.set (0.5);
+
+
+ fade_in_table.attach (fade_in_label_align, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+
+ fade_in_table.attach (fade_in_length_label, 0, 1, 1, 2, GTK_EXPAND, 0, 0, 0);
+ fade_in_table.attach (fade_in_length_spinner, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+
+ fade_in_table.attach (fade_in_active_button, 0, 2, 3, 5, GTK_FILL|GTK_EXPAND, 0);
+
+ /* fade out */
+
+ fade_out_table.set_border_width (5);
+ fade_out_table.set_homogeneous (false);
+
+ fade_out_label.set_name ("AudioRegionEditorLabel");
+ fade_out_active_button_label.set_name ("AudioRegionEditorSmallLabel");
+ fade_out_length_label.set_name ("AudioRegionEditorSmallLabel");
+
+ fade_out_label.set_text (_("FADE OUT"));
+ fade_out_active_button_label.set_text (_("active"));
+ fade_out_length_label.set_text (_("msecs"));
+
+ fade_out_active_button.add (fade_out_active_button_label);
+
+ fade_out_length_spinner.set_name("GenericSpinner");
+
+ fade_out_length_spinner.set_digits (3);
+
+ fade_out_length_spinner.focus_in_event.connect (slot (*this, &AudioRegionEditor::focus_change));
+ fade_out_length_spinner.focus_out_event.connect (slot (*this, &AudioRegionEditor::focus_change));
+ fade_out_length_spinner.activate.connect (slot (*this, &AudioRegionEditor::activation));
+
+ Gtkmmext::set_usize_to_display_given_text (fade_out_length_spinner, "500g", 20, -1);
+
+ fade_out_label_align.add (fade_out_label);
+ fade_out_label_align.set (0.5);
+
+ fade_out_table.attach (fade_out_label_align, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+
+ fade_out_table.attach (fade_out_length_label, 0, 1, 1, 2, GTK_EXPAND, 0, 0, 0);
+ fade_out_table.attach (fade_out_length_spinner, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, 0, 0, 0);
+
+ fade_out_table.attach (fade_out_active_button, 0, 2, 3, 5, GTK_FILL|GTK_EXPAND, 0);
+
+ lower_hbox.pack_start (time_table, true, true);
+ lower_hbox.pack_start (sep1, false, false);
+ lower_hbox.pack_start (envelope_loop_table, true, true);
+ lower_hbox.pack_start (sep2, false, false);
+ lower_hbox.pack_start (fade_in_table, true, true);
+ lower_hbox.pack_start (fade_out_table, true, true);
+
+ upper_vbox.pack_start (top_row_hbox, true, true);
+ upper_vbox.pack_start (sep3, false, false);
+ upper_vbox.pack_start (lower_hbox, true, true);
+
+ add (upper_vbox);
+ set_name ("AudioRegionEditorWindow");
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK);
+
+ delete_event.connect (bind (slot (just_hide_it), static_cast<Window *> (this)));
+
+ string title = _("ardour: region ");
+ title += _region.name();
+ set_title (title);
+
+ name_changed ();
+ bounds_changed (Change (StartChanged|LengthChanged|PositionChanged));
+ envelope_active_changed ();
+ mute_changed ();
+ opacity_changed ();
+ lock_changed ();
+ layer_changed ();
+ fade_in_changed ();
+ fade_out_changed ();
+
+ XMLNode *node = _region.extra_xml ("GUI");
+ XMLProperty *prop = 0;
+ bool showing_envelope = false;
+
+ if (node && (prop = node->property ("envelope-visible")) != 0) {
+ if (prop->value() == "yes") {
+ showing_envelope = true;
+ }
+ }
+
+ if (showing_envelope) {
+ envelope_view_button.set_active (true);
+ } else {
+ envelope_view_button.set_active (false);
+ }
+
+ _region.StateChanged.connect (slot (*this, &AudioRegionEditor::region_changed));
+
+ spin_arrow_grab = false;
+
+ connect_editor_events ();
+}
+
+AudioRegionEditor::~AudioRegionEditor ()
+{
+}
+
+void
+AudioRegionEditor::region_changed (Change what_changed)
+{
+ if (what_changed & NameChanged) {
+ name_changed ();
+ }
+ if (what_changed & BoundsChanged) {
+ bounds_changed (what_changed);
+ }
+
+ if (what_changed & Region::OpacityChanged) {
+ opacity_changed ();
+ }
+ if (what_changed & Region::MuteChanged) {
+ mute_changed ();
+ }
+ if (what_changed & Region::LockChanged) {
+ lock_changed ();
+ }
+ if (what_changed & Region::LayerChanged) {
+ layer_changed ();
+ }
+
+ if (what_changed & AudioRegion::EnvelopeActiveChanged) {
+ envelope_active_changed ();
+ }
+ if (what_changed & AudioRegion::FadeInChanged) {
+ fade_in_changed ();
+ }
+ if (what_changed & AudioRegion::FadeOutChanged) {
+ fade_out_changed ();
+ }
+ if (what_changed & AudioRegion::FadeInActiveChanged) {
+ fade_in_active_changed ();
+ }
+ if (what_changed & AudioRegion::FadeOutActiveChanged) {
+ fade_out_active_changed ();
+ }
+}
+
+void
+AudioRegionEditor::fade_in_realized ()
+{
+ fade_in_changed ();
+}
+
+void
+AudioRegionEditor::fade_out_realized ()
+{
+ fade_out_changed ();
+}
+
+gint
+AudioRegionEditor::bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
+{
+ switch (ev->button) {
+ case 1:
+ case 2:
+ case 3:
+ if (ev->type == GDK_BUTTON_PRESS) { /* no double clicks here */
+ if (!spin_arrow_grab) {
+ if ((ev->window == but->gtkobj()->panel)) {
+ spin_arrow_grab = true;
+ (this->*pmf)();
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+gint
+AudioRegionEditor::breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)())
+{
+ if (spin_arrow_grab) {
+ (this->*pmf)();
+ spin_arrow_grab = false;
+ }
+ return FALSE;
+}
+
+void
+AudioRegionEditor::start_editing_fade_in ()
+{
+ _region.freeze ();
+}
+
+void
+AudioRegionEditor::stop_editing_fade_in ()
+{
+ _region.thaw (_("fade in edit"));
+}
+
+void
+AudioRegionEditor::start_editing_fade_out ()
+{
+ _region.freeze ();
+}
+
+void
+AudioRegionEditor::stop_editing_fade_out ()
+{
+ _region.thaw (_("fade out edit"));
+}
+
+void
+AudioRegionEditor::connect_editor_events ()
+{
+ name_entry.changed.connect (slot (*this, &AudioRegionEditor::name_entry_changed));
+
+ start_clock.ValueChanged.connect (slot (*this, &AudioRegionEditor::start_clock_changed));
+ end_clock.ValueChanged.connect (slot (*this, &AudioRegionEditor::end_clock_changed));
+ length_clock.ValueChanged.connect (slot (*this, &AudioRegionEditor::length_clock_changed));
+
+ fade_in_length_spinner.button_press_event.connect (bind (slot (*this, &AudioRegionEditor::bpressed), &fade_in_length_spinner,
+ &AudioRegionEditor::start_editing_fade_in));
+ fade_in_length_spinner.button_release_event.connect (bind (slot (this, &AudioRegionEditor::breleased), &fade_in_length_spinner,
+ &AudioRegionEditor::stop_editing_fade_in));
+
+ fade_out_length_spinner.button_press_event.connect (bind (slot (*this, &AudioRegionEditor::bpressed), &fade_out_length_spinner,
+ &AudioRegionEditor::start_editing_fade_out));
+ fade_out_length_spinner.button_release_event.connect (bind (slot (this, &AudioRegionEditor::breleased), &fade_out_length_spinner,
+ &AudioRegionEditor::stop_editing_fade_out));
+
+ fade_in_length_adjustment.value_changed.connect (slot (*this, &AudioRegionEditor::fade_in_length_adjustment_changed));
+ fade_out_length_adjustment.value_changed.connect (slot (*this, &AudioRegionEditor::fade_out_length_adjustment_changed));
+
+ fade_in_active_button.toggled.connect (slot (*this, &AudioRegionEditor::fade_in_active_toggled));
+ fade_out_active_button.toggled.connect (slot (*this, &AudioRegionEditor::fade_out_active_toggled));
+
+ envelope_active_button.button_press_event.connect (slot (*this, &AudioRegionEditor::envelope_active_button_press));
+ envelope_active_button.button_release_event.connect (slot (*this, &AudioRegionEditor::envelope_active_button_release));
+ audition_button.toggled.connect (slot (*this, &AudioRegionEditor::audition_button_toggled));
+ envelope_view_button.toggled.connect (slot (*this, &AudioRegionEditor::envelope_view_button_toggled));
+ lock_button.clicked.connect (slot (*this, &AudioRegionEditor::lock_button_clicked));
+ mute_button.clicked.connect (slot (*this, &AudioRegionEditor::mute_button_clicked));
+ opaque_button.clicked.connect (slot (*this, &AudioRegionEditor::opaque_button_clicked));
+ raise_button.clicked.connect (slot (*this, &AudioRegionEditor::raise_button_clicked));
+ lower_button.clicked.connect (slot (*this, &AudioRegionEditor::lower_button_clicked));
+}
+
+void
+AudioRegionEditor::start_clock_changed ()
+{
+ _region.set_position (start_clock.current_time(), this);
+}
+
+void
+AudioRegionEditor::end_clock_changed ()
+{
+ _region.trim_end (end_clock.current_time(), this);
+
+ end_clock.set (_region.position() + _region.length(), true);
+}
+
+void
+AudioRegionEditor::length_clock_changed ()
+{
+ jack_nframes_t frames = length_clock.current_time();
+ _region.trim_end (_region.position() + frames, this);
+
+ length_clock.set (_region.length());
+}
+
+gint
+AudioRegionEditor::envelope_active_button_press(GdkEventButton *ev)
+{
+ return stop_signal (envelope_active_button, "button_press_event");
+}
+
+gint
+AudioRegionEditor::envelope_active_button_release (GdkEventButton *ev)
+{
+ _region.set_envelope_active (!_region.envelope_active());
+ return stop_signal (envelope_active_button, "button_release_event");
+}
+
+void
+AudioRegionEditor::envelope_view_button_toggled ()
+{
+ bool visible = envelope_view_button.get_active ();
+
+ _region_view.set_envelope_visible (visible);
+}
+
+void
+AudioRegionEditor::audition_button_toggled ()
+{
+ if (audition_button.get_active()) {
+ _session.audition_region (_region);
+ } else {
+ _session.cancel_audition ();
+ }
+}
+
+void
+AudioRegionEditor::raise_button_clicked ()
+{
+ _region.raise ();
+}
+
+void
+AudioRegionEditor::lower_button_clicked ()
+{
+ _region.lower ();
+}
+
+void
+AudioRegionEditor::opaque_button_clicked ()
+{
+ bool ractive = _region.opaque();
+
+ if (opaque_button.get_active() != ractive) {
+ _region.set_opaque (!ractive);
+ }
+}
+
+void
+AudioRegionEditor::mute_button_clicked ()
+{
+ bool ractive = _region.muted();
+
+ if (mute_button.get_active() != ractive) {
+ _region.set_muted (!ractive);
+ }
+}
+
+void
+AudioRegionEditor::lock_button_clicked ()
+{
+ bool ractive = _region.locked();
+
+ if (lock_button.get_active() != ractive) {
+ _region.set_locked (!ractive);
+ }
+}
+
+void
+AudioRegionEditor::layer_changed ()
+{
+ char buf[8];
+ snprintf (buf, sizeof(buf), "%d", (int) _region.layer() + 1);
+ layer_value_label.set_text (buf);
+}
+
+void
+AudioRegionEditor::name_changed ()
+{
+ if (name_entry.get_text() != _region.name()) {
+ name_entry.set_text (_region.name());
+ }
+}
+
+void
+AudioRegionEditor::lock_changed ()
+{
+ bool yn;
+
+ if ((yn = _region.locked()) != lock_button.get_active()) {
+ lock_button.set_active (yn);
+ }
+
+ start_clock.set_sensitive (!yn);
+ end_clock.set_sensitive (!yn);
+ length_clock.set_sensitive (!yn);
+}
+
+void
+AudioRegionEditor::envelope_active_changed ()
+{
+ bool yn;
+
+ if ((yn = _region.envelope_active()) != envelope_active_button.get_active()) {
+ envelope_active_button.set_active (yn);
+ }
+}
+
+void
+AudioRegionEditor::opacity_changed ()
+{
+ bool yn;
+ if ((yn = _region.opaque()) != opaque_button.get_active()) {
+ opaque_button.set_active (yn);
+ }
+}
+
+void
+AudioRegionEditor::mute_changed ()
+{
+ bool yn;
+ if ((yn = _region.muted()) != mute_button.get_active()) {
+ mute_button.set_active (yn);
+ }
+}
+
+void
+AudioRegionEditor::bounds_changed (Change what_changed)
+{
+ if (what_changed & Change ((PositionChanged|LengthChanged))) {
+ start_clock.set (_region.position(), true);
+ end_clock.set (_region.position() + _region.length(), true);
+ length_clock.set (_region.length(), true);
+ }
+}
+
+gint
+AudioRegionEditor::focus_change (GdkEventFocus *ev)
+{
+ if (ev->in) {
+ ARDOUR_UI::instance()->allow_focus (true);
+ } else {
+ ARDOUR_UI::instance()->allow_focus (false);
+ }
+ return TRUE;
+}
+
+void
+AudioRegionEditor::activation ()
+{
+ ARDOUR_UI::instance()->allow_focus (false);
+}
+
+void
+AudioRegionEditor::name_entry_changed ()
+{
+ if (name_entry.get_text() != _region.name()) {
+ _region.set_name (name_entry.get_text());
+ }
+}
+
+void
+AudioRegionEditor::fade_in_changed ()
+{
+ float msecs = fade_in_length_adjustment.get_value();
+ jack_nframes_t sr = _session.frame_rate();
+ jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
+ jack_nframes_t frames;
+ bool x;
+
+ if (adj_frames != (frames = (jack_nframes_t) _region.fade_in().back()->when)) {
+ fade_in_length_adjustment.set_value ((frames * 1000.0f) / sr);
+ }
+
+ if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
+ fade_in_active_button.set_active (x);
+ }
+}
+
+void
+AudioRegionEditor::fade_out_changed ()
+{
+ float msecs = fade_out_length_adjustment.get_value();
+ jack_nframes_t sr = _session.frame_rate();
+ jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f));
+ jack_nframes_t frames;
+ bool x;
+ if (adj_frames != (frames = (jack_nframes_t) _region.fade_out().back()->when)) {
+ fade_out_length_adjustment.set_value ((frames * 1000.0f) / sr);
+ }
+
+ if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
+ fade_out_active_button.set_active (x);
+ }
+}
+
+void
+AudioRegionEditor::fade_in_length_adjustment_changed ()
+{
+ jack_nframes_t fade_length = (jack_nframes_t) floor (fade_in_length_adjustment.get_value() * _session.frame_rate() * 0.001);
+ fade_length = max (fade_length, (jack_nframes_t) 64);
+ fade_length = min (fade_length, _region.length());
+
+ _region.set_fade_in_length (fade_length);
+ /* region is frozen, no worries */
+ fade_in_changed();
+}
+
+void
+AudioRegionEditor::fade_out_length_adjustment_changed ()
+{
+ jack_nframes_t fade_length = (jack_nframes_t) floor (fade_out_length_adjustment.get_value() * _session.frame_rate() * 0.001);
+ fade_length = max (fade_length, (jack_nframes_t) 64);
+ fade_length = min (fade_length, _region.length());
+
+ _region.set_fade_out_length (fade_length);
+ /* region is frozen, no worries */
+ fade_out_changed();
+}
+
+void
+AudioRegionEditor::fade_in_active_toggled ()
+{
+ _region.set_fade_in_active (fade_in_active_button.get_active());
+}
+
+void
+AudioRegionEditor::fade_out_active_toggled ()
+{
+ _region.set_fade_out_active (fade_out_active_button.get_active());
+}
+
+void
+AudioRegionEditor::fade_out_active_changed ()
+{
+ bool x;
+
+ if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) {
+ fade_out_active_button.set_active (x);
+ }
+}
+
+void
+AudioRegionEditor::fade_in_active_changed ()
+{
+ bool x;
+
+ if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) {
+ fade_in_active_button.set_active (x);
+ }
+}
diff --git a/gtk2_ardour/region_editor.h b/gtk2_ardour/region_editor.h
new file mode 100644
index 0000000000..2f01ff1686
--- /dev/null
+++ b/gtk2_ardour/region_editor.h
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_region_edit_h__
+#define __gtk_ardour_region_edit_h__
+
+#include <map>
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <sigc++/signal_system.h>
+
+#include "audio_clock.h"
+#include "ardour_dialog.h"
+
+namespace ARDOUR {
+ class AudioRegion;
+ class Session;
+}
+
+class AudioRegionView;
+
+class AudioRegionEditor : public ArdourDialog
+{
+ public:
+ AudioRegionEditor (ARDOUR::Session&, ARDOUR::AudioRegion&, AudioRegionView& rv);
+ ~AudioRegionEditor ();
+
+ private:
+ ARDOUR::Session& _session;
+ ARDOUR::AudioRegion& _region;
+ AudioRegionView& _region_view;
+
+ void connect_editor_events ();
+
+ Gtk::Label name_label;
+ Gtk::Entry name_entry;
+ Gtk::HBox name_hbox;
+
+ Gtk::HBox top_row_hbox;
+ Gtk::HBox top_row_button_hbox;
+
+ Gtk::ToggleButton lock_button;
+ Gtk::ToggleButton mute_button;
+ Gtk::ToggleButton opaque_button;
+ Gtk::ToggleButton envelope_active_button;
+ Gtk::ToggleButton envelope_view_button;
+ Gtk::Label envelope_active_button_label;
+ Gtk::Label envelope_view_button_label;
+
+ Gtk::Button raise_button;
+ Gtk::Arrow raise_arrow;
+ Gtk::Button lower_button;
+ Gtk::Arrow lower_arrow;
+ Gtk::Frame layer_frame;
+ Gtk::Label layer_value_label;
+ Gtk::Label layer_label;
+ Gtk::HBox layer_hbox;
+
+ Gtk::ToggleButton audition_button;
+ Gtk::Label audition_label;
+
+ Gtk::VBox upper_vbox;
+ Gtk::HBox lower_hbox;
+
+ Gtk::Table time_table;
+
+ Gtk::Label start_label;
+ Gtk::Label end_label;
+ Gtk::Label length_label;
+ Gtk::Alignment start_alignment;
+ Gtk::Alignment end_alignment;
+ Gtk::Alignment length_alignment;
+
+ AudioClock start_clock;
+ AudioClock end_clock;
+ AudioClock length_clock;
+ AudioClock sync_offset_clock;
+
+ Gtk::Table envelope_loop_table;
+ Gtk::Button loop_button;
+ Gtk::Label loop_label;
+ Gtk::Label envelope_label;
+
+ Gtk::Table fade_in_table;
+ Gtk::Label fade_in_label;
+ Gtk::Alignment fade_in_label_align;
+ Gtk::Label fade_in_active_button_label;
+ Gtk::ToggleButton fade_in_active_button;
+ Gtk::Label fade_in_length_label;
+
+ Gtk::Adjustment fade_in_length_adjustment;
+ Gtk::SpinButton fade_in_length_spinner;
+
+ Gtk::Table fade_out_table;
+ Gtk::Label fade_out_label;
+ Gtk::Alignment fade_out_label_align;
+ Gtk::Label fade_out_active_button_label;
+ Gtk::ToggleButton fade_out_active_button;
+ Gtk::Label fade_out_length_label;
+
+ Gtk::Adjustment fade_out_length_adjustment;
+ Gtk::SpinButton fade_out_length_spinner;
+
+ Gtk::HSeparator sep3;
+ Gtk::VSeparator sep1;
+ Gtk::VSeparator sep2;
+
+ void region_changed (ARDOUR::Change);
+ void bounds_changed (ARDOUR::Change);
+ void name_changed ();
+ void opacity_changed ();
+ void mute_changed ();
+ void envelope_active_changed ();
+ void lock_changed ();
+ void layer_changed ();
+
+ void fade_in_length_adjustment_changed ();
+ void fade_out_length_adjustment_changed ();
+ void fade_in_changed ();
+ void fade_out_changed ();
+
+ gint focus_change (GdkEventFocus *);
+ void activation ();
+
+ void name_entry_changed ();
+ void start_clock_changed ();
+ void end_clock_changed ();
+ void length_clock_changed ();
+
+ gint envelope_active_button_press (GdkEventButton *);
+ gint envelope_active_button_release (GdkEventButton *);
+
+ void audition_button_toggled ();
+ void envelope_view_button_toggled ();
+ void lock_button_clicked ();
+ void mute_button_clicked ();
+ void opaque_button_clicked ();
+ void raise_button_clicked ();
+ void lower_button_clicked ();
+
+ void fade_in_active_toggled ();
+ void fade_out_active_toggled ();
+ void fade_in_active_changed ();
+ void fade_out_active_changed ();
+
+ void fade_in_realized ();
+ void fade_out_realized ();
+
+ void start_editing_fade_in ();
+ void start_editing_fade_out ();
+ void stop_editing_fade_in ();
+ void stop_editing_fade_out ();
+
+ gint bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)());
+ gint breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)());
+
+ bool spin_arrow_grab;
+};
+
+#endif /* __gtk_ardour_region_edit_h__ */
diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc
new file mode 100644
index 0000000000..c3d81bbf8a
--- /dev/null
+++ b/gtk2_ardour/region_gain_line.cc
@@ -0,0 +1,96 @@
+#include <ardour/curve.h>
+#include <ardour/audioregion.h>
+
+#include "region_gain_line.h"
+#include "regionview.h"
+#include "utils.h"
+
+#include "time_axis_view.h"
+#include "editor.h"
+
+#include <ardour/session.h>
+
+
+#include "i18n.h"
+
+
+using namespace std;
+using namespace ARDOUR;
+
+AudioRegionGainLine::AudioRegionGainLine (string name, Session& s, AudioRegionView& r, GtkCanvasItem* parent,
+ Curve& c,
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer))
+ : AutomationLine (name, r.get_time_axis_view(), parent, c, point_callback, line_callback),
+ session (s),
+ rv (r)
+{
+ gtk_canvas_item_raise_to_top (group);
+ set_verbose_cursor_uses_gain_mapping (true);
+ terminal_points_can_slide = false;
+}
+
+void
+AudioRegionGainLine::view_to_model_y (double& y)
+{
+ y = slider_position_to_gain (y);
+ y = max (0.0, y);
+ y = min (2.0, y);
+}
+
+void
+AudioRegionGainLine::model_to_view_y (double& y)
+{
+ y = gain_to_slider_position (y);
+}
+
+void
+AudioRegionGainLine::start_drag (ControlPoint* cp, float fraction)
+{
+ AutomationLine::start_drag(cp,fraction);
+ if (!rv.region.envelope_active()) {
+ trackview.session().add_undo( bind( slot(rv.region, &AudioRegion::set_envelope_active), false) );
+ }
+}
+
+// This is an extended copy from AutomationList
+void
+AudioRegionGainLine::remove_point (ControlPoint& cp)
+{
+ ModelRepresentation mr;
+
+ model_representation (cp, mr);
+
+ trackview.editor.current_session()->begin_reversible_command (_("remove control point"));
+ trackview.editor.current_session()->add_undo (get_memento());
+
+ if (!rv.region.envelope_active()) {
+ trackview.session().add_undo( bind( slot(rv.region, &AudioRegion::set_envelope_active), false) );
+ trackview.session().add_redo( bind( slot(rv.region, &AudioRegion::set_envelope_active), true) );
+ rv.region.set_envelope_active(true);
+ }
+
+ alist.erase (mr.start, mr.end);
+
+ trackview.editor.current_session()->add_redo_no_execute (get_memento());
+ trackview.editor.current_session()->commit_reversible_command ();
+ trackview.editor.current_session()->set_dirty ();
+}
+
+void
+AudioRegionGainLine::end_drag (ControlPoint* cp)
+{
+ if (!rv.region.envelope_active()) {
+ trackview.session().add_redo( bind( slot(rv.region, &AudioRegion::set_envelope_active), true) );
+ rv.region.set_envelope_active(true);
+ }
+ AutomationLine::end_drag(cp);
+}
+
+
+// This is a copy from AutomationList
+UndoAction
+AudioRegionGainLine::get_memento ()
+{
+ return alist.get_memento();
+}
diff --git a/gtk2_ardour/region_gain_line.h b/gtk2_ardour/region_gain_line.h
new file mode 100644
index 0000000000..455be65c9d
--- /dev/null
+++ b/gtk2_ardour/region_gain_line.h
@@ -0,0 +1,43 @@
+#ifndef __ardour_gtk_region_gain_line_h__
+#define __ardour_gtk_region_gain_line_h__
+
+#include <ardour/ardour.h>
+#include <gtk-canvas.h>
+#include <gtk--.h>
+
+#include "automation_line.h"
+
+namespace ARDOUR {
+ class Session;
+}
+
+class TimeAxisView;
+class AudioRegionView;
+
+class AudioRegionGainLine : public AutomationLine
+{
+ public:
+ AudioRegionGainLine (string name, ARDOUR::Session&, AudioRegionView&, GtkCanvasItem* parent,
+ ARDOUR::Curve&,
+ gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer),
+ gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer));
+
+ void view_to_model_y (double&);
+ void model_to_view_y (double&);
+
+ void start_drag (ControlPoint*, float fraction);
+ void end_drag (ControlPoint*);
+
+ void remove_point (ControlPoint&);
+
+
+
+ private:
+ ARDOUR::Session& session;
+ AudioRegionView& rv;
+
+ UndoAction get_memento();
+};
+
+
+#endif /* __ardour_gtk_region_gain_line_h__ */
diff --git a/gtk2_ardour/region_selection.cc b/gtk2_ardour/region_selection.cc
new file mode 100644
index 0000000000..b0afa26999
--- /dev/null
+++ b/gtk2_ardour/region_selection.cc
@@ -0,0 +1,204 @@
+#include <algorithm>
+
+#include <ardour/audioregion.h>
+
+#include "regionview.h"
+#include "region_selection.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+
+
+bool
+AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionView* b) const
+{
+ if (a == b) {
+ return false;
+ } else {
+ return a < b;
+ }
+}
+
+AudioRegionSelection::AudioRegionSelection ()
+{
+ _current_start = 0;
+ _current_end = 0;
+}
+
+AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other)
+{
+
+ for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
+ add (*i, false);
+ }
+ _current_start = other._current_start;
+ _current_end = other._current_end;
+}
+
+
+
+AudioRegionSelection&
+AudioRegionSelection::operator= (const AudioRegionSelection& other)
+{
+ if (this != &other) {
+
+ clear_all();
+
+ for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
+ add (*i, false);
+ }
+
+ _current_start = other._current_start;
+ _current_end = other._current_end;
+ }
+
+ return *this;
+}
+
+void
+AudioRegionSelection::clear_all()
+{
+ clear();
+ _bylayer.clear();
+}
+
+bool AudioRegionSelection::contains (AudioRegionView* rv)
+{
+ if (this->find (rv) != end()) {
+ return true;
+ }
+ else {
+ return false;
+ }
+
+}
+
+void
+AudioRegionSelection::add (AudioRegionView* rv, bool dosort)
+{
+ if (this->find (rv) != end()) {
+ /* we already have it */
+ return;
+ }
+
+ rv->AudioRegionViewGoingAway.connect (slot (*this, &AudioRegionSelection::remove_it));
+
+ if (rv->region.first_frame() < _current_start || empty()) {
+ _current_start = rv->region.first_frame();
+ }
+
+ if (rv->region.last_frame() > _current_end || empty()) {
+ _current_end = rv->region.last_frame();
+ }
+
+ insert (rv);
+
+ // add to layer sorted list
+ add_to_layer (rv);
+
+}
+
+void
+AudioRegionSelection::remove_it (AudioRegionView *rv)
+{
+ remove (rv);
+}
+
+bool
+AudioRegionSelection::remove (AudioRegionView* rv)
+{
+ AudioRegionSelection::iterator i;
+
+ if ((i = this->find (rv)) != end()) {
+
+ erase (i);
+
+ // remove from layer sorted list
+ _bylayer.remove (rv);
+
+ if (empty()) {
+
+ _current_start = 0;
+ _current_end = 0;
+
+ } else {
+
+ AudioRegion& region ((*i)->region);
+
+ if (region.first_frame() == _current_start) {
+
+ /* reset current start */
+
+ jack_nframes_t ref = max_frames;
+
+ for (i = begin (); i != end(); ++i) {
+ if (region.first_frame() < ref) {
+ ref = region.first_frame();
+ }
+ }
+
+ _current_start = ref;
+
+ }
+
+ if (region.last_frame() == _current_end) {
+
+ /* reset current end */
+
+ jack_nframes_t ref = 0;
+
+ for (i = begin (); i != end(); ++i) {
+ if (region.first_frame() > ref) {
+ ref = region.first_frame();
+ }
+ }
+
+ _current_end = ref;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void
+AudioRegionSelection::add_to_layer (AudioRegionView * rv)
+{
+ // insert it into layer sorted position
+
+ list<AudioRegionView*>::iterator i;
+
+ for (i = _bylayer.begin(); i != _bylayer.end(); ++i)
+ {
+ if (rv->region.layer() < (*i)->region.layer()) {
+ _bylayer.insert(i, rv);
+ return;
+ }
+ }
+
+ // insert at end if we get here
+ _bylayer.insert(i, rv);
+}
+
+struct RegionSortByTime {
+ bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
+ return a->region.position() < b->region.position();
+ }
+};
+
+
+void
+AudioRegionSelection::by_position (list<AudioRegionView*>& foo) const
+{
+ list<AudioRegionView*>::const_iterator i;
+ RegionSortByTime sorter;
+
+ for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
+ foo.push_back (*i);
+ }
+
+ foo.sort (sorter);
+ return;
+}
diff --git a/gtk2_ardour/region_selection.h b/gtk2_ardour/region_selection.h
new file mode 100644
index 0000000000..73fabeb0b2
--- /dev/null
+++ b/gtk2_ardour/region_selection.h
@@ -0,0 +1,56 @@
+#ifndef __ardour_gtk_region_selection_h__
+#define __ardour_gtk_region_selection_h__
+
+#include <set>
+#include <list>
+#include <sigc++/signal_system.h>
+#include <ardour/types.h>
+
+using std::list;
+using std::set;
+
+class AudioRegionView;
+
+struct AudioRegionComparator {
+ bool operator() (const AudioRegionView* a, const AudioRegionView* b) const;
+};
+
+class AudioRegionSelection : public set<AudioRegionView*, AudioRegionComparator>, public SigC::Object
+{
+ public:
+ AudioRegionSelection();
+ AudioRegionSelection (const AudioRegionSelection&);
+
+ AudioRegionSelection& operator= (const AudioRegionSelection&);
+
+ void add (AudioRegionView*, bool dosort = true);
+ bool remove (AudioRegionView*);
+ bool contains (AudioRegionView*);
+
+ void clear_all();
+
+ jack_nframes_t start () const {
+ return _current_start;
+ }
+
+ /* collides with list<>::end */
+
+ jack_nframes_t end_frame () const {
+ return _current_end;
+ }
+
+ const list<AudioRegionView *> & by_layer() const { return _bylayer; }
+ void by_position (list<AudioRegionView*>&) const;
+
+ private:
+ void remove_it (AudioRegionView*);
+
+ void add_to_layer (AudioRegionView *);
+
+ jack_nframes_t _current_start;
+ jack_nframes_t _current_end;
+
+ list<AudioRegionView *> _bylayer;
+};
+
+#endif /* __ardour_gtk_region_selection_h__ */
diff --git a/gtk2_ardour/regionview.cc b/gtk2_ardour/regionview.cc
new file mode 100644
index 0000000000..73856e920d
--- /dev/null
+++ b/gtk2_ardour/regionview.cc
@@ -0,0 +1,1406 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cmath>
+#include <algorithm>
+
+#include <gtk--.h>
+
+#include <gtkmmext/gtk_ui.h>
+
+#include <ardour/playlist.h>
+#include <ardour/audioregion.h>
+#include <ardour/sndfilesource.h>
+#include <ardour/diskstream.h>
+
+#include "streamview.h"
+#include "regionview.h"
+#include "audio_time_axis.h"
+#include "canvas-simplerect.h"
+#include "canvas-simpleline.h"
+#include "canvas-waveview.h"
+#include "public_editor.h"
+#include "region_editor.h"
+#include "region_gain_line.h"
+#include "ghostregion.h"
+#include "audio_time_axis.h"
+#include "utils.h"
+#include "rgb_macros.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Editing;
+
+static const int32_t sync_mark_width = 9;
+
+SigC::Signal1<void,AudioRegionView*> AudioRegionView::AudioRegionViewGoingAway;
+
+AudioRegionView::AudioRegionView (GtkCanvasGroup *parent, AudioTimeAxisView &tv,
+ AudioRegion& r,
+ double spu,
+ double amplitude_above_axis,
+ GdkColor& basic_color,
+ bool wfw)
+
+ : TimeAxisViewItem (r.name(), parent, tv, spu, basic_color, r.position(), r.length(),
+ TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
+ TimeAxisViewItem::ShowNameHighlight|
+ TimeAxisViewItem::ShowFrame)),
+
+ region (r)
+{
+ GtkCanvasPoints *shape;
+ XMLNode *node;
+
+ editor = 0;
+ valid = true;
+ in_destructor = false;
+ _amplitude_above_axis = amplitude_above_axis;
+ zero_line = 0;
+ wait_for_waves = wfw;
+ _height = 0;
+
+ _flags = 0;
+
+ if ((node = region.extra_xml ("GUI")) != 0) {
+ set_flags (node);
+ } else {
+ _flags = WaveformVisible;
+ store_flags ();
+ }
+
+ if (trackview.editor.new_regionviews_display_gain()) {
+ _flags |= EnvelopeVisible;
+ }
+
+ compute_colors (basic_color);
+
+ create_waves ();
+
+ gtk_object_set_data (GTK_OBJECT(name_highlight), "regionview", this);
+ gtk_object_set_data (GTK_OBJECT(name_text), "regionview", this);
+
+ shape = gtk_canvas_points_new (4);
+
+ /* an equilateral triangle */
+
+ shape->coords[0] = -((sync_mark_width-1)/2);
+ shape->coords[1] = 1;
+
+ shape->coords[2] = (sync_mark_width - 1)/2;
+ shape->coords[3] = 1;
+
+ shape->coords[4] = 0;
+ shape->coords[5] = sync_mark_width - 1;
+
+ shape->coords[6] = -((sync_mark_width-1)/2);
+ shape->coords[7] = 1;
+
+ // cerr << "set sync mark al points, nc = " << shape->num_points << endl;
+ sync_mark = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_polygon_get_type(),
+ "points", shape,
+ "fill_color_rgba", fill_color,
+ NULL);
+ gtk_canvas_item_hide (sync_mark);
+ gtk_canvas_points_unref (shape);
+
+
+ fade_in_shape = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_polygon_get_type(),
+ "fill_color_rgba", fade_color,
+ NULL);
+ gtk_object_set_data (GTK_OBJECT(fade_in_shape), "regionview", this);
+
+ fade_out_shape = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_polygon_get_type(),
+ "fill_color_rgba", fade_color,
+ NULL);
+ gtk_object_set_data (GTK_OBJECT(fade_out_shape), "regionview", this);
+
+
+
+ {
+ uint32_t r,g,b,a;
+ UINT_TO_RGBA(fill_color,&r,&g,&b,&a);
+
+
+ fade_in_handle = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_simplerect_get_type(),
+ "fill_color_rgba", RGBA_TO_UINT(r,g,b,0),
+ "outline_pixels", 0,
+ "y1", 2.0,
+ "y2", 7.0,
+ NULL);
+ gtk_object_set_data (GTK_OBJECT(fade_in_handle), "regionview", this);
+
+ fade_out_handle = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_simplerect_get_type(),
+ "fill_color_rgba", RGBA_TO_UINT(r,g,b,0),
+ "outline_pixels", 0,
+ "y1", 2.0,
+ "y2", 7.0,
+ NULL);
+ gtk_object_set_data (GTK_OBJECT(fade_out_handle), "regionview", this);
+ }
+
+ string foo = region.name();
+ foo += ':';
+ foo += "gain";
+
+ gain_line = new AudioRegionGainLine (foo, tv.session(), *this, group, region.envelope(),
+ PublicEditor::canvas_control_point_event,
+ PublicEditor::canvas_line_event);
+
+ if (!(_flags & EnvelopeVisible)) {
+ gain_line->hide ();
+ } else {
+ gain_line->show ();
+ }
+
+ reset_width_dependent_items ((double) region.length() / samples_per_unit);
+
+ gain_line->reset ();
+
+ set_height (trackview.height);
+
+ region_muted ();
+ region_sync_changed ();
+ region_resized (BoundsChanged);
+ set_waveview_data_src();
+ region_locked ();
+ envelope_active_changed ();
+ fade_in_active_changed ();
+ fade_out_active_changed ();
+
+ region.StateChanged.connect (slot (*this, &AudioRegionView::region_changed));
+
+ gtk_signal_connect (GTK_OBJECT(group), "event",
+ (GtkSignalFunc) PublicEditor::canvas_region_view_event,
+ this);
+ gtk_signal_connect (GTK_OBJECT(name_highlight), "event",
+ (GtkSignalFunc) PublicEditor::canvas_region_view_name_highlight_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(name_text), "event",
+ (GtkSignalFunc) PublicEditor::canvas_region_view_name_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(fade_in_shape), "event",
+ (GtkSignalFunc) PublicEditor::canvas_fade_in_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(fade_in_handle), "event",
+ (GtkSignalFunc) PublicEditor::canvas_fade_in_handle_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(fade_out_shape), "event",
+ (GtkSignalFunc) PublicEditor::canvas_fade_out_event,
+ this);
+
+ gtk_signal_connect (GTK_OBJECT(fade_out_handle), "event",
+ (GtkSignalFunc) PublicEditor::canvas_fade_out_handle_event,
+ this);
+
+ set_colors ();
+
+ /* XXX sync mark drag? */
+
+}
+
+AudioRegionView::~AudioRegionView ()
+{
+ in_destructor = true;
+
+ AudioRegionViewGoingAway (this); /* EMIT_SIGNAL */
+
+ for (vector<GtkCanvasWaveViewCache *>::iterator cache = wave_caches.begin(); cache != wave_caches.end() ; ++cache) {
+ gtk_canvas_waveview_cache_destroy (*cache);
+ }
+
+ /* all waveviews will be destroyed when the group is destroyed */
+
+ for (vector<GhostRegion*>::iterator g = ghosts.begin(); g != ghosts.end(); ++g) {
+ delete *g;
+ }
+
+ if (editor) {
+ delete editor;
+ }
+
+ delete gain_line;
+}
+
+gint
+AudioRegionView::_lock_toggle (GtkCanvasItem* item, GdkEvent* ev, void* arg)
+{
+ switch (ev->type) {
+ case GDK_BUTTON_RELEASE:
+ static_cast<AudioRegionView*>(arg)->lock_toggle ();
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+void
+AudioRegionView::lock_toggle ()
+{
+ region.set_locked (!region.locked());
+}
+
+void
+AudioRegionView::region_changed (Change what_changed)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &AudioRegionView::region_changed), what_changed));
+
+ if (what_changed & BoundsChanged) {
+ region_resized (what_changed);
+ region_sync_changed ();
+ }
+ if (what_changed & Region::MuteChanged) {
+ region_muted ();
+ }
+ if (what_changed & Region::OpacityChanged) {
+ region_opacity ();
+ }
+ if (what_changed & ARDOUR::NameChanged) {
+ region_renamed ();
+ }
+ if (what_changed & Region::SyncOffsetChanged) {
+ region_sync_changed ();
+ }
+ if (what_changed & Region::LayerChanged) {
+ region_layered ();
+ }
+ if (what_changed & Region::LockChanged) {
+ region_locked ();
+ }
+ if (what_changed & AudioRegion::ScaleAmplitudeChanged) {
+ region_scale_amplitude_changed ();
+ }
+ if (what_changed & AudioRegion::FadeInChanged) {
+ fade_in_changed ();
+ }
+ if (what_changed & AudioRegion::FadeOutChanged) {
+ fade_out_changed ();
+ }
+ if (what_changed & AudioRegion::FadeInActiveChanged) {
+ fade_in_active_changed ();
+ }
+ if (what_changed & AudioRegion::FadeOutActiveChanged) {
+ fade_out_active_changed ();
+ }
+ if (what_changed & AudioRegion::EnvelopeActiveChanged) {
+ envelope_active_changed ();
+ }
+}
+
+void
+AudioRegionView::fade_in_changed ()
+{
+ reset_fade_in_shape ();
+}
+
+void
+AudioRegionView::fade_out_changed ()
+{
+ reset_fade_out_shape ();
+}
+
+void
+AudioRegionView::set_fade_in_active (bool yn)
+{
+ region.set_fade_in_active (yn);
+}
+
+void
+AudioRegionView::set_fade_out_active (bool yn)
+{
+ region.set_fade_out_active (yn);
+}
+
+void
+AudioRegionView::fade_in_active_changed ()
+{
+ uint32_t r,g,b,a;
+ uint32_t col;
+ UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+
+ if (region.fade_in_active()) {
+ col = RGBA_TO_UINT(r,g,b,120);
+ gtk_canvas_item_set (fade_in_shape,
+ "fill_color_rgba", col,
+ "width_pixels", 0,
+ "outline_color_rgba", RGBA_TO_UINT(r,g,b,0),
+ NULL);
+ } else {
+ col = RGBA_TO_UINT(r,g,b,0);
+ gtk_canvas_item_set (fade_in_shape,
+ "fill_color_rgba", col,
+ "width_pixels", 1,
+ "outline_color_rgba", RGBA_TO_UINT(r,g,b,255),
+ NULL);
+ }
+}
+
+void
+AudioRegionView::fade_out_active_changed ()
+{
+ uint32_t r,g,b,a;
+ uint32_t col;
+ UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+
+ if (region.fade_out_active()) {
+ col = RGBA_TO_UINT(r,g,b,120);
+ gtk_canvas_item_set (fade_out_shape,
+ "fill_color_rgba", col,
+ "width_pixels", 0,
+ "outline_color_rgba", RGBA_TO_UINT(r,g,b,0),
+ NULL);
+ } else {
+ col = RGBA_TO_UINT(r,g,b,0);
+ gtk_canvas_item_set (fade_out_shape,
+ "fill_color_rgba", col,
+ "width_pixels", 1,
+ "outline_color_rgba", RGBA_TO_UINT(r,g,b,255),
+ NULL);
+ }
+}
+
+
+void
+AudioRegionView::region_scale_amplitude_changed ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &AudioRegionView::region_scale_amplitude_changed));
+
+ for (uint32_t n = 0; n < waves.size(); ++n) {
+ // force a reload of the cache
+ gtk_canvas_item_set (waves[n], "data_src", &region, NULL);
+ }
+}
+
+void
+AudioRegionView::region_locked ()
+{
+ /* name will show locked status */
+ region_renamed ();
+}
+
+void
+AudioRegionView::region_resized (Change what_changed)
+{
+ double unit_length;
+
+ if (what_changed & ARDOUR::PositionChanged) {
+ set_position (region.position(), 0);
+ }
+
+ if (what_changed & Change (StartChanged|LengthChanged)) {
+
+ set_duration (region.length(), 0);
+
+ unit_length = region.length() / samples_per_unit;
+
+ reset_width_dependent_items (unit_length);
+
+ for (uint32_t n = 0; n < waves.size(); ++n) {
+ gtk_canvas_item_set (waves[n], "region_start", (guint32) region.start(), NULL);
+ }
+
+ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+
+ (*i)->set_duration (unit_length);
+
+ for (vector<GtkCanvasItem*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
+ gtk_canvas_item_set ((*w), "region_start", region.start(), NULL);
+ }
+ }
+ }
+}
+
+void
+AudioRegionView::reset_width_dependent_items (double pixel_width)
+{
+ TimeAxisViewItem::reset_width_dependent_items (pixel_width);
+ _pixel_width = pixel_width;
+
+ if (zero_line) {
+ gtk_canvas_item_set (zero_line, "x2", pixel_width - 1.0, NULL);
+ }
+
+ if (pixel_width <= 6.0) {
+ gtk_canvas_item_hide (fade_in_handle);
+ gtk_canvas_item_hide (fade_out_handle);
+ } else {
+ if (_height < 5.0) {
+ gtk_canvas_item_hide (fade_in_handle);
+ gtk_canvas_item_hide (fade_out_handle);
+ } else {
+ gtk_canvas_item_show (fade_in_handle);
+ gtk_canvas_item_show (fade_out_handle);
+ }
+ }
+
+ reset_fade_shapes ();
+}
+
+void
+AudioRegionView::region_layered ()
+{
+ AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (&get_time_axis_view());
+ atv->view->region_layered (this);
+}
+
+void
+AudioRegionView::region_muted ()
+{
+ set_frame_color ();
+ region_renamed ();
+
+ for (uint32_t n=0; n < waves.size(); ++n) {
+ if (region.muted()) {
+ gtk_canvas_item_set (waves[n], "wave_color", color_map[cMutedWaveForm], NULL);
+ } else {
+ gtk_canvas_item_set (waves[n], "wave_color", color_map[cWaveForm], NULL);
+ }
+ }
+}
+
+void
+AudioRegionView::region_opacity ()
+{
+ set_frame_color ();
+}
+
+void
+AudioRegionView::raise ()
+{
+ region.raise ();
+}
+
+void
+AudioRegionView::raise_to_top ()
+{
+ region.raise_to_top ();
+}
+
+void
+AudioRegionView::lower ()
+{
+ region.lower ();
+}
+
+void
+AudioRegionView::lower_to_bottom ()
+{
+ region.lower_to_bottom ();
+}
+
+bool
+AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored)
+{
+ double delta;
+ bool ret;
+
+ if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) {
+ return false;
+ }
+
+ if (ignored) {
+ *ignored = delta;
+ }
+
+ if (delta) {
+ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+ gtk_canvas_item_move ((*i)->group, delta, 0.0);
+ }
+ }
+
+ return ret;
+}
+
+void
+AudioRegionView::set_height (gdouble height)
+{
+ uint32_t wcnt = waves.size();
+
+ TimeAxisViewItem::set_height (height - 2);
+
+ _height = height;
+
+ for (uint32_t n=0; n < wcnt; ++n) {
+ gdouble ht;
+
+ if ((height) < NAME_HIGHLIGHT_THRESH) {
+ ht = ((height-2*wcnt) / (double) wcnt);
+ } else {
+ ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt);
+ }
+
+ gdouble yoff = n * (ht+1);
+
+ gtk_canvas_item_set (waves[n], "height", ht, NULL);
+ gtk_canvas_item_set (waves[n], "y", yoff + 2, NULL);
+ }
+
+ if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) {
+ gain_line->hide ();
+ } else {
+ if (_flags & EnvelopeVisible) {
+ gain_line->show ();
+ }
+ }
+
+ manage_zero_line ();
+ gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE));
+ reset_fade_shapes ();
+
+ gtk_canvas_item_raise_to_top (name_text) ;
+}
+
+void
+AudioRegionView::manage_zero_line ()
+{
+ if (!zero_line) {
+ return;
+ }
+
+ if (_height >= 100) {
+ gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0;
+ gtk_canvas_item_set (zero_line,
+ "y1", wave_midpoint,
+ "y2", wave_midpoint,
+ NULL);
+ gtk_canvas_item_show (zero_line);
+ } else {
+ gtk_canvas_item_hide (zero_line);
+ }
+}
+
+void
+AudioRegionView::reset_fade_shapes ()
+{
+ reset_fade_in_shape ();
+ reset_fade_out_shape ();
+}
+
+void
+AudioRegionView::reset_fade_in_shape ()
+{
+ reset_fade_in_shape_width ((jack_nframes_t) region.fade_in().back()->when);
+}
+
+void
+AudioRegionView::reset_fade_in_shape_width (jack_nframes_t width)
+{
+ /* smallest size for a fade is 64 frames */
+
+ width = std::max ((jack_nframes_t) 64, width);
+
+ GtkCanvasPoints* points;
+ double pwidth = width / samples_per_unit;
+ uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
+ double h;
+
+ if (_height < 5) {
+ gtk_canvas_item_hide (fade_in_shape);
+ gtk_canvas_item_hide (fade_in_handle);
+ return;
+ }
+
+ double handle_center;
+ handle_center = pwidth;
+
+ if (handle_center > 7.0) {
+ handle_center -= 3.0;
+ } else {
+ handle_center = 3.0;
+ }
+
+ gtk_canvas_item_set (fade_in_handle,
+ "x1", handle_center - 3.0,
+ "x2", handle_center + 3.0,
+ NULL);
+
+ if (pwidth < 5) {
+ gtk_canvas_item_hide (fade_in_shape);
+ return;
+ }
+
+ gtk_canvas_item_show (fade_in_shape);
+
+ float curve[npoints];
+ region.fade_in().get_vector (0, region.fade_in().back()->when, curve, npoints);
+
+ points = get_canvas_points ("fade in shape", npoints+3);
+
+ if (_height > NAME_HIGHLIGHT_THRESH) {
+ h = _height - NAME_HIGHLIGHT_SIZE;
+ } else {
+ h = _height;
+ }
+
+ /* points *MUST* be in anti-clockwise order */
+
+ uint32_t pi, pc;
+ double xdelta = pwidth/npoints;
+
+ for (pi = 0, pc = 0; pc < npoints; ++pc) {
+ points->coords[pi++] = 1 + (pc * xdelta);
+ points->coords[pi++] = 2 + (h - (curve[pc] * h));
+ }
+
+ /* fold back */
+
+ points->coords[pi++] = pwidth;
+ points->coords[pi++] = 2;
+
+ points->coords[pi++] = 1;
+ points->coords[pi++] = 2;
+
+ /* connect the dots ... */
+
+ points->coords[pi++] = points->coords[0];
+ points->coords[pi] = points->coords[1];
+
+ gtk_canvas_item_set (fade_in_shape, "points", points, NULL);
+ gtk_canvas_points_unref (points);
+}
+
+void
+AudioRegionView::reset_fade_out_shape ()
+{
+ reset_fade_out_shape_width ((jack_nframes_t) region.fade_out().back()->when);
+}
+
+void
+AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width)
+{
+ /* smallest size for a fade is 64 frames */
+
+ width = std::max ((jack_nframes_t) 64, width);
+
+ GtkCanvasPoints* points;
+ double pwidth = width / samples_per_unit;
+ uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth);
+ double h;
+
+ if (_height < 5) {
+ gtk_canvas_item_hide (fade_out_shape);
+ gtk_canvas_item_hide (fade_out_handle);
+ return;
+ }
+
+ double handle_center;
+ handle_center = (region.length() - width) / samples_per_unit;
+
+ if (handle_center > 7.0) {
+ handle_center -= 3.0;
+ } else {
+ handle_center = 3.0;
+ }
+
+ gtk_canvas_item_set (fade_out_handle,
+ "x1", handle_center - 3.0,
+ "x2", handle_center + 3.0,
+ NULL);
+
+ /* don't show shape if its too small */
+
+ if (pwidth < 5) {
+ gtk_canvas_item_hide (fade_out_shape);
+ return;
+ }
+
+ gtk_canvas_item_show (fade_out_shape);
+
+ float curve[npoints];
+ region.fade_out().get_vector (0, region.fade_out().back()->when, curve, npoints);
+
+ if (_height > NAME_HIGHLIGHT_THRESH) {
+ h = _height - NAME_HIGHLIGHT_SIZE;
+ } else {
+ h = _height;
+ }
+
+ /* points *MUST* be in anti-clockwise order */
+
+ points = get_canvas_points ("fade out shape", npoints+3);
+
+ uint32_t pi, pc;
+ double xdelta = pwidth/npoints;
+
+ for (pi = 0, pc = 0; pc < npoints; ++pc) {
+ points->coords[pi++] = _pixel_width - 1 - pwidth + (pc*xdelta);
+ points->coords[pi++] = 2 + (h - (curve[pc] * h));
+ }
+
+ /* fold back */
+
+ points->coords[pi++] = _pixel_width;
+ points->coords[pi++] = h;
+
+ points->coords[pi++] = _pixel_width;
+ points->coords[pi++] = 2;
+
+ /* connect the dots ... */
+
+ points->coords[pi++] = points->coords[0];
+ points->coords[pi] = points->coords[1];
+
+ gtk_canvas_item_set (fade_out_shape, "points", points, NULL);
+ gtk_canvas_points_unref (points);
+}
+
+void
+AudioRegionView::set_samples_per_unit (gdouble spu)
+{
+ TimeAxisViewItem::set_samples_per_unit (spu);
+
+ for (uint32_t n=0; n < waves.size(); ++n) {
+ gtk_canvas_item_set (waves[n], "samples_per_unit", spu, NULL);
+ }
+
+ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+ (*i)->set_samples_per_unit (spu);
+ (*i)->set_duration (region.length() / samples_per_unit);
+ }
+
+ gain_line->reset ();
+ reset_fade_shapes ();
+ region_sync_changed ();
+}
+
+bool
+AudioRegionView::set_duration (jack_nframes_t frames, void *src)
+{
+ if (!TimeAxisViewItem::set_duration (frames, src)) {
+ return false;
+ }
+
+ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+ (*i)->set_duration (region.length() / samples_per_unit);
+ }
+
+ return true;
+}
+
+void
+AudioRegionView::set_amplitude_above_axis (gdouble spp)
+{
+ for (uint32_t n=0; n < waves.size(); ++n) {
+ gtk_canvas_item_set (waves[n], "amplitude_above_axis", spp, NULL);
+ }
+}
+
+void
+AudioRegionView::compute_colors (GdkColor& basic_color)
+{
+ TimeAxisViewItem::compute_colors (basic_color);
+ uint32_t r, g, b, a;
+
+ /* gain color computed in envelope_active_changed() */
+
+ UINT_TO_RGBA (fill_color, &r, &g, &b, &a);
+ fade_color = RGBA_TO_UINT(r,g,b,120);
+}
+
+void
+AudioRegionView::set_colors ()
+{
+ TimeAxisViewItem::set_colors ();
+
+ gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
+ gtk_canvas_item_set (sync_mark, "fill_color_rgba", fill_color, NULL);
+
+ for (uint32_t n=0; n < waves.size(); ++n) {
+ if (region.muted()) {
+ gtk_canvas_item_set (waves[n], "wave_color", color_map[cMutedWaveForm], NULL);
+ } else {
+ gtk_canvas_item_set (waves[n], "wave_color", color_map[cWaveForm], NULL);
+ }
+ }
+}
+
+void
+AudioRegionView::set_frame_color ()
+{
+ if (region.opaque()) {
+ fill_opacity = 180;
+ } else {
+ fill_opacity = 100;
+ }
+
+ TimeAxisViewItem::set_frame_color ();
+}
+
+void
+AudioRegionView::show_region_editor ()
+{
+ if (editor == 0) {
+ editor = new AudioRegionEditor (trackview.session(), region, *this);
+ editor->realize ();
+ trackview.editor.ensure_float (*editor);
+ }
+
+ editor->show_all ();
+ editor->get_window().raise();
+}
+
+void
+AudioRegionView::hide_region_editor()
+{
+ if (editor) {
+ editor->hide_all ();
+ }
+}
+
+void
+AudioRegionView::region_renamed ()
+{
+ string str;
+
+ if (region.locked()) {
+ str += '>';
+ str += region.name();
+ str += '<';
+ } else {
+ str = region.name();
+ }
+
+ if (region.muted()) {
+ str = string ("!") + str;
+ }
+
+ set_item_name (region.name(), this);
+ set_name_text (str);
+}
+
+void
+AudioRegionView::region_sync_changed ()
+{
+ int sync_dir;
+ jack_nframes_t sync_offset;
+
+ sync_offset = region.sync_offset (sync_dir);
+
+ /* this has to handle both a genuine change of position, a change of samples_per_unit,
+ and a change in the bounds of the region.
+ */
+
+ if (sync_offset == 0) {
+
+ /* no sync mark - its the start of the region */
+
+ gtk_canvas_item_hide (sync_mark);
+
+ } else {
+
+ if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > region.length()))) {
+
+ /* no sync mark - its out of the bounds of the region */
+
+ gtk_canvas_item_hide (sync_mark);
+
+ } else {
+
+ /* lets do it */
+
+ GtkArg args[1];
+ GtkCanvasPoints* points;
+
+ args[0].name = X_("points");
+
+ gtk_object_getv (GTK_OBJECT(sync_mark), 1, args);
+ points = static_cast<GtkCanvasPoints *> (GTK_VALUE_POINTER(args[0]));
+
+ double offset = sync_offset / samples_per_unit;
+
+ points->coords[0] = offset - ((sync_mark_width-1)/2);
+ points->coords[1] = 1;
+
+ points->coords[2] = offset + (sync_mark_width-1)/2;
+ points->coords[3] = 1;
+
+ points->coords[4] = offset;
+ points->coords[5] = sync_mark_width - 1;
+
+ points->coords[6] = offset - ((sync_mark_width-1)/2);
+ points->coords[7] = 1;
+
+ gtk_canvas_item_show (sync_mark);
+ gtk_canvas_item_set (sync_mark, "points", points, NULL);
+
+ gtk_canvas_points_unref (points);
+ }
+ }
+}
+
+void
+AudioRegionView::set_waveform_visible (bool yn)
+{
+ if (((_flags & WaveformVisible) != yn)) {
+ if (yn) {
+ for (uint32_t n=0; n < waves.size(); ++n) {
+ gtk_canvas_item_show (waves[n]);
+ }
+ _flags |= WaveformVisible;
+ } else {
+ for (uint32_t n=0; n < waves.size(); ++n) {
+ gtk_canvas_item_hide (waves[n]);
+ }
+ _flags &= ~WaveformVisible;
+ }
+ store_flags ();
+ }
+}
+
+void
+AudioRegionView::temporarily_hide_envelope ()
+{
+ gain_line->hide ();
+}
+
+void
+AudioRegionView::unhide_envelope ()
+{
+ if (_flags & EnvelopeVisible) {
+ gain_line->show ();
+ }
+}
+
+void
+AudioRegionView::set_envelope_visible (bool yn)
+{
+ if ((_flags & EnvelopeVisible) != yn) {
+ if (yn) {
+ gain_line->show ();
+ _flags |= EnvelopeVisible;
+ } else {
+ gain_line->hide ();
+ _flags &= ~EnvelopeVisible;
+ }
+ store_flags ();
+ }
+}
+
+void
+AudioRegionView::create_waves ()
+{
+ bool create_zero_line = true;
+
+ AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
+
+ if (!atv.get_diskstream()) {
+ return;
+ }
+
+ uint32_t nchans = atv.get_diskstream()->n_channels();
+
+// if (wait_for_waves) {
+ /* in tmp_waves, set up null pointers for each channel so the vector is allocated */
+ for (uint32_t n = 0; n < nchans; ++n) {
+ tmp_waves.push_back (0);
+ }
+// }
+
+ for (uint32_t n = 0; n < nchans; ++n) {
+
+ if (n >= region.n_channels()) {
+ break;
+ }
+
+ wave_caches.push_back (gtk_canvas_waveview_cache_new ());
+
+ if (wait_for_waves) {
+ if (region.source(n).peaks_ready (bind (slot (*this, &AudioRegionView::peaks_ready_handler), n))) {
+ create_one_wave (n, true);
+ } else {
+ create_zero_line = false;
+ }
+ } else {
+ create_one_wave (n, true);
+ }
+ }
+
+ if (create_zero_line) {
+ zero_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_simpleline_get_type(),
+ "x1", (gdouble) 1.0,
+ "x2", (gdouble) (region.length() / samples_per_unit) - 1.0,
+ "color_rgba", (guint) color_map[cZeroLine],
+ NULL);
+ manage_zero_line ();
+ }
+}
+
+void
+AudioRegionView::create_one_wave (uint32_t which, bool direct)
+{
+ AudioTimeAxisView& atv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
+ uint32_t nchans = atv.get_diskstream()->n_channels();
+ uint32_t n;
+ uint32_t nwaves = std::min (nchans, region.n_channels());
+
+ gdouble ht;
+ if (trackview.height < NAME_HIGHLIGHT_SIZE) {
+ ht = ((trackview.height) / (double) nchans);
+ } else {
+ ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans);
+ }
+ gdouble yoff = which * ht;
+
+ GtkCanvasItem *wave = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_waveview_get_type (),
+ "data_src", (gpointer) &region,
+ "cache", wave_caches[which],
+ "cache_updater", (gboolean) true,
+ "channel", (guint32) which,
+ "length_function", (gpointer) region_length_from_c,
+ "sourcefile_length_function",(gpointer) sourcefile_length_from_c,
+ "peak_function", (gpointer) region_read_peaks_from_c,
+ "x", 0.0,
+ "y", yoff,
+ "height", (double) ht,
+ "samples_per_unit", samples_per_unit,
+ "amplitude_above_axis", _amplitude_above_axis,
+ "wave_color", (guint32) (region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm]),
+ "region_start",(guint32) region.start(),
+ NULL);
+
+ if (!(_flags & WaveformVisible)) {
+ gtk_canvas_item_hide (wave);
+ }
+
+ /* note: calling this function is serialized by the lock
+ held in the peak building thread that signals that
+ peaks are ready for use *or* by the fact that it is
+ called one by one from the GUI thread.
+ */
+
+ if (which < nchans) {
+ tmp_waves[which] = (wave);
+ } else {
+ /* n-channel track, >n-channel source */
+ }
+
+ /* see if we're all ready */
+
+ for (n = 0; n < nchans; ++n) {
+ if (tmp_waves[n] == 0) {
+ break;
+ }
+ }
+
+ if (n == nwaves) {
+ /* all waves are ready */
+ tmp_waves.resize(nwaves);
+ waves = tmp_waves;
+ tmp_waves.clear ();
+
+ if (!zero_line) {
+ zero_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(group),
+ gtk_canvas_simpleline_get_type(),
+ "x1", (gdouble) 1.0,
+ "x2", (gdouble) (region.length() / samples_per_unit) - 1.0,
+ "color_rgba", (guint) color_map[cZeroLine],
+ NULL);
+ manage_zero_line ();
+ }
+ }
+}
+
+void
+AudioRegionView::peaks_ready_handler (uint32_t which)
+{
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &AudioRegionView::create_one_wave), which, false));
+}
+
+void
+AudioRegionView::add_gain_point_event (GtkCanvasItem *item, GdkEvent *ev)
+{
+ double x, y;
+
+ /* don't create points that can't be seen */
+
+ set_envelope_visible (true);
+
+ x = ev->button.x;
+ y = ev->button.y;
+
+ gtk_canvas_item_w2i (item, &x, &y);
+
+ jack_nframes_t fx = trackview.editor.pixel_to_frame (x);
+
+ if (fx > region.length()) {
+ return;
+ }
+
+ /* compute vertical fractional position */
+
+ y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE));
+
+ /* map using gain line */
+
+ gain_line->view_to_model_y (y);
+
+ trackview.session().begin_reversible_command (_("add gain control point"));
+ trackview.session().add_undo (region.envelope().get_memento());
+
+
+ if (!region.envelope_active()) {
+ trackview.session().add_undo( bind( slot(region, &AudioRegion::set_envelope_active), false) );
+ region.set_envelope_active(true);
+ trackview.session().add_redo( bind( slot(region, &AudioRegion::set_envelope_active), true) );
+ }
+
+ region.envelope().add (fx, y);
+
+ trackview.session().add_redo_no_execute (region.envelope().get_memento());
+ trackview.session().commit_reversible_command ();
+}
+
+void
+AudioRegionView::remove_gain_point_event (GtkCanvasItem *item, GdkEvent *ev)
+{
+ ControlPoint *cp = reinterpret_cast<ControlPoint *> (gtk_object_get_data(GTK_OBJECT(item), "control_point"));
+ region.envelope().erase (cp->model);
+}
+
+void
+AudioRegionView::store_flags()
+{
+ XMLNode *node = new XMLNode ("GUI");
+
+ node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no");
+ node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no");
+
+ region.add_extra_xml (*node);
+}
+
+void
+AudioRegionView::set_flags (XMLNode* node)
+{
+ XMLProperty *prop;
+
+ if ((prop = node->property ("waveform-visible")) != 0) {
+ if (prop->value() == "yes") {
+ _flags |= WaveformVisible;
+ }
+ }
+
+ if ((prop = node->property ("envelope-visible")) != 0) {
+ if (prop->value() == "yes") {
+ _flags |= EnvelopeVisible;
+ }
+ }
+}
+
+void
+AudioRegionView::set_waveform_shape (WaveformShape shape)
+{
+ bool yn;
+
+ /* this slightly odd approach is to leave the door open to
+ other "shapes" such as spectral displays, etc.
+ */
+
+ switch (shape) {
+ case Rectified:
+ yn = true;
+ break;
+
+ default:
+ yn = false;
+ break;
+ }
+
+ if (yn != (bool) (_flags & WaveformRectified)) {
+ for (vector<GtkCanvasItem *>::iterator wave = waves.begin(); wave != waves.end() ; ++wave) {
+ gtk_canvas_item_set ((*wave), "rectified", (gboolean) yn, NULL);
+ }
+
+ if (zero_line) {
+ if (yn) {
+ gtk_canvas_item_hide (zero_line);
+ } else {
+ gtk_canvas_item_show (zero_line);
+ }
+ }
+
+ if (yn) {
+ _flags |= WaveformRectified;
+ } else {
+ _flags &= ~WaveformRectified;
+ }
+ }
+}
+
+std::string
+AudioRegionView::get_item_name ()
+{
+ return region.name();
+}
+
+void
+AudioRegionView::move (double x_delta, double y_delta)
+{
+ if (region.locked() || (x_delta == 0 && y_delta == 0)) {
+ return;
+ }
+
+ gtk_canvas_item_move (get_canvas_group(), x_delta, y_delta);
+
+ /* note: ghosts never leave their tracks so y_delta for them is always zero */
+
+ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+ gtk_canvas_item_move ((*i)->group, x_delta, 0.0);
+ }
+}
+
+GhostRegion*
+AudioRegionView::add_ghost (AutomationTimeAxisView& atv)
+{
+ AudioTimeAxisView& myatv (*(dynamic_cast<AudioTimeAxisView*>(&trackview))); // ick
+ double unit_position = region.position () / samples_per_unit;
+ GhostRegion* ghost = new GhostRegion (atv, unit_position);
+ uint32_t nchans;
+
+ nchans = myatv.get_diskstream()->n_channels();
+
+ for (uint32_t n = 0; n < nchans; ++n) {
+
+ if (n >= region.n_channels()) {
+ break;
+ }
+
+ GtkCanvasItem *wave = gtk_canvas_item_new (GTK_CANVAS_GROUP(ghost->group),
+ gtk_canvas_waveview_get_type (),
+ "data_src", (gpointer) &region,
+ "cache", wave_caches[n],
+ "cache_updater", (gboolean) false,
+ "channel", (guint32) n,
+ "length_function", (gpointer) region_length_from_c,
+ "sourcefile_length_function",(gpointer) sourcefile_length_from_c,
+ "peak_function", (gpointer) region_read_peaks_from_c,
+ "x", 0.0,
+ "samples_per_unit", samples_per_unit,
+ "amplitude_above_axis", _amplitude_above_axis,
+ "wave_color", color_map[cGhostTrackWave],
+ "region_start", (guint32) region.start(),
+ NULL);
+
+
+ ghost->waves.push_back(wave);
+ }
+
+ ghost->set_height ();
+ ghost->set_duration (region.length() / samples_per_unit);
+ ghosts.push_back (ghost);
+
+ ghost->GoingAway.connect (slot (*this, &AudioRegionView::remove_ghost));
+
+ return ghost;
+}
+
+void
+AudioRegionView::remove_ghost (GhostRegion* ghost)
+{
+ if (in_destructor) {
+ return;
+ }
+
+ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+ if (*i == ghost) {
+ ghosts.erase (i);
+ break;
+ }
+ }
+}
+
+uint32_t
+AudioRegionView::get_fill_color ()
+{
+ return fill_color;
+}
+
+void
+AudioRegionView::entered ()
+{
+ if (_flags & EnvelopeVisible) {
+ gain_line->show_all_control_points ();
+ }
+
+ uint32_t r,g,b,a;
+ UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+ a=255;
+
+ gtk_canvas_item_set (fade_in_handle, "fill_color_rgba", RGBA_TO_UINT(r,g,b,a), NULL);
+ gtk_canvas_item_set (fade_out_handle, "fill_color_rgba", RGBA_TO_UINT(r,g,b,a), NULL);
+}
+
+void
+AudioRegionView::exited ()
+{
+ gain_line->hide_all_but_selected_control_points ();
+
+ uint32_t r,g,b,a;
+ UINT_TO_RGBA(fade_color,&r,&g,&b,&a);
+ a=0;
+
+ gtk_canvas_item_set (fade_in_handle, "fill_color_rgba", RGBA_TO_UINT(r,g,b,a), NULL);
+ gtk_canvas_item_set (fade_out_handle, "fill_color_rgba", RGBA_TO_UINT(r,g,b,a), NULL);
+}
+
+void
+AudioRegionView::envelope_active_changed ()
+{
+ gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]);
+}
+
+void
+AudioRegionView::set_waveview_data_src()
+{
+
+ double unit_length= region.length() / samples_per_unit;
+
+ for (uint32_t n = 0; n < waves.size(); ++n) {
+ // TODO: something else to let it know the channel
+ gtk_canvas_item_set (waves[n], "data_src", &region, NULL);
+ }
+
+ for (vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
+
+ (*i)->set_duration (unit_length);
+
+ for (vector<GtkCanvasItem*>::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) {
+ gtk_canvas_item_set ((*w), "data_src", &region, NULL);
+ }
+ }
+
+}
+
+
diff --git a/gtk2_ardour/regionview.h b/gtk2_ardour/regionview.h
new file mode 100644
index 0000000000..0a40622bd0
--- /dev/null
+++ b/gtk2_ardour/regionview.h
@@ -0,0 +1,187 @@
+/*
+ Copyright (C) 2001-2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_region_view_h__
+#define __gtk_ardour_region_view_h__
+
+#include <vector>
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <sigc++/signal_system.h>
+#include <ardour/region.h>
+
+#include "time_axis_view_item.h"
+#include "automation_line.h"
+#include "enums.h"
+#include "canvas-waveview.h"
+
+namespace ARDOUR {
+ class AudioRegion;
+ class PeakData;
+};
+
+class AudioTimeAxisView;
+class AudioRegionGainLine;
+class AudioRegionEditor;
+class GhostRegion;
+class AutomationTimeAxisView;
+
+class AudioRegionView : public TimeAxisViewItem
+{
+ public:
+ AudioRegionView (GtkCanvasGroup *,
+ AudioTimeAxisView&,
+ ARDOUR::AudioRegion&,
+ double initial_samples_per_unit,
+ double amplitude_above_axis,
+ GdkColor& base_color,
+ bool wait_for_waves);
+ ~AudioRegionView ();
+
+ ARDOUR::AudioRegion& region; // ok, let 'em have it
+ bool is_valid() const { return valid; }
+ void set_valid (bool yn) { valid = yn; }
+
+ std::string get_item_name();
+ void set_height (double);
+ void set_samples_per_unit (double);
+ bool set_duration (jack_nframes_t, void*);
+
+ void set_amplitude_above_axis (gdouble spp);
+
+ void move (double xdelta, double ydelta);
+
+ void raise ();
+ void raise_to_top ();
+ void lower ();
+ void lower_to_bottom ();
+
+ bool set_position(jack_nframes_t pos, void* src, double* delta = 0);
+
+ void temporarily_hide_envelope (); // dangerous
+ void unhide_envelope (); // dangerous
+
+ void set_envelope_visible (bool);
+ void set_waveform_visible (bool yn);
+ void set_waveform_shape (WaveformShape);
+
+ bool waveform_rectified() const { return _flags & WaveformRectified; }
+ bool waveform_visible() const { return _flags & WaveformVisible; }
+ bool envelope_visible() const { return _flags & EnvelopeVisible; }
+
+ void show_region_editor ();
+ void hide_region_editor();
+
+ void add_gain_point_event (GtkCanvasItem *item, GdkEvent *event);
+ void remove_gain_point_event (GtkCanvasItem *item, GdkEvent *event);
+
+ AudioRegionGainLine* get_gain_line() const { return gain_line; }
+
+ void region_changed (ARDOUR::Change);
+ void envelope_active_changed ();
+
+ static SigC::Signal1<void,AudioRegionView*> AudioRegionViewGoingAway;
+ SigC::Signal0<void> GoingAway;
+
+ GhostRegion* add_ghost (AutomationTimeAxisView&);
+ void remove_ghost (GhostRegion*);
+
+ void reset_fade_in_shape_width (jack_nframes_t);
+ void reset_fade_out_shape_width (jack_nframes_t);
+ void set_fade_in_active (bool);
+ void set_fade_out_active (bool);
+
+ uint32_t get_fill_color ();
+
+ virtual void entered ();
+ virtual void exited ();
+
+ private:
+ enum Flags {
+ EnvelopeVisible = 0x1,
+ WaveformVisible = 0x4,
+ WaveformRectified = 0x8
+ };
+
+ vector<GtkCanvasItem *> waves; /* waveviews */
+ vector<GtkCanvasItem *> tmp_waves; /* see ::create_waves()*/
+ GtkCanvasItem* sync_mark; /* polgyon for sync position */
+ GtkCanvasItem* no_wave_msg; /* text */
+ GtkCanvasItem* zero_line; /* simpleline */
+ GtkCanvasItem* fade_in_shape; /* polygon */
+ GtkCanvasItem* fade_out_shape; /* polygon */
+ GtkCanvasItem* fade_in_handle; /* simplerect */
+ GtkCanvasItem* fade_out_handle; /* simplerect */
+
+ AudioRegionGainLine* gain_line;
+ AudioRegionEditor *editor;
+
+ vector<ControlPoint *> control_points;
+ double _amplitude_above_axis;
+ double current_visible_sync_position;
+
+ uint32_t _flags;
+ uint32_t fade_color;
+ bool valid; /* see StreamView::redisplay_diskstream() */
+ double _pixel_width;
+ double _height;
+ bool in_destructor;
+ bool wait_for_waves;
+
+ void reset_fade_shapes ();
+ void reset_fade_in_shape ();
+ void reset_fade_out_shape ();
+ void fade_in_changed ();
+ void fade_out_changed ();
+ void fade_in_active_changed ();
+ void fade_out_active_changed ();
+
+ void region_resized (ARDOUR::Change);
+ void region_moved (void *);
+ void region_muted ();
+ void region_locked ();
+ void region_opacity ();
+ void region_layered ();
+ void region_renamed ();
+ void region_sync_changed ();
+ void region_scale_amplitude_changed ();
+
+ static gint _lock_toggle (GtkCanvasItem*, GdkEvent*, void*);
+ void lock_toggle ();
+
+ void create_waves ();
+ void create_one_wave (uint32_t, bool);
+ void manage_zero_line ();
+ void peaks_ready_handler (uint32_t);
+ void reset_name (gdouble width);
+ void set_flags (XMLNode *);
+ void store_flags ();
+
+ void set_colors ();
+ void compute_colors (GdkColor&);
+ void set_frame_color ();
+ void reset_width_dependent_items (double pixel_width);
+ void set_waveview_data_src();
+
+ vector<GtkCanvasWaveViewCache*> wave_caches;
+ vector<GhostRegion*> ghosts;
+};
+
+#endif /* __gtk_ardour_region_view_h__ */
diff --git a/gtk2_ardour/rgb_macros.h b/gtk2_ardour/rgb_macros.h
new file mode 100644
index 0000000000..f0a67ec0bd
--- /dev/null
+++ b/gtk2_ardour/rgb_macros.h
@@ -0,0 +1,288 @@
+/*
+ Copyright (C) 2000 EMC Capital Management, Inc.
+
+ Developed by Jon Trowbridge <trow@gnu.org> and
+ Havoc Pennington <hp@pobox.com>.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_rgb_macros_h__
+#define __gtk_ardour_rgb_macros_h__
+
+/*
+ Some convenient macros for drawing into an RGB buffer.
+ Beware of side effects, code-bloat, and all of the other classic
+ cpp-perils...
+*/
+
+#define RGB_TO_UINT(r,g,b) ((((guint)(r))<<16)|(((guint)(g))<<8)|((guint)(b)))
+#define RGB_TO_RGBA(x,a) (((x) << 8) | ((((guint)a) & 0xff)))
+#define RGBA_TO_UINT(r,g,b,a) RGB_TO_RGBA(RGB_TO_UINT(r,g,b), a)
+#define RGB_WHITE RGB_TO_UINT(0xff, 0xff, 0xff)
+#define RGB_BLACK RGB_TO_UINT(0x00, 0x00, 0x00)
+#define RGB_RED RGB_TO_UINT(0xff, 0x00, 0x00)
+#define RGB_GREEN RGB_TO_UINT(0x00, 0xff, 0x00)
+#define RGB_BLUE RGB_TO_UINT(0x00, 0x00, 0xff)
+#define RGB_YELLOW RGB_TO_UINT(0xff, 0xff, 0x00)
+#define RGB_VIOLET RGB_TO_UINT(0xff, 0x00, 0xff)
+#define RGB_CYAN RGB_TO_UINT(0x00, 0xff, 0xff)
+#define RGBA_WHITE RGB_TO_RGBA(RGB_WHITE, 0xff)
+#define RGBA_BLACK RGB_TO_RGBA(RGB_BLACK, 0xff)
+#define RGBA_RED RGB_TO_RGBA(RGB_RED, 0xff)
+#define RGBA_GREEN RGB_TO_RGBA(RGB_GREEN, 0xff)
+#define RGBA_BLUE RGB_TO_RGBA(RGB_BLUE, 0xff)
+#define RGBA_YELLOW RGB_TO_RGBA(RGB_YELLOW, 0xff)
+#define RGBA_VIOLET RGB_TO_RGBA(RGB_VIOLET, 0xff)
+#define RGBA_CYAN RGB_TO_RGBA(RGB_CYAN, 0xff)
+#define RGB_GREY(x) RGB_TO_UINT(x,x,x)
+#define RGBA_GREY(x) RGB_TO_RGBA(RGB_GREY(x), 0xff)
+#define UINT_RGBA_R(x) (((guint)(x))>>24)
+#define UINT_RGBA_G(x) ((((guint)(x))>>16)&0xff)
+#define UINT_RGBA_B(x) ((((guint)(x))>>8)&0xff)
+#define UINT_RGBA_A(x) (((guint)(x))&0xff)
+#define UINT_RGBA_CHANGE_R(x, r) (((x)&(~(0xff<<24)))|(((r)&0xff)<<24))
+#define UINT_RGBA_CHANGE_G(x, g) (((x)&(~(0xff<<16)))|(((g)&0xff)<<16))
+#define UINT_RGBA_CHANGE_B(x, b) (((x)&(~(0xff<<8)))|(((b)&0xff)<<8))
+#define UINT_RGBA_CHANGE_A(x, a) (((x)&(~0xff))|((a)&0xff))
+#define UINT_TO_RGB(u,r,g,b) \
+{ (*(r)) = ((u)>>16)&0xff; (*(g)) = ((u)>>8)&0xff; (*(b)) = (u)&0xff; }
+#define UINT_TO_RGBA(u,r,g,b,a) \
+{ UINT_TO_RGB(((u)>>8),r,g,b); (*(a)) = (u)&0xff; }
+#define MONO_INTERPOLATE(v1, v2, t) ((gint)rint((v2)*(t)+(v1)*(1-(t))))
+#define UINT_INTERPOLATE(c1, c2, t) \
+ RGBA_TO_UINT( MONO_INTERPOLATE(UINT_RGBA_R(c1), UINT_RGBA_R(c2), t), \
+ MONO_INTERPOLATE(UINT_RGBA_G(c1), UINT_RGBA_G(c2), t), \
+ MONO_INTERPOLATE(UINT_RGBA_B(c1), UINT_RGBA_B(c2), t), \
+ MONO_INTERPOLATE(UINT_RGBA_A(c1), UINT_RGBA_A(c2), t) )
+#define PIXEL_RGB(p, r, g, b) \
+{((guchar*)(p))[0]=(r); ((guchar*)(p))[1]=(g); ((guchar*)(p))[2]=(b);}
+#define PIXEL_RGBA(p, r, g, b, a) \
+{ if ((a)>=0xff) { PIXEL_RGB(p,r,g,b) } \
+ else if ((a)>0) { \
+ guint pixel_tmp; \
+ pixel_tmp = ((guchar*)(p))[0]; \
+ ((guchar*)(p))[0] = pixel_tmp + ((((r)-pixel_tmp)*(a)+0x80) >> 8); \
+ pixel_tmp = ((guchar*)(p))[1]; \
+ ((guchar*)(p))[1] = pixel_tmp + ((((g)-pixel_tmp)*(a)+0x80) >> 8); \
+ pixel_tmp = ((guchar*)(p))[2]; \
+ ((guchar*)(p))[2] = pixel_tmp + ((((b)-pixel_tmp)*(a)+0x80) >> 8); }}
+#define PIXEL_RGB_UINT(p, i) \
+UINT_TO_RGB((i), ((guchar*)p), ((guchar*)p)+1, ((guchar*)p)+2)
+#define PIXEL_RGBA_UINT(p, i) \
+ PIXEL_RGBA((p), ((i)>>24)&0xff, ((i)>>16)&0xff, ((i)>>8)&0xff, (i)&0xff)
+#define PIXEL_BLACK(p) PIXEL_RGB(p,0,0,0)
+#define PIXEL_WHITE(p) PIXEL_RGB(p,0xff,0xff,0xff)
+#define PIXEL_GREY(p,g) PIXEL_RGB(p,g,g,g)
+#define PIXEL_GREYA(p,g,a) PIXEL_RGBA(p,g,g,g,a)
+#define BUF_PTR(inbuf, ptx, pty) \
+ ((inbuf)->buf + 3*((ptx)-(inbuf)->rect.x0) + (inbuf)->buf_rowstride*((pty)-(inbuf)->rect.y0))
+#define BUF_INBOUNDS_X(inbuf, ptx) \
+((inbuf)->rect.x0 <= (ptx) && (ptx) < (inbuf)->rect.x1)
+#define BUF_INBOUNDS_Y(inbuf, pty) \
+((inbuf)->rect.y0 <= (pty) && (pty) < (inbuf)->rect.y1)
+#define PAINT_DOT(inbuf, colr, colg, colb,ptx, pty) \
+{ \
+ guchar* pd_p; \
+ if (BUF_INBOUNDS_X(inbuf, ptx) && BUF_INBOUNDS_Y(inbuf, pty)) { \
+ pd_p = BUF_PTR(inbuf, ptx, pty); \
+ PIXEL_RGB(pd_p, (colr), (colg), (colb)); \
+ } \
+}
+#define FAST_PAINT_DOT(inbuf, colr, colg, colb,ptx, pty) \
+{ \
+ guchar* pd_p; \
+ pd_p = BUF_PTR(inbuf, ptx, pty); \
+ PIXEL_RGB(pd_p, (colr), (colg), (colb)); \
+}
+#define PAINT_DOTA(inbuf, colr, colg, colb, cola, ptx, pty) \
+{ \
+ guchar* pd_p; \
+ if (BUF_INBOUNDS_X(inbuf, ptx) && BUF_INBOUNDS_Y(inbuf, pty)) { \
+ pd_p = BUF_PTR(inbuf, ptx, pty); \
+ PIXEL_RGBA(pd_p, (colr), (colg), (colb), (cola)); \
+ } \
+}
+#define FAST_PAINT_DOTA(inbuf, colr, colg, colb, cola, ptx, pty) \
+{ \
+ guchar* pd_p; \
+ pd_p = BUF_PTR(inbuf, ptx, pty); \
+ PIXEL_RGBA(pd_p, (colr), (colg), (colb), (cola)); \
+}
+#define PAINT_HORIZ(inbuf, colr, colg, colb, ptx0, ptx1, pty) \
+{ \
+ GtkCanvasBuf* ph_buf = (inbuf); \
+ guchar* ph_p; \
+ gint ph_a0, ph_a1; \
+ gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb); \
+\
+ ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \
+ ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \
+\
+ if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \
+ ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
+ while (ph_a0 < ph_a1) { \
+ PIXEL_RGB(ph_p, ph_colr, ph_colg, ph_colb); \
+ ++ph_a0; \
+ ph_p += 3; \
+ } \
+ } \
+}
+#define FAST_PAINT_HORIZ(inbuf, colr, colg, colb, ptx0, ptx1, pty) \
+{ \
+ GtkCanvasBuf* ph_buf = (inbuf); \
+ guchar* ph_p; \
+ gint ph_a0, ph_a1; \
+ gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb); \
+\
+ ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \
+ ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \
+\
+ if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \
+ ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
+ while (ph_a0 < ph_a1) { \
+ PIXEL_RGB(ph_p, ph_colr, ph_colg, ph_colb); \
+ ++ph_a0; \
+ ph_p += 3; \
+ } \
+ } \
+}
+#define PAINT_HORIZA(inbuf, colr, colg, colb, cola, ptx0, ptx1, pty) \
+{ \
+ GtkCanvasBuf* ph_buf = (inbuf); \
+ guchar* ph_p; \
+ gint ph_a0, ph_a1; \
+ gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb), ph_cola=(cola); \
+\
+ ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \
+ ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \
+\
+ if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \
+ ph_p = BUF_PTR(ph_buf, ph_a0, pty); \
+ while (ph_a0 < ph_a1) { \
+ PIXEL_RGBA(ph_p, ph_colr, ph_colg, ph_colb, ph_cola); \
+ ++ph_a0; \
+ ph_p += 3; \
+ } \
+ } \
+}
+#define PAINT_VERT(inbuf, colr, colg, colb, ptx, pty0, pty1) \
+{ \
+ GtkCanvasBuf* pv_buf = (inbuf); \
+ guchar* pv_p; \
+ gint pv_b0, pv_b1; \
+ gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb);\
+\
+ pv_b0 = MAX(pv_buf->rect.y0, (pty0)); \
+ pv_b1 = MIN(pv_buf->rect.y1, (pty1)); \
+\
+ if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, ptx)) { \
+ pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \
+ while (pv_b0 < pv_b1) { \
+ PIXEL_RGB(pv_p, pv_colr, pv_colg, pv_colb); \
+ ++pv_b0; \
+ pv_p += pv_buf->buf_rowstride; \
+ } \
+ } \
+}
+#define FAST_PAINT_VERT(inbuf, colr, colg, colb, ptx, pty0, pty1) \
+{ \
+ GtkCanvasBuf* fpv_buf = (inbuf); \
+ guchar* fpv_p; \
+ gint fpv_b0, fpv_b1; \
+\
+ fpv_b0 = MAX(fpv_buf->rect.y0, (pty0)); \
+ fpv_b1 = MIN(fpv_buf->rect.y1, (pty1)); \
+\
+ fpv_p = BUF_PTR(fpv_buf, ptx, fpv_b0); \
+\
+ while (fpv_b0 < fpv_b1) { \
+ PIXEL_RGB(fpv_p, colr, colg, colb); \
+ ++fpv_b0; \
+ fpv_p += fpv_buf->buf_rowstride; \
+ } \
+}
+#define PAINT_VERTA(inbuf, colr, colg, colb, cola, ptx, pty0, pty1) \
+{ \
+ GtkCanvasBuf* pv_buf = (inbuf); \
+ guchar* pv_p; \
+ gint pv_b0, pv_b1; \
+ gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb), pv_cola=(cola);\
+\
+ pv_b0 = MAX(pv_buf->rect.y0, (pty0)); \
+ pv_b1 = MIN(pv_buf->rect.y1, (pty1)); \
+\
+ if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, ptx)) { \
+ pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \
+ while (pv_b0 < pv_b1) { \
+ PIXEL_RGBA(pv_p, pv_colr, pv_colg, pv_colb, pv_cola); \
+ ++pv_b0; \
+ pv_p += pv_buf->buf_rowstride; \
+ } \
+ } \
+}
+
+/* Paint a solid-colored box into a GtkCanvasBuf (clipping as necessary).
+ The box contains (ptx0,pty0), but not (ptx1, pty1).
+ Each macro arg should appear exactly once in the body of the code. */
+#define PAINT_BOX(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1) \
+{ \
+ GtkCanvasBuf* pb_buf = (inbuf); \
+ guchar* pb_p; \
+ guchar* pb_pp; \
+ gint pb_a0, pb_a1, pb_b0, pb_b1, pb_i, pb_j; \
+ gint pb_colr=(colr), pb_colg=(colg), pb_colb=(colb), pb_cola=(cola); \
+\
+ pb_a0 = MAX(pb_buf->rect.x0, (ptx0)); \
+ pb_a1 = MIN(pb_buf->rect.x1, (ptx1)); \
+ pb_b0 = MAX(pb_buf->rect.y0, (pty0)); \
+ pb_b1 = MIN(pb_buf->rect.y1, (pty1)); \
+\
+ if (pb_a0 < pb_a1 && pb_b0 < pb_b1) { \
+ pb_p = BUF_PTR(pb_buf, pb_a0, pb_b0); \
+ for (pb_j=pb_b0; pb_j<pb_b1; ++pb_j) { \
+ pb_pp = pb_p; \
+ for (pb_i=pb_a0; pb_i<pb_a1; ++pb_i) { \
+ PIXEL_RGBA(pb_pp, pb_colr, pb_colg, pb_colb, pb_cola); \
+ pb_pp += 3; \
+ } \
+ pb_p += pb_buf->buf_rowstride; \
+ } \
+ } \
+}
+
+/* No bounds checking in this version */
+
+#define FAST_PAINT_BOX(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1) \
+{ \
+ GtkCanvasBuf* pb_buf = (inbuf); \
+ guchar* pb_p; \
+ guchar* pb_pp; \
+ gint pb_i, pb_j; \
+\
+ pb_p = BUF_PTR(pb_buf, ptx0, pty0); \
+ for (pb_j=pty0; pb_j<pty1; ++pb_j) { \
+ pb_pp = pb_p; \
+ for (pb_i=ptx0; pb_i<ptx1; ++pb_i) { \
+ PIXEL_RGBA(pb_pp, colr, colg, colb, cola); \
+ pb_pp += 3; \
+ } \
+ pb_p += pb_buf->buf_rowstride; \
+ } \
+}
+
+#endif /* __gtk_ardour_rgb_macros_h__ */
diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc
new file mode 100644
index 0000000000..17901e9e7c
--- /dev/null
+++ b/gtk2_ardour/route_params_ui.cc
@@ -0,0 +1,705 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+
+#include <pbd/lockmonitor.h>
+#include <gtkmmext/utils.h>
+#include <gtkmmext/stop_signal.h>
+
+#include <ardour/session.h>
+#include <ardour/session_route.h>
+#include <ardour/diskstream.h>
+#include <ardour/plugin.h>
+#include <ardour/plugin_manager.h>
+#include <ardour/ardour.h>
+#include <ardour/session.h>
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/send.h>
+#include <ardour/insert.h>
+#include <ardour/connection.h>
+#include <ardour/session_connection.h>
+
+#include "route_params_ui.h"
+#include "keyboard.h"
+#include "mixer_strip.h"
+#include "plugin_selector.h"
+#include "ardour_ui.h"
+#include "plugin_ui.h"
+#include "io_selector.h"
+#include "send_ui.h"
+#include "utils.h"
+#include "gui_thread.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace Gtk;
+using namespace SigC;
+
+static const gchar *route_display_titles[] = { N_("Tracks/Buses"), 0 };
+static const gchar *pre_display_titles[] = { N_("Pre Redirects"), 0 };
+static const gchar *post_display_titles[] = { N_("Post Redirects"), 0 };
+
+RouteParams_UI::RouteParams_UI (AudioEngine& eng)
+ : ArdourDialog ("track/bus inspector"),
+ engine (eng),
+ route_select_list (internationalize(route_display_titles)),
+ _route(0),
+ track_menu(0)
+{
+ pre_redirect_box = 0;
+ post_redirect_box = 0;
+ _route = 0;
+ _pre_redirect = 0;
+ _post_redirect = 0;
+ _input_iosel = 0;
+ _output_iosel = 0;
+ _active_pre_view = 0;
+ _active_post_view = 0;
+
+ using namespace Notebook_Helpers;
+
+ input_frame.set_shadow_type(GTK_SHADOW_NONE);
+ output_frame.set_shadow_type(GTK_SHADOW_NONE);
+
+ notebook.set_show_tabs (true);
+ notebook.set_show_border (true);
+ notebook.set_name ("RouteParamNotebook");
+
+ route_select_list.column_titles_active();
+ route_select_list.set_name ("RouteParamsListDisplay");
+ route_select_list.set_shadow_type (GTK_SHADOW_IN);
+ route_select_list.set_selection_mode (GTK_SELECTION_SINGLE);
+ route_select_list.set_reorderable (false);
+ route_select_list.set_usize (75, -1);
+ route_select_scroller.add (route_select_list);
+ route_select_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ route_select_frame.set_name("RouteSelectBaseFrame");
+ route_select_frame.set_shadow_type (GTK_SHADOW_IN);
+ route_select_frame.add(route_select_scroller);
+
+ list_vpacker.pack_start (route_select_frame, true, true);
+
+ notebook.pages().push_back (TabElem (input_frame, _("Inputs")));
+ notebook.pages().push_back (TabElem (output_frame, _("Outputs")));
+ notebook.pages().push_back (TabElem (pre_redir_hpane, _("Pre-fader Redirects")));
+ notebook.pages().push_back (TabElem (post_redir_hpane, _("Post-fader Redirects")));
+
+ notebook.set_name ("InspectorNotebook");
+
+ title_label.set_name ("RouteParamsTitleLabel");
+ update_title();
+
+ // changeable area
+ route_param_frame.set_name("RouteParamsBaseFrame");
+ route_param_frame.set_shadow_type (GTK_SHADOW_IN);
+
+
+ route_hpacker.pack_start (notebook, true, true);
+
+
+ route_vpacker.pack_start (title_label, false, false);
+ route_vpacker.pack_start (route_hpacker, true, true);
+
+
+ list_hpane.add1 (list_vpacker);
+ list_hpane.add2 (route_vpacker);
+
+ list_hpane.set_position(110);
+
+ pre_redir_hpane.set_position(110);
+ post_redir_hpane.set_position(110);
+
+ global_vpacker.pack_start (list_hpane, true, true);
+
+ add (global_vpacker);
+ set_name ("RouteParamsWindow");
+ set_default_size (620,370);
+ set_title (_("ardour: track/bus inspector"));
+ set_wmclass (_("ardour_route_parameters"), "Ardour");
+
+ // events
+ route_select_list.select_row.connect (slot (*this, &RouteParams_UI::route_selected));
+ route_select_list.unselect_row.connect (slot (*this, &RouteParams_UI::route_unselected));
+ route_select_list.click_column.connect (slot (*this, &RouteParams_UI::show_track_menu));
+
+
+ add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_BUTTON_RELEASE_MASK);
+
+ _plugin_selector = new PluginSelector (PluginManager::the_manager());
+ _plugin_selector->delete_event.connect (bind (slot (just_hide_it),
+ static_cast<Window *> (_plugin_selector)));
+
+
+ delete_event.connect (bind (slot (just_hide_it), static_cast<Gtk::Window*> (this)));
+}
+
+RouteParams_UI::~RouteParams_UI ()
+{
+}
+
+void
+RouteParams_UI::add_route (Route* route)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::add_route), route));
+
+ if (route->hidden()) {
+ return;
+ }
+
+ const gchar *rowdata[1];
+ rowdata[0] = route->name().c_str();
+ route_select_list.rows().push_back (rowdata);
+ route_select_list.rows().back().set_data (route);
+ //route_select_list.rows().back().select ();
+
+ route->name_changed.connect (bind (slot (*this, &RouteParams_UI::route_name_changed), route));
+ route->GoingAway.connect (bind (slot (*this, &RouteParams_UI::route_removed), route));
+}
+
+
+void
+RouteParams_UI::route_name_changed (void *src, Route *route)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::route_name_changed), src, route));
+
+ CList_Helpers::RowList::iterator i;
+
+ if ((i = route_select_list.rows().find_data (route)) == route_select_list.rows().end()) {
+ error << _("route display list item for renamed route not found!") << endmsg;
+ return;
+ }
+
+ route_select_list.cell ((*i)->get_row_num(), 0).set_text (route->name());
+
+ if (route == _route) {
+ track_input_label.set_text (route->name());
+ update_title();
+ }
+}
+
+void
+RouteParams_UI::setup_redirect_boxes()
+{
+ if (session && _route) {
+
+ // just in case... shouldn't need this
+ cleanup_redirect_boxes();
+
+ // construct new redirect boxes
+ pre_redirect_box = new RedirectBox(PreFader, *session, *_route, *_plugin_selector, _rr_selection);
+ post_redirect_box = new RedirectBox(PostFader, *session, *_route, *_plugin_selector, _rr_selection);
+
+ pre_redirect_box->set_title (pre_display_titles[0]);
+ pre_redirect_box->set_title_shown (true);
+ post_redirect_box->set_title (post_display_titles[0]);
+ post_redirect_box->set_title_shown (true);
+
+ pre_redir_hpane.add1 (*pre_redirect_box);
+ post_redir_hpane.add1 (*post_redirect_box);
+
+ pre_redirect_box->RedirectSelected.connect (bind (slot (*this, &RouteParams_UI::redirect_selected), PreFader));
+ pre_redirect_box->RedirectUnselected.connect (bind (slot (*this, &RouteParams_UI::redirect_selected), PreFader));
+ post_redirect_box->RedirectSelected.connect (bind (slot (*this, &RouteParams_UI::redirect_selected), PostFader));
+ post_redirect_box->RedirectUnselected.connect (bind (slot (*this, &RouteParams_UI::redirect_selected), PostFader));
+
+ }
+
+}
+
+void
+RouteParams_UI::cleanup_redirect_boxes()
+{
+ if (pre_redirect_box) {
+ pre_redir_hpane.remove(*pre_redirect_box);
+ delete pre_redirect_box;
+ pre_redirect_box = 0;
+ }
+
+ if (post_redirect_box) {
+ post_redir_hpane.remove(*post_redirect_box);
+ delete post_redirect_box;
+ post_redirect_box = 0;
+ }
+}
+
+void
+RouteParams_UI::setup_io_frames()
+{
+ cleanup_io_frames();
+
+ // input
+ _input_iosel = new IOSelector (*session, *_route, true);
+ _input_iosel->redisplay ();
+ input_frame.add (*_input_iosel);
+ input_frame.show_all();
+
+ // output
+ _output_iosel = new IOSelector (*session, *_route, false);
+ _output_iosel->redisplay ();
+ output_frame.add (*_output_iosel);
+ output_frame.show_all();
+}
+
+void
+RouteParams_UI::cleanup_io_frames()
+{
+ if (_input_iosel) {
+ _input_iosel->Finished (IOSelector::Cancelled);
+ input_frame.remove();
+ delete _input_iosel;
+ _input_iosel = 0;
+ }
+
+ if (_output_iosel) {
+ _output_iosel->Finished (IOSelector::Cancelled);
+
+ output_frame.remove();
+ delete _output_iosel;
+ _output_iosel = 0;
+ }
+}
+
+void
+RouteParams_UI::cleanup_pre_view (bool stopupdate)
+{
+ if (_active_pre_view) {
+ PluginUI * plugui = 0;
+
+ if (stopupdate && (plugui = dynamic_cast<PluginUI*>(_active_pre_view)) != 0) {
+ plugui->stop_updating (0);
+ }
+
+ _pre_plugin_conn.disconnect();
+ pre_redir_hpane.remove(*_active_pre_view);
+ delete _active_pre_view;
+ _active_pre_view = 0;
+ }
+}
+
+void
+RouteParams_UI::cleanup_post_view (bool stopupdate)
+{
+ if (_active_post_view) {
+ PluginUI * plugui = 0;
+
+ if (stopupdate && (plugui = dynamic_cast<PluginUI*>(_active_post_view)) != 0) {
+ plugui->stop_updating (0);
+ }
+ _post_plugin_conn.disconnect();
+ post_redir_hpane.remove(*_active_post_view);
+ delete _active_post_view;
+ _active_post_view = 0;
+ }
+}
+
+
+void
+RouteParams_UI::route_removed (Route *route)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::route_removed), route));
+ /*
+ route_select_list.freeze ();
+ route_select_list.clear ();
+ session->foreach_route (this, &RouteParams_UI::add_route);
+ route_select_list.thaw ();
+ */
+
+ CList_Helpers::RowList::iterator i;
+
+ if ((i = route_select_list.rows().find_data (route)) == route_select_list.rows().end()) {
+ // couldn't find route to be deleted
+ return;
+ }
+
+ if (route == _route)
+ {
+ cleanup_io_frames();
+ cleanup_pre_view();
+ cleanup_post_view();
+ cleanup_redirect_boxes();
+
+ _route = 0;
+ _pre_redirect = 0;
+ _post_redirect = 0;
+ update_title();
+ }
+
+ route_select_list.rows().erase(i);
+
+}
+
+void
+RouteParams_UI::set_session (Session *sess)
+{
+ ArdourDialog::set_session (sess);
+
+ route_select_list.freeze ();
+ route_select_list.clear ();
+
+ if (session) {
+ session->foreach_route (this, &RouteParams_UI::add_route);
+ session->going_away.connect (slot (*this, &ArdourDialog::session_gone));
+ session->RouteAdded.connect (slot (*this, &RouteParams_UI::add_route));
+ start_updating ();
+ } else {
+ stop_updating ();
+ }
+
+ route_select_list.thaw ();
+
+ _plugin_selector->set_session (session);
+}
+
+
+void
+RouteParams_UI::session_gone ()
+{
+
+ route_select_list.clear ();
+
+ cleanup_io_frames();
+ cleanup_pre_view();
+ cleanup_post_view();
+ cleanup_redirect_boxes();
+
+ _route = 0;
+ _pre_redirect = 0;
+ _post_redirect = 0;
+ update_title();
+
+ ArdourDialog::session_gone();
+
+}
+
+void
+RouteParams_UI::route_selected (gint row, gint col, GdkEvent *ev)
+{
+ Route *route;
+
+ if ((route = (Route *) route_select_list.get_row_data (row)) != 0) {
+
+ if (_route == route) {
+ // do nothing
+ return;
+ }
+
+ // remove event binding from previously selected
+ if (_route) {
+ _route_conn.disconnect();
+ _route_ds_conn.disconnect();
+ cleanup_redirect_boxes();
+ cleanup_pre_view();
+ cleanup_post_view();
+ cleanup_io_frames();
+ }
+
+ // update the other panes with the correct info
+ _route = route;
+ //update_routeinfo (route);
+
+ setup_io_frames();
+ setup_redirect_boxes();
+
+ // bind to redirects changed event for this route
+ _route_conn = route->redirects_changed.connect (slot (*this, &RouteParams_UI::redirects_changed));
+
+ track_input_label.set_text (_route->name());
+
+ update_title();
+ }
+}
+
+void
+RouteParams_UI::route_unselected (gint row, gint col, GdkEvent *ev)
+{
+ if (_route) {
+ _route_conn.disconnect();
+
+ // remove from view
+ cleanup_io_frames();
+ cleanup_pre_view();
+ cleanup_post_view();
+ cleanup_redirect_boxes();
+
+ _route = 0;
+ _pre_redirect = 0;
+ _post_redirect = 0;
+ track_input_label.set_text(_("NO TRACK"));
+ update_title();
+ }
+}
+
+void
+RouteParams_UI::redirects_changed (void *src)
+
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::redirects_changed), src));
+
+// pre_redirect_list.freeze ();
+// pre_redirect_list.clear ();
+// post_redirect_list.freeze ();
+// post_redirect_list.clear ();
+// if (_route) {
+// _route->foreach_redirect (this, &RouteParams_UI::add_redirect_to_display);
+// }
+// pre_redirect_list.thaw ();
+// post_redirect_list.thaw ();
+
+ cleanup_pre_view();
+ cleanup_post_view();
+
+ _pre_redirect = 0;
+ _post_redirect = 0;
+ //update_title();
+}
+
+
+
+void
+RouteParams_UI::show_track_menu (gint arg)
+{
+ using namespace Menu_Helpers;
+
+ if (track_menu == 0) {
+ track_menu = new Menu;
+ track_menu->set_name ("ArdourContextMenu");
+ track_menu->items().push_back
+ (MenuElem (_("Add Track/Bus"),
+ slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::add_route)));
+ }
+ track_menu->popup (1, 0);
+}
+
+
+
+void
+RouteParams_UI::redirect_selected (ARDOUR::Redirect *redirect, ARDOUR::Placement place)
+{
+ Insert *insert;
+
+ if ((place == PreFader && _pre_redirect == redirect)
+ || (place == PostFader && _post_redirect == redirect)){
+ return;
+ }
+
+ if ((insert = dynamic_cast<Insert *> (redirect)) == 0) {
+
+ Send *send;
+
+ if ((send = dynamic_cast<Send *> (redirect)) != 0) {
+
+ /* its a send */
+
+ SendUI *send_ui = new SendUI (*send, *session);
+
+ if (place == PreFader) {
+ cleanup_pre_view();
+ _pre_plugin_conn = send->GoingAway.connect (slot (*this, &RouteParams_UI::redirect_going_away));
+ _active_pre_view = send_ui;
+
+ pre_redir_hpane.add2 (*_active_pre_view);
+ pre_redir_hpane.show_all();
+ }
+ else {
+ cleanup_post_view();
+ _post_plugin_conn = send->GoingAway.connect (slot (*this, &RouteParams_UI::redirect_going_away));
+ _active_post_view = send_ui;
+
+ post_redir_hpane.add2 (*_active_post_view);
+ post_redir_hpane.show_all();
+ }
+ }
+
+ } else {
+ /* its an insert, though we don't know what kind yet. */
+
+ PluginInsert *plugin_insert;
+ PortInsert *port_insert;
+
+ if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
+
+ PluginUI *plugin_ui = new PluginUI (session->engine(), *plugin_insert, true);
+
+ if (place == PreFader) {
+ cleanup_pre_view();
+ _pre_plugin_conn = plugin_insert->plugin().GoingAway.connect (bind (slot (*this, &RouteParams_UI::plugin_going_away), PreFader));
+ plugin_ui->start_updating (0);
+ _active_pre_view = plugin_ui;
+ pre_redir_hpane.add2 (*_active_pre_view);
+ pre_redir_hpane.show_all();
+ }
+ else {
+ cleanup_post_view();
+ _post_plugin_conn = plugin_insert->plugin().GoingAway.connect (bind (slot (*this, &RouteParams_UI::plugin_going_away), PostFader));
+ plugin_ui->start_updating (0);
+ _active_post_view = plugin_ui;
+ post_redir_hpane.add2 (*_active_post_view);
+ post_redir_hpane.show_all();
+ }
+
+ } else if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
+
+ PortInsertUI *portinsert_ui = new PortInsertUI (*session, *port_insert);
+
+ if (place == PreFader) {
+ cleanup_pre_view();
+ _pre_plugin_conn = port_insert->GoingAway.connect (slot (*this, &RouteParams_UI::redirect_going_away));
+ _active_pre_view = portinsert_ui;
+ pre_redir_hpane.add2 (*_active_pre_view);
+ portinsert_ui->redisplay();
+ pre_redir_hpane.show_all();
+ }
+ else {
+ cleanup_post_view();
+ _post_plugin_conn = port_insert->GoingAway.connect (slot (*this, &RouteParams_UI::redirect_going_away));
+ _active_post_view = portinsert_ui;
+ post_redir_hpane.add2 (*_active_post_view);
+ portinsert_ui->redisplay();
+ post_redir_hpane.show_all();
+ }
+ }
+
+ }
+
+ if (place == PreFader) {
+ _pre_redirect = redirect;
+ }
+ else {
+ _post_redirect = redirect;
+ }
+
+ update_title();
+
+}
+
+void
+RouteParams_UI::redirect_unselected (ARDOUR::Redirect *redirect)
+{
+ // not called anymore
+
+ if (redirect == _pre_redirect) {
+ cleanup_pre_view();
+ _pre_redirect = 0;
+ }
+ else if (redirect == _post_redirect) {
+ cleanup_post_view();
+ _post_redirect = 0;
+ }
+}
+
+
+
+void
+RouteParams_UI::plugin_going_away (Plugin *plugin, Placement place)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::plugin_going_away), plugin, place));
+
+ // delete the current view without calling finish
+
+ if (place == PreFader) {
+ cleanup_pre_view (false);
+ _pre_redirect = 0;
+ }
+ else {
+ cleanup_post_view (false);
+ _post_redirect = 0;
+ }
+}
+
+void
+RouteParams_UI::redirect_going_away (ARDOUR::Redirect *plugin)
+
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::redirect_going_away), plugin));
+
+ printf ("redirect going away\n");
+ // delete the current view without calling finish
+ if (plugin == _pre_redirect) {
+ cleanup_pre_view (false);
+ _pre_redirect = 0;
+ }
+ else if (plugin == _post_redirect) {
+ cleanup_post_view (false);
+ _post_redirect = 0;
+ }
+}
+
+
+void
+RouteParams_UI::update_title ()
+{
+ if (_route) {
+ string title;
+ title += _route->name();
+// title += ": ";
+
+// if (_redirect && (_current_view == PLUGIN_CONFIG_VIEW || _current_view == SEND_CONFIG_VIEW)) {
+// title += _redirect->name();
+// }
+// else if (_current_view == INPUT_CONFIG_VIEW) {
+// title += _("INPUT");
+// }
+// else if (_current_view == OUTPUT_CONFIG_VIEW) {
+// title += _("OUTPUT");
+// }
+
+ title_label.set_text(title);
+
+ title = _("ardour: track/bus inspector: ") + title;
+ set_title(title);
+ }
+ else {
+ title_label.set_text(_("No Route Selected"));
+ set_title(_("ardour: track/bus/inspector: no route selected"));
+ }
+}
+
+
+void
+RouteParams_UI::start_updating ()
+{
+ update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
+ (slot (*this, &RouteParams_UI::update_views));
+}
+
+void
+RouteParams_UI::stop_updating ()
+{
+ update_connection.disconnect();
+}
+
+void
+RouteParams_UI::update_views ()
+{
+ SendUI *sui;
+ // TODO: only do it if correct tab is showing
+
+ if ((sui = dynamic_cast<SendUI*> (_active_pre_view)) != 0) {
+ sui->update ();
+ }
+ if ((sui = dynamic_cast<SendUI*> (_active_post_view)) != 0) {
+ sui->update ();
+ }
+
+}
diff --git a/gtk2_ardour/route_params_ui.h b/gtk2_ardour/route_params_ui.h
new file mode 100644
index 0000000000..deaac6f279
--- /dev/null
+++ b/gtk2_ardour/route_params_ui.h
@@ -0,0 +1,184 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_route_params_ui_h__
+#define __ardour_route_params_ui_h__
+
+#include <list>
+
+#include <gtk--.h>
+
+#include <ardour/ardour.h>
+#include <ardour/stateful.h>
+#include <ardour/io.h>
+#include <ardour/redirect.h>
+
+#include "io_selector.h"
+#include "ardour_dialog.h"
+#include "keyboard_target.h"
+#include "redirect_box.h"
+#include "route_redirect_selection.h"
+
+namespace ARDOUR {
+ class Route;
+ class Send;
+ class Insert;
+ class Session;
+ class PortInsert;
+ class Connection;
+ class Plugin;
+}
+
+class PluginSelector;
+
+class RouteParams_UI : public ArdourDialog
+{
+ public:
+ RouteParams_UI (ARDOUR::AudioEngine&);
+ ~RouteParams_UI();
+
+ void set_session (ARDOUR::Session *);
+ void session_gone ();
+ PluginSelector& plugin_selector() { return *_plugin_selector; }
+
+ private:
+ ARDOUR::AudioEngine& engine;
+
+ Gtk::HBox global_hpacker;
+ Gtk::VBox global_vpacker;
+ Gtk::ScrolledWindow scroller;
+ Gtk::EventBox scroller_base;
+ Gtk::HBox scroller_hpacker;
+ Gtk::VBox mixer_scroller_vpacker;
+
+ Gtk::VBox list_vpacker;
+ Gtk::CList route_select_list;
+ Gtk::Label route_list_button_label;
+ Gtk::Button route_list_button;
+ Gtk::ScrolledWindow route_select_scroller;
+
+ Gtk::Notebook notebook;
+ Gtk::Frame input_frame;
+ Gtk::Frame output_frame;
+ Gtk::HPaned pre_redir_hpane;
+ Gtk::HPaned post_redir_hpane;
+
+ Gtk::Frame route_select_frame;
+
+ Gtk::HBox route_hpacker;
+ Gtk::VBox route_vpacker;
+
+ RedirectBox * pre_redirect_box;
+ RedirectBox * post_redirect_box;
+
+ Gtk::HPaned list_hpane;
+
+ Gtk::HPaned right_hpane;
+
+ Gtk::Frame route_choice_frame;
+
+ Gtk::Frame route_param_frame;
+
+ Gtk::VBox choice_vpacker;
+
+
+ Gtk::ToggleButton input_button;
+ Gtk::ToggleButton output_button;
+ Gtk::Label track_input_label;
+
+ Gtk::Label title_label;
+
+ Gtk::Container * _active_pre_view;
+ Gtk::Container * _active_post_view;
+ IOSelector * _input_iosel;
+ IOSelector * _output_iosel;
+
+ PluginSelector *_plugin_selector;
+ RouteRedirectSelection _rr_selection;
+
+ ARDOUR::Route *_route;
+ SigC::Connection _route_conn;
+ SigC::Connection _route_ds_conn;
+
+ ARDOUR::Redirect * _pre_redirect;
+ SigC::Connection _pre_plugin_conn;
+
+ ARDOUR::Redirect * _post_redirect;
+ SigC::Connection _post_plugin_conn;
+
+
+ enum ConfigView {
+ NO_CONFIG_VIEW = 0,
+ INPUT_CONFIG_VIEW,
+ OUTPUT_CONFIG_VIEW,
+ PLUGIN_CONFIG_VIEW,
+ PORTINSERT_CONFIG_VIEW,
+ SEND_CONFIG_VIEW
+ };
+
+ ConfigView _current_view;
+
+ void add_route (ARDOUR::Route*);
+
+ void route_name_changed (void *src, ARDOUR::Route *route);
+ void route_removed (ARDOUR::Route *route);
+
+
+ void route_selected (gint row, gint col, GdkEvent *ev);
+ void route_unselected (gint row, gint col, GdkEvent *ev);
+
+ void setup_io_frames();
+ void cleanup_io_frames();
+ void cleanup_pre_view(bool stopupdate = true);
+ void cleanup_post_view(bool stopupdate = true);
+
+
+
+ void redirects_changed (void *src);
+
+ void setup_redirect_boxes();
+ void cleanup_redirect_boxes();
+
+ void redirect_selected (ARDOUR::Redirect *, ARDOUR::Placement);
+ void redirect_unselected (ARDOUR::Redirect *);
+
+ void plugin_going_away (ARDOUR::Plugin *foo, ARDOUR::Placement);
+ void redirect_going_away (ARDOUR::Redirect *foo);
+
+ gint edit_input_configuration (GdkEventButton *ev);
+ gint edit_output_configuration (GdkEventButton *ev);
+
+ void update_routeinfo (ARDOUR::Route * route);
+
+ Gtk::Menu *track_menu;
+ void show_track_menu(gint arg);
+
+ void update_title ();
+ //void unselect_all_redirects ();
+
+ SigC::Connection update_connection;
+ void update_views ();
+
+ void start_updating ();
+ void stop_updating ();
+};
+
+
+#endif /* __ardour_route_params_ui_h__ */
diff --git a/gtk2_ardour/route_redirect_selection.cc b/gtk2_ardour/route_redirect_selection.cc
new file mode 100644
index 0000000000..730f3317fe
--- /dev/null
+++ b/gtk2_ardour/route_redirect_selection.cc
@@ -0,0 +1,183 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+#include <sigc++/bind.h>
+#include <pbd/error.h>
+
+#include <ardour/playlist.h>
+#include <ardour/redirect.h>
+#include <ardour/route.h>
+
+#include "route_redirect_selection.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+
+RouteRedirectSelection&
+RouteRedirectSelection::operator= (const RouteRedirectSelection& other)
+{
+ if (&other != this) {
+ redirects = other.redirects;
+ routes = other.routes;
+ }
+ return *this;
+}
+
+bool
+operator== (const RouteRedirectSelection& a, const RouteRedirectSelection& b)
+{
+ return a.redirects == b.redirects &&
+ a.routes == b.routes;
+}
+
+void
+RouteRedirectSelection::clear ()
+{
+ clear_redirects ();
+ clear_routes ();
+}
+
+void
+RouteRedirectSelection::clear_redirects ()
+{
+ for (RedirectSelection::iterator i = redirects.begin(); i != redirects.end(); ) {
+ RedirectSelection::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ delete *i;
+
+ i = tmp;
+ }
+
+ redirects.clear ();
+ RedirectsChanged ();
+}
+
+void
+RouteRedirectSelection::clear_routes ()
+{
+ routes.clear ();
+ RoutesChanged ();
+}
+
+void
+RouteRedirectSelection::add (Redirect* r)
+{
+ if (find (redirects.begin(), redirects.end(), r) == redirects.end()) {
+ redirects.push_back (r);
+
+ void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
+ r->GoingAway.connect (slot (*this, pmf));
+
+ RedirectsChanged();
+ }
+}
+
+void
+RouteRedirectSelection::add (const vector<Redirect*>& rlist)
+{
+ bool changed = false;
+
+ for (vector<Redirect*>::const_iterator i = rlist.begin(); i != rlist.end(); ++i) {
+ if (find (redirects.begin(), redirects.end(), *i) == redirects.end()) {
+ redirects.push_back (*i);
+
+ void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
+ (*i)->GoingAway.connect (slot (*this, pmf));
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ RedirectsChanged();
+ }
+}
+
+void
+RouteRedirectSelection::remove (Redirect* r)
+{
+ list<Redirect*>::iterator i;
+ if ((i = find (redirects.begin(), redirects.end(), r)) != redirects.end()) {
+ redirects.erase (i);
+ RedirectsChanged ();
+ }
+}
+
+void
+RouteRedirectSelection::set (Redirect *r)
+{
+ clear_redirects ();
+ add (r);
+}
+
+void
+RouteRedirectSelection::set (const vector<Redirect*>& rlist)
+{
+ clear_redirects ();
+ add (rlist);
+}
+
+void
+RouteRedirectSelection::add (Route* r)
+{
+ if (find (routes.begin(), routes.end(), r) == routes.end()) {
+ routes.push_back (r);
+
+ void (RouteRedirectSelection::*pmf)(Route*) = &RouteRedirectSelection::remove;
+ r->GoingAway.connect (bind (slot (*this, pmf), r));
+
+ RoutesChanged();
+ }
+}
+
+void
+RouteRedirectSelection::remove (Route* r)
+{
+ list<Route*>::iterator i;
+ if ((i = find (routes.begin(), routes.end(), r)) != routes.end()) {
+ routes.erase (i);
+ RoutesChanged ();
+ }
+}
+
+void
+RouteRedirectSelection::set (Route *r)
+{
+ clear_routes ();
+ add (r);
+}
+
+bool
+RouteRedirectSelection::selected (Route* ms)
+{
+ return find (routes.begin(), routes.end(), ms) != routes.end();
+}
+
+bool
+RouteRedirectSelection::empty ()
+{
+ return redirects.empty () && routes.empty ();
+}
+
diff --git a/gtk2_ardour/route_redirect_selection.h b/gtk2_ardour/route_redirect_selection.h
new file mode 100644
index 0000000000..33aa44aaa2
--- /dev/null
+++ b/gtk2_ardour/route_redirect_selection.h
@@ -0,0 +1,64 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_route_redirect_selection_h__
+#define __ardour_gtk_route_redirect_selection_h__
+
+#include <vector>
+#include <sigc++/signal_system.h>
+
+#include "redirect_selection.h"
+#include "route_selection.h"
+
+class RouteRedirectSelection : public SigC::Object
+{
+ public:
+ RedirectSelection redirects;
+ RouteSelection routes;
+
+ RouteRedirectSelection() {}
+
+ RouteRedirectSelection& operator= (const RouteRedirectSelection& other);
+
+ SigC::Signal0<void> RedirectsChanged;
+ SigC::Signal0<void> RoutesChanged;
+
+ void clear ();
+ bool empty();
+
+ void set (ARDOUR::Redirect*);
+ void set (const std::vector<ARDOUR::Redirect*>&);
+ void add (ARDOUR::Redirect*);
+ void add (const std::vector<ARDOUR::Redirect*>&);
+ void remove (ARDOUR::Redirect*);
+
+ void set (ARDOUR::Route*);
+ void add (ARDOUR::Route*);
+ void remove (ARDOUR::Route*);
+
+ void clear_redirects ();
+ void clear_routes ();
+
+ bool selected (ARDOUR::Route*);
+};
+
+bool operator==(const RouteRedirectSelection& a, const RouteRedirectSelection& b);
+
+#endif /* __ardour_gtk_route_redirect_selection_h__ */
diff --git a/gtk2_ardour/route_selection.h b/gtk2_ardour/route_selection.h
new file mode 100644
index 0000000000..50797deed3
--- /dev/null
+++ b/gtk2_ardour/route_selection.h
@@ -0,0 +1,12 @@
+#ifndef __ardour_gtk_route_selection_h__
+#define __ardour_gtk_route_selection_h__
+
+#include <list>
+
+namespace ARDOUR {
+ class Route;
+}
+
+struct RouteSelection : list<ARDOUR::Route*> {};
+
+#endif /* __ardour_gtk_route_selection_h__ */
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
new file mode 100644
index 0000000000..bd9c535ecd
--- /dev/null
+++ b/gtk2_ardour/route_ui.cc
@@ -0,0 +1,852 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/choice.h>
+#include <gtkmmext/bindable_button.h>
+#include <gtkmmext/doi.h>
+
+#include <ardour/route_group.h>
+
+#include "route_ui.h"
+#include "keyboard.h"
+#include "utils.h"
+#include "prompter.h"
+#include "gui_thread.h"
+
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/diskstream.h>
+
+#include "i18n.h"
+
+using namespace SigC;
+using namespace Gtk;
+using namespace Gtkmmext;
+using namespace ARDOUR;
+
+
+RouteUI::RouteUI (ARDOUR::Route& rt, ARDOUR::Session& sess, const char* m_name,
+ const char* s_name, const char* r_name)
+ : AxisView(sess),
+ _route(rt),
+ mute_button(0),
+ solo_button(0),
+ rec_enable_button(0)
+{
+ xml_node = 0;
+ mute_menu = 0;
+ solo_menu = 0;
+ ignore_toggle = false;
+ wait_for_release = false;
+ route_active_menu_item = 0;
+
+ if (set_color_from_route()) {
+ set_color (unique_random_color());
+ }
+
+ _route.GoingAway.connect (slot (*this, &RouteUI::route_removed));
+ _route.active_changed.connect (slot (*this, &RouteUI::route_active_changed));
+
+ mute_button = manage (new BindableToggleButton (& _route.midi_mute_control(), m_name ));
+ mute_button->set_bind_button_state (2, GDK_CONTROL_MASK);
+ solo_button = manage (new BindableToggleButton (& _route.midi_solo_control(), s_name ));
+ solo_button->set_bind_button_state (2, GDK_CONTROL_MASK);
+
+ if (is_audio_track()) {
+ AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
+
+ get_diskstream()->record_enable_changed.connect (slot (*this, &RouteUI::route_rec_enable_changed));
+
+ _session.RecordEnabled.connect (slot (*this, &RouteUI::session_rec_enable_changed));
+ _session.RecordDisabled.connect (slot (*this, &RouteUI::session_rec_enable_changed));
+
+ rec_enable_button = manage (new BindableToggleButton (& at->midi_rec_enable_control(), r_name ));
+ rec_enable_button->set_bind_button_state (2, GDK_CONTROL_MASK);
+
+ } else {
+ rec_enable_button = manage (new BindableToggleButton (0, r_name ));
+ }
+
+ mute_button->unset_flags (GTK_CAN_FOCUS);
+ solo_button->unset_flags (GTK_CAN_FOCUS);
+ rec_enable_button->unset_flags (GTK_CAN_FOCUS);
+
+ /* map the current state */
+
+ update_rec_display ();
+ map_frozen ();
+}
+
+RouteUI::~RouteUI()
+{
+ delete mute_menu;
+}
+
+gint
+RouteUI::mute_press(GdkEventButton* ev)
+{
+ if (!ignore_toggle) {
+
+ if (Keyboard::is_context_menu_event (ev)) {
+
+ if (mute_menu == 0){
+ build_mute_menu();
+ }
+
+ mute_menu->popup(0,0);
+
+ } else {
+
+ if (ev->button == 2) {
+ // ctrl-button2 click is the midi binding click
+ // button2-click is "momentary"
+
+ if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
+ wait_for_release = true;
+ }
+ }
+
+ if (ev->button == 1 || ev->button == 2) {
+
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+
+ /* ctrl-shift-click applies change to all routes */
+
+ _session.begin_reversible_command (_("mute change"));
+ _session.add_undo (_session.global_mute_memento(this));
+ _session.set_all_mute (!_route.muted());
+ _session.add_redo_no_execute (_session.global_mute_memento(this));
+ _session.commit_reversible_command ();
+
+ } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+
+ /* ctrl-click applies change to the mix group.
+ ctrl-button2 is MIDI learn.
+ */
+
+ if (ev->button == 1) {
+ set_mix_group_mute (_route, !_route.muted());
+ }
+
+ } else {
+
+ /* plain click applies change to this route */
+
+ reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route.muted(), this);
+ }
+ }
+ }
+
+ }
+
+ return stop_signal (*mute_button, "button-press-event");
+}
+
+gint
+RouteUI::mute_release(GdkEventButton* ev)
+{
+ if (!ignore_toggle) {
+ if (wait_for_release){
+ wait_for_release = false;
+ // undo the last op
+ // because the press was the last undoable thing we did
+ _session.undo (1U);
+ stop_signal (*mute_button, "button-release-event");
+ }
+ }
+ return TRUE;
+}
+
+gint
+RouteUI::solo_press(GdkEventButton* ev)
+{
+ if (!ignore_toggle) {
+
+ if (Keyboard::is_context_menu_event (ev)) {
+
+ if (solo_menu == 0) {
+ build_solo_menu ();
+ }
+
+ solo_menu->popup (1, 0);
+
+ } else {
+
+ if (ev->button == 2) {
+
+ // ctrl-button2 click is the midi binding click
+ // button2-click is "momentary"
+
+ if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
+ wait_for_release = true;
+ }
+ }
+
+ if (ev->button == 1 || ev->button == 2) {
+
+ if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+
+ /* ctrl-shift-click applies change to all routes */
+
+ _session.begin_reversible_command (_("solo change"));
+ _session.add_undo (_session.global_solo_memento(this));
+ _session.set_all_solo (!_route.soloed());
+ _session.add_redo_no_execute (_session.global_solo_memento(this));
+ _session.commit_reversible_command ();
+
+ } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
+
+ // ctrl-alt-click: exclusively solo this track, not a toggle */
+
+ _session.begin_reversible_command (_("solo change"));
+ _session.add_undo (_session.global_solo_memento(this));
+ _session.set_all_solo (false);
+ _route.set_solo (true, this);
+ _session.add_redo_no_execute (_session.global_solo_memento(this));
+ _session.commit_reversible_command ();
+
+ } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
+
+ // 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)) {
+
+ /* ctrl-click: solo mix group.
+ ctrl-button2 is MIDI learn.
+ */
+
+ if (ev->button == 1) {
+ set_mix_group_solo (_route, !_route.soloed());
+ }
+
+ } else {
+
+ /* click: solo this route */
+
+ reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route.soloed(), this);
+ }
+ }
+ }
+ }
+
+ return stop_signal (*solo_button, "button-press-event");
+}
+
+gint
+RouteUI::solo_release(GdkEventButton* ev)
+{
+ if(!ignore_toggle){
+ if (wait_for_release){
+ wait_for_release = false;
+ // undo the last op
+ // because the press was the last undoable thing we did
+
+ _session.undo (1U);
+
+ stop_signal (*solo_button, "button-release-event");
+ }
+ }
+ return TRUE;
+}
+
+gint
+RouteUI::rec_enable_press(GdkEventButton* ev)
+{
+ if (!ignore_toggle && is_audio_track()) {
+
+ if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ // do nothing on midi bind event
+ }
+ else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+
+ _session.begin_reversible_command (_("rec-enable change"));
+ _session.add_undo (_session.global_record_enable_memento(this));
+
+ if (rec_enable_button->get_active()) {
+ _session.record_disenable_all ();
+ } else {
+ _session.record_enable_all ();
+ }
+
+ _session.add_redo_no_execute (_session.global_record_enable_memento(this));
+ _session.commit_reversible_command ();
+
+ } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+
+ set_mix_group_rec_enable (_route, !_route.record_enabled());
+
+ } else {
+
+ reversibly_apply_audio_track_boolean ("rec-enable change", &AudioTrack::set_record_enable, !audio_track()->record_enabled(), this);
+
+ ignore_toggle = true;
+ rec_enable_button->set_active(audio_track()->record_enabled());
+ ignore_toggle = false;
+ }
+
+ stop_signal (*rec_enable_button, "button-press-event");
+ }
+
+ return TRUE;
+}
+
+void
+RouteUI::solo_changed(void* src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &RouteUI::update_solo_display));
+}
+
+void
+RouteUI::update_solo_display ()
+{
+ bool x;
+
+ if (solo_button->get_active() != (x = _route.soloed())){
+ ignore_toggle = true;
+ solo_button->set_active(x);
+ ignore_toggle = false;
+ }
+
+ /* show solo safe */
+
+ if (_route.solo_safe()){
+ solo_button->set_name(safe_solo_button_name());
+ } else {
+ solo_button->set_name(solo_button_name());
+ }
+}
+
+void
+RouteUI::mute_changed(void* src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &RouteUI::update_mute_display));
+}
+
+void
+RouteUI::update_mute_display ()
+{
+ bool x;
+
+ if (mute_button->get_active() != (x = _route.muted())){
+ ignore_toggle = true;
+ mute_button->set_active(x);
+ ignore_toggle = false;
+ }
+}
+
+void
+RouteUI::route_rec_enable_changed (void *src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &RouteUI::update_rec_display));
+}
+
+void
+RouteUI::session_rec_enable_changed ()
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &RouteUI::update_rec_display));
+}
+
+void
+RouteUI::update_rec_display ()
+{
+ bool model = _route.record_enabled();
+ bool view = rec_enable_button->get_active();
+
+ /* first make sure the button's "depressed" visual
+ is correct.
+ */
+
+ if (model != view) {
+ ignore_toggle = true;
+ rec_enable_button->set_active (model);
+ ignore_toggle = false;
+ }
+
+ /* now make sure its color state is correct */
+
+ if (model) {
+
+ switch (_session.record_status ()) {
+ case Session::Disabled:
+ case Session::Enabled:
+ if (rec_enable_button->get_state() != GTK_STATE_ACTIVE) {
+ rec_enable_button->set_state (GTK_STATE_ACTIVE);
+ }
+ break;
+
+ case Session::Recording:
+ if (rec_enable_button->get_state() != GTK_STATE_SELECTED) {
+ rec_enable_button->set_state (GTK_STATE_SELECTED);
+ }
+ break;
+ }
+
+ } else {
+ if (rec_enable_button->get_state() != GTK_STATE_NORMAL) {
+ rec_enable_button->set_state (GTK_STATE_NORMAL);
+ }
+ }
+}
+
+void
+RouteUI::build_solo_menu (void)
+{
+ using namespace Menu_Helpers;
+
+ solo_menu = new Menu;
+ solo_menu->set_name ("ArdourContextMenu");
+ MenuList& items = solo_menu->items();
+ CheckMenuItem* check;
+
+ check = new CheckMenuItem(_("Solo-safe"));
+ check->set_active (_route.solo_safe());
+ check->toggled.connect (bind (slot (*this, &RouteUI::toggle_solo_safe), check));
+ _route.solo_safe_changed.connect(bind (slot (*this, &RouteUI::solo_safe_toggle), check));
+ items.push_back (CheckMenuElem(*check));
+ check->show_all();
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("MIDI Bind"), slot (*mute_button, &BindableToggleButton::midi_learn)));
+
+}
+
+void
+RouteUI::build_mute_menu(void)
+{
+ using namespace Menu_Helpers;
+
+ mute_menu = new Menu;
+ mute_menu->set_name ("ArdourContextMenu");
+ MenuList& items = mute_menu->items();
+ CheckMenuItem* check;
+
+ check = new CheckMenuItem(_("Pre Fader"));
+ init_mute_menu(PRE_FADER, check);
+ check->toggled.connect(bind (slot (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
+ _route.pre_fader_changed.connect(bind (slot (*this, &RouteUI::pre_fader_toggle), check));
+ items.push_back (CheckMenuElem(*check));
+ check->show_all();
+
+ check = new CheckMenuItem(_("Post Fader"));
+ init_mute_menu(POST_FADER, check);
+ check->toggled.connect(bind (slot (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
+ _route.post_fader_changed.connect(bind (slot (*this, &RouteUI::post_fader_toggle), check));
+ items.push_back (CheckMenuElem(*check));
+ check->show_all();
+
+ check = new CheckMenuItem(_("Control Outs"));
+ init_mute_menu(CONTROL_OUTS, check);
+ check->toggled.connect(bind (slot (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
+ _route.control_outs_changed.connect(bind (slot (*this, &RouteUI::control_outs_toggle), check));
+ items.push_back (CheckMenuElem(*check));
+ check->show_all();
+
+ check = new CheckMenuItem(_("Main Outs"));
+ init_mute_menu(MAIN_OUTS, check);
+ check->toggled.connect(bind (slot (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
+ _route.main_outs_changed.connect(bind (slot (*this, &RouteUI::main_outs_toggle), check));
+ items.push_back (CheckMenuElem(*check));
+ check->show_all();
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("MIDI Bind"), slot (*mute_button, &BindableToggleButton::midi_learn)));
+}
+
+void
+RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
+{
+ if (_route.get_mute_config (type)) {
+ check->set_active (true);
+ }
+}
+
+void
+RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
+{
+ _route.set_mute_config(type, check->get_active(), this);
+}
+
+void
+RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
+{
+ _route.set_solo_safe (check->get_active(), this);
+}
+
+void
+RouteUI::set_mix_group_solo(Route& route, bool yn)
+{
+ RouteGroup* mix_group;
+
+ if((mix_group = route.mix_group()) != 0){
+ _session.begin_reversible_command (_("mix group solo change"));
+ _session.add_undo (_session.global_solo_memento (this));
+ mix_group->apply(&Route::set_solo, yn, this);
+ _session.add_redo_no_execute (_session.global_solo_memento(this));
+ _session.commit_reversible_command ();
+ } else {
+ reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route.soloed(), this);
+ }
+}
+
+void
+RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
+{
+ _session.begin_reversible_command (name);
+ _session.add_undo (bind (slot (_route, func), !yn, (void *) arg));
+ _session.add_redo (bind (slot (_route, func), yn, (void *) arg));
+ _session.commit_reversible_command ();
+}
+
+void
+RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
+{
+ _session.begin_reversible_command (name);
+ _session.add_undo (bind (slot (*audio_track(), func), !yn, (void *) arg));
+ _session.add_redo (bind (slot (*audio_track(), func), yn, (void *) arg));
+ _session.commit_reversible_command ();
+}
+
+void
+RouteUI::set_mix_group_mute(Route& route, bool yn)
+{
+ RouteGroup* mix_group;
+
+ if((mix_group = route.mix_group()) != 0){
+ _session.begin_reversible_command (_("mix group mute change"));
+ _session.add_undo (_session.global_mute_memento (this));
+ mix_group->apply(&Route::set_mute, yn, this);
+ _session.add_redo_no_execute (_session.global_mute_memento(this));
+ _session.commit_reversible_command ();
+ } else {
+ reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route.muted(), this);
+ }
+}
+
+void
+RouteUI::set_mix_group_rec_enable(Route& route, bool yn)
+{
+ RouteGroup* mix_group;
+
+ if((mix_group = route.mix_group()) != 0){
+ _session.begin_reversible_command (_("mix group rec-enable change"));
+ _session.add_undo (_session.global_record_enable_memento (this));
+ mix_group->apply (&Route::set_record_enable, yn, this);
+ _session.add_redo_no_execute (_session.global_record_enable_memento(this));
+ _session.commit_reversible_command ();
+ } else {
+ reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route.record_enabled(), this);
+ }
+}
+
+
+bool
+RouteUI::choose_color()
+{
+ bool picked;
+ GdkColor color;
+ gdouble current[4];
+
+ current[0] = _color.get_red() / 65535.0;
+ current[1] = _color.get_green() / 65535.0;
+ current[2] = _color.get_blue() / 65535.0;
+ current[3] = 1.0;
+
+ color = Gtkmmext::UI::instance()->get_color (_("ardour: color selection"), picked, current);
+
+ if (picked) {
+ set_color (color);
+ }
+
+ return picked;
+}
+
+void
+RouteUI::set_color (Gdk_Color c)
+{
+ char buf[64];
+
+ _color = c;
+
+ ensure_xml_node ();
+ snprintf (buf, sizeof (buf), "%d:%d:%d", c.red, c.green, c.blue);
+ xml_node->add_property ("color", buf);
+
+ _route.gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
+}
+
+
+void
+RouteUI::ensure_xml_node ()
+{
+ if (xml_node == 0) {
+ if ((xml_node = _route.extra_xml ("GUI")) == 0) {
+ xml_node = new XMLNode ("GUI");
+ _route.add_extra_xml (*xml_node);
+ }
+ }
+}
+
+XMLNode*
+RouteUI::get_child_xml_node (string childname)
+{
+ XMLNode* child;
+
+ ensure_xml_node ();
+
+
+ if ((child = find_named_node (*xml_node, childname)) == 0) {
+ child = new XMLNode (childname);
+ xml_node->add_child_nocopy (*child);
+ }
+
+ return child;
+}
+
+int
+RouteUI::set_color_from_route ()
+{
+ XMLProperty *prop;
+
+ RouteUI::ensure_xml_node ();
+
+ if ((prop = xml_node->property ("color")) != 0) {
+ int r, g, b;
+ sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
+ _color.red = r;
+ _color.green = g;
+ _color.blue = b;
+ return 0;
+ }
+ return 1;
+}
+
+void
+RouteUI::remove_this_route ()
+{
+ vector<string> choices;
+ string prompt;
+
+ if (is_audio_track()) {
+ prompt = compose (_("Do you really want to remove track \"%1\" ?\nYou may also lose the playlist used by this track.\n(cannot be undone)"), _route.name());
+ } else {
+ prompt = compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route.name());
+ }
+
+ choices.push_back (_("Yes, remove it."));
+ choices.push_back (_("No, do nothing."));
+
+ Choice prompter (prompt, choices);
+
+ prompter.chosen.connect (Gtk::Main::quit.slot());
+ prompter.show_all ();
+
+ Gtk::Main::run ();
+
+ if (prompter.get_choice() == 0) {
+ Main::idle.connect (bind (slot (&RouteUI::idle_remove_this_route), this));
+ }
+}
+
+gint
+RouteUI::idle_remove_this_route (RouteUI *rui)
+{
+ rui->_session.remove_route (rui->_route);
+ return FALSE;
+}
+
+void
+RouteUI::route_removed ()
+{
+ ENSURE_GUI_THREAD(slot (*this, &RouteUI::route_removed));
+
+ delete this;
+}
+
+void
+RouteUI::route_rename ()
+{
+ ArdourPrompter name_prompter (true);
+ name_prompter.set_prompt (_("new name: "));
+ name_prompter.set_initial_text (_route.name());
+ name_prompter.done.connect (Gtk::Main::quit.slot());
+ name_prompter.show_all ();
+
+ Gtk::Main::run();
+
+ if (name_prompter.status == Gtkmmext::Prompter::cancelled) {
+ return;
+ }
+
+ string result;
+ name_prompter.get_result (result);
+
+ if (result.length() == 0) {
+ return;
+ }
+
+ strip_whitespace_edges (result);
+ _route.set_name (result, this);
+}
+
+void
+RouteUI::name_changed (void *src)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::name_changed), src));
+
+ name_label.set_text (_route.name());
+}
+
+void
+RouteUI::toggle_route_active ()
+{
+ bool yn;
+
+ if (route_active_menu_item) {
+ if (route_active_menu_item->get_active() != (yn = _route.active())) {
+ _route.set_active (!yn);
+ }
+ }
+}
+
+void
+RouteUI::route_active_changed ()
+{
+ if (route_active_menu_item) {
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*route_active_menu_item, &CheckMenuItem::set_active), _route.active()));
+ }
+}
+
+void
+RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
+{
+ bool yn = _route.solo_safe ();
+
+ if (check->get_active() != yn) {
+ check->set_active (yn);
+ }
+}
+void
+RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::pre_fader_toggle), src, check));
+
+ bool yn = _route.get_mute_config(PRE_FADER);
+ if (check->get_active() != yn) {
+ check->set_active (yn);
+ }
+}
+
+void
+RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::post_fader_toggle), src, check));
+
+ bool yn = _route.get_mute_config(POST_FADER);
+ if (check->get_active() != yn) {
+ check->set_active (yn);
+ }
+}
+
+void
+RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::control_outs_toggle), src, check));
+
+ bool yn = _route.get_mute_config(CONTROL_OUTS);
+ if (check->get_active() != yn) {
+ check->set_active (yn);
+ }
+}
+
+void
+RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::main_outs_toggle), src, check));
+
+ bool yn = _route.get_mute_config(MAIN_OUTS);
+ if (check->get_active() != yn) {
+ check->set_active (yn);
+ }
+}
+
+void
+RouteUI::disconnect_input ()
+{
+ _route.disconnect_inputs (this);
+}
+
+void
+RouteUI::disconnect_output ()
+{
+ _route.disconnect_outputs (this);
+}
+
+bool
+RouteUI::is_audio_track () const
+{
+ return dynamic_cast<AudioTrack*>(&_route) != 0;
+}
+
+DiskStream*
+RouteUI::get_diskstream () const
+{
+ AudioTrack *at;
+
+ if ((at = dynamic_cast<AudioTrack*>(&_route)) != 0) {
+ return &at->disk_stream();
+ } else {
+ return 0;
+ }
+}
+
+AudioTrack*
+RouteUI::audio_track() const
+{
+ return dynamic_cast<AudioTrack*>(&_route);
+}
+string
+RouteUI::name() const
+{
+ return _route.name();
+}
+
+void
+RouteUI::map_frozen ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &RouteUI::map_frozen));
+
+ AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
+
+ if (at) {
+ switch (at->freeze_state()) {
+ case AudioTrack::Frozen:
+ rec_enable_button->set_sensitive (false);
+ break;
+ default:
+ rec_enable_button->set_sensitive (true);
+ break;
+ }
+ }
+}
diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h
new file mode 100644
index 0000000000..acdc084306
--- /dev/null
+++ b/gtk2_ardour/route_ui.h
@@ -0,0 +1,140 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_route_ui__
+#define __ardour_route_ui__
+
+#include <list>
+
+#include <gtk--.h>
+#include <pbd/xml++.h>
+#include <ardour/ardour.h>
+#include <ardour/route.h>
+
+#include "axis_view.h"
+
+namespace Gtkmmext {
+ class BindableToggleButton;
+}
+
+namespace ARDOUR {
+ class AudioTrack;
+}
+
+class RouteUI : public virtual AxisView
+{
+ public:
+ RouteUI(ARDOUR::Route&, ARDOUR::Session&, const char*, const char*, const char*);
+ virtual ~RouteUI();
+
+ bool is_audio_track() const;
+ ARDOUR::DiskStream* get_diskstream() const;
+
+ ARDOUR::Route& route() const { return _route; }
+ ARDOUR::AudioTrack* audio_track() const;
+
+ string name() const;
+
+ ARDOUR::Route& _route;
+
+
+ void set_color (Gdk_Color c);
+ bool choose_color ();
+
+ bool ignore_toggle;
+ bool wait_for_release;
+
+ Gtkmmext::BindableToggleButton * mute_button;
+ Gtkmmext::BindableToggleButton * solo_button;
+ Gtkmmext::BindableToggleButton * rec_enable_button;
+
+ virtual string solo_button_name () const { return "SoloButton"; }
+ virtual string safe_solo_button_name () const { return "SafeSoloButton"; }
+
+ Gtk::Menu* mute_menu;
+ Gtk::Menu* solo_menu;
+
+ XMLNode *xml_node;
+ void ensure_xml_node ();
+
+ XMLNode* get_child_xml_node (std::string childname);
+
+ gint mute_press(GdkEventButton*);
+ gint mute_release(GdkEventButton*);
+ gint solo_press(GdkEventButton*);
+ gint solo_release(GdkEventButton*);
+ gint rec_enable_press(GdkEventButton*);
+
+ void solo_changed(void*);
+ void mute_changed(void*);
+ void route_rec_enable_changed(void*);
+ void session_rec_enable_changed();
+
+ void build_solo_menu (void);
+
+ void solo_safe_toggle (void*, Gtk::CheckMenuItem*);
+ void toggle_solo_safe (Gtk::CheckMenuItem*);
+
+ void toggle_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*);
+ void pre_fader_toggle(void*, Gtk::CheckMenuItem*);
+ void post_fader_toggle(void*, Gtk::CheckMenuItem*);
+ void control_outs_toggle(void*, Gtk::CheckMenuItem*);
+ void main_outs_toggle(void*, Gtk::CheckMenuItem*);
+
+ void build_mute_menu(void);
+ void init_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*);
+
+ void set_mix_group_solo(ARDOUR::Route&, bool);
+ void set_mix_group_mute(ARDOUR::Route&, bool);
+ void set_mix_group_rec_enable(ARDOUR::Route&, bool);
+
+ int set_color_from_route ();
+
+ SigC::Connection blink_connection;
+
+ void rec_enable_button_blink (bool onoff, ARDOUR::DiskStream *, Gtk::Widget *w);
+
+ void remove_this_route ();
+ static gint idle_remove_this_route (RouteUI *);
+
+ void route_rename();
+
+ virtual void name_changed (void *src);
+ void route_removed ();
+
+ static gint okay_gplusplus_cannot_do_complex_templates (RouteUI *rui);
+
+ Gtk::CheckMenuItem *route_active_menu_item;
+ void toggle_route_active ();
+ virtual void route_active_changed ();
+
+ void disconnect_input ();
+ void disconnect_output ();
+
+ void update_rec_display ();
+ void update_mute_display ();
+ void update_solo_display ();
+ virtual void map_frozen ();
+
+ void reversibly_apply_route_boolean (string name, void (ARDOUR::Route::*func)(bool, void*), bool, void *);
+ void reversibly_apply_audio_track_boolean (string name, void (ARDOUR::AudioTrack::*func)(bool, void*), bool, void *);
+};
+
+#endif /* __ardour_route_ui__ */
diff --git a/gtk2_ardour/selectable.h b/gtk2_ardour/selectable.h
new file mode 100644
index 0000000000..fdd6f7ff9f
--- /dev/null
+++ b/gtk2_ardour/selectable.h
@@ -0,0 +1,41 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_selectable_h__
+#define __ardour_gtk_selectable_h__
+
+class Selectable
+{
+ public:
+ Selectable() {
+ _selected = false;
+ }
+
+ virtual ~Selectable() {}
+
+ virtual void set_selected (bool) {
+ _selected = true;
+ }
+
+ protected:
+ bool _selected;
+};
+
+#endif /* __ardour_gtk_selectable_h__ */
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
new file mode 100644
index 0000000000..71b957d517
--- /dev/null
+++ b/gtk2_ardour/selection.cc
@@ -0,0 +1,573 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+#include <sigc++/bind.h>
+#include <pbd/error.h>
+
+#include <ardour/playlist.h>
+
+#include "regionview.h"
+#include "selection.h"
+#include "selection_templates.h"
+#include "time_axis_view.h"
+#include "automation_time_axis.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+
+struct AudioRangeComparator {
+ bool operator()(AudioRange a, AudioRange b) {
+ return a.start < b.start;
+ }
+};
+
+Selection&
+Selection::operator= (const Selection& other)
+{
+ if (&other != this) {
+ audio_regions = other.audio_regions;
+ tracks = other.tracks;
+ time = other.time;
+ lines = other.lines;
+ }
+ return *this;
+}
+
+bool
+operator== (const Selection& a, const Selection& b)
+{
+ return a.audio_regions == b.audio_regions &&
+ a.tracks == b.tracks &&
+ a.time.track == b.time.track &&
+ a.time.group == b.time.group &&
+ a.time == b.time &&
+ a.lines == b.lines &&
+ a.playlists == b.playlists &&
+ a.redirects == b.redirects;
+}
+
+void
+Selection::clear ()
+{
+ clear_tracks ();
+ clear_audio_regions ();
+ clear_points ();
+ clear_lines();
+ clear_time ();
+ clear_playlists ();
+ clear_redirects ();
+}
+
+void
+Selection::dump_region_layers()
+{
+ cerr << "region selection layer dump" << endl;
+ for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
+ cerr << "layer: " << (int)(*i)->region.layer() << endl;
+ }
+}
+
+
+void
+Selection::clear_redirects ()
+{
+ if (!redirects.empty()) {
+ redirects.clear ();
+ RedirectsChanged ();
+ }
+}
+
+void
+Selection::clear_audio_regions ()
+{
+ if (!audio_regions.empty()) {
+ audio_regions.clear_all ();
+ RegionsChanged();
+ }
+}
+
+void
+Selection::clear_tracks ()
+{
+ if (!tracks.empty()) {
+ tracks.clear ();
+ TracksChanged();
+ }
+}
+
+void
+Selection::clear_time ()
+{
+ time.track = 0;
+ time.group = 0;
+ time.clear();
+
+ TimeChanged ();
+}
+
+void
+Selection::clear_playlists ()
+{
+ /* Selections own their playlists */
+
+ for (PlaylistSelection::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+ (*i)->unref ();
+ }
+
+ if (!playlists.empty()) {
+ playlists.clear ();
+ PlaylistsChanged();
+ }
+}
+
+void
+Selection::clear_lines ()
+{
+ if (!lines.empty()) {
+ lines.clear ();
+ LinesChanged();
+ }
+}
+
+void
+Selection::add (Redirect* r)
+{
+ if (find (redirects.begin(), redirects.end(), r) == redirects.end()) {
+ redirects.push_back (r);
+ RedirectsChanged();
+ }
+}
+
+void
+Selection::add (Playlist* pl)
+{
+ if (find (playlists.begin(), playlists.end(), pl) == playlists.end()) {
+ pl->ref ();
+ playlists.push_back(pl);
+ PlaylistsChanged ();
+ }
+}
+
+void
+Selection::add (const list<Playlist*>& pllist)
+{
+ bool changed = false;
+
+ for (list<Playlist*>::const_iterator i = pllist.begin(); i != pllist.end(); ++i) {
+ if (find (playlists.begin(), playlists.end(), (*i)) == playlists.end()) {
+ (*i)->ref ();
+ playlists.push_back (*i);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ PlaylistsChanged ();
+ }
+}
+
+void
+Selection::add (const list<TimeAxisView*>& track_list)
+{
+ bool changed = false;
+
+ for (list<TimeAxisView*>::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
+ if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) {
+ void (Selection::*pmf)(TimeAxisView*) = &Selection::remove;
+ (*i)->GoingAway.connect (bind (slot (*this, pmf), (*i)));
+ tracks.push_back (*i);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ TracksChanged ();
+ }
+}
+
+void
+Selection::add (TimeAxisView* track)
+{
+ if (find (tracks.begin(), tracks.end(), track) == tracks.end()) {
+ void (Selection::*pmf)(TimeAxisView*) = &Selection::remove;
+ track->GoingAway.connect (bind (slot (*this, pmf), track));
+ tracks.push_back (track);
+ TracksChanged();
+ }
+}
+
+void
+Selection::add (AudioRegionView* r)
+{
+ if (find (audio_regions.begin(), audio_regions.end(), r) == audio_regions.end()) {
+ audio_regions.add (r);
+ RegionsChanged ();
+ }
+}
+
+void
+Selection::add (vector<AudioRegionView*>& v)
+{
+ bool changed = false;
+
+ for (vector<AudioRegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
+ if (find (audio_regions.begin(), audio_regions.end(), (*i)) == audio_regions.end()) {
+ audio_regions.add ((*i));
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ RegionsChanged ();
+ }
+}
+
+long
+Selection::add (jack_nframes_t start, jack_nframes_t end)
+{
+ AudioRangeComparator cmp;
+
+ time.push_back (AudioRange (start, end, next_time_id++));
+ time.consolidate ();
+ time.sort (cmp);
+
+ TimeChanged ();
+
+ return next_time_id - 1;
+}
+
+void
+Selection::replace (uint32_t sid, jack_nframes_t start, jack_nframes_t end)
+{
+ for (list<AudioRange>::iterator i = time.begin(); i != time.end(); ++i) {
+ if ((*i).id == sid) {
+ time.erase (i);
+ time.push_back (AudioRange(start,end, sid));
+
+ /* don't consolidate here */
+
+
+ AudioRangeComparator cmp;
+ time.sort (cmp);
+
+ TimeChanged ();
+ break;
+ }
+ }
+}
+
+void
+Selection::add (AutomationList* ac)
+{
+ if (find (lines.begin(), lines.end(), ac) == lines.end()) {
+ lines.push_back (ac);
+ LinesChanged();
+ }
+}
+
+void
+Selection::remove (Redirect* r)
+{
+ list<Redirect*>::iterator i;
+ if ((i = find (redirects.begin(), redirects.end(), r)) != redirects.end()) {
+ redirects.erase (i);
+ RedirectsChanged ();
+ }
+}
+
+void
+Selection::remove (TimeAxisView* track)
+{
+ list<TimeAxisView*>::iterator i;
+ if ((i = find (tracks.begin(), tracks.end(), track)) != tracks.end()) {
+ tracks.erase (i);
+ TracksChanged();
+ }
+}
+
+void
+Selection::remove (const list<TimeAxisView*>& track_list)
+{
+ bool changed = false;
+
+ for (list<TimeAxisView*>::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
+
+ list<TimeAxisView*>::iterator x;
+
+ if ((x = find (tracks.begin(), tracks.end(), (*i))) != tracks.end()) {
+ tracks.erase (x);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ TracksChanged();
+ }
+}
+
+void
+Selection::remove (Playlist* track)
+{
+ list<Playlist*>::iterator i;
+ if ((i = find (playlists.begin(), playlists.end(), track)) != playlists.end()) {
+ playlists.erase (i);
+ PlaylistsChanged();
+ }
+}
+
+void
+Selection::remove (const list<Playlist*>& pllist)
+{
+ bool changed = false;
+
+ for (list<Playlist*>::const_iterator i = pllist.begin(); i != pllist.end(); ++i) {
+
+ list<Playlist*>::iterator x;
+
+ if ((x = find (playlists.begin(), playlists.end(), (*i))) != playlists.end()) {
+ playlists.erase (x);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ PlaylistsChanged();
+ }
+}
+
+void
+Selection::remove (AudioRegionView* r)
+{
+ audio_regions.remove (r);
+ RegionsChanged ();
+}
+
+
+void
+Selection::remove (uint32_t selection_id)
+{
+ if (time.empty()) {
+ return;
+ }
+
+ for (list<AudioRange>::iterator i = time.begin(); i != time.end(); ++i) {
+ if ((*i).id == selection_id) {
+ time.erase (i);
+
+ TimeChanged ();
+ break;
+ }
+ }
+}
+
+void
+Selection::remove (jack_nframes_t start, jack_nframes_t end)
+{
+}
+
+void
+Selection::remove (AutomationList *ac)
+{
+ list<AutomationList*>::iterator i;
+ if ((i = find (lines.begin(), lines.end(), ac)) != lines.end()) {
+ lines.erase (i);
+ LinesChanged();
+ }
+}
+
+void
+Selection::set (Redirect *r)
+{
+ clear_redirects ();
+ add (r);
+}
+
+void
+Selection::set (TimeAxisView* track)
+{
+ clear_tracks ();
+ add (track);
+}
+
+void
+Selection::set (const list<TimeAxisView*>& track_list)
+{
+ clear_tracks ();
+ add (track_list);
+}
+
+void
+Selection::set (Playlist* playlist)
+{
+ clear_playlists ();
+ add (playlist);
+}
+
+void
+Selection::set (const list<Playlist*>& pllist)
+{
+ clear_playlists ();
+ add (pllist);
+}
+
+void
+Selection::set (AudioRegionView* r)
+{
+ clear_audio_regions ();
+ add (r);
+}
+
+void
+Selection::set (vector<AudioRegionView*>& v)
+{
+
+ clear_audio_regions ();
+ // make sure to deselect any automation selections
+ clear_points();
+ add (v);
+}
+
+long
+Selection::set (TimeAxisView* track, jack_nframes_t start, jack_nframes_t end)
+{
+ if ((start == 0 && end == 0) || end < start) {
+ return 0;
+ }
+
+ if (time.empty()) {
+ time.push_back (AudioRange (start, end, next_time_id++));
+ } else {
+ /* reuse the first entry, and remove all the rest */
+
+ while (time.size() > 1) {
+ time.pop_front();
+ }
+ time.front().start = start;
+ time.front().end = end;
+ }
+
+ if (track) {
+ time.track = track;
+ time.group = track->edit_group();
+ } else {
+ time.track = 0;
+ time.group = 0;
+ }
+
+ time.consolidate ();
+
+ TimeChanged ();
+
+ return time.front().id;
+}
+
+void
+Selection::set (AutomationList *ac)
+{
+ lines.clear();
+ add (ac);
+}
+
+bool
+Selection::selected (TimeAxisView* tv)
+{
+ return find (tracks.begin(), tracks.end(), tv) != tracks.end();
+}
+
+bool
+Selection::selected (AudioRegionView* arv)
+{
+ return find (audio_regions.begin(), audio_regions.end(), arv) != audio_regions.end();
+}
+
+bool
+Selection::empty ()
+{
+ return audio_regions.empty () &&
+ tracks.empty () &&
+ points.empty () &&
+ playlists.empty () &&
+ lines.empty () &&
+ time.empty () &&
+ playlists.empty () &&
+ redirects.empty ()
+ ;
+}
+
+void
+Selection::set (list<Selectable*>& selectables)
+{
+ clear_audio_regions();
+ clear_points ();
+ add (selectables);
+}
+
+void
+Selection::add (list<Selectable*>& selectables)
+{
+ AudioRegionView* arv;
+ AutomationSelectable* as;
+ vector<AudioRegionView*> arvs;
+ vector<AutomationSelectable*> autos;
+
+ for (std::list<Selectable*>::iterator i = selectables.begin(); i != selectables.end(); ++i) {
+ if ((arv = dynamic_cast<AudioRegionView*> (*i)) != 0) {
+ arvs.push_back (arv);
+ } else if ((as = dynamic_cast<AutomationSelectable*> (*i)) != 0) {
+ autos.push_back (as);
+ } else {
+ fatal << _("programming error: ")
+ << X_("unknown selectable type passed to Selection::set()")
+ << endmsg;
+ /*NOTREACHED*/
+ }
+ }
+
+ if (!arvs.empty()) {
+ add (arvs);
+ }
+
+ if (!autos.empty()) {
+ add (autos);
+ }
+}
+
+void
+Selection::clear_points ()
+{
+ if (!points.empty()) {
+ points.clear ();
+ PointsChanged ();
+ }
+}
+
+void
+Selection::add (vector<AutomationSelectable*>& autos)
+{
+ for (vector<AutomationSelectable*>::iterator i = autos.begin(); i != autos.end(); ++i) {
+ points.push_back (**i);
+ delete *i;
+ }
+
+ PointsChanged ();
+}
diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h
new file mode 100644
index 0000000000..30f6983efa
--- /dev/null
+++ b/gtk2_ardour/selection.h
@@ -0,0 +1,134 @@
+/*
+ Copyright (C) 2000-2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_selection_h__
+#define __ardour_gtk_selection_h__
+
+#include <sigc++/signal_system.h>
+
+#include "time_selection.h"
+#include "region_selection.h"
+#include "track_selection.h"
+#include "automation_selection.h"
+#include "playlist_selection.h"
+#include "redirect_selection.h"
+#include "point_selection.h"
+
+class TimeAxisView;
+class AudioRegionView;
+class Selectable;
+
+class Selection : public SigC::Object
+{
+ public:
+ enum SelectionType {
+ Object = 0x1,
+ Range = 0x2
+ };
+
+ TrackSelection tracks;
+ AudioRegionSelection audio_regions;
+ TimeSelection time;
+ AutomationSelection lines;
+ PlaylistSelection playlists;
+ RedirectSelection redirects;
+ PointSelection points;
+
+ Selection() {
+ next_time_id = 0;
+ clear();
+ }
+
+ Selection& operator= (const Selection& other);
+
+ SigC::Signal0<void> RegionsChanged;
+ SigC::Signal0<void> TracksChanged;
+ SigC::Signal0<void> TimeChanged;
+ SigC::Signal0<void> LinesChanged;
+ SigC::Signal0<void> PlaylistsChanged;
+ SigC::Signal0<void> RedirectsChanged;
+ SigC::Signal0<void> PointsChanged;
+
+ void clear ();
+ bool empty();
+
+ void dump_region_layers();
+
+ bool selected (TimeAxisView*);
+ bool selected (AudioRegionView*);
+
+ void set (list<Selectable*>&);
+ void add (list<Selectable*>&);
+
+ void set (TimeAxisView*);
+ void set (const list<TimeAxisView*>&);
+ void set (AudioRegionView*);
+ void set (std::vector<AudioRegionView*>&);
+ long set (TimeAxisView*, jack_nframes_t, jack_nframes_t);
+ void set (ARDOUR::AutomationList*);
+ void set (ARDOUR::Playlist*);
+ void set (const list<ARDOUR::Playlist*>&);
+ void set (ARDOUR::Redirect*);
+ void set (AutomationSelectable*);
+
+ void add (TimeAxisView*);
+ void add (const list<TimeAxisView*>&);
+ void add (AudioRegionView*);
+ void add (std::vector<AudioRegionView*>&);
+ long add (jack_nframes_t, jack_nframes_t);
+ void add (ARDOUR::AutomationList*);
+ void add (ARDOUR::Playlist*);
+ void add (const list<ARDOUR::Playlist*>&);
+ void add (ARDOUR::Redirect*);
+
+ void remove (TimeAxisView*);
+ void remove (const list<TimeAxisView*>&);
+ void remove (AudioRegionView*);
+ void remove (uint32_t selection_id);
+ void remove (jack_nframes_t, jack_nframes_t);
+ void remove (ARDOUR::AutomationList*);
+ void remove (ARDOUR::Playlist*);
+ void remove (const list<ARDOUR::Playlist*>&);
+ void remove (ARDOUR::Redirect*);
+
+ void replace (uint32_t time_index, jack_nframes_t start, jack_nframes_t end);
+
+ void clear_audio_regions();
+ void clear_tracks ();
+ void clear_time();
+ void clear_lines ();
+ void clear_playlists ();
+ void clear_redirects ();
+ void clear_points ();
+
+ void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void));
+ void foreach_audio_region (void (ARDOUR::Region::*method)(void));
+ template<class A> void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg);
+ template<class A> void foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg);
+
+ private:
+ uint32_t next_time_id;
+
+ void add (vector<AutomationSelectable*>&);
+};
+
+bool operator==(const Selection& a, const Selection& b);
+
+#endif /* __ardour_gtk_selection_h__ */
diff --git a/gtk2_ardour/selection_templates.h b/gtk2_ardour/selection_templates.h
new file mode 100644
index 0000000000..c2ca70b526
--- /dev/null
+++ b/gtk2_ardour/selection_templates.h
@@ -0,0 +1,80 @@
+/*
+ Copyright (C) 2000-2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_selection_templates_h__
+#define __ardour_gtk_selection_templates_h__
+
+/* these inlines require knowledge of Region and Route classes,
+ and so they are in a separate header file from selection.h to
+ avoid multiplying dependencies.
+*/
+
+#include <ardour/region.h>
+#include <ardour/audioregion.h>
+
+#include "selection.h"
+
+inline void
+Selection::foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void)) {
+ for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
+ ((*i)->region.*(method))();
+ }
+}
+
+inline void
+Selection::foreach_audio_region (void (ARDOUR::Region::*method)(void)) {
+ for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
+ ((*i)->region.*(method))();
+ }
+}
+
+template<class A> inline void
+Selection::foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg) {
+ for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
+ ((*i)->region.*(method))(arg);
+ }
+}
+
+template<class A> inline void
+Selection::foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg) {
+ for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
+ ((*i)->region.*(method))(arg);
+ }
+}
+
+#if 0
+
+template<class A> inline void
+Selection::foreach_route (void (ARDOUR::Route::*method)(A), A arg) {
+ for (list<ARDOUR::Route*>::iterator i = routes.begin(); i != routes.end(); ++i) {
+ ((*i)->region.*(method))(arg);
+ }
+}
+
+template<class A1, class A2> inline void
+Selection::foreach_route (void (ARDOUR::Route::*method)(A1,A2), A1 arg1, A2 arg2) {
+ for (list<ARDOUR::Route*>::iterator i = routes.begin(); i != routes.end(); ++i) {
+ ((*i)->region.*(method))(arg1, arg2);
+ }
+}
+
+#endif
+
+#endif /* __ardour_gtk_selection_templates_h__ */
diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc
new file mode 100644
index 0000000000..25546fb92a
--- /dev/null
+++ b/gtk2_ardour/send_ui.cc
@@ -0,0 +1,152 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <ardour/send.h>
+#include <gtkmmext/doi.h>
+
+#include "utils.h"
+#include "send_ui.h"
+#include "io_selector.h"
+#include "ardour_ui.h"
+#include "gui_thread.h"
+
+using namespace ARDOUR;
+
+SendUI::SendUI (Send& s, Session& se)
+ : _send (s),
+ _session (se),
+ gpm (s, se),
+ panners (s, se)
+{
+ hbox.pack_start (gpm, true, true);
+ set_name ("SendUIFrame");
+
+ vbox.set_spacing (5);
+ vbox.set_border_width (5);
+
+ vbox.pack_start (hbox, false, false, false);
+ vbox.pack_start (panners, false,false);
+
+ io = new IOSelector (se, s, false);
+
+ pack_start (vbox, false, false);
+
+ pack_start (*io, true, true);
+
+ show_all ();
+
+ _send.set_metering (true);
+
+ _send.output_changed.connect (slot (*this, &SendUI::ins_changed));
+ _send.output_changed.connect (slot (*this, &SendUI::outs_changed));
+
+ panners.set_width (Wide);
+ panners.setup_pan ();
+
+ gpm.setup_meters ();
+ gpm.set_fader_name ("SendUIFrame");
+
+ screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (slot (*this, &SendUI::update));
+ fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (slot (*this, &SendUI::fast_update));
+}
+
+SendUI::~SendUI ()
+{
+ _send.set_metering (false);
+
+ /* XXX not clear that we need to do this */
+
+ screen_update_connection.disconnect();
+ fast_screen_update_connection.disconnect();
+}
+
+void
+SendUI::ins_changed (IOChange change, void* ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &SendUI::ins_changed), change, ignored));
+ if (change & ConfigurationChanged) {
+ panners.setup_pan ();
+ }
+}
+
+void
+SendUI::outs_changed (IOChange change, void* ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &SendUI::outs_changed), change, ignored));
+ if (change & ConfigurationChanged) {
+ panners.setup_pan ();
+ gpm.setup_meters ();
+ }
+}
+
+void
+SendUI::send_going_away (Redirect *ignored)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &SendUI::send_going_away), ignored));
+
+ delete this;
+}
+
+void
+SendUI::update ()
+{
+ gpm.update_meters ();
+}
+
+void
+SendUI::fast_update ()
+{
+ if (_session.meter_falloff() > 0.0f) {
+ gpm.update_meters_falloff ();
+ }
+}
+
+SendUIWindow::SendUIWindow (Send& s, Session& ss)
+{
+ ui = new SendUI (s, ss);
+
+ vpacker.set_border_width (5);
+
+ hpacker.pack_start (*ui, true, true);
+
+ vpacker.pack_start (hpacker);
+
+ add (vpacker);
+ set_name ("SendUIWindow");
+
+ s.GoingAway.connect (slot (*this, &SendUIWindow::send_going_away));
+
+ delete_event.connect (bind (slot (just_hide_it), reinterpret_cast<Window *> (this)));
+
+}
+
+SendUIWindow::~SendUIWindow ()
+{
+ delete ui;
+}
+
+void
+SendUIWindow::send_going_away (Redirect *ignored)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &SendUIWindow::send_going_away), ignored));
+
+ delete this;
+}
+
diff --git a/gtk2_ardour/send_ui.h b/gtk2_ardour/send_ui.h
new file mode 100644
index 0000000000..744469b3c9
--- /dev/null
+++ b/gtk2_ardour/send_ui.h
@@ -0,0 +1,79 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_send_ui_h__
+#define __ardour_gtk_send_ui_h__
+
+#include "gain_meter.h"
+#include "panner_ui.h"
+
+namespace ARDOUR {
+ class Send;
+ class Session;
+ class Redirect;
+}
+
+class IOSelector;
+
+class SendUI : public Gtk::HBox
+{
+ public:
+ SendUI (ARDOUR::Send&, ARDOUR::Session&);
+ ~SendUI();
+
+ void update ();
+ void fast_update ();
+
+ IOSelector* io;
+
+ private:
+ ARDOUR::Send& _send;
+ ARDOUR::Session& _session;
+ GainMeter gpm;
+ PannerUI panners;
+ Gtk::VBox vbox;
+ Gtk::VBox hbox;
+
+ SigC::Connection screen_update_connection;
+ SigC::Connection fast_screen_update_connection;
+
+ void send_going_away (ARDOUR::Redirect*);
+ void ins_changed (ARDOUR::IOChange, void*);
+ void outs_changed (ARDOUR::IOChange, void*);
+};
+
+class SendUIWindow : public Gtk::Window
+{
+ public:
+ SendUIWindow(ARDOUR::Send&, ARDOUR::Session&);
+ ~SendUIWindow();
+
+ SendUI* ui;
+
+ private:
+ Gtk::VBox vpacker;
+ Gtk::HBox hpacker;
+
+ void send_going_away (ARDOUR::Redirect*);
+};
+
+#endif /* __ardour_gtk_send_ui_h__ */
+
+
diff --git a/gtk2_ardour/splash.ppm b/gtk2_ardour/splash.ppm
new file mode 100644
index 0000000000..850f4072f7
--- /dev/null
+++ b/gtk2_ardour/splash.ppm
@@ -0,0 +1,32 @@
+P6
+# CREATOR: The GIMP's PNM Filter Version 1.0
+321 216
+255
+fffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333DDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUffffffUUUDDD333UUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUffffffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333DDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUffffffUUUDDD333UUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUffffffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333DDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUwwwUUUUUUDDDDDDDDDfffUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUwwwUUUUUUDDDDDDDDDfffUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUU333DDDUUUUUUUUUUUUUUUfffUUUfffUUUDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUU333UUUfffDDDfffDDDDDDUUUfffUUUfffDDDUUUDDDUUUUUUfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUU333DDDUUUUUUUUUUUUUUUfffUUUfffUUUDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUU333UUUfffDDDfffDDDDDDUUUfffUUUfffDDDUUUDDDUUUUUUfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUfffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUDDDDDDDDDUUU333DDD333UUU333UUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDDDD333DDDUUUDDDUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUDDDDDDDDDUUU333DDD333UUU333UUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDDDD333DDDUUUDDDUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDfffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUfffUUUUUUDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333DDDDDD333UUUDDDUUUDDDUUUDDDUUUDDDUUU333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDfff333DDDDDDDDDDDDDDDUUUUUUUUUfffUUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333UUUUUUUUUUUUfffUUUUUUUUUfffffffffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUfffUUUUUUDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333DDDDDD333UUUDDDUUUDDDUUUDDDUUUDDDUUU333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDfff333DDDDDDDDDDDDDDDUUUUUUUUUfffUUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333UUUUUUUUUUUUfffUUUUUUUUUfffffffffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUfffUUUUUUDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333UUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUU333UUUDDDDDD333DDDDDD333333UUUUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDfffDDDDDDUUUffffffUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUU333UUUDDDDDD333DDDDDD333333UUUUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDfffDDDDDDUUUffffffUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUfffDDDDDDUUUfffUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUfffUUUUUUDDDUUUDDDfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUfffDDDDDDUUUfffUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUfffUUUUUUDDDUUUDDDfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDD333DDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDDDDDDDDDDDUUU333DDD333fffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDD333DDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDDDDDDDDDDDUUU333DDD333fffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDUUUDDDfffDDDUUUDDD333UUUDDD333DDDDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUU333333DDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDUUUDDDfffDDDUUUDDD333UUUDDD333DDDDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUU333333DDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUfffUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUU333UUUUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUUUUUUUUUU333DDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUfffUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUU333UUUUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUUUUUUUUUU333DDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUffffffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUfffDDDUUUUUUDDDUUUUUU333DDDUUUUUUfffUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUU333DDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUffffffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUfffDDDUUUUUUDDDUUUUUU333DDDUUUUUUfffUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUU333DDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUffffffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDfffUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUDDD333DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDD333DDD333DDDUUUDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDfffUUUDDDUUUUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUUUUUUUfffDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDfffUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUDDD333DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDD333DDD333DDDUUUDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDfffUUUDDDUUUUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUUUUUUUfffDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDfffUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUDDD333DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDD333DDD333DDDUUUDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDDDDDDDfffDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDDUUUUUUUUUDDDDDD333DDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUffffffUUUUUUfffUUUUUUUUUUUUUUUfffUUUfffDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUffffffUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDDUUUUUUUUUDDDDDD333DDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUffffffUUUUUUfffUUUUUUUUUUUUUUUfffUUUfffDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUffffffUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDD333DDD333UUUUUUUUUDDDUUUUUUUUUUUUUUU333UUU333333DDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDD333DDDUUUDDD333DDDDDD333DDDDDDDDDfffUUUUUUUUUUUUffffffUUUUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDUUUDDDUUUDDDffffffUUUUUUUUUUUUfffDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDD333DDD333UUUUUUUUUDDDUUUUUUUUUUUUUUU333UUU333333DDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDD333DDDUUUDDD333DDDDDD333DDDDDDDDDfffUUUUUUUUUUUUffffffUUUUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDUUUDDDUUUDDDffffffUUUUUUUUUUUUfffDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDD333DDD333UUUUUUUUUDDDUUUUUUUUUUUUUUU333UUU333333DDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDD333DDDUUU333UUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDD333UUUDDDDDDUUUfffDDDDDDUUU333DDDDDDDDDUUUDDDUUUUUU333DDDfffUUUfffUUUDDDUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDUUU333UUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDD333UUUDDDDDDUUUfffDDDDDDUUU333DDDDDDDDDUUUDDDUUUUUU333DDDfffUUUfffUUUDDDUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDUUU333UUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUU333UUUDDDDDD333DDDUUUUUUUUUfffDDDDDDUUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDD333DDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUU333DDDUUUUUUfffUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDffffffUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUfffUUUUUUDDDfffUUUUUUDDDUUUUUUDDDfffDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUU333UUUDDDDDD333DDDUUUUUUUUUfffDDDDDDUUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDD333DDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUU333DDDUUUUUUfffUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDffffffUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUfffUUUUUUDDDfffUUUUUUDDDUUUUUUDDDfffDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUU333UUUDDDDDD333DDDUUUUUUUUUfffDDDDDDUUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDD333DDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDfffUUUDDDDDDUUUDDDUUUUUUfffUUUDDD333333DDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUDDDUUUDDDDDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUfffUUUfffUUUDDDDDDfffUUUDDDDDDUUUDDDUUUUUUfffUUUDDD333333DDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUDDDUUUDDDDDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUfffUUUfffUUUDDDDDDfffUUUDDDDDDUUUDDDUUUUUUfffUUUDDD333333DDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDDDDUUU333DDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDD333DDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUUUU333UUU333DDDDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUfffDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDDDDUUU333DDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDD333DDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUUUU333UUU333DDDDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUfffDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDDDDUUU333DDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDD333DDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDD333DDD333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDfffUUUDDDUUUDDDDDDDDDDDDDDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDD333DDD333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDfffUUUDDDUUUDDDDDDDDDDDDDDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDD333DDD333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDD333DDDDDDDDDUUUDDDUUUUUUDDDDDD333UUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUUUUffffffUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDD333DDDDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffUUUUUU333UUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUU333333DDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUDDDUUUUUUDDDDDD333UUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUUUUffffffUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDD333DDDDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffUUUUUU333UUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUU333333DDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUDDDUUUUUUDDDDDD333UUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUUUUffffffUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDfffDDDDDDDDDDDDDDDUUUDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDfffDDDUUUDDDDDDDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUDDD333DDDDDDUUUUUUfffUUUUUUUUUfff333DDDUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDfffDDDDDDDDDDDDDDDpppDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDfffDDDUUUDDDDDDDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUDDD333DDDDDDUUUUUUfffUUUUUUUUUfff333DDDUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDfffDDDDDDDDDDDDDDDUUUDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333333UUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDfffUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDD333UUUUUUDDDDDDUUU333DDDDDDDDDDDD333DDDUUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDfffDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUU333DDDDDDDDD333333UUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUVVVhhhjjjîîîDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDfffUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDD333UUUUUUDDDDDDUUU333DDDDDDDDDDDD333DDDUUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDfffDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUU333DDDDDDDDD333333UUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDfffUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDD333333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDD333333DDDDDDDDDDDDDDDfffDDDUUUUUUDDD333DDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUU333DDDUUU333333DDDUUUDDDDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDD333333UUUiiiuuuqqqoooppp†††———»»»äääDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDD333333DDDDDDDDDDDDDDDfffDDDUUUUUUDDD333DDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUU333DDDUUU333333DDDUUUDDDDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDD333333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDD333333DDDDDDDDDDDDDDDfffDDDUUUUUUDDD333DDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDD333333DDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333UUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDD333333UUUUUUfffUUUDDD333DDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333DDD333UUUUUU333DDDDDD333UUUUUUffffffDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDD333333DDDWWWrrršššsssWWW///444ŸŸŸ´´´´´´ßßß¿¿¿UUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDD333333UUUUUUfffUUUDDD333DDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333DDD333UUUUUU333DDDDDD333UUUUUUffffffDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDD333333DDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333UUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDD333333UUUUUUfffUUUDDD333DDDDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDDDDDDD333UUUUUUUUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDUUUUUUDDDDDD333UUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUU333UUUDDDDDDUUUUUU333DDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333DDDDDDUUUDDDfffUUUfffDDDDDDUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUfffUUUUUUUUUUUUmmm´´´´´´ðð𜜜UUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDUUUUUUDDDDDD333UUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUU333UUUDDDDDDUUUUUU333DDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333DDDDDDUUUDDDfffUUUfffDDDDDDUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDDDDDDD333UUUUUUUUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333DDDDDDDDDDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDfffUUUUUUUUUDDD333DDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDD333UUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDD333DDD333DDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUfffUUUfffUUUDDDDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUUUUUUUDDD&&&===´´´´´´ööö‹‹‹DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333DDDDDDDDDDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDfffUUUUUUUUUDDD333DDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDD333UUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDD333DDD333DDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUfffUUUfffUUUDDDDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333DDDDDDDDDDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDfffUUUUUUUUUDDD333UUUDDD333UUUDDDfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDD333DDDUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUfffUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDD333UUUDDDfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDD333---$$$´´´´´´÷÷÷gggDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUfffUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDD333UUUDDDfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDD333DDDUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDfffffffffDDDDDDUUUUUUDDD333DDDUUUDDDDDDfffUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDfffUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUfff333UUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUDDD"""DDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDfffffffffDDDDDDUUUUUUDDD333DDD999888´´´¿¿¿öööDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDfffUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUfff333UUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUDDD"""DDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDfffffffffDDDDDDUUUUUUDDD333DDDUUUDDDDDDfffUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDfffUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffPPP´´´ÏÏÏÒÒÒDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDD333DDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDD333DDDUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUeee´´´æææ»»»DDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDD333DDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDD333DDDUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDfffUUUfffUUUUUUDDDfffDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUzzz´´´ðð𜜜DDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDfffUUUfffUUUUUUDDDfffDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDD333DDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUU333UUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDUUUUUUfffUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDD
+
+
+•••´´´ööö‹‹‹UUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDD333DDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUU333UUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDUUUUUUfffUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDDDDDDDDUUUUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUU333333DDDUUUDDDDDDDDD333333DDD333DDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUU333UUUfffUUUUUUDDD333333DDD333UUUUUUDDDDDDDDDUUUfffUUUUUUDDDDDDDDDDDDUUUUUUDDDfffDDDDDDUUUUUUDDDDDDUUUDDDDDD333UUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333DDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333UUUUUUUUU333DDDUUUUUUUUUDDDDDDUUUUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUU
+
+
+•••´´´ööö‹‹‹UUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD999´´´ÏÏÏÔÔÔUUUlll›››UUUUUUDDD333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDDDDUUU333DDD333UUUDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfff333DDDUUUUUUUUUDDDUUUfffUUUUUUUUU333ffffffDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDfff333DDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDDDDUUUDDD333DDD333DDDDDDUUUDDDDDDDDD000%%%………ÚÚÚžžž333DDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDD
+
+
+¦¦¦¿¿¿ðððWWWUUUDDDfffDDDDDDUUUDDDDDDUUUDDDDDDUUUUUU
+
+
+´´´ïïŠUUUDDDDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDD///???´´´ùùù€€€DDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDD•••´´´ãããÂÂÂUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDD555 ´´´´´´öööDDDUUUUUUDDDDDDUUUUUUDDDUUUUUU---///´´´îîî®®®DDDDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDDDD333UUU„„„´´´øøøDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUfffUUULLL´´´¿¿¿óóóDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUU333DDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDfffDDDfffUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDDUUUDDDUUU333333333DDDUUUfffUUUUUUUUUUUUDDDDDDDDD333333DDDDDD333DDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUfffDDD|||´´´éé饥¥DDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDD---´´´ÔÔÔ»»»UUUDDDUUUUUUUUU333DDDDDDUUUDDDDDDDDDUUUUUUUUUUUU```´´´ïïï›››fffDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUBBB­­­¹¹¹õõõWWWUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDDUUU```´´´÷÷÷xxxDDD333DDDDDDDDDUUUDDDUUU333333333DDD
+
+
+´´´ñññfffDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDD
+
+
+´´´èè踸¸DDD333DDDDDDUUUUUUUUUDDDDDDDDDUUUDDDeee´´´´´´úúúDDD333UUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDLLL­­­ââ⢢¢UUUUUUUUUfffDDDDDDUUUDDDDDDDDDDDD999###´´´ãããÂÂÂUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUDDD333555'''­­­´´´úúú———fffDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUfffUUU
+
+
+•••´´´õõõ€€€DDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDAAAAAA{{{•••´´´´´´ùùùUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUfff```´´´ñññUUU333DDDDDDUUUDDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDfffDDDUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDfffUUUUUUUUUUUUDDD333DDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDfffUUUUUUUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDD333DDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDD333fffUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUU333333DDDDDD333DDDDDDUUUDDDUUUUUUUUUUUUPPP´´´´´´úúúŒŒŒUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDD888<<<™™™ŸŸŸ´´´èèèÃÃÃUUUDDDUUUDDDDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUU===´´´´´´úúúDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUU
+
+
+SSSªªª´´´ÝÝÝçç爈ˆUUUUUUUUUDDDUUU]]]˜˜˜dddUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDQQQ´´´´´´´´´ÅÅÅÚÚÚÓÓÓÍÍÍÉÉÉ”””TTTUUUDDDDDDDDDDDDDDDUUU[[[´´´´´´ÌÌÌßßßßßßÒÒÒ‘‘‘jjjUUUUUUDDDUUUUUUUUUfffUUUUUUUUU
+
+
+NNN•••´´´¹¹¹ÉÉÉÓÓÓÃÃߟŸsss___DDDDDDDDDDDDDDDDDDUUUHHHŸŸŸÃÃþ¾¾›››ggg[[[DDDDDDDDDfffUUUDDDUUUUUUUUUfff///ZZZ±±±£££fffDDDDDDDDDUUUDDDfffDDDUUUDDDUUUDDDDDD333UUUDDDBBBnnnŸŸŸ´´´¿¿¿ÏÏÏÐÐп¿¿ŒŒŒpppTTTDDDDDD333UUUDDDDDD===
diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc
new file mode 100644
index 0000000000..021da1626b
--- /dev/null
+++ b/gtk2_ardour/streamview.cc
@@ -0,0 +1,921 @@
+#include <cmath>
+
+#include <gtk--.h>
+
+#include <gtkmmext/gtk_ui.h>
+
+#include <ardour/audioplaylist.h>
+#include <ardour/audioregion.h>
+#include <ardour/diskstream.h>
+#include <ardour/audio_track.h>
+#include <ardour/playlist_templates.h>
+#include <ardour/source.h>
+
+#include "streamview.h"
+#include "regionview.h"
+#include "audio_time_axis.h"
+#include "canvas-waveview.h"
+#include "canvas-simplerect.h"
+#include "region_selection.h"
+#include "selection.h"
+#include "public_editor.h"
+#include "ardour_ui.h"
+#include "crossfade_view.h"
+#include "rgb_macros.h"
+#include "extra_bind.h"
+#include "gui_thread.h"
+
+using namespace ARDOUR;
+using namespace Editing;
+
+StreamView::StreamView (AudioTimeAxisView& tv)
+ : _trackview (tv)
+{
+ region_color = _trackview.color();
+ crossfades_visible = true;
+
+ if (tv.is_audio_track()) {
+ /* TRACK */
+ //stream_base_color = RGBA_TO_UINT (222,223,218,255);
+ stream_base_color = color_map[cAudioTrackBase];
+ } else {
+ /* BUS */
+ //stream_base_color = RGBA_TO_UINT (230,226,238,255);
+ stream_base_color = color_map[cAudioBusBase];
+ }
+
+ /* set_position() will position the group */
+
+ canvas_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(_trackview.canvas_display),
+ gtk_canvas_group_get_type (),
+ NULL);
+
+ canvas_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 1000000.0,
+ "y2", (double) tv.height,
+ "outline_color_rgba", color_map[cAudioTrackOutline],
+ /* outline ends and bottom */
+ "outline_what", (guint32) (0x1|0x2|0x8),
+ "fill_color_rgba", stream_base_color,
+ NULL);
+
+ gtk_signal_connect (GTK_OBJECT(canvas_rect), "event",
+ (GtkSignalFunc) PublicEditor::canvas_stream_view_event, &_trackview);
+
+ _samples_per_unit = _trackview.editor.get_current_zoom();
+ _amplitude_above_axis = 1.0;
+
+ if (_trackview.is_audio_track()) {
+ _trackview.audio_track()->diskstream_changed.connect (slot (*this, &StreamView::diskstream_changed));
+ _trackview.session().TransportStateChange.connect (slot (*this, &StreamView::transport_changed));
+ _trackview.get_diskstream()->record_enable_changed.connect (slot (*this, &StreamView::rec_enable_changed));
+ _trackview.session().RecordEnabled.connect (slot (*this, &StreamView::sess_rec_enable_changed));
+ _trackview.session().RecordDisabled.connect (slot (*this, &StreamView::sess_rec_enable_changed));
+ }
+
+ rec_updating = false;
+ rec_active = false;
+ use_rec_regions = tv.editor.show_waveforms_recording ();
+ last_rec_peak_frame = 0;
+}
+
+StreamView::~StreamView ()
+{
+ undisplay_diskstream ();
+ gtk_object_destroy (GTK_OBJECT(canvas_group));
+}
+
+void
+StreamView::attach ()
+{
+ if (_trackview.is_audio_track()) {
+ display_diskstream (_trackview.get_diskstream());
+ }
+}
+
+int
+StreamView::set_position (gdouble x, gdouble y)
+
+{
+ gtk_canvas_item_set (canvas_group, "x", x, "y", y, NULL);
+ return 0;
+}
+
+int
+StreamView::set_height (gdouble h)
+{
+ /* limit the values to something sane-ish */
+
+ if (h < 10.0 || h > 1000.0) {
+ return -1;
+ }
+
+ gtk_object_set (GTK_OBJECT(canvas_rect), "y2", h, NULL);
+
+ for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ (*i)->set_height (h);
+ }
+
+ for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+ (*i)->set_height (h);
+ }
+
+ for (vector<RecBoxInfo>::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) {
+ RecBoxInfo &recbox = (*i);
+ gtk_object_set (GTK_OBJECT( recbox.rectangle ), "y2", h - 1, NULL);
+ }
+
+ return 0;
+}
+
+int
+StreamView::set_samples_per_unit (gdouble spp)
+{
+ AudioRegionViewList::iterator i;
+
+ if (spp < 1.0) {
+ return -1;
+ }
+
+ _samples_per_unit = spp;
+
+ for (i = region_views.begin(); i != region_views.end(); ++i) {
+ (*i)->set_samples_per_unit (spp);
+ }
+
+ for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
+ (*xi)->set_samples_per_unit (spp);
+ }
+
+ for (vector<RecBoxInfo>::iterator xi = rec_rects.begin(); xi != rec_rects.end(); ++xi) {
+ RecBoxInfo &recbox = (*xi);
+
+ gdouble xstart = _trackview.editor.frame_to_pixel ( recbox.start );
+ gdouble xend = _trackview.editor.frame_to_pixel ( recbox.start + recbox.length );
+
+ gtk_canvas_item_set (recbox.rectangle, "x1", xstart, NULL);
+ gtk_canvas_item_set (recbox.rectangle, "x2", xend, NULL);
+ }
+
+ return 0;
+}
+
+int
+StreamView::set_amplitude_above_axis (gdouble app)
+
+{
+ AudioRegionViewList::iterator i;
+
+ if (app < 1.0) {
+ return -1;
+ }
+
+ _amplitude_above_axis = app;
+
+ for (i = region_views.begin(); i != region_views.end(); ++i) {
+ (*i)->set_amplitude_above_axis (app);
+ }
+
+ return 0;
+}
+
+void
+StreamView::add_region_view (Region *r)
+{
+ add_region_view_internal (r, true);
+}
+
+void
+StreamView::add_region_view_internal (Region *r, bool wait_for_waves)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::add_region_view), r));
+
+ AudioRegion* region = dynamic_cast<AudioRegion*> (r);
+
+ if (region == 0) {
+ return;
+ }
+
+ AudioRegionView *region_view;
+ list<AudioRegionView *>::iterator i;
+
+ for (i = region_views.begin(); i != region_views.end(); ++i) {
+ if (&(*i)->region == region) {
+
+ /* great. we already have a AudioRegionView for this Region. use it again.
+ */
+
+ (*i)->set_valid (true);
+ return;
+ }
+ }
+
+ region_view = new AudioRegionView (GTK_CANVAS_GROUP(canvas_group),
+ _trackview,
+ *region,
+ _samples_per_unit,
+ _amplitude_above_axis,
+ region_color,
+ wait_for_waves);
+
+ region_views.push_front (region_view);
+
+ /* follow global waveform setting */
+
+ region_view->set_waveform_visible(_trackview.editor.show_waveforms());
+
+ /* catch regionview going away */
+
+ region->GoingAway.connect (slot (*this, &StreamView::remove_region_view));
+
+ AudioRegionViewAdded (region_view);
+}
+
+void
+StreamView::remove_region_view (Region *r)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::remove_region_view), r));
+
+ AudioRegion* ar = dynamic_cast<AudioRegion*> (r);
+
+ if (ar == 0) {
+ return;
+ }
+
+ for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ if (&((*i)->region) == ar) {
+ delete *i;
+ region_views.erase (i);
+ break;
+ }
+ }
+
+ for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) {
+ list<CrossfadeView*>::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ if ((*i)->crossfade.involves (*ar)) {
+ delete *i;
+ crossfade_views.erase (i);
+ }
+
+ i = tmp;
+ }
+}
+
+void
+StreamView::remove_rec_region (Region *r)
+{
+ ENSURE_GUI_THREAD(bind (slot (*this, &StreamView::remove_rec_region), r));
+
+ if (!Gtkmmext::UI::instance()->caller_is_gui_thread()) {
+ fatal << "region deleted from non-GUI thread!" << endmsg;
+ /*NOTREACHED*/
+ }
+
+ AudioRegion* ar = dynamic_cast<AudioRegion*> (r);
+
+ if (ar == 0) {
+ return;
+ }
+
+ for (list<AudioRegion *>::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) {
+ if (*i == ar) {
+ rec_regions.erase (i);
+ break;
+ }
+ }
+}
+
+void
+StreamView::undisplay_diskstream ()
+{
+ for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ delete *i;
+ }
+
+ for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+ delete *i;
+ }
+
+ region_views.clear();
+ crossfade_views.clear ();
+}
+
+void
+StreamView::display_diskstream (DiskStream *ds)
+{
+ playlist_change_connection.disconnect();
+ playlist_changed (ds);
+ playlist_change_connection = ds->PlaylistChanged.connect (bind (slot (*this, &StreamView::playlist_changed), ds));
+}
+
+void
+StreamView::playlist_modified ()
+{
+ ENSURE_GUI_THREAD (slot (*this, &StreamView::playlist_modified));
+
+ /* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked
+ correctly.
+ */
+
+ for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ region_layered (*i);
+ }
+
+ for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+ gtk_canvas_item_raise_to_top ((*i)->get_canvas_group());
+ }
+}
+
+void
+StreamView::playlist_changed (DiskStream *ds)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::playlist_changed), ds));
+
+ /* disconnect from old playlist */
+
+ for (vector<SigC::Connection>::iterator i = playlist_connections.begin(); i != playlist_connections.end(); ++i) {
+ (*i).disconnect();
+ }
+
+ playlist_connections.clear();
+ undisplay_diskstream ();
+
+ /* draw it */
+
+ redisplay_diskstream ();
+
+ /* catch changes */
+
+ playlist_connections.push_back (ds->playlist()->RegionAdded.connect (slot (*this, &StreamView::add_region_view)));
+ playlist_connections.push_back (ds->playlist()->RegionRemoved.connect (slot (*this, &StreamView::remove_region_view)));
+ playlist_connections.push_back (ds->playlist()->StateChanged.connect (slot (*this, &StreamView::playlist_state_changed)));
+ playlist_connections.push_back (ds->playlist()->Modified.connect (slot (*this, &StreamView::playlist_modified)));
+ playlist_connections.push_back (ds->playlist()->NewCrossfade.connect (slot (*this, &StreamView::add_crossfade)));
+}
+
+void
+StreamView::add_crossfade (Crossfade *crossfade)
+{
+ AudioRegionView* lview = 0;
+ AudioRegionView* rview = 0;
+
+ ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::add_crossfade), crossfade));
+
+ /* first see if we already have a CrossfadeView for this Crossfade */
+
+ for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+ if (&(*i)->crossfade == crossfade) {
+ if (!crossfades_visible) {
+ (*i)->hide();
+ } else {
+ (*i)->show ();
+ }
+ (*i)->set_valid (true);
+ return;
+ }
+ }
+
+ /* create a new one */
+
+ for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ if (!lview && &((*i)->region) == &crossfade->out()) {
+ lview = *i;
+ }
+ if (!rview && &((*i)->region) == &crossfade->in()) {
+ rview = *i;
+ }
+ }
+
+ CrossfadeView *cv = new CrossfadeView (GTK_CANVAS_GROUP(_trackview.canvas_display),
+ _trackview,
+ *crossfade,
+ _samples_per_unit,
+ region_color,
+ *lview, *rview);
+
+ crossfade->Invalidated.connect (slot (*this, &StreamView::remove_crossfade));
+ crossfade_views.push_back (cv);
+
+ if (!crossfades_visible) {
+ cv->hide ();
+ }
+}
+
+void
+StreamView::remove_crossfade (Crossfade *xfade)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::remove_crossfade), xfade));
+
+ for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+ if (&(*i)->crossfade == xfade) {
+ delete *i;
+ crossfade_views.erase (i);
+ break;
+ }
+ }
+}
+
+void
+StreamView::playlist_state_changed (Change ignored)
+{
+ ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::playlist_state_changed), ignored));
+
+ redisplay_diskstream ();
+}
+
+void
+StreamView::redisplay_diskstream ()
+{
+ list<AudioRegionView *>::iterator i, tmp;
+ list<CrossfadeView*>::iterator xi, tmpx;
+
+ for (i = region_views.begin(); i != region_views.end(); ++i) {
+ (*i)->set_valid (false);
+ }
+
+ for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) {
+ (*xi)->set_valid (false);
+ if ((*xi)->visible()) {
+ (*xi)->show ();
+ }
+ }
+
+ if (_trackview.is_audio_track()) {
+ _trackview.get_diskstream()->playlist()->foreach_region (this, &StreamView::add_region_view);
+ _trackview.get_diskstream()->playlist()->foreach_crossfade (this, &StreamView::add_crossfade);
+ }
+
+ for (i = region_views.begin(); i != region_views.end(); ) {
+ tmp = i;
+ tmp++;
+
+ if (!(*i)->is_valid()) {
+ delete *i;
+ region_views.erase (i);
+ }
+
+ i = tmp;
+ }
+
+ for (xi = crossfade_views.begin(); xi != crossfade_views.end();) {
+ tmpx = xi;
+ tmpx++;
+
+ if (!(*xi)->valid()) {
+ delete *xi;
+ crossfade_views.erase (xi);
+ }
+
+ xi = tmpx;
+ }
+
+ /* now fix layering */
+
+ playlist_modified ();
+}
+
+void
+StreamView::diskstream_changed (void *src_ignored)
+{
+ AudioTrack *at;
+
+ if ((at = _trackview.audio_track()) != 0) {
+ DiskStream& ds = at->disk_stream();
+ /* XXX grrr: when will SigC++ allow me to bind references? */
+ Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &StreamView::display_diskstream), &ds));
+ } else {
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &StreamView::undisplay_diskstream));
+ }
+}
+
+void
+StreamView::apply_color (GdkColor& color, ColorTarget target)
+
+{
+ list<AudioRegionView *>::iterator i;
+
+ switch (target) {
+ case RegionColor:
+ region_color = color;
+ for (i = region_views.begin(); i != region_views.end(); ++i) {
+ (*i)->set_color (region_color);
+ }
+ // stream_base_color = RGBA_TO_UINT (color.red/256, color.green/256, color.blue/256, 255);
+ // gtk_canvas_item_set (canvas_rect, "fill_color_rgba", stream_base_color, NULL);
+ break;
+
+ case StreamBaseColor:
+ // stream_base_color = RGBA_TO_UINT (color.red/256, color.green/256, color.blue/256, 255);
+ // gtk_canvas_item_set (canvas_rect, "fill_color_rgba", stream_base_color, NULL);
+ break;
+ }
+}
+
+void
+StreamView::set_show_waveforms (bool yn)
+{
+ for (list<AudioRegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ (*i)->set_waveform_visible (yn);
+ }
+}
+
+void
+StreamView::set_selected_regionviews (AudioRegionSelection& regions)
+{
+ bool selected;
+
+ for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+
+ selected = false;
+
+ for (AudioRegionSelection::iterator ii = regions.begin(); ii != regions.end(); ++ii) {
+ if (*i == *ii) {
+ selected = true;
+ }
+ }
+
+ (*i)->set_selected (selected, this);
+ }
+}
+
+void
+StreamView::get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable*>& results)
+{
+ for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ if ((*i)->region.coverage(start, end) != OverlapNone) {
+ results.push_back (*i);
+ }
+ }
+}
+
+void
+StreamView::get_inverted_selectables (Selection& sel, list<Selectable*>& results)
+{
+ for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ if (!sel.audio_regions.contains (*i)) {
+ results.push_back (*i);
+ }
+ }
+}
+
+void
+StreamView::set_waveform_shape (WaveformShape shape)
+{
+ for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ (*i)->set_waveform_shape (shape);
+ }
+}
+
+void
+StreamView::region_layered (AudioRegionView* rv)
+{
+ gtk_canvas_item_lower_to_bottom (rv->get_canvas_group());
+
+ /* don't ever leave it at the bottom, since then it doesn't
+ get events - the parent group does instead ...
+ */
+
+ gtk_canvas_item_raise (rv->get_canvas_group(), rv->region.layer() + 1);
+}
+
+void
+StreamView::rec_enable_changed (void *src)
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &StreamView::setup_rec_box));
+}
+
+void
+StreamView::sess_rec_enable_changed ()
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &StreamView::setup_rec_box));
+}
+
+void
+StreamView::transport_changed()
+{
+ Gtkmmext::UI::instance()->call_slot (slot (*this, &StreamView::setup_rec_box));
+}
+
+void
+StreamView::setup_rec_box ()
+{
+ // cerr << _trackview.name() << " streamview SRB\n";
+
+ if (_trackview.session().transport_rolling()) {
+
+ // cerr << "\trolling\n";
+
+ if (!rec_active
+ && _trackview.session().record_status() == Session::Recording
+ && _trackview.get_diskstream()->record_enabled()) {
+
+ if (use_rec_regions && rec_regions.size() == rec_rects.size()) {
+ /* add a new region, but don't bother if they set use_rec_regions mid-record */
+
+ AudioRegion::SourceList sources;
+
+ for (list<SigC::Connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
+ (*prc).disconnect();
+ }
+ peak_ready_connections.clear();
+
+ for (uint32_t n=0; n < _trackview.get_diskstream()->n_channels(); ++n) {
+ Source *src = (Source *) _trackview.get_diskstream()->write_source (n);
+ if (src) {
+ sources.push_back (src);
+ peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (slot (*this, &StreamView::rec_peak_range_ready), src)));
+ }
+ }
+
+ // handle multi
+
+ jack_nframes_t start = 0;
+ if (rec_regions.size() > 0) {
+ start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1);
+ }
+
+ AudioRegion * region = new AudioRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false);
+ region->set_position (_trackview.session().transport_frame(), this);
+ rec_regions.push_back (region);
+ /* catch it if it goes away */
+ region->GoingAway.connect (slot (*this, &StreamView::remove_rec_region));
+
+ /* we add the region later */
+ }
+
+ /* start a new rec box */
+
+ AudioTrack* at;
+
+ at = _trackview.audio_track(); /* we know what it is already */
+ DiskStream& ds = at->disk_stream();
+ jack_nframes_t frame_pos = ds.current_capture_start ();
+ gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
+ gdouble xend = xstart;
+
+ GtkCanvasItem * rec_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", xstart,
+ "y1", 1.0,
+ "x2", xend,
+ "y2", (double) _trackview.height - 1,
+ "outline_color_rgba", color_map[cRecordingRectOutline],
+ "fill_color_rgba", color_map[cRecordingRectFill],
+ NULL);
+
+ RecBoxInfo recbox;
+ recbox.rectangle = rec_rect;
+ recbox.start = _trackview.session().transport_frame();
+ recbox.length = 0;
+
+ rec_rects.push_back (recbox);
+
+ screen_update_connection.disconnect();
+ screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (slot (*this, &StreamView::update_rec_box));
+ rec_updating = true;
+ rec_active = true;
+
+ } else if (rec_active &&
+ (_trackview.session().record_status() != Session::Recording ||
+ !_trackview.get_diskstream()->record_enabled())) {
+
+ screen_update_connection.disconnect();
+ rec_active = false;
+ rec_updating = false;
+
+ }
+
+ } else {
+
+ // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl;
+
+ if (!rec_rects.empty() || !rec_regions.empty()) {
+
+ /* disconnect rapid update */
+ screen_update_connection.disconnect();
+
+ for (list<SigC::Connection>::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) {
+ (*prc).disconnect();
+ }
+ peak_ready_connections.clear();
+
+ rec_updating = false;
+ rec_active = false;
+ last_rec_peak_frame = 0;
+
+ /* remove temp regions */
+ for (list<AudioRegion*>::iterator iter=rec_regions.begin(); iter != rec_regions.end(); )
+ {
+ list<AudioRegion*>::iterator tmp;
+
+ tmp = iter;
+ ++tmp;
+
+ /* this will trigger the remove_region_view */
+ delete *iter;
+
+ iter = tmp;
+ }
+
+ rec_regions.clear();
+
+ // cerr << "\tclear " << rec_rects.size() << " rec rects\n";
+
+
+ /* transport stopped, clear boxes */
+ for (vector<RecBoxInfo>::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) {
+ RecBoxInfo &rect = (*iter);
+ gtk_object_destroy (GTK_OBJECT(rect.rectangle));
+ }
+
+ rec_rects.clear();
+
+ }
+ }
+}
+
+
+void
+StreamView::update_rec_box ()
+{
+ /* only update the last box */
+ if (rec_active && rec_rects.size() > 0) {
+ RecBoxInfo & rect = rec_rects.back();
+ jack_nframes_t at = _trackview.get_diskstream()->current_capture_end();
+
+ rect.length = at - rect.start;
+
+ gdouble xstart = _trackview.editor.frame_to_pixel ( rect.start );
+ gdouble xend = _trackview.editor.frame_to_pixel ( at );
+
+ gtk_canvas_item_set (rect.rectangle, "x1", xstart, NULL);
+ gtk_canvas_item_set (rect.rectangle, "x2", xend, NULL);
+ }
+}
+
+AudioRegionView*
+StreamView::find_view (const AudioRegion& region)
+{
+ for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+
+ if (&(*i)->region == &region) {
+ return *i;
+ }
+ }
+ return 0;
+}
+
+void
+StreamView::foreach_regionview (SigC::Slot1<void,AudioRegionView*> slot)
+{
+ for (list<AudioRegionView*>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ slot (*i);
+ }
+}
+
+void
+StreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void))
+{
+ for (list<CrossfadeView*>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+ ((*i)->*pmf) ();
+ }
+}
+
+void
+StreamView::rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, Source * src)
+{
+ // this is called from the peak building thread
+
+ ENSURE_GUI_THREAD(bind (slot (*this, &StreamView::rec_peak_range_ready), start, cnt, src));
+
+ if (rec_peak_ready_map.size() == 0 || start+cnt > last_rec_peak_frame) {
+ last_rec_peak_frame = start + cnt;
+ }
+
+ rec_peak_ready_map[src] = true;
+
+ if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) {
+ this->update_rec_regions ();
+ rec_peak_ready_map.clear();
+ }
+}
+
+void
+StreamView::update_rec_regions ()
+{
+ if (use_rec_regions) {
+
+ uint32_t n = 0;
+
+ for (list<AudioRegion*>::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) {
+
+ list<AudioRegion*>::iterator tmp;
+
+ tmp = iter;
+ ++tmp;
+
+ if ((GTK_OBJECT_FLAGS(GTK_OBJECT(rec_rects[n].rectangle)) & GTK_CANVAS_ITEM_VISIBLE) == 0) {
+ /* rect already hidden, this region is done */
+ iter = tmp;
+ continue;
+ }
+
+ AudioRegion * region = (*iter);
+ jack_nframes_t origlen = region->length();
+
+ if (region == rec_regions.back() && rec_active) {
+
+ if (last_rec_peak_frame > region->start()) {
+
+ jack_nframes_t nlen = last_rec_peak_frame - region->start();
+
+ if (nlen != region->length()) {
+
+ region->freeze ();
+ region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
+ region->set_length (nlen, this);
+ region->thaw ("updated");
+
+ if (origlen == 1) {
+ /* our special initial length */
+ add_region_view_internal (region, false);
+ }
+
+ /* also update rect */
+ GtkCanvasItem * rect = rec_rects[n].rectangle;
+ gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length());
+ gtk_canvas_item_set (rect, "x2", xend, NULL);
+ }
+ }
+
+ } else {
+
+ jack_nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n);
+
+ if (nlen != region->length()) {
+
+ if (region->source(0).length() >= region->start() + nlen) {
+
+ region->freeze ();
+ region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this);
+ region->set_length (nlen, this);
+ region->thaw ("updated");
+
+ if (origlen == 1) {
+ /* our special initial length */
+ add_region_view_internal (region, false);
+ }
+
+ /* also hide rect */
+ GtkCanvasItem * rect = rec_rects[n].rectangle;
+ gtk_canvas_item_hide (rect);
+
+ }
+ }
+ }
+
+ iter = tmp;
+ }
+ }
+}
+
+void
+StreamView::show_all_xfades ()
+{
+ foreach_crossfadeview (&CrossfadeView::show);
+ crossfades_visible = true;
+}
+
+void
+StreamView::hide_all_xfades ()
+{
+ foreach_crossfadeview (&CrossfadeView::hide);
+ crossfades_visible = false;
+}
+
+void
+StreamView::hide_xfades_involving (AudioRegionView& rv)
+{
+ for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+ if ((*i)->crossfade.involves (rv.region)) {
+ (*i)->fake_hide ();
+ }
+ }
+}
+
+void
+StreamView::reveal_xfades_involving (AudioRegionView& rv)
+{
+ for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) {
+ if ((*i)->crossfade.involves (rv.region) && (*i)->visible()) {
+ (*i)->show ();
+ }
+ }
+}
diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h
new file mode 100644
index 0000000000..8d9162c8ab
--- /dev/null
+++ b/gtk2_ardour/streamview.h
@@ -0,0 +1,171 @@
+/*
+ Copyright (C) 2001 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_streamview_h__
+#define __ardour_streamview_h__
+
+#include <list>
+#include <map>
+#include <cmath>
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+
+#include <ardour/location.h>
+#include "enums.h"
+
+namespace ARDOUR {
+ class Route;
+ class DiskStream;
+ class Crossfade;
+ class PeakData;
+ class AudioRegion;
+ class Source;
+}
+
+struct RecBoxInfo {
+ GtkCanvasItem* rectangle;
+ jack_nframes_t start;
+ jack_nframes_t length;
+};
+
+class PublicEditor;
+class Selectable;
+class AudioTimeAxisView;
+class AudioRegionView;
+class AudioRegionSelection;
+class CrossfadeView;
+class Selection;
+
+class StreamView : public SigC::Object
+{
+ public:
+ StreamView (AudioTimeAxisView&);
+ ~StreamView ();
+
+ void set_waveform_shape (WaveformShape);
+
+ AudioTimeAxisView& trackview() { return _trackview; }
+
+ void set_zoom_all();
+
+ int set_height (gdouble);
+ int set_position (gdouble x, gdouble y);
+
+ int set_samples_per_unit (gdouble spp);
+ gdouble get_samples_per_unit () { return _samples_per_unit; }
+
+ int set_amplitude_above_axis (gdouble app);
+ gdouble get_amplitude_above_axis () { return _amplitude_above_axis; }
+
+ void set_show_waveforms (bool yn);
+ void set_show_waveforms_recording (bool yn) { use_rec_regions = yn; }
+
+ GtkCanvasItem* canvas_item() { return canvas_group; }
+
+ SigC::Signal1<void,AudioRegionView*> AudioRegionViewAdded;
+
+ enum ColorTarget {
+ RegionColor,
+ StreamBaseColor
+ };
+
+ void apply_color (GdkColor&, ColorTarget t);
+ void set_selected_regionviews (AudioRegionSelection&);
+ void get_selectables (jack_nframes_t start, jack_nframes_t end, list<Selectable* >&);
+ void get_inverted_selectables (Selection&, list<Selectable* >& results);
+ GdkColor get_region_color () const { return region_color; }
+
+ void foreach_regionview (SigC::Slot1<void,AudioRegionView*> slot);
+ void foreach_crossfadeview (void (CrossfadeView::*pmf)(void));
+
+ void attach ();
+
+ void region_layered (AudioRegionView*);
+
+ AudioRegionView* find_view (const ARDOUR::AudioRegion&);
+
+ void show_all_xfades ();
+ void hide_all_xfades ();
+ void hide_xfades_involving (AudioRegionView&);
+ void reveal_xfades_involving (AudioRegionView&);
+
+ private:
+ AudioTimeAxisView& _trackview;
+
+ GtkCanvasItem* canvas_group;
+ GtkCanvasItem* canvas_rect; /* frame around the whole thing */
+
+ typedef list<AudioRegionView* > AudioRegionViewList;
+ AudioRegionViewList region_views;
+
+ typedef list<CrossfadeView*> CrossfadeViewList;
+ CrossfadeViewList crossfade_views;
+
+ double _samples_per_unit;
+ double _amplitude_above_axis;
+
+ SigC::Connection screen_update_connection;
+ vector<RecBoxInfo> rec_rects;
+ list<ARDOUR::AudioRegion* > rec_regions;
+ bool rec_updating;
+ bool rec_active;
+ bool use_rec_regions;
+ list<SigC::Connection> peak_ready_connections;
+ jack_nframes_t last_rec_peak_frame;
+ map<ARDOUR::Source*, bool> rec_peak_ready_map;
+
+ void update_rec_box ();
+ void transport_changed();
+ void rec_enable_changed(void* src = 0);
+ void sess_rec_enable_changed();
+ void setup_rec_box ();
+ void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src);
+ void update_rec_regions ();
+
+ void add_region_view (ARDOUR::Region*);
+ void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves);
+ void remove_region_view (ARDOUR::Region* );
+ void remove_rec_region (ARDOUR::Region*);
+ void remove_audio_region_view (ARDOUR::AudioRegion* );
+ void remove_audio_rec_region (ARDOUR::AudioRegion*);
+
+ void display_diskstream (ARDOUR::DiskStream* );
+ void undisplay_diskstream ();
+ void redisplay_diskstream ();
+ void diskstream_changed (void* );
+ void playlist_state_changed (ARDOUR::Change);
+ void playlist_changed (ARDOUR::DiskStream* );
+ void playlist_modified ();
+
+ bool crossfades_visible;
+ void add_crossfade (ARDOUR::Crossfade*);
+ void remove_crossfade (ARDOUR::Crossfade*);
+
+ /* XXX why are these different? */
+
+ GdkColor region_color;
+ uint32_t stream_base_color;
+
+ vector<SigC::Connection> playlist_connections;
+ SigC::Connection playlist_change_connection;
+};
+
+#endif /* __ardour_streamview_h__ */
diff --git a/gtk2_ardour/strip_selection.h b/gtk2_ardour/strip_selection.h
new file mode 100644
index 0000000000..5204873c7a
--- /dev/null
+++ b/gtk2_ardour/strip_selection.h
@@ -0,0 +1,10 @@
+#ifndef __ardour_gtk_strip_selection_h__
+#define __ardour_gtk_strip_selection_h__
+
+#include <list>
+
+class MixerStrip;
+
+struct MixerStripSelection : list<MixerStrip*> {};
+
+#endif /* __ardour_gtk_strip_selection_h__ */
diff --git a/gtk2_ardour/tempo_dialog.cc b/gtk2_ardour/tempo_dialog.cc
new file mode 100644
index 0000000000..3428985518
--- /dev/null
+++ b/gtk2_ardour/tempo_dialog.cc
@@ -0,0 +1,333 @@
+#include <cstdio> // for snprintf, grrr
+
+#include <gtkmmext/utils.h>
+
+#include "tempo_dialog.h"
+
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace ARDOUR;
+
+TempoDialog::TempoDialog (TempoMap& map, jack_nframes_t frame, string action)
+ : ArdourDialog ("tempo dialog"),
+ bpm_frame (_("Beats per minute")),
+ ok_button (action),
+ cancel_button (_("Cancel")),
+ when_bar_label (_("Bar")),
+ when_beat_label (_("Beat")),
+ when_table (2, 2),
+ when_frame (_("Location"))
+{
+ BBT_Time when;
+ Tempo tempo (map.tempo_at (frame));
+ map.bbt_time (frame, when);
+
+ init (when, tempo.beats_per_minute(), true);
+}
+
+TempoDialog::TempoDialog (TempoSection& section, string action)
+ : ArdourDialog ("tempo dialog"),
+ bpm_frame (_("Beats per minute")),
+ ok_button (action),
+ cancel_button (_("Cancel")),
+ when_bar_label (_("Bar")),
+ when_beat_label (_("Beat")),
+ when_table (2, 2),
+ when_frame (_("Location"))
+{
+ init (section.start(), section.beats_per_minute(), section.movable());
+}
+
+void
+TempoDialog::init (const BBT_Time& when, double bpm, bool movable)
+{
+ snprintf (buf, sizeof (buf), "%.2f", bpm);
+ bpm_entry.set_text (buf);
+ bpm_entry.select_region (0, -1);
+
+ hspacer1.set_border_width (5);
+ hspacer1.pack_start (bpm_entry, false, false);
+ vspacer1.set_border_width (5);
+ vspacer1.pack_start (hspacer1, false, false);
+
+ bpm_frame.add (vspacer1);
+
+ button_box.set_border_width (10);
+ button_box.set_spacing (5);
+ button_box.set_homogeneous (true);
+ button_box.pack_start (ok_button);
+ button_box.pack_start (cancel_button);
+
+ vpacker.set_border_width (10);
+ vpacker.set_spacing (5);
+
+ if (movable) {
+ snprintf (buf, sizeof (buf), "%" PRIu32, when.bars);
+ when_bar_entry.set_text (buf);
+ snprintf (buf, sizeof (buf), "%" PRIu32, when.beats);
+ when_beat_entry.set_text (buf);
+
+ when_bar_entry.set_name ("MetricEntry");
+ when_beat_entry.set_name ("MetricEntry");
+
+ when_bar_label.set_name ("MetricLabel");
+ when_beat_label.set_name ("MetricLabel");
+
+ Gtkmmext::set_usize_to_display_given_text (when_bar_entry, "999g", 5, 7);
+ Gtkmmext::set_usize_to_display_given_text (when_beat_entry, "999g", 5, 7);
+
+ when_table.set_homogeneous (true);
+ when_table.set_row_spacings (2);
+ when_table.set_col_spacings (2);
+ when_table.set_border_width (5);
+
+ when_table.attach (when_bar_label, 0, 1, 0, 1, 0, GTK_FILL|GTK_EXPAND);
+ when_table.attach (when_bar_entry, 0, 1, 1, 2, 0, GTK_FILL|GTK_EXPAND);
+
+ when_table.attach (when_beat_label, 1, 2, 0, 1, 0, 0);
+ when_table.attach (when_beat_entry, 1, 2, 1, 2, 0, 0);
+
+ when_frame.set_name ("MetricDialogFrame");
+ when_frame.add (when_table);
+
+ vpacker.pack_start (when_frame, false, false);
+ }
+
+ vpacker.pack_start (bpm_frame, false, false);
+ vpacker.pack_start (button_box, false, false);
+
+ bpm_frame.set_name ("MetricDialogFrame");
+ bpm_entry.set_name ("MetricEntry");
+ ok_button.set_name ("MetricButton");
+ cancel_button.set_name ("MetricButton");
+
+ add (vpacker);
+ set_name ("MetricDialog");
+
+ set_keyboard_input(true);
+}
+
+double
+TempoDialog::get_bpm ()
+{
+ double bpm;
+
+ if (sscanf (bpm_entry.get_text().c_str(), "%lf", &bpm) != 1) {
+ return 0;
+ }
+
+ return bpm;
+}
+
+bool
+TempoDialog::get_bbt_time (BBT_Time& requested)
+{
+ if (sscanf (when_bar_entry.get_text().c_str(), "%" PRIu32, &requested.bars) != 1) {
+ return false;
+ }
+
+ if (sscanf (when_beat_entry.get_text().c_str(), "%" PRIu32, &requested.beats) != 1) {
+ return false;
+ }
+
+ return true;
+}
+
+
+MeterDialog::MeterDialog (TempoMap& map, jack_nframes_t frame, string action)
+ : ArdourDialog ("meter dialog"),
+ note_frame (_("Meter denominator")),
+ bpb_frame (_("Beats per bar")),
+ ok_button (action),
+ cancel_button (_("Cancel")),
+ when_bar_label (_("Bar")),
+ when_beat_label (_("Beat")),
+ when_frame (_("Location"))
+{
+ BBT_Time when;
+ frame = map.round_to_bar(frame,0);
+ Meter meter (map.meter_at(frame));
+
+ map.bbt_time (frame, when);
+ init (when, meter.beats_per_bar(), meter.note_divisor(), true);
+}
+
+MeterDialog::MeterDialog (MeterSection& section, string action)
+ : ArdourDialog ("meter dialog"),
+ note_frame (_("Meter denominator")),
+ bpb_frame (_("Beats per bar")),
+ ok_button (action),
+ cancel_button (_("Cancel")),
+ when_bar_label (_("Bar")),
+ when_beat_label (_("Beat")),
+ when_frame (_("Location"))
+{
+ init (section.start(), section.beats_per_bar(), section.note_divisor(), section.movable());
+}
+
+void
+MeterDialog::init (const BBT_Time& when, double bpb, double note_type, bool movable)
+{
+ snprintf (buf, sizeof (buf), "%.2f", bpb);
+ bpb_entry.set_text (buf);
+ bpb_entry.select_region (0, -1);
+ Gtkmmext::set_usize_to_display_given_text (bpb_entry, "999999g", 5, 5);
+
+
+ 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)"));
+
+ note_types.set_popdown_strings (strings);
+
+ if (note_type==1.0f)
+ note_types.get_entry()->set_text(_("whole (1)"));
+ else if (note_type==2.0f)
+ note_types.get_entry()->set_text(_("second (2)"));
+ else if (note_type==3.0f)
+ note_types.get_entry()->set_text(_("third (3)"));
+ else if (note_type==4.0f)
+ note_types.get_entry()->set_text(_("quarter (4)"));
+ else if (note_type==8.0f)
+ note_types.get_entry()->set_text(_("eighth (8)"));
+ else if (note_type==16.0f)
+ note_types.get_entry()->set_text(_("sixteenth (16)"));
+ else if (note_type==32.0f)
+ note_types.get_entry()->set_text(_("thirty-second (32)"));
+ else
+ note_types.get_entry()->set_text(_("quarter (4)"));
+
+ /* strings.back() just happens to be the longest one to display */
+ Gtkmmext::set_usize_to_display_given_text (*(note_types.get_entry()), strings.back(), 7, 7);
+
+ hspacer1.set_border_width (5);
+ hspacer1.pack_start (note_types, false, false);
+ vspacer1.set_border_width (5);
+ vspacer1.pack_start (hspacer1, false, false);
+
+ hspacer2.set_border_width (5);
+ hspacer2.pack_start (bpb_entry, false, false);
+ vspacer2.set_border_width (5);
+ vspacer2.pack_start (hspacer2, false, false);
+
+ note_frame.add (vspacer1);
+ bpb_frame.add (vspacer2);
+
+ button_box.set_border_width (10);
+ button_box.set_spacing (5);
+ button_box.set_homogeneous (true);
+ button_box.pack_start (ok_button);
+ button_box.pack_start (cancel_button);
+
+ vpacker.set_border_width (10);
+ vpacker.set_spacing (5);
+
+ if (movable) {
+ snprintf (buf, sizeof (buf), "%" PRIu32, when.bars);
+ when_bar_entry.set_text (buf);
+ snprintf (buf, sizeof (buf), "%" PRIu32, when.beats);
+ when_beat_entry.set_text (buf);
+
+ when_bar_entry.set_name ("MetricEntry");
+ when_beat_entry.set_name ("MetricEntry");
+
+ when_bar_label.set_name ("MetricLabel");
+ when_beat_label.set_name ("MetricLabel");
+
+ Gtkmmext::set_usize_to_display_given_text (when_bar_entry, "999g", 5, 7);
+ Gtkmmext::set_usize_to_display_given_text (when_beat_entry, "999g", 5, 7);
+
+ when_table.set_homogeneous (true);
+ when_table.set_row_spacings (2);
+ when_table.set_col_spacings (2);
+ when_table.set_border_width (5);
+
+ when_table.attach (when_bar_label, 0, 1, 0, 1, 0, GTK_FILL|GTK_EXPAND);
+ when_table.attach (when_bar_entry, 0, 1, 1, 2, 0, GTK_FILL|GTK_EXPAND);
+
+ when_table.attach (when_beat_label, 1, 2, 0, 1, 0, 0);
+ when_table.attach (when_beat_entry, 1, 2, 1, 2, 0, 0);
+
+ when_frame.set_name ("MetricDialogFrame");
+ when_frame.add (when_table);
+
+ vpacker.pack_start (when_frame, false, false);
+ }
+
+ vpacker.pack_start (bpb_frame, false, false);
+ vpacker.pack_start (note_frame, false, false);
+ vpacker.pack_start (button_box, false, false);
+
+ bpb_frame.set_name ("MetricDialogFrame");
+ note_frame.set_name ("MetricDialogFrame");
+ note_types.get_entry()->set_name ("MetricEntry");
+ bpb_entry.set_name ("MetricEntry");
+ ok_button.set_name ("MetricButton");
+ cancel_button.set_name ("MetricButton");
+
+ add (vpacker);
+ set_name ("MetricDialog");
+
+ set_keyboard_input(true);
+}
+
+double
+MeterDialog::get_bpb ()
+{
+ double bpb = 0;
+
+ if (sscanf (bpb_entry.get_text().c_str(), "%lf", &bpb) != 1) {
+ return 0;
+ }
+
+ return bpb;
+}
+
+double
+MeterDialog::get_note_type ()
+{
+ double note_type = 0;
+ vector<const gchar *>::iterator i;
+ string text = note_types.get_entry()->get_text();
+
+ for (i = strings.begin(); i != strings.end(); ++i) {
+ if (text == *i) {
+ if (sscanf (text.c_str(), "%*[^0-9]%lf", &note_type) != 1) {
+ error << 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 << compose(_("incomprehensible note type entry (%1)"), text) << endmsg;
+ return 0;
+ }
+ }
+
+ return note_type;
+}
+
+bool
+MeterDialog::get_bbt_time (BBT_Time& requested)
+{
+ requested.ticks = 0;
+
+ if (sscanf (when_bar_entry.get_text().c_str(), "%" PRIu32, &requested.bars) != 1) {
+ return false;
+ }
+
+ if (sscanf (when_beat_entry.get_text().c_str(), "%" PRIu32, &requested.beats) != 1) {
+ return false;
+ }
+
+ return true;
+}
diff --git a/gtk2_ardour/tempo_dialog.h b/gtk2_ardour/tempo_dialog.h
new file mode 100644
index 0000000000..b091007c7d
--- /dev/null
+++ b/gtk2_ardour/tempo_dialog.h
@@ -0,0 +1,70 @@
+#ifndef __ardour_gtk_tempo_dialog_h__
+#define __ardour_gtk_tempo_dialog_h__
+
+#include <gtk--.h>
+#include <ardour/types.h>
+#include <ardour/tempo.h>
+
+#include "ardour_dialog.h"
+
+struct TempoDialog : public ArdourDialog
+{
+ Gtk::Entry bpm_entry;
+ Gtk::Frame bpm_frame;
+ Gtk::VBox vpacker;
+ Gtk::Button ok_button;
+ Gtk::Button cancel_button;
+ Gtk::HBox button_box;
+ Gtk::HBox hspacer1;
+ Gtk::VBox vspacer1;
+ Gtk::Entry when_bar_entry;
+ Gtk::Entry when_beat_entry;
+ Gtk::Label when_bar_label;
+ Gtk::Label when_beat_label;
+ Gtk::Table when_table;
+ Gtk::Frame when_frame;
+ char buf[64];
+
+ TempoDialog (ARDOUR::TempoMap&, jack_nframes_t, string action);
+ TempoDialog (ARDOUR::TempoSection&, string action);
+
+ double get_bpm ();
+ bool get_bbt_time (ARDOUR::BBT_Time&);
+
+ private:
+ void init (const ARDOUR::BBT_Time& start, double, bool);
+};
+
+struct MeterDialog : public ArdourDialog
+{
+ Gtk::Entry bpb_entry;
+ Gtk::Combo note_types;
+ vector<const gchar *> strings;
+ Gtk::Frame note_frame;
+ Gtk::Frame bpb_frame;
+ Gtk::VBox vpacker;
+ Gtk::Button ok_button;
+ Gtk::Button cancel_button;
+ Gtk::HBox button_box;
+ Gtk::HBox hspacer1, hspacer2;
+ Gtk::VBox vspacer1, vspacer2;
+ Gtk::Entry when_bar_entry;
+ Gtk::Entry when_beat_entry;
+ Gtk::Label when_bar_label;
+ Gtk::Label when_beat_label;
+ Gtk::Table when_table;
+ Gtk::Frame when_frame;
+ char buf[64];
+
+ MeterDialog (ARDOUR::TempoMap&, jack_nframes_t, string action);
+ MeterDialog (ARDOUR::MeterSection&, string action);
+
+ double get_bpb ();
+ double get_note_type ();
+ bool get_bbt_time (ARDOUR::BBT_Time&);
+
+ private:
+ void init (const ARDOUR::BBT_Time&, double, double, bool);
+};
+
+#endif /* __ardour_gtk_tempo_dialog_h__ */
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
new file mode 100644
index 0000000000..b0573714ad
--- /dev/null
+++ b/gtk2_ardour/time_axis_view.cc
@@ -0,0 +1,803 @@
+/*
+ Copyright (C) 2000 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+#include <algorithm>
+#include <string>
+#include <list>
+
+#include <pbd/error.h>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/stop_signal.h>
+
+#include <ardour/session.h>
+#include <ardour/utils.h>
+#include <ardour/ladspa_plugin.h>
+#include <ardour/insert.h>
+#include <ardour/location.h>
+
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "time_axis_view.h"
+#include "canvas-simplerect.h"
+#include "selection.h"
+#include "keyboard.h"
+#include "rgb_macros.h"
+
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace SigC;
+using namespace ARDOUR;
+using namespace Editing;
+
+const double trim_handle_size = 6.0; /* pixels */
+
+TimeAxisView::TimeAxisView(ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* rent, Gtk::Widget *canvas)
+ : AxisView(sess),
+ editor(ed),
+ controls_table (2, 9)
+{
+ canvas_display = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(canvas->gtkobj())),
+ gtk_canvas_group_get_type(),
+ "x", 0.0,
+ "y", 0.0,
+ NULL);
+
+ selection_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display),
+ gtk_canvas_group_get_type (),
+ NULL);
+ gtk_canvas_item_hide (selection_group);
+
+ control_parent = 0;
+ display_menu = 0;
+ size_menu = 0;
+ _marked_for_display = false;
+ _hidden = false;
+ height = 0;
+ effective_height = 0;
+ parent = rent;
+ _has_state = false;
+
+ /*
+ Create the standard LHS Controls
+ We create the top-level container and name add the name label here,
+ subclasses can add to the layout as required
+ */
+
+ name_entry.set_name ("EditorTrackNameDisplay");
+ name_entry.button_release_event.connect (slot (*this, &TimeAxisView::name_entry_button_release));
+ name_entry.button_press_event.connect (slot (*this, &TimeAxisView::name_entry_button_press));
+
+ name_entry.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event));
+ name_entry.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event));
+
+ Gtkmmext::set_usize_to_display_given_text (name_entry, N_("gTortnam"), 10, 10); // just represents a short name
+
+ name_label.set_name ("TrackLabel");
+ name_label.set_alignment (0.0, 0.5);
+
+ // name_hbox.set_border_width (2);
+ // name_hbox.set_spacing (5);
+
+ /* typically, either name_label OR name_entry are visible,
+ but not both. its up to derived classes to show/hide them as they
+ wish.
+ */
+
+ name_hbox.pack_start (name_label, true, true);
+ name_hbox.pack_start (name_entry, true, true);
+ name_hbox.show ();
+
+ controls_table.set_border_width (2);
+ controls_table.set_row_spacings (0);
+ controls_table.set_col_spacings (0);
+ controls_table.set_homogeneous (true);
+ controls_table.show ();
+
+ controls_table.attach (name_hbox, 0, 5, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND);
+
+ controls_table.show ();
+
+ controls_vbox.pack_start (controls_table, false, false);
+ controls_vbox.show ();
+
+ controls_ebox.set_name ("TimeAxisViewControlsBaseUnselected");
+ controls_ebox.add (controls_vbox);
+ controls_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
+ controls_ebox.set_flags (GTK_CAN_FOCUS);
+
+ controls_ebox.button_release_event.connect (slot (*this, &TimeAxisView::controls_ebox_button_release));
+
+ controls_lhs_pad.set_name ("TimeAxisViewControlsPadding");
+ controls_hbox.pack_start (controls_lhs_pad,false,false);
+ controls_hbox.pack_start (controls_ebox,true,true);
+ controls_hbox.show ();
+
+ controls_frame.add (controls_hbox);
+ controls_frame.set_name ("TimeAxisViewControlsBaseUnselected");
+ controls_frame.set_shadow_type (GTK_SHADOW_OUT);
+}
+
+TimeAxisView::~TimeAxisView()
+{
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ delete *i;
+ }
+
+ for (list<SelectionRect*>::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) {
+ gtk_object_destroy (GTK_OBJECT((*i)->rect));
+ gtk_object_destroy (GTK_OBJECT((*i)->start_trim));
+ gtk_object_destroy (GTK_OBJECT((*i)->end_trim));
+ }
+
+ for (list<SelectionRect*>::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) {
+ gtk_object_destroy (GTK_OBJECT((*i)->rect));
+ gtk_object_destroy (GTK_OBJECT((*i)->start_trim));
+ gtk_object_destroy (GTK_OBJECT((*i)->end_trim));
+ }
+
+ if (selection_group) {
+ gtk_object_destroy (GTK_OBJECT (selection_group));
+ selection_group = 0;
+ }
+
+ if (canvas_display) {
+ gtk_object_destroy (GTK_OBJECT (canvas_display));
+ canvas_display = 0;
+ }
+
+ if (display_menu) {
+ delete display_menu;
+ display_menu = 0;
+ }
+
+ if (size_menu) {
+ delete size_menu;
+ size_menu = 0;
+ }
+}
+
+guint32
+TimeAxisView::show_at (double y, int& nth, VBox *parent)
+{
+ gdouble ix1, ix2, iy1, iy2;
+ effective_height = 0;
+
+ if (control_parent) {
+ control_parent->reorder_child (controls_frame, nth);
+ } else {
+ control_parent = parent;
+ parent->pack_start (controls_frame, false, false);
+ parent->reorder_child (controls_frame, nth);
+ }
+
+ controls_frame.show ();
+ controls_ebox.show ();
+
+ /* the coordinates used here are in the system of the
+ item's parent ...
+ */
+
+ gtk_canvas_item_get_bounds (canvas_display, &ix1, &iy1, &ix2, &iy2);
+ gtk_canvas_item_i2w (canvas_display->parent, &ix1, &iy1);
+ if (iy1 < 0) {
+ iy1 = 0;
+ }
+ gtk_canvas_item_move (canvas_display, 0.0, y - iy1);
+ gtk_canvas_item_show (canvas_display); /* XXX not necessary */
+
+ y_position = y;
+ order = nth;
+ _hidden = false;
+
+ effective_height = height;
+
+ /* now show children */
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+
+ if ((*i)->marked_for_display()) {
+ gtk_canvas_item_show ((*i)->canvas_display);
+ }
+
+ if (GTK_OBJECT_FLAGS(GTK_OBJECT((*i)->canvas_display)) & GTK_CANVAS_ITEM_VISIBLE) {
+ ++nth;
+ effective_height += (*i)->show_at (y + effective_height, nth, parent);
+ }
+ }
+
+ return effective_height;
+}
+
+gint
+TimeAxisView::controls_ebox_button_release (GdkEventButton* ev)
+{
+ switch (ev->button) {
+ case 1:
+ selection_click (ev);
+ break;
+
+ case 3:
+ popup_display_menu (ev->time);
+ break;
+
+ case 4:
+ if (Keyboard::no_modifier_keys_pressed (ev)) {
+ editor.scroll_tracks_up_line ();
+ } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ step_height (true);
+ }
+ break;
+
+ case 5:
+ if (Keyboard::no_modifier_keys_pressed (ev)) {
+ editor.scroll_tracks_down_line ();
+ } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+ step_height (false);
+ }
+ break;
+
+
+ }
+
+ return TRUE;
+}
+
+void
+TimeAxisView::selection_click (GdkEventButton* ev)
+{
+ if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) {
+
+ if (editor.get_selection().selected (this)) {
+ editor.get_selection().remove (this);
+ } else {
+ editor.get_selection().add (this);
+ }
+
+ } else {
+
+ editor.get_selection().set (this);
+ }
+}
+
+void
+TimeAxisView::hide ()
+{
+ if (_hidden) {
+ return;
+ }
+
+ gtk_canvas_item_hide (canvas_display);
+ controls_frame.hide ();
+
+ if (control_parent) {
+ control_parent->remove (controls_frame);
+ control_parent = 0;
+ }
+
+ y_position = -1;
+ _hidden = true;
+
+ /* now hide children */
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->hide ();
+ }
+
+ Hiding ();
+}
+
+void
+TimeAxisView::step_height (bool bigger)
+{
+ switch (height) {
+ case Largest:
+ if (!bigger) set_height (Large);
+ break;
+ case Large:
+ if (bigger) set_height (Largest);
+ else set_height (Larger);
+ break;
+ case Larger:
+ if (bigger) set_height (Large);
+ else set_height (Normal);
+ break;
+ case Normal:
+ if (bigger) set_height (Larger);
+ else set_height (Smaller);
+ break;
+ case Smaller:
+ if (bigger) set_height (Normal);
+ else set_height (Small);
+ break;
+ case Small:
+ if (bigger) set_height (Smaller);
+ break;
+ }
+}
+
+
+void
+TimeAxisView::set_height (TrackHeight h)
+{
+ height = (guint32) h;
+ controls_frame.set_usize (-1, height);
+
+ if (GTK_OBJECT_FLAGS(GTK_OBJECT(selection_group)) & GTK_CANVAS_ITEM_VISIBLE) {
+ /* resize the selection rect */
+ show_selection (editor.get_selection().time);
+ }
+
+// for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+// (*i)->set_height (h);
+// }
+
+}
+
+
+gint
+TimeAxisView::name_entry_button_press (GdkEventButton *ev)
+{
+ if (ev->button == 3) {
+ return do_not_propagate (ev);
+ }
+ return FALSE;
+}
+
+gint
+TimeAxisView::name_entry_button_release (GdkEventButton *ev)
+{
+ if (ev->button == 3) {
+ popup_display_menu (ev->time);
+ return stop_signal (name_entry, "button_release_event");
+ }
+ return FALSE;
+}
+
+void
+TimeAxisView::popup_display_menu (guint32 when)
+{
+ if (display_menu == 0) {
+ build_display_menu ();
+ }
+ display_menu->popup (1, when);
+}
+
+gint
+TimeAxisView::size_click (GdkEventButton *ev)
+{
+ popup_size_menu (ev->time);
+ return TRUE;
+}
+
+void
+TimeAxisView::popup_size_menu (guint32 when)
+{
+ if (size_menu == 0) {
+ build_size_menu ();
+ }
+ size_menu->popup (1, when);
+}
+
+void
+TimeAxisView::set_selected (bool yn)
+{
+ AxisView::set_selected (yn);
+
+ if (_selected) {
+ controls_ebox.set_name (controls_base_selected_name);
+ controls_frame.set_name (controls_base_selected_name);
+
+ /* propagate any existing selection, if the mode is right */
+
+ if (editor.current_mouse_mode() == Editing::MouseRange && !editor.get_selection().time.empty()) {
+ show_selection (editor.get_selection().time);
+ }
+
+ } else {
+ controls_ebox.set_name (controls_base_unselected_name);
+ controls_frame.set_name (controls_base_unselected_name);
+
+ hide_selection ();
+
+ /* children will be set for the yn=true case. but when deselecting
+ the editor only has a list of top-level trackviews, so we
+ have to do this here.
+ */
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->set_selected (false);
+ }
+
+
+ }
+}
+
+void
+TimeAxisView::build_size_menu ()
+{
+ using namespace Menu_Helpers;
+
+ size_menu = new Menu;
+ size_menu->set_name ("ArdourContextMenu");
+ MenuList& items = size_menu->items();
+
+ items.push_back (MenuElem (_("Largest"), bind (slot (*this, &TimeAxisView::set_height), Largest)));
+ items.push_back (MenuElem (_("Large"), bind (slot (*this, &TimeAxisView::set_height), Large)));
+ items.push_back (MenuElem (_("Larger"), bind (slot (*this, &TimeAxisView::set_height), Larger)));
+ items.push_back (MenuElem (_("Normal"), bind (slot (*this, &TimeAxisView::set_height), Normal)));
+ items.push_back (MenuElem (_("Smaller"), bind (slot (*this, &TimeAxisView::set_height), Smaller)));
+ items.push_back (MenuElem (_("Small"), bind (slot (*this, &TimeAxisView::set_height), Small)));
+}
+
+void
+TimeAxisView::build_display_menu ()
+{
+ using namespace Menu_Helpers;
+
+ display_menu = new Menu;
+ display_menu->set_name ("ArdourContextMenu");
+
+ // Just let implementing classes define what goes into the manu
+}
+
+void
+TimeAxisView::set_samples_per_unit (double spu)
+{
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->set_samples_per_unit (spu);
+ }
+}
+
+void
+TimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end)
+{
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->show_timestretch (start, end);
+ }
+}
+
+void
+TimeAxisView::hide_timestretch ()
+{
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->hide_timestretch ();
+ }
+}
+
+void
+TimeAxisView::show_selection (TimeSelection& ts)
+{
+ double x1;
+ double x2;
+ double y2;
+ SelectionRect *rect;
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->show_selection (ts);
+ }
+
+ if (GTK_OBJECT_FLAGS(GTK_OBJECT(selection_group)) & GTK_CANVAS_ITEM_VISIBLE) {
+ while (!used_selection_rects.empty()) {
+ free_selection_rects.push_front (used_selection_rects.front());
+ used_selection_rects.pop_front();
+ gtk_canvas_item_hide (free_selection_rects.front()->rect);
+ gtk_canvas_item_hide (free_selection_rects.front()->start_trim);
+ gtk_canvas_item_hide (free_selection_rects.front()->end_trim);
+ }
+ gtk_canvas_item_hide (selection_group);
+ }
+
+ gtk_canvas_item_show (selection_group);
+ gtk_canvas_item_raise_to_top (selection_group);
+
+ for (list<AudioRange>::iterator i = ts.begin(); i != ts.end(); ++i) {
+ jack_nframes_t start, end, cnt;
+
+ start = (*i).start;
+ end = (*i).end;
+ cnt = end - start + 1;
+
+ rect = get_selection_rect ((*i).id);
+
+ x1 = start / editor.get_current_zoom();
+ x2 = (start + cnt - 1) / editor.get_current_zoom();
+ y2 = height;
+
+ gtk_object_set (GTK_OBJECT(rect->rect),
+ "x1", x1,
+ "y1", 1.0,
+ "x2", x2,
+ "y2", y2,
+ NULL);
+
+ // trim boxes are at the top for selections
+
+ if (x2 > x1) {
+ gtk_object_set (GTK_OBJECT(rect->start_trim),
+ "x1", x1,
+ "y1", 1.0,
+ "x2", x1 + trim_handle_size,
+ "y2", 1.0 + trim_handle_size,
+ NULL);
+ gtk_object_set (GTK_OBJECT(rect->end_trim),
+ "x1", x2 - trim_handle_size,
+ "y1", 1.0,
+ "x2", x2,
+ "y2", 1.0 + trim_handle_size,
+ NULL);
+ gtk_canvas_item_show (rect->start_trim);
+ gtk_canvas_item_show (rect->end_trim);
+ } else {
+ gtk_canvas_item_hide (rect->start_trim);
+ gtk_canvas_item_hide (rect->end_trim);
+ }
+
+ gtk_canvas_item_show (rect->rect);
+ used_selection_rects.push_back (rect);
+ }
+}
+
+void
+TimeAxisView::reshow_selection (TimeSelection& ts)
+{
+ show_selection (ts);
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->show_selection (ts);
+ }
+}
+
+void
+TimeAxisView::hide_selection ()
+{
+ if (GTK_OBJECT_FLAGS(GTK_OBJECT(selection_group)) & GTK_CANVAS_ITEM_VISIBLE) {
+ while (!used_selection_rects.empty()) {
+ free_selection_rects.push_front (used_selection_rects.front());
+ used_selection_rects.pop_front();
+ gtk_canvas_item_hide (free_selection_rects.front()->rect);
+ gtk_canvas_item_hide (free_selection_rects.front()->start_trim);
+ gtk_canvas_item_hide (free_selection_rects.front()->end_trim);
+ }
+ gtk_canvas_item_hide (selection_group);
+ }
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->hide_selection ();
+ }
+}
+
+void
+TimeAxisView::order_selection_trims (GtkCanvasItem *item, bool put_start_on_top)
+{
+ /* find the selection rect this is for. we have the item corresponding to one
+ of the trim handles.
+ */
+
+ for (list<SelectionRect*>::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) {
+ if ((*i)->start_trim == item || (*i)->end_trim == item) {
+
+ /* make one trim handle be "above" the other so that if they overlap,
+ the top one is the one last used.
+ */
+
+ gtk_canvas_item_raise_to_top ((*i)->rect);
+ gtk_canvas_item_raise_to_top (put_start_on_top ? (*i)->start_trim : (*i)->end_trim);
+ gtk_canvas_item_raise_to_top (put_start_on_top ? (*i)->end_trim : (*i)->start_trim);
+
+ break;
+ }
+ }
+}
+
+SelectionRect *
+TimeAxisView::get_selection_rect (uint32_t id)
+{
+ SelectionRect *rect;
+
+ /* check to see if we already have a visible rect for this particular selection ID */
+
+ for (list<SelectionRect*>::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) {
+ if ((*i)->id == id) {
+ return (*i);
+ }
+ }
+
+ /* ditto for the free rect list */
+
+ for (list<SelectionRect*>::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) {
+ if ((*i)->id == id) {
+ free_selection_rects.erase (i);
+ return (*i);
+ }
+ }
+
+ /* no existing matching rect, so go get a new one from the free list, or create one if there are none */
+
+ if (free_selection_rects.empty()) {
+
+ rect = new SelectionRect;
+
+ rect->rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(selection_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "y1", 0.0,
+ "x2", 0.0,
+ "y2", 0.0,
+ "fill_color_rgba", color_map[cSelectionRectFill],
+ "outline_color_rgba" , color_map[cSelectionRectOutline],
+ NULL);
+
+
+ rect->start_trim = gtk_canvas_item_new (GTK_CANVAS_GROUP(selection_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", (gdouble) 0.0,
+ "x2", (gdouble) 0.0,
+ "fill_color_rgba" , color_map[cSelectionStartFill],
+ "outline_color_rgba" , color_map[cSelectionStartOutline],
+ NULL);
+
+ rect->end_trim = gtk_canvas_item_new (GTK_CANVAS_GROUP(selection_group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", 0.0,
+ "x2", 0.0,
+ "fill_color_rgba" , color_map[cSelectionEndFill],
+ "outline_color_rgba" , color_map[cSelectionEndOutline],
+ NULL);
+ free_selection_rects.push_front (rect);
+
+ gtk_signal_connect (GTK_OBJECT(rect->rect), "event",
+ (GtkSignalFunc) PublicEditor::canvas_selection_rect_event,
+ &editor);
+ gtk_signal_connect (GTK_OBJECT(rect->start_trim), "event",
+ (GtkSignalFunc) PublicEditor::canvas_selection_start_trim_event,
+ &editor);
+ gtk_signal_connect (GTK_OBJECT(rect->end_trim), "event",
+ (GtkSignalFunc) PublicEditor::canvas_selection_end_trim_event,
+ &editor);
+
+ gtk_object_set_data(GTK_OBJECT(rect->rect), "rect", rect);
+ gtk_object_set_data(GTK_OBJECT(rect->start_trim), "rect", rect);
+ gtk_object_set_data(GTK_OBJECT(rect->end_trim), "rect", rect);
+ }
+
+ rect = free_selection_rects.front();
+ rect->id = id;
+ free_selection_rects.pop_front();
+ return rect;
+}
+
+bool
+TimeAxisView::is_child (TimeAxisView* tav)
+{
+ return find (children.begin(), children.end(), tav) != children.end();
+}
+
+void
+TimeAxisView::add_child (TimeAxisView* child)
+{
+ children.push_back (child);
+}
+
+void
+TimeAxisView::remove_child (TimeAxisView* child)
+{
+ vector<TimeAxisView*>::iterator i;
+
+ if ((i = find (children.begin(), children.end(), child)) != children.end()) {
+ children.erase (i);
+ }
+}
+
+void
+TimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& result)
+{
+ return;
+}
+
+void
+TimeAxisView::get_inverted_selectables (Selection& sel, list<Selectable*>& result)
+{
+ return;
+}
+
+bool
+TimeAxisView::touched (double top, double bot)
+{
+ /* remember: this is X Window - coordinate space starts in upper left and moves down.
+ y_position is the "origin" or "top" of the track.
+ */
+
+ double mybot = y_position + height; // XXX need to include Editor::track_spacing;
+
+ return ((y_position <= bot && y_position >= top) ||
+ ((mybot <= bot) && (top < mybot)) ||
+ (mybot >= bot && y_position < top));
+}
+
+void
+TimeAxisView::set_parent (TimeAxisView& p)
+{
+ parent = &p;
+}
+
+bool
+TimeAxisView::has_state () const
+{
+ return _has_state;
+}
+
+TimeAxisView*
+TimeAxisView::get_parent_with_state ()
+{
+ if (parent == 0) {
+ return 0;
+ }
+
+ if (parent->has_state()) {
+ return parent;
+ }
+
+ return parent->get_parent_with_state ();
+}
+
+void
+TimeAxisView::set_state (const XMLNode& node)
+{
+ const XMLProperty *prop;
+
+ if ((prop = node.property ("track_height")) != 0) {
+
+ if (prop->value() == "largest") {
+ set_height (Largest);
+ } else if (prop->value() == "large") {
+ set_height (Large);
+ } else if (prop->value() == "larger") {
+ set_height (Larger);
+ } else if (prop->value() == "normal") {
+ set_height (Normal);
+ } else if (prop->value() == "smaller") {
+ set_height (Smaller);
+ } else if (prop->value() == "small") {
+ set_height (Small);
+ } else {
+ error << compose(_("unknown track height name \"%1\" in XML GUI information"), prop->value()) << endmsg;
+ set_height (Normal);
+ }
+
+ } else {
+ set_height (Normal);
+ }
+}
+
+void
+TimeAxisView::reset_height()
+{
+ set_height ((TrackHeight) height);
+
+ for (vector<TimeAxisView*>::iterator i = children.begin(); i != children.end(); ++i) {
+ (*i)->set_height ((TrackHeight)(*i)->height);
+ }
+}
+
diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h
new file mode 100644
index 0000000000..a125e188ba
--- /dev/null
+++ b/gtk2_ardour/time_axis_view.h
@@ -0,0 +1,290 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_time_axis_h__
+#define __ardour_gtk_time_axis_h__
+
+#include <vector>
+#include <list>
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+
+#include <ardour/types.h>
+#include <ardour/region.h>
+
+#include "prompter.h"
+#include "axis_view.h"
+#include "enums.h"
+#include "editing.h"
+
+namespace ARDOUR {
+ class Session;
+ class Region;
+ class Session;
+ class RouteGroup;
+ class Playlist;
+}
+
+class PublicEditor;
+class AudioRegionSelection;
+class TimeSelection;
+class PointSelection;
+class TimeAxisViewItem;
+class Selection;
+class Selectable;
+
+/**
+ * TimeAxisView defines the abstract base class for time-axis views.
+ *
+ * This class provides the basic LHS controls and display methods. This should be
+ * extended to create functional time-axis based views.
+ *
+ */
+class TimeAxisView : public virtual AxisView
+{
+ public:
+ enum TrackHeight {
+ /* canvas units. they need to be odd
+ valued so that there is a precise
+ middle.
+ */
+ Largest = 301,
+ Large = 201,
+ Larger = 101,
+ Normal = 51,
+ Smaller = 31,
+ Small = 21
+ };
+
+ TimeAxisView(ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* parent, Gtk::Widget *canvas);
+ virtual ~TimeAxisView ();
+
+ /* public data: XXX create accessor/mutators for these ?? */
+
+ PublicEditor& editor;
+
+ guint32 height; /* in canvas units */
+ guint32 effective_height; /* in canvas units */
+ double y_position;
+ int order;
+
+
+ GtkCanvasItem *canvas_display;
+ Gtk::VBox *control_parent;
+
+ /* The Standard LHS Controls */
+ Gtk::Frame controls_frame;
+ Gtk::HBox controls_hbox;
+ Gtk::EventBox controls_lhs_pad;
+ Gtk::Table controls_table;
+ Gtk::EventBox controls_ebox;
+ Gtk::VBox controls_vbox;
+ Gtk::HBox name_hbox;
+ Gtk::Frame name_frame;
+ Gtk::Entry name_entry;
+
+ /**
+ * Display this TrackView as the nth component of the parent box, at y.
+ *
+ * @param y
+ * @param nth
+ * @param parent the parent component
+ * @return the height of this TrackView
+ */
+ virtual guint32 show_at (double y, int& nth, Gtk::VBox *parent);
+
+ bool touched (double top, double bot);
+
+ /**
+ * Hides this TrackView
+ */
+ virtual void hide ();
+ bool hidden() const { return _hidden; }
+
+ virtual void set_selected (bool);
+
+ /**
+ * potential handler for entered events
+ */
+
+ virtual void entered () {}
+ virtual void exited () {}
+
+ /**
+ * Sets the height of this TrackView to one of ths TrackHeghts
+ *
+ * @param h the TrackHeight value to set
+ */
+ virtual void set_height (TrackHeight h);
+ void reset_height();
+ /**
+ * Steps through the defined TrackHeights for this TrackView.
+ * Sets bigger to true to step up in size, set to fals eot step smaller.
+ *
+ * @param bigger true if stepping should increase in size, false otherwise
+ */
+ virtual void step_height (bool bigger);
+
+ virtual ARDOUR::RouteGroup* edit_group() const { return 0; }
+ virtual ARDOUR::Playlist* playlist() const { return 0; }
+
+ virtual void set_samples_per_unit (double);
+ virtual void show_selection (TimeSelection&);
+ virtual void hide_selection ();
+ virtual void reshow_selection (TimeSelection&);
+ virtual void show_timestretch (jack_nframes_t start, jack_nframes_t end);
+ virtual void hide_timestretch ();
+
+ virtual void hide_dependent_views (TimeAxisViewItem&) {}
+ virtual void reveal_dependent_views (TimeAxisViewItem&) {}
+
+ /* editing operations */
+
+ virtual bool cut_copy_clear (Selection&, Editing::CutCopyOp) { return false; }
+ virtual bool paste (jack_nframes_t, float times, Selection&, size_t nth) { return false; }
+
+ virtual void set_selected_regionviews (AudioRegionSelection&) {}
+ virtual void set_selected_points (PointSelection&) {}
+
+ virtual ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir) {
+ return 0;
+ }
+
+ void order_selection_trims (GtkCanvasItem *item, bool put_start_on_top);
+
+ virtual void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list<Selectable*>& results);
+ virtual void get_inverted_selectables (Selection&, list<Selectable *>& results);
+
+ /* state/serialization management */
+
+ void set_parent (TimeAxisView& p);
+ bool has_state () const;
+
+ virtual void set_state (const XMLNode&);
+ virtual XMLNode* get_state_node () { return 0; }
+
+ /* call this on the parent */
+
+ virtual XMLNode* get_child_xml_node (std::string childname) { return 0; }
+
+ protected:
+
+ string controls_base_unselected_name;
+ string controls_base_selected_name;
+
+ /**
+ * Handle mouse press on our LHS control name entry.
+ *
+ * @param ev the event
+ */
+ virtual gint name_entry_button_press (GdkEventButton *ev);
+
+ /**
+ * Handle mouse relaese on our LHS control name entry.
+ *
+ *@ param ev the event
+ */
+ virtual gint name_entry_button_release (GdkEventButton *ev);
+
+ /**
+ * Handle mouse relaese on our LHS control name ebox.
+ *
+ *@ param ev the event
+ */
+ virtual gint controls_ebox_button_release (GdkEventButton *ev);
+
+ /**
+ * Displays the standard LHS control menu at when.
+ *
+ * @param when the popup activation time
+ */
+ virtual void popup_display_menu (guint32 when);
+
+ /**
+ * Build the standard LHS control menu.
+ * Subclasses should extend this method to add their own menu options.
+ *
+ */
+ virtual void build_display_menu ();
+
+ /**
+ * Do anything that needs to be done to dynamically reset
+ * the LHS control menu.
+ */
+ virtual gint handle_display_menu_map_event (GdkEventAny *ev) { return FALSE; }
+
+ /**
+ * Build the standard LHS control size menu for the default TrackHeight options.
+ *
+ */
+ virtual void build_size_menu();
+
+ /**
+ * Displays the standard LHS controls size menu for the TrackHeight.
+ *
+ * @parem when the popup activation time
+ */
+ void popup_size_menu(guint32 when);
+
+ /**
+ * Handle the size option of out main menu.
+ *
+ * @param ev the event
+ */
+ gint size_click(GdkEventButton *ev);
+
+ /* The standard LHS Track control popup-menus */
+
+ Gtk::Menu *display_menu;
+ Gtk::Menu *size_menu;
+
+ Gtk::Label name_label;
+
+ TimeAxisView* parent;
+
+ /* find the parent with state */
+
+ TimeAxisView* get_parent_with_state();
+
+ std::vector<TimeAxisView*> children;
+ bool is_child (TimeAxisView*);
+
+ void remove_child (TimeAxisView*);
+ void add_child (TimeAxisView*);
+
+ /* selection display */
+
+ GtkCanvasItem *selection_group;
+
+ list<SelectionRect*> free_selection_rects;
+ list<SelectionRect*> used_selection_rects;
+
+ SelectionRect* get_selection_rect(uint32_t id);
+
+ virtual void selection_click (GdkEventButton*);
+
+ bool _hidden;
+ bool _has_state;
+
+}; /* class TimeAxisView */
+
+#endif /* __ardour_gtk_time_axis_h__ */
+
diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc
new file mode 100644
index 0000000000..9dffe8fcf6
--- /dev/null
+++ b/gtk2_ardour/time_axis_view_item.cc
@@ -0,0 +1,950 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <pbd/error.h>
+
+#include <ardour/types.h>
+#include <ardour/ardour.h>
+
+#include "public_editor.h"
+#include "time_axis_view_item.h"
+#include "time_axis_view.h"
+#include "canvas-simplerect.h"
+#include "canvas-imageframe.h"
+#include "utils.h"
+#include "rgb_macros.h"
+
+#include "i18n.h"
+
+using namespace std;
+using namespace Editing;
+
+//------------------------------------------------------------------------------
+/** Initialize static memeber data */
+std::string TimeAxisViewItem::NAME_FONT;
+const double TimeAxisViewItem::NAME_X_OFFSET = 15.0;
+const double TimeAxisViewItem::NAME_Y_OFFSET = 15.0 ; /* XXX depends a lot on the font size, sigh. */
+const double TimeAxisViewItem::NAME_HIGHLIGHT_SIZE = 15.0 ; /* ditto */
+const double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH = 32.0 ; /* ditto */
+const double TimeAxisViewItem::GRAB_HANDLE_LENGTH = 6 ;
+
+
+//---------------------------------------------------------------------------------------//
+// Constructor / Desctructor
+
+/**
+ * Constructs a new TimeAxisViewItem.
+ *
+ * @param it_name the unique name/Id of this item
+ * @param parant the parent canvas group
+ * @param tv the TimeAxisView we are going to be added to
+ * @param spu samples per unit
+ * @param base_color
+ * @param start the start point of this item
+ * @param duration the duration of this item
+ */
+TimeAxisViewItem::TimeAxisViewItem(std::string it_name, GtkCanvasGroup* parent, TimeAxisView& tv, double spu, GdkColor& base_color,
+ jack_nframes_t start, jack_nframes_t duration,
+ Visibility visibility)
+ : trackview (tv)
+{
+ if (NAME_FONT.empty()) {
+ NAME_FONT = get_font_for_style (N_("TimeAxisViewItemName"));
+ }
+
+ item_name = it_name ;
+ samples_per_unit = spu ;
+ should_show_selection = true;
+ frame_position = start ;
+ item_duration = duration ;
+ name_connected = false;
+ fill_opacity = 50;
+ position_locked = false ;
+ max_item_duration = ARDOUR::max_frames;
+ min_item_duration = 0 ;
+ show_vestigial = true;
+
+ if (duration == 0) {
+ warning << "Time Axis Item Duration == 0" << endl ;
+ }
+
+ group = gtk_canvas_item_new(GTK_CANVAS_GROUP(parent),gtk_canvas_group_get_type(),NULL) ;
+
+ vestigial_frame = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", (double) 0.0,
+ "y1", (double) 1.0,
+ "x2", 2.0,
+ "y2", (double) trackview.height,
+ "outline_color_rgba", color_map[cVestigialFrameOutline],
+ "fill_color_rgba", color_map[cVestigialFrameFill],
+ NULL);
+ gtk_canvas_item_hide (vestigial_frame);
+
+ if (visibility & ShowFrame) {
+ frame = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", (double) 0.0,
+ "y1", (double) 1.0,
+ "x2", (double) trackview.editor.frame_to_pixel(duration),
+ "y2", (double) trackview.height,
+ "outline_color_rgba", color_map[cTimeAxisFrameOutline],
+ "fill_color_rgba", color_map[cTimeAxisFrameFill],
+ NULL);
+ } else {
+ frame = 0;
+ }
+
+ if (visibility & ShowNameHighlight) {
+ name_highlight = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", (double) 1.0,
+ "x2", (double) (trackview.editor.frame_to_pixel(item_duration)) - 1,
+ "y1", (double) (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE),
+ "y2", (double) (trackview.height - 1),
+ "outline_color_rgba", color_map[cNameHighlightFill],
+ "fill_color_rgba", color_map[cNameHighlightOutline],
+ NULL) ;
+ gtk_object_set_data(GTK_OBJECT(name_highlight), "timeaxisviewitem", this) ;
+ } else {
+ name_highlight = 0;
+ }
+
+ if (visibility & ShowNameText) {
+ name_text = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
+ gtk_canvas_text_get_type(),
+ "x", (double) TimeAxisViewItem::NAME_X_OFFSET,
+ "y", (double) trackview.height + 1.0 - TimeAxisViewItem::NAME_Y_OFFSET,
+ "font", NAME_FONT.c_str(),
+ "anchor", GTK_ANCHOR_NW,
+ NULL) ;
+ gtk_object_set_data(GTK_OBJECT(name_text), "timeaxisviewitem", this) ;
+
+ } else {
+ name_text = 0;
+ }
+
+ /* create our grab handles used for trimming/duration etc */
+
+ if (visibility & ShowHandles) {
+ frame_handle_start = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", (double) 0.0,
+ "x2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH,
+ "y1", (double) 1.0,
+ "y2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH+1,
+ "outline_color_rgba", color_map[cFrameHandleStartOutline],
+ "fill_color_rgba", color_map[cFrameHandleStartFill],
+ NULL) ;
+
+ frame_handle_end = gtk_canvas_item_new(GTK_CANVAS_GROUP(group),
+ gtk_canvas_simplerect_get_type(),
+ "x1", (double) (trackview.editor.frame_to_pixel(get_duration())) - (TimeAxisViewItem::GRAB_HANDLE_LENGTH),
+ "x2", (double) trackview.editor.frame_to_pixel(get_duration()),
+ "y1", (double) 1,
+ "y2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH + 1,
+ "outline_color_rgba", color_map[cFrameHandleEndOutline],
+ "fill_color_rgba", color_map[cFrameHandleEndFill],
+ NULL) ;
+ } else {
+ frame_handle_start = 0;
+ frame_handle_end = 0;
+ }
+
+ set_color (base_color) ;
+
+ set_duration (item_duration, this) ;
+ set_position (start, this) ;
+}
+
+
+/**
+ * Destructor
+ */
+TimeAxisViewItem::~TimeAxisViewItem()
+{
+ gtk_object_destroy (GTK_OBJECT(group));
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Position and duration Accessors/Mutators
+
+/**
+ * Set the position of this item upon the timeline to the specified value
+ *
+ * @param pos the new position
+ * @param src the identity of the object that initiated the change
+ * @return true if the position change was a success, false otherwise
+ */
+bool
+TimeAxisViewItem::set_position(jack_nframes_t pos, void* src, double* delta)
+{
+ if (position_locked) {
+ return false;
+ }
+
+ frame_position = pos;
+
+ /* This sucks. The GtkCanvas version I am using
+ doesn't correctly implement gtk_canvas_group_set_arg(),
+ so that simply setting the "x" arg of the group
+ fails to move the group. Instead, we have to
+ use gtk_canvas_item_move(), which does the right
+ thing. I see that in GNOME CVS, the current (Sept 2001)
+ version of GNOME Canvas rectifies this issue cleanly.
+ */
+
+ GtkArg args[1] ;
+ double old_unit_pos ;
+ double new_unit_pos = pos / samples_per_unit ;
+
+ args[0].name = "x" ;
+ gtk_object_getv (GTK_OBJECT(group), 1, args) ;
+ old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ;
+
+ if (new_unit_pos != old_unit_pos) {
+ gtk_canvas_item_move (group, new_unit_pos - old_unit_pos, 0.0) ;
+ }
+
+ if (delta) {
+ (*delta) = new_unit_pos - old_unit_pos;
+ }
+
+ PositionChanged (frame_position, src) ; /* EMIT_SIGNAL */
+
+ return true;
+}
+
+/**
+ * Return the position of this item upon the timeline
+ *
+ * @return the position of this item
+ */
+jack_nframes_t
+TimeAxisViewItem::get_position() const
+{
+ return frame_position;
+}
+
+/**
+ * Sets the duration of this item
+ *
+ * @param dur the new duration of this item
+ * @param src the identity of the object that initiated the change
+ * @return true if the duration change was succesful, false otherwise
+ */
+bool
+TimeAxisViewItem::set_duration (jack_nframes_t dur, void* src)
+{
+ if ((dur > max_item_duration) || (dur < min_item_duration)) {
+ warning << compose (_("new duration %1 frames is out of bounds for %2"), get_item_name(), dur)
+ << endmsg;
+ return false;
+ }
+
+ if (dur == 0) {
+ gtk_canvas_item_hide (group);
+ }
+
+ item_duration = dur;
+
+ double pixel_width = trackview.editor.frame_to_pixel (dur);
+
+ reset_width_dependent_items (pixel_width);
+
+ DurationChanged (dur, src) ; /* EMIT_SIGNAL */
+ return true;
+}
+
+/**
+ * Returns the duration of this item
+ *
+ */
+jack_nframes_t
+TimeAxisViewItem::get_duration() const
+{
+ return (item_duration);
+}
+
+/**
+ * Sets the maximum duration that this item make have.
+ *
+ * @param dur the new maximum duration
+ * @param src the identity of the object that initiated the change
+ */
+void
+TimeAxisViewItem::set_max_duration(jack_nframes_t dur, void* src)
+{
+ max_item_duration = dur ;
+ MaxDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
+}
+
+/**
+ * Returns the maxmimum duration that this item may be set to
+ *
+ * @return the maximum duration that this item may be set to
+ */
+jack_nframes_t
+TimeAxisViewItem::get_max_duration() const
+{
+ return(max_item_duration) ;
+}
+
+/**
+ * Sets the minimu duration that this item may be set to
+ *
+ * @param the minimum duration that this item may be set to
+ * @param src the identity of the object that initiated the change
+ */
+void
+TimeAxisViewItem::set_min_duration(jack_nframes_t dur, void* src)
+{
+ min_item_duration = dur ;
+ MinDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */
+}
+
+/**
+ * Returns the minimum duration that this item mey be set to
+ *
+ * @return the nimum duration that this item mey be set to
+ */
+jack_nframes_t
+TimeAxisViewItem::get_min_duration() const
+{
+ return(min_item_duration) ;
+}
+
+/**
+ * Sets whether the position of this Item is locked to its current position
+ * Locked items cannot be moved until the item is unlocked again.
+ *
+ * @param yn set to true to lock this item to its current position
+ * @param src the identity of the object that initiated the change
+ */
+void
+TimeAxisViewItem::set_position_locked(bool yn, void* src)
+{
+ position_locked = yn ;
+ set_trim_handle_colors() ;
+ PositionLockChanged (position_locked, src); /* EMIT_SIGNAL */
+}
+
+/**
+ * Returns whether this item is locked to its current position
+ *
+ * @return true if this item is locked to its current posotion
+ * false otherwise
+ */
+bool
+TimeAxisViewItem::get_position_locked() const
+{
+ return (position_locked);
+}
+
+/**
+ * Sets whether the Maximum Duration constraint is active and should be enforced
+ *
+ * @param active set true to enforce the max duration constraint
+ * @param src the identity of the object that initiated the change
+ */
+void
+TimeAxisViewItem::set_max_duration_active(bool active, void* src)
+{
+ max_duration_active = active ;
+}
+
+/**
+ * Returns whether the Maximum Duration constraint is active and should be enforced
+ *
+ * @return true if the maximum duration constraint is active, false otherwise
+ */
+bool
+TimeAxisViewItem::get_max_duration_active() const
+{
+ return(max_duration_active) ;
+}
+
+/**
+ * Sets whether the Minimum Duration constraint is active and should be enforced
+ *
+ * @param active set true to enforce the min duration constraint
+ * @param src the identity of the object that initiated the change
+ */
+void
+TimeAxisViewItem::set_min_duration_active(bool active, void* src)
+{
+ min_duration_active = active ;
+}
+
+/**
+ * Returns whether the Maximum Duration constraint is active and should be enforced
+ *
+ * @return true if the maximum duration constraint is active, false otherwise
+ */
+bool
+TimeAxisViewItem::get_min_duration_active() const
+{
+ return(min_duration_active) ;
+}
+
+//---------------------------------------------------------------------------------------//
+// Name/Id Accessors/Mutators
+
+/**
+ * Set the name/Id of this item.
+ *
+ * @param new_name the new name of this item
+ * @param src the identity of the object that initiated the change
+ */
+void
+TimeAxisViewItem::set_item_name(std::string new_name, void* src)
+{
+ if (new_name != item_name) {
+ std::string temp_name = item_name ;
+ item_name = new_name ;
+ NameChanged (item_name, temp_name, src) ; /* EMIT_SIGNAL */
+ }
+}
+
+/**
+ * Returns the name/id of this item
+ *
+ * @return the name/id of this item
+ */
+std::string
+TimeAxisViewItem::get_item_name() const
+{
+ return(item_name) ;
+}
+
+//---------------------------------------------------------------------------------------//
+// Selection Methods
+
+/**
+ * Set to true to indicate that this item is currently selected
+ *
+ * @param yn true if this item is currently selected
+ * @param src the identity of the object that initiated the change
+ */
+void
+TimeAxisViewItem::set_selected(bool yn, void* src)
+{
+ if (_selected != yn) {
+ _selected = yn ;
+ set_frame_color ();
+ Selected (_selected) ; /* EMIT_SIGNAL */
+ }
+}
+
+/**
+ * Returns whether this item is currently selected.
+ *
+ * @return true if this item is currently selected, false otherwise
+ */
+bool
+TimeAxisViewItem::get_selected() const
+{
+ return (_selected) ;
+}
+
+void
+TimeAxisViewItem::set_should_show_selection (bool yn)
+{
+ if (should_show_selection != yn) {
+ should_show_selection = yn;
+ set_frame_color ();
+ }
+}
+
+//---------------------------------------------------------------------------------------//
+// Parent Componenet Methods
+
+/**
+ * Returns the TimeAxisView that this item is upon
+ *
+ * @return the timeAxisView that this item is placed upon
+ */
+TimeAxisView&
+TimeAxisViewItem::get_time_axis_view()
+{
+ return trackview;
+}
+//---------------------------------------------------------------------------------------//
+// ui methods & data
+
+/**
+ * Sets the displayed item text
+ * This item is the visual text name displayed on the canvas item, this can be different to the name of the item
+ *
+ * @param new_name the new name text to display
+ */
+void
+TimeAxisViewItem::set_name_text(std::string new_name)
+{
+ if (name_text) {
+ gtk_canvas_item_set (name_text, "text", new_name.c_str(), NULL);
+ }
+}
+
+/**
+ * Set the height of this item
+ *
+ * @param h the new height
+ */
+void
+TimeAxisViewItem::set_height(double height)
+{
+ if (name_highlight) {
+ if (height < NAME_HIGHLIGHT_THRESH) {
+ gtk_canvas_item_hide (name_highlight);
+ gtk_canvas_item_hide (name_text);
+ } else {
+ gtk_canvas_item_show (name_highlight);
+ gtk_canvas_item_show (name_text);
+ }
+
+ if (height > NAME_HIGHLIGHT_SIZE) {
+ gtk_canvas_item_set (name_highlight,
+ "y1", (double) height+1 - NAME_HIGHLIGHT_SIZE,
+ "y2", (double) height,
+ NULL);
+ }
+ else {
+ /* it gets hidden now anyway */
+ gtk_canvas_item_set (name_highlight,
+ "y1", (double) 1.0,
+ "y2", (double) height,
+ NULL);
+ }
+ }
+
+ if (name_text) {
+ gtk_canvas_item_set (name_text, "y", height+1 - NAME_Y_OFFSET, NULL);
+ if (height < NAME_HIGHLIGHT_THRESH) {
+ gtk_canvas_item_set(name_text, "fill_color_rgba", fill_color, NULL) ;
+ }
+ else {
+ gtk_canvas_item_set(name_text, "fill_color_rgba", label_color, NULL) ;
+ }
+ }
+
+ if (frame) {
+ gtk_canvas_item_set (frame, "y2", height+1, NULL) ;
+ }
+
+ gtk_canvas_item_set (vestigial_frame, "y2", height+1, NULL) ;
+}
+
+/**
+ *
+ */
+void
+TimeAxisViewItem::set_color(GdkColor& base_color)
+{
+ compute_colors (base_color);
+ set_colors ();
+}
+
+/**
+ *
+ */
+GtkCanvasItem*
+TimeAxisViewItem::get_canvas_frame()
+{
+ return(frame) ;
+}
+
+/**
+ *
+ */
+GtkCanvasItem*
+TimeAxisViewItem::get_canvas_group()
+{
+ return(group) ;
+}
+
+/**
+ *
+ */
+GtkCanvasItem*
+TimeAxisViewItem::get_name_highlight()
+{
+ return(name_highlight) ;
+}
+
+/**
+ *
+ */
+GtkCanvasItem*
+TimeAxisViewItem::get_name_text()
+{
+ return(name_text) ;
+}
+
+/**
+ * Calculates some contrasting color for displaying various parts of this item, based upon the base color
+ *
+ * @param color the base color of the item
+ */
+void
+TimeAxisViewItem::compute_colors(GdkColor& base_color)
+{
+ unsigned char radius ;
+ char minor_shift ;
+
+ unsigned char r,g,b ;
+
+ /* FILL: this is simple */
+ r = base_color.red/256 ;
+ g = base_color.green/256 ;
+ b = base_color.blue/256 ;
+ fill_color = RGBA_TO_UINT(r,g,b,255) ;
+
+ /* for minor colors:
+ if the overall saturation is strong, make the minor colors light.
+ if its weak, make them dark.
+
+ we do this by moving an equal distance to the other side of the
+ central circle in the color wheel from where we started.
+ */
+
+ radius = (unsigned char) rint (floor (sqrt (static_cast<double>(r*r + g*g + b+b))/3.0f)) ;
+ minor_shift = 125 - radius ;
+
+ /* LABEL: rotate around color wheel by 120 degrees anti-clockwise */
+
+ r = base_color.red/256;
+ g = base_color.green/256;
+ b = base_color.blue/256;
+
+ if (r > b)
+ {
+ if (r > g)
+ {
+ /* red sector => green */
+ swap (r,g);
+ }
+ else
+ {
+ /* green sector => blue */
+ swap (g,b);
+ }
+ }
+ else
+ {
+ if (b > g)
+ {
+ /* blue sector => red */
+ swap (b,r);
+ }
+ else
+ {
+ /* green sector => blue */
+ swap (g,b);
+ }
+ }
+
+ r += minor_shift;
+ b += minor_shift;
+ g += minor_shift;
+
+ label_color = RGBA_TO_UINT(r,g,b,255);
+ r = (base_color.red/256) + 127 ;
+ g = (base_color.green/256) + 127 ;
+ b = (base_color.blue/256) + 127 ;
+
+ label_color = RGBA_TO_UINT(r,g,b,255);
+
+ /* XXX can we do better than this ? */
+ /* We're trying ;) */
+ /* NUKECOLORS */
+
+ //frame_color_r = 192;
+ //frame_color_g = 192;
+ //frame_color_b = 194;
+
+ //selected_frame_color_r = 182;
+ //selected_frame_color_g = 145;
+ //selected_frame_color_b = 168;
+
+ //handle_color_r = 25 ;
+ //handle_color_g = 0 ;
+ //handle_color_b = 255 ;
+ //lock_handle_color_r = 235 ;
+ //lock_handle_color_g = 16;
+ //lock_handle_color_b = 16;
+}
+
+/**
+ * Convenience method to set the various canvas item colors
+ */
+void
+TimeAxisViewItem::set_colors()
+{
+ set_frame_color() ;
+ if (name_text) {
+ double height = NAME_HIGHLIGHT_THRESH;
+
+ if (frame) {
+ GtkArg args[1] ;
+ args[0].name = "y2" ;
+ gtk_object_getv (GTK_OBJECT(frame), 1, args);
+ height = GTK_VALUE_DOUBLE (args[0]);
+ }
+
+ if (height < NAME_HIGHLIGHT_THRESH) {
+ gtk_canvas_item_set(name_text, "fill_color_rgba", fill_color, NULL) ;
+ }
+ else {
+ gtk_canvas_item_set(name_text, "fill_color_rgba", label_color, NULL) ;
+ }
+ }
+
+ if (name_highlight) {
+ gtk_canvas_item_set(name_highlight, "fill_color_rgba", fill_color, NULL) ;
+ gtk_canvas_item_set(name_highlight, "outline_color_rgba", fill_color, NULL) ;
+ }
+ set_trim_handle_colors() ;
+}
+
+/**
+ * Sets the frame color depending on whether this item is selected
+ */
+void
+TimeAxisViewItem::set_frame_color()
+{
+ if (frame) {
+ uint32_t r,g,b,a;
+
+ if (_selected && should_show_selection) {
+ UINT_TO_RGBA(color_map[cSelectedFrameBase], &r, &g, &b, &a);
+ gtk_canvas_item_set(frame, "fill_color_rgba", RGBA_TO_UINT(r, g, b, fill_opacity), NULL) ;
+ } else {
+ UINT_TO_RGBA(color_map[cFrameBase], &r, &g, &b, &a);
+ gtk_canvas_item_set(frame, "fill_color_rgba", RGBA_TO_UINT(r, g, b, fill_opacity), NULL) ;
+ }
+ }
+}
+
+/**
+ * Sets the colors of the start and end trim handle depending on object state
+ *
+ */
+void
+TimeAxisViewItem::set_trim_handle_colors()
+{
+ if (frame_handle_start) {
+ if (position_locked) {
+ gtk_canvas_item_set(frame_handle_start, "fill_color_rgba", color_map[cTrimHandleLockedStart], NULL);
+ gtk_canvas_item_set(frame_handle_end, "fill_color_rgba", color_map[cTrimHandleLockedEnd], NULL) ;
+ } else {
+ gtk_canvas_item_set(frame_handle_start, "fill_color_rgba", color_map[cTrimHandleStart], NULL) ;
+ gtk_canvas_item_set(frame_handle_end, "fill_color_rgba", color_map[cTrimHandleEnd], NULL) ;
+ }
+ }
+}
+
+double
+TimeAxisViewItem::get_samples_per_unit()
+{
+ return(samples_per_unit) ;
+}
+
+void
+TimeAxisViewItem::set_samples_per_unit (double spu)
+{
+ samples_per_unit = spu ;
+ set_position (this->get_position(), this);
+ reset_width_dependent_items ((double)get_duration() / samples_per_unit);
+}
+
+void
+TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
+{
+ if (pixel_width < GRAB_HANDLE_LENGTH * 2) {
+
+ if (frame_handle_start) {
+ gtk_canvas_item_hide (frame_handle_start);
+ gtk_canvas_item_hide (frame_handle_end);
+ }
+
+ } if (pixel_width < 2.0) {
+
+ if (show_vestigial) {
+ gtk_canvas_item_show (vestigial_frame);
+ }
+
+ if (name_highlight) {
+ gtk_canvas_item_hide (name_highlight);
+ gtk_canvas_item_hide (name_text);
+ }
+
+ if (frame) {
+ gtk_canvas_item_hide (frame);
+ }
+
+ if (frame_handle_start) {
+ gtk_canvas_item_hide (frame_handle_start);
+ gtk_canvas_item_hide (frame_handle_end);
+ }
+
+ } else {
+ gtk_canvas_item_hide (vestigial_frame);
+
+ if (name_highlight) {
+
+ GtkArg args[1] ;
+ args[0].name = "y2" ;
+ gtk_object_getv (GTK_OBJECT(name_highlight), 1, args);
+ double height = GTK_VALUE_DOUBLE (args[0]);
+
+ if (height < NAME_HIGHLIGHT_THRESH) {
+ gtk_canvas_item_hide (name_highlight);
+ gtk_canvas_item_hide (name_text);
+ } else {
+ gtk_canvas_item_show (name_highlight);
+ gtk_canvas_item_show (name_text);
+ reset_name_width (pixel_width);
+ }
+
+ gtk_canvas_item_set (name_highlight, "x2", pixel_width - 1.0, NULL);
+ }
+
+ if (frame) {
+ gtk_canvas_item_show (frame);
+ gtk_canvas_item_set (frame, "x2", pixel_width, NULL);
+ }
+
+ if (frame_handle_start) {
+ if (pixel_width < (2*TimeAxisViewItem::GRAB_HANDLE_LENGTH)) {
+ gtk_canvas_item_hide (frame_handle_start);
+ gtk_canvas_item_hide (frame_handle_end);
+ }
+ gtk_canvas_item_show (frame_handle_start);
+ gtk_canvas_item_set(GTK_CANVAS_ITEM(frame_handle_end), "x1", pixel_width - (TimeAxisViewItem::GRAB_HANDLE_LENGTH ), NULL) ;
+ gtk_canvas_item_show (frame_handle_end);
+ gtk_canvas_item_set(GTK_CANVAS_ITEM(frame_handle_end), "x2", pixel_width, NULL) ;
+ }
+ }
+}
+
+void
+TimeAxisViewItem::reset_name_width (double pixel_width)
+{
+ gint width;
+ gint lbearing;
+ gint rbearing;
+ gint ascent;
+ gint descent;
+ Gdk_Font font (NAME_FONT);
+
+ if (name_text == 0) {
+ return;
+ }
+
+ int namelen = item_name.length();
+ char cstr[namelen+1];
+ strcpy (cstr, item_name.c_str());
+
+ while (namelen) {
+
+ gdk_string_extents (font,
+ cstr,
+ &lbearing,
+ &rbearing,
+ &width,
+ &ascent,
+ &descent);
+
+ if (width < (pixel_width - NAME_X_OFFSET)) {
+ break;
+ }
+
+ --namelen;
+ cstr[namelen] = '\0';
+
+ }
+
+ if (namelen == 0) {
+
+ gtk_canvas_item_hide (name_text);
+
+ } else {
+
+ /* don't use name for event handling if it leaves no room
+ for trimming to work.
+ */
+
+ if (pixel_width - width < (NAME_X_OFFSET * 2.0)) {
+ if (name_connected) {
+ name_connected = false;
+ }
+ } else {
+ if (!name_connected) {
+ name_connected = true;
+ }
+ }
+
+ gtk_canvas_item_set (name_text, "text", cstr, NULL);
+ gtk_canvas_item_show (name_text);
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Handle time axis removal
+
+/**
+ * Handles the Removal of this time axis item
+ * This _needs_ to be called to alert others of the removal properly, ie where the source
+ * of the removal came from.
+ *
+ * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method
+ * just now to capture the source of the removal
+ *
+ * @param src the identity of the object that initiated the change
+ */
+void
+TimeAxisViewItem::remove_this_item(void* src)
+{
+ /*
+ defer to idle loop, otherwise we'll delete this object
+ while we're still inside this function ...
+ */
+ Gtk::Main::idle.connect(bind(slot(&TimeAxisViewItem::idle_remove_this_item), this, src));
+}
+
+/**
+ * Callback used to remove this time axis item during the gtk idle loop
+ * This is used to avoid deleting the obejct while inside the remove_this_item
+ * method
+ *
+ * @param item the ImageFrameTimeAxisGroup to remove
+ * @param src the identity of the object that initiated the change
+ */
+gint
+TimeAxisViewItem::idle_remove_this_item(TimeAxisViewItem* item, void* src)
+{
+ item->ItemRemoved(item->get_item_name(), src) ; /* EMIT_SIGNAL */
+ delete item ;
+ item = 0 ;
+ return(false) ;
+}
diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h
new file mode 100644
index 0000000000..a1eff29c4b
--- /dev/null
+++ b/gtk2_ardour/time_axis_view_item.h
@@ -0,0 +1,453 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __gtk_ardour_time_axis_view_item_h__
+#define __gtk_ardour_time_axis_view_item_h__
+
+#include <sigc++/signal_system.h>
+#include <gtk-canvas.h>
+#include <jack/jack.h>
+#include <string>
+
+#include "selectable.h"
+
+class TimeAxisView;
+
+/**
+ * A base class for 'items' that may appear upon a TimeAxisView
+ *
+ */
+class TimeAxisViewItem : public SigC::Object, public Selectable
+{
+ public:
+ virtual ~TimeAxisViewItem() ;
+
+ /**
+ * Set the position of this item upon the timeline to the specified value
+ *
+ * @param pos the new position
+ * @param src the identity of the object that initiated the change
+ * @return true if the position change was a success, false otherwise
+ */
+ virtual bool set_position(jack_nframes_t pos, void* src, double* delta = 0) ;
+
+ /**
+ * Return the position of this item upon the timeline
+ *
+ * @return the position of this item
+ */
+ jack_nframes_t get_position() const ;
+
+ /**
+ * Sets the duration of this item
+ *
+ * @param dur the new duration of this item
+ * @param src the identity of the object that initiated the change
+ * @return true if the duration change was succesful, false otherwise
+ */
+ virtual bool set_duration(jack_nframes_t dur, void* src) ;
+
+ /**
+ * Returns the duration of this item
+ *
+ */
+ jack_nframes_t get_duration() const ;
+
+ /**
+ * Sets the maximum duration that this item make have.
+ *
+ * @param dur the new maximum duration
+ * @param src the identity of the object that initiated the change
+ */
+ virtual void set_max_duration(jack_nframes_t dur, void* src) ;
+
+ /**
+ * Returns the maxmimum duration that this item may be set to
+ *
+ * @return the maximum duration that this item may be set to
+ */
+ jack_nframes_t get_max_duration() const ;
+
+ /**
+ * Sets the minimu duration that this item may be set to
+ *
+ * @param the minimum duration that this item may be set to
+ * @param src the identity of the object that initiated the change
+ */
+ virtual void set_min_duration(jack_nframes_t dur, void* src) ;
+
+ /**
+ * Returns the minimum duration that this item mey be set to
+ *
+ * @return the nimum duration that this item mey be set to
+ */
+ jack_nframes_t get_min_duration() const ;
+
+ /**
+ * Sets whether the position of this Item is locked to its current position
+ * Locked items cannot be moved until the item is unlocked again.
+ *
+ * @param yn set to true to lock this item to its current position
+ * @param src the identity of the object that initiated the change
+ */
+ virtual void set_position_locked(bool yn, void* src) ;
+
+ /**
+ * Returns whether this item is locked to its current position
+ *
+ * @return true if this item is locked to its current posotion
+ * false otherwise
+ */
+ bool get_position_locked() const ;
+
+ /**
+ * Sets whether the Maximum Duration constraint is active and should be enforced
+ *
+ * @param active set true to enforce the max duration constraint
+ * @param src the identity of the object that initiated the change
+ */
+ void set_max_duration_active(bool active, void* src) ;
+
+ /**
+ * Returns whether the Maximum Duration constraint is active and should be enforced
+ *
+ * @return true if the maximum duration constraint is active, false otherwise
+ */
+ bool get_max_duration_active() const ;
+
+ /**
+ * Sets whether the Minimum Duration constraint is active and should be enforced
+ *
+ * @param active set true to enforce the min duration constraint
+ * @param src the identity of the object that initiated the change
+ */
+ void set_min_duration_active(bool active, void* src) ;
+
+ /**
+ * Returns whether the Maximum Duration constraint is active and should be enforced
+ *
+ * @return true if the maximum duration constraint is active, false otherwise
+ */
+ bool get_min_duration_active() const ;
+
+ /**
+ * Set the name/Id of this item.
+ *
+ * @param new_name the new name of this item
+ * @param src the identity of the object that initiated the change
+ */
+ void set_item_name(std::string new_name, void* src) ;
+
+ /**
+ * Returns the name/id of this item
+ *
+ * @return the name/id of this item
+ */
+ virtual std::string get_item_name() const ;
+
+ /**
+ * Set to true to indicate that this item is currently selected
+ *
+ * @param yn true if this item is currently selected
+ * @param src the identity of the object that initiated the change
+ */
+ virtual void set_selected(bool yn, void* src) ;
+
+ /**
+ * Set to true to indicate that this item should show its selection status
+ *
+ * @param yn true if this item should show its selected status
+ */
+ virtual void set_should_show_selection (bool yn) ;
+
+ /**
+ * Returns whether this item is currently selected.
+ *
+ * @return true if this item is currently selected, false otherwise
+ */
+ bool get_selected() const ;
+
+ //---------------------------------------------------------------------------------------//
+ // Parent Component Methods
+
+ /**
+ * Returns the TimeAxisView that this item is upon
+ *
+ * @return the timeAxisView that this item is placed upon
+ */
+ TimeAxisView& get_time_axis_view() ;
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods & data
+
+ /**
+ * Sets the displayed item text
+ * This item is the visual text name displayed on the canvas item, this can be different to the name of the item
+ *
+ * @param new_name the new name text to display
+ */
+ void set_name_text(std::string new_name) ;
+
+ /**
+ * Set the height of this item
+ *
+ * @param h the new height
+ */
+ virtual void set_height(double h) ;
+
+ /**
+ *
+ */
+ void set_color(GdkColor& color) ;
+
+ /**
+ *
+ */
+ GtkCanvasItem* get_canvas_frame() ;
+
+ /**
+ *
+ */
+ GtkCanvasItem* get_canvas_group();
+
+ /**
+ *
+ */
+ GtkCanvasItem* get_name_highlight();
+
+ /**
+ *
+ */
+ GtkCanvasItem* get_name_text();
+
+ /**
+ * Sets the samples per unit of this item.
+ * this item is used to determine the relative visual size and position of this item
+ * based upon its duration and start value.
+ *
+ * @param spu the new samples per unit value
+ */
+ virtual void set_samples_per_unit(double spu) ;
+
+ /**
+ * Returns the current samples per unit of this item
+ *
+ * @return the samples per unit of this item
+ */
+ double get_samples_per_unit() ;
+
+ virtual void raise () { return; }
+ virtual void raise_to_top () { return; }
+ virtual void lower () { return; }
+ virtual void lower_to_bottom () { return; }
+
+ /**
+ * returns true if the name area should respond to events.
+ */
+ bool name_active() const { return name_connected; }
+
+ // Default sizes, font and spacing
+ static std::string NAME_FONT ;
+ static const double NAME_X_OFFSET ;
+ static const double NAME_Y_OFFSET ;
+ static const double NAME_HIGHLIGHT_SIZE ;
+ static const double NAME_HIGHLIGHT_THRESH ;
+ static const double GRAB_HANDLE_LENGTH ;
+
+ /**
+ * Handles the Removal of this time axis item
+ * This _needs_ to be called to alert others of the removal properly, ie where the source
+ * of the removal came from.
+ *
+ * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method
+ * just now to capture the source of the removal
+ *
+ * @param src the identity of the object that initiated the change
+ */
+ virtual void remove_this_item(void* src) ;
+
+ /**
+ * Emitted when this Group has been removed
+ * This is different to the GoingAway signal in that this signal
+ * is emitted during the deletion of this Time Axis, and not during
+ * the destructor, this allows us to capture the source of the deletion
+ * event
+ */
+ SigC::Signal2<void,std::string,void*> ItemRemoved ;
+
+ /** Emitted when the name/Id of this item is changed */
+ SigC::Signal3<void,std::string,std::string,void*> NameChanged ;
+
+ /** Emiited when the position of this item changes */
+ SigC::Signal2<void,jack_nframes_t,void*> PositionChanged ;
+
+ /** Emitted when the position lock of this item is changed */
+ SigC::Signal2<void,bool,void*> PositionLockChanged ;
+
+ /** Emitted when the duration of this item changes */
+ SigC::Signal2<void,jack_nframes_t,void*> DurationChanged ;
+
+ /** Emitted when the maximum item duration is changed */
+ SigC::Signal2<void,jack_nframes_t,void*> MaxDurationChanged ;
+
+ /** Emitted when the mionimum item duration is changed */
+ SigC::Signal2<void,jack_nframes_t,void*> MinDurationChanged ;
+
+ /** Emitted when the selected status of this item changes */
+ SigC::Signal1<void, bool> Selected ;
+
+
+ protected:
+
+ enum Visibility {
+ ShowFrame = 0x1,
+ ShowNameHighlight = 0x2,
+ ShowNameText = 0x4,
+ ShowHandles = 0x8
+ };
+
+ /**
+ * Constructs a new TimeAxisViewItem.
+ *
+ * @param it_name the unique name/Id of this item
+ * @param parent the parent canvas group
+ * @param tv the TimeAxisView we are going to be added to
+ * @param spu samples per unit
+ * @param base_color
+ * @param start the start point of this item
+ * @param duration the duration of this item
+ */
+ TimeAxisViewItem(std::string it_name, GtkCanvasGroup* parent, TimeAxisView& tv, double spu, GdkColor& base_color,
+ jack_nframes_t start, jack_nframes_t duration, Visibility v = Visibility (0));
+
+ /**
+ * Calculates some contrasting color for displaying various parts of this item, based upon the base color
+ *
+ * @param color the base color of the item
+ */
+ virtual void compute_colors(GdkColor& color) ;
+
+ /**
+ * convenience method to set the various canvas item colors
+ */
+ virtual void set_colors() ;
+
+ /**
+ * Sets the frame color depending on whether this item is selected
+ */
+ void set_frame_color() ;
+
+ /**
+ * Sets the colors of the start and end trim handle depending on object state
+ *
+ */
+ void set_trim_handle_colors() ;
+
+ virtual void reset_width_dependent_items (double pixel_width);
+ void reset_name_width (double pixel_width);
+
+ /**
+ * Callback used to remove this item during the gtk idle loop
+ * This is used to avoid deleting the obejct while inside the remove_this_group
+ * method
+ *
+ * @param item the time axis item to remove
+ * @param src the identity of the object that initiated the change
+ */
+ static gint idle_remove_this_item(TimeAxisViewItem* item, void* src) ;
+
+ /** The time axis that this item is upon */
+ TimeAxisView& trackview ;
+
+ /** indicates whether this item is locked to its current position */
+ bool position_locked ;
+
+ /** The posotion of this item on the timeline */
+ jack_nframes_t frame_position ;
+
+ /** the duration of this item upon the timeline */
+ jack_nframes_t item_duration ;
+
+ /** the maximum duration that we allow this item to take */
+ jack_nframes_t max_item_duration ;
+
+ /** the minimu duration that we allow this item to take */
+ jack_nframes_t min_item_duration ;
+
+ /** indicates whether this Max Duration constraint is active */
+ bool max_duration_active ;
+
+ /** indicates whether this Min Duration constraint is active */
+ bool min_duration_active ;
+
+ /** the curretn samples per canvas unit */
+ double samples_per_unit ;
+
+ /** indicates if this item is currently selected */
+ bool selected ;
+
+ /** should the item show its selected status */
+ bool should_show_selection;
+
+ /**
+ * The unique item name of this Item
+ * Each item upon a time axis must have a unique id
+ */
+ std::string item_name ;
+
+ /**
+ * true if the name should respond to events
+ */
+ bool name_connected;
+
+ /**
+ * true if a small vestigial rect should be shown when the item gets very narrow
+ */
+
+ bool show_vestigial;
+
+ uint32_t fill_opacity;
+ uint32_t fill_color ;
+ uint32_t frame_color_r ;
+ uint32_t frame_color_g ;
+ uint32_t frame_color_b ;
+ uint32_t selected_frame_color_r ;
+ uint32_t selected_frame_color_g ;
+ uint32_t selected_frame_color_b ;
+ uint32_t label_color ;
+
+ uint32_t handle_color_r ;
+ uint32_t handle_color_g ;
+ uint32_t handle_color_b ;
+ uint32_t lock_handle_color_r ;
+ uint32_t lock_handle_color_g ;
+ uint32_t lock_handle_color_b ;
+
+ GtkCanvasItem* group ; /* the group */
+ GtkCanvasItem* vestigial_frame ; /* simplerect */
+ GtkCanvasItem* frame ; /* simplerect */
+ GtkCanvasItem* name_text ; /* text */
+ GtkCanvasItem* name_highlight ; /* simplerect */
+ GtkCanvasItem* frame_handle_start ; /* simplerect */
+ GtkCanvasItem* frame_handle_end ; /* simplerect */
+
+}; /* class TimeAxisViewItem */
+
+#endif /* __gtk_ardour_time_axis_view_item_h__ */
diff --git a/gtk2_ardour/time_selection.cc b/gtk2_ardour/time_selection.cc
new file mode 100644
index 0000000000..551e861176
--- /dev/null
+++ b/gtk2_ardour/time_selection.cc
@@ -0,0 +1,108 @@
+/*
+ Copyright (C) 2003-2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <algorithm>
+
+#include <pbd/error.h>
+#include <ardour/ardour.h>
+
+#include "time_selection.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+
+AudioRange&
+TimeSelection::operator[] (uint32_t which)
+{
+ for (std::list<AudioRange>::iterator i = begin(); i != end(); ++i) {
+ if ((*i).id == which) {
+ return *i;
+ }
+ }
+ fatal << compose (_("programming error: request for non-existent audio range (%1)!"), which) << endmsg;
+ /*NOTREACHED*/
+ return *(new AudioRange(0,0,0)); /* keep the compiler happy; never called */
+}
+
+bool
+TimeSelection::consolidate ()
+{
+ bool changed = false;
+
+ restart:
+ for (std::list<AudioRange>::iterator a = begin(); a != end(); ++a) {
+ for (std::list<AudioRange>::iterator b = begin(); b != end(); ++b) {
+
+ if (&(*a) == &(*b)) {
+ continue;
+ }
+
+ if ((*a).coverage ((*b).start, (*b).end) != OverlapNone) {
+ (*a).start = std::min ((*a).start, (*b).start);
+ (*a).end = std::max ((*a).end, (*b).end);
+ erase (b);
+ changed = true;
+ goto restart;
+ }
+ }
+ }
+
+ return changed;
+}
+
+jack_nframes_t
+TimeSelection::start ()
+{
+ if (empty()) {
+ return 0;
+ }
+
+ jack_nframes_t first = max_frames;
+
+ for (std::list<AudioRange>::iterator i = begin(); i != end(); ++i) {
+ if ((*i).start < first) {
+ first = (*i).start;
+ }
+ }
+ return first;
+}
+
+jack_nframes_t
+TimeSelection::end_frame ()
+{
+ jack_nframes_t last = 0;
+
+ /* XXX make this work like RegionSelection: no linear search needed */
+
+ for (std::list<AudioRange>::iterator i = begin(); i != end(); ++i) {
+ if ((*i).end > last) {
+ last = (*i).end;
+ }
+ }
+ return last;
+}
+
+jack_nframes_t
+TimeSelection::length()
+{
+ return end_frame() - start() + 1;
+}
+
diff --git a/gtk2_ardour/time_selection.h b/gtk2_ardour/time_selection.h
new file mode 100644
index 0000000000..f0db774733
--- /dev/null
+++ b/gtk2_ardour/time_selection.h
@@ -0,0 +1,38 @@
+#ifndef __ardour_gtk_time_selection_h__
+#define __ardour_gtk_time_selection_h__
+
+#include <list>
+#include <ardour/types.h>
+
+namespace ARDOUR {
+ class RouteGroup;
+}
+
+class TimeAxisView;
+
+struct TimeSelection : public std::list<ARDOUR::AudioRange> {
+
+ /* if (track == 0 && group == 0) then it applies to all
+ tracks.
+
+ if (track != 0 && group == 0) then it applies just to
+ that track.
+
+ if (group != 0) then it applies to all tracks in
+ the group.
+ */
+
+ TimeAxisView* track;
+ ARDOUR::RouteGroup* group;
+
+ ARDOUR::AudioRange& operator[](uint32_t);
+
+ jack_nframes_t start();
+ jack_nframes_t end_frame();
+ jack_nframes_t length();
+
+ bool consolidate ();
+};
+
+
+#endif /* __ardour_gtk_time_selection_h__ */
diff --git a/gtk2_ardour/track_selection.h b/gtk2_ardour/track_selection.h
new file mode 100644
index 0000000000..0c92ea40c2
--- /dev/null
+++ b/gtk2_ardour/track_selection.h
@@ -0,0 +1,10 @@
+#ifndef __ardour_gtk_track_selection_h__
+#define __ardour_gtk_track_selection_h__
+
+#include <list>
+
+class TimeAxisView;
+
+struct TrackSelection : public list<TimeAxisView*> {};
+
+#endif /* __ardour_gtk_track_selection_h__ */
diff --git a/gtk2_ardour/transport_xpms b/gtk2_ardour/transport_xpms
new file mode 100644
index 0000000000..a36071df92
--- /dev/null
+++ b/gtk2_ardour/transport_xpms
@@ -0,0 +1,181 @@
+/* XPM */
+static const gchar * loop_xpm[] = {
+"19 19 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ... ",
+" .+.. ",
+" .++.. ",
+" ...+++.... ",
+" ...++++++++... ",
+" ..+++.+++..+++.. ",
+" ..++...++.....++..",
+" .++.. .+.. ..++.",
+" .+.. ... ..+.",
+" .+. .+.",
+" .+.. ... ..+.",
+" .++.. ..+. ..++.",
+" ..++.....++...++..",
+" ..+++..+++.+++.. ",
+" ...++++++++... ",
+" ....+++... ",
+" ..++. ",
+" ..+. ",
+" ... "};
+
+/* XPM */
+static const gchar * arrow_xpm[] = {
+"19 19 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ",
+" ... ",
+" .+.. ",
+" .++.. ",
+" .+++.. ",
+" .++++.. ",
+" .+++++.. ",
+" .++++++.. ",
+" .+++++++.. ",
+" .++++++++. ",
+" .+++++++.. ",
+" .++++++.. ",
+" .+++++.. ",
+" .++++.. ",
+" .+++.. ",
+" .++.. ",
+" .+.. ",
+" ... ",
+" "};
+
+/* XPM */
+static const gchar * play_selection_xpm[] = {
+"19 19 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ",
+".... ... ....",
+".++. .+.. .++.",
+".++. .++.. .++.",
+".++. .+++.. .++.",
+".++. .++++.. .++.",
+".++. .+++++.. .++.",
+".++. .++++++.. .++.",
+".++...+++++++...++.",
+".+++++++++++++++++.",
+".++...+++++++...++.",
+".++. .++++++.. .++.",
+".++. .+++++.. .++.",
+".++. .++++.. .++.",
+".++. .+++.. .++.",
+".++. .++.. .++.",
+".++. .+.. .++.",
+".... ... ....",
+" "};
+
+/* XPM */
+static const gchar * end_xpm[] = {
+"19 19 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ",
+" ... ... ",
+" .+.. .+.. ",
+" .++.. .++. ",
+" .+++.. .++. ",
+" .++++.. .++. ",
+" .+++++.. .++. ",
+" .++++++...++. ",
+" .+++++++..++. ",
+" .+++++++..++. ",
+" .+++++++..++. ",
+" .++++++...++. ",
+" .+++++.. .++. ",
+" .++++.. .++. ",
+" .+++.. .++. ",
+" .++.. .++. ",
+" .+.. .+.. ",
+" ... ... ",
+" "};
+
+/* XPM */
+static const gchar * rec_xpm[] = {
+"19 19 5 1",
+" c None",
+". c #FFFFFF",
+"+ c #FDBEB6",
+"@ c #F92104",
+"# c #FB7A69",
+" ",
+" ",
+" ..... ",
+" .+@@@@@+. ",
+" .@@@@@@@@#. ",
+" .@@@@@@@@@@#. ",
+" +@@@@@@@@@@@+ ",
+" .@@@@@@@@@@@@@. ",
+" .@@@@@@@@@@@@@. ",
+" .@@@@@@@@@@@@@. ",
+" .@@@@@@@@@@@@@. ",
+" .@@@@@@@@@@@@@. ",
+" +@@@@@@@@@@@+ ",
+" .@@@@@@@@@@#. ",
+" .@@@@@@@@#. ",
+" .+@@@@@+. ",
+" ..... ",
+" ",
+" "};
+/* XPM */
+static const gchar * start_xpm[] = {
+"19 19 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ",
+" ... ... ",
+" ..+. ..+. ",
+" .++. ..++. ",
+" .++. ..+++. ",
+" .++. ..++++. ",
+" .++. ..+++++. ",
+" .++...++++++. ",
+" .++..+++++++. ",
+" .++..+++++++. ",
+" .++..+++++++. ",
+" .++...++++++. ",
+" .++. ..+++++. ",
+" .++. ..++++. ",
+" .++. ..+++. ",
+" .++. ..++. ",
+" ..+. ..+. ",
+" ... ... ",
+" "};
+/* XPM */
+static const gchar * stop_xpm[] = {
+"19 19 3 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+" ",
+" ",
+" ",
+" ",
+" ........... ",
+" .+++++++++. ",
+" .+++++++++. ",
+" .+++++++++. ",
+" .+++++++++. ",
+" .+++++++++. ",
+" .+++++++++. ",
+" .+++++++++. ",
+" .+++++++++. ",
+" .+++++++++. ",
+" ........... ",
+" ",
+" ",
+" ",
+" "};
diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc
new file mode 100644
index 0000000000..4a023b8ad9
--- /dev/null
+++ b/gtk2_ardour/utils.cc
@@ -0,0 +1,520 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cctype>
+#include <libart_lgpl/art_misc.h>
+#include <gtk--/window.h>
+#include <gtk--/combo.h>
+#include <gtk--/label.h>
+#include <gtk--/paned.h>
+#include <gtk/gtkpaned.h>
+
+#include <gtkmmext/utils.h>
+
+#include "ardour_ui.h"
+#include "utils.h"
+#include "i18n.h"
+#include "rgb_macros.h"
+
+using namespace std;
+using namespace Gtk;
+
+string
+short_version (string orig, string::size_type target_length)
+{
+ /* this tries to create a recognizable abbreviation
+ of "orig" by removing characters until we meet
+ a certain target length.
+
+ note that we deliberately leave digits in the result
+ without modification.
+ */
+
+
+ string::size_type pos;
+
+ /* remove white-space and punctuation, starting at end */
+
+ while (orig.length() > target_length) {
+ if ((pos = orig.find_last_of (_("\"\n\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="))) == string::npos) {
+ break;
+ }
+ orig.replace (pos, 1, "");
+ }
+
+ /* remove lower-case vowels, starting at end */
+
+ while (orig.length() > target_length) {
+ if ((pos = orig.find_last_of (_("aeiou"))) == string::npos) {
+ break;
+ }
+ orig.replace (pos, 1, "");
+ }
+
+ /* remove upper-case vowels, starting at end */
+
+ while (orig.length() > target_length) {
+ if ((pos = orig.find_last_of (_("AEIOU"))) == string::npos) {
+ break;
+ }
+ orig.replace (pos, 1, "");
+ }
+
+ /* remove lower-case consonants, starting at end */
+
+ while (orig.length() > target_length) {
+ if ((pos = orig.find_last_of (_("bcdfghjklmnpqrtvwxyz"))) == string::npos) {
+ break;
+ }
+ orig.replace (pos, 1, "");
+ }
+
+ /* remove upper-case consonants, starting at end */
+
+ while (orig.length() > target_length) {
+ if ((pos = orig.find_last_of (_("BCDFGHJKLMNPQRTVWXYZ"))) == string::npos) {
+ break;
+ }
+ orig.replace (pos, 1, "");
+ }
+
+ /* whatever the length is now, use it */
+
+ return orig;
+}
+
+string
+fit_to_pixels (string str, int32_t pixel_width, Gdk_Font& font)
+{
+ gint width;
+ gint lbearing;
+ gint rbearing;
+ gint ascent;
+ gint descent;
+
+ int namelen = str.length();
+ char cstr[namelen+1];
+ strcpy (cstr, str.c_str());
+
+ while (namelen) {
+
+ gdk_string_extents (font,
+ cstr,
+ &lbearing,
+ &rbearing,
+ &width,
+ &ascent,
+ &descent);
+
+ if (width < (pixel_width)) {
+ break;
+ }
+
+ --namelen;
+ cstr[namelen] = '\0';
+
+ }
+
+ return cstr;
+}
+
+int
+atoi (const string& s)
+{
+ return atoi (s.c_str());
+}
+
+double
+atof (const string& s)
+{
+ return atof (s.c_str());
+}
+
+void
+strip_whitespace_edges (string& str)
+{
+ string::size_type i;
+ string::size_type len;
+ string::size_type s;
+
+ len = str.length();
+
+ for (i = 0; i < len; ++i) {
+ if (isgraph (str[i])) {
+ break;
+ }
+ }
+
+ s = i;
+
+ for (i = len - 1; i >= 0; --i) {
+ if (isgraph (str[i])) {
+ break;
+ }
+ }
+
+ str = str.substr (s, (i - s) + 1);
+}
+
+vector<string>
+internationalize (const char **array)
+{
+ vector<string> v;
+
+ for (uint32_t i = 0; array[i]; ++i) {
+ v.push_back (_(array[i]));
+ }
+
+ return v;
+}
+
+gint
+just_hide_it (GdkEventAny *ev, Gtk::Window *win)
+{
+ ARDOUR_UI::instance()->allow_focus (false);
+ win->hide_all ();
+ return TRUE;
+}
+
+void
+allow_keyboard_focus (bool yn)
+{
+ ARDOUR_UI::instance()->allow_focus (yn);
+}
+
+/* xpm2rgb copied from nixieclock, which bore the legend:
+
+ nixieclock - a nixie desktop timepiece
+ Copyright (C) 2000 Greg Ercolano, erco@3dsite.com
+
+ and was released under the GPL.
+*/
+
+unsigned char*
+xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h)
+{
+ static long vals[256], val;
+ uint32_t t, x, y, colors, cpp;
+ unsigned char c;
+ unsigned char *savergb, *rgb;
+
+ // PARSE HEADER
+
+ if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) {
+ error << compose (_("bad XPM header %1"), xpm[0])
+ << endmsg;
+ return 0;
+ }
+
+ savergb = rgb = (unsigned char*)art_alloc (h * w * 3);
+
+ // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
+ for (t = 0; t < colors; ++t) {
+ sscanf (xpm[t+1], "%c c #%lx", &c, &val);
+ vals[c] = val;
+ }
+
+ // COLORMAP -> RGB CONVERSION
+ // Get low 3 bytes from vals[]
+ //
+
+ const char *p;
+ for (y = h-1; y > 0; --y) {
+
+ for (p = xpm[1+colors+(h-y-1)], x = 0; x < w; x++, rgb += 3) {
+ val = vals[(int)*p++];
+ *(rgb+2) = val & 0xff; val >>= 8; // 2:B
+ *(rgb+1) = val & 0xff; val >>= 8; // 1:G
+ *(rgb+0) = val & 0xff; // 0:R
+ }
+ }
+
+ return (savergb);
+}
+
+unsigned char*
+xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
+{
+ static long vals[256], val;
+ uint32_t t, x, y, colors, cpp;
+ unsigned char c;
+ unsigned char *savergb, *rgb;
+ char transparent;
+
+ // PARSE HEADER
+
+ if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) {
+ error << compose (_("bad XPM header %1"), xpm[0])
+ << endmsg;
+ return 0;
+ }
+
+ savergb = rgb = (unsigned char*)art_alloc (h * w * 4);
+
+ // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
+
+ if (strstr (xpm[1], "None")) {
+ sscanf (xpm[1], "%c", &transparent);
+ t = 1;
+ } else {
+ transparent = 0;
+ t = 0;
+ }
+
+ for (; t < colors; ++t) {
+ sscanf (xpm[t+1], "%c c #%lx", &c, &val);
+ vals[c] = val;
+ }
+
+ // COLORMAP -> RGB CONVERSION
+ // Get low 3 bytes from vals[]
+ //
+
+ const char *p;
+ for (y = h-1; y > 0; --y) {
+
+ char alpha;
+
+ for (p = xpm[1+colors+(h-y-1)], x = 0; x < w; x++, rgb += 4) {
+
+ if (transparent && (*p++ == transparent)) {
+ alpha = 0;
+ val = 0;
+ } else {
+ alpha = 255;
+ val = vals[(int)*p];
+ }
+
+ *(rgb+3) = alpha; // 3: alpha
+ *(rgb+2) = val & 0xff; val >>= 8; // 2:B
+ *(rgb+1) = val & 0xff; val >>= 8; // 1:G
+ *(rgb+0) = val & 0xff; // 0:R
+ }
+ }
+
+ return (savergb);
+}
+
+GtkCanvasPoints*
+get_canvas_points (string who, uint32_t npoints)
+{
+ // cerr << who << ": wants " << npoints << " canvas points" << endl;
+#ifdef TRAP_EXCESSIVE_POINT_REQUESTS
+ if (npoints > (uint32_t) gdk_screen_width() + 4) {
+ abort ();
+ }
+#endif
+ return gtk_canvas_points_new (npoints);
+}
+
+int
+channel_combo_get_channel_count (Gtk::Combo& combo)
+{
+ string str = combo.get_entry()->get_text();
+ int chns;
+
+ if (str == _("mono")) {
+ return 1;
+ } else if (str == _("stereo")) {
+ return 2;
+ } else if ((chns = atoi (str)) != 0) {
+ return chns;
+ } else {
+ return 0;
+ }
+}
+
+static int32_t
+int_from_hex (char hic, char loc)
+{
+ int hi; /* hi byte */
+ int lo; /* low byte */
+
+ hi = (int) hic;
+
+ if( ('0'<=hi) && (hi<='9') ) {
+ hi -= '0';
+ } else if( ('a'<= hi) && (hi<= 'f') ) {
+ hi -= ('a'-10);
+ } else if( ('A'<=hi) && (hi<='F') ) {
+ hi -= ('A'-10);
+ }
+
+ lo = (int) loc;
+
+ if( ('0'<=lo) && (lo<='9') ) {
+ lo -= '0';
+ } else if( ('a'<=lo) && (lo<='f') ) {
+ lo -= ('a'-10);
+ } else if( ('A'<=lo) && (lo<='F') ) {
+ lo -= ('A'-10);
+ }
+
+ return lo + (16 * hi);
+}
+
+void
+url_decode (string& url)
+{
+ string::iterator last;
+ string::iterator next;
+
+ for (string::iterator i = url.begin(); i != url.end(); ++i) {
+ if ((*i) == '+') {
+ *i = ' ';
+ }
+ }
+
+ if (url.length() <= 3) {
+ return;
+ }
+
+ last = url.end();
+
+ --last; /* points at last char */
+ --last; /* points at last char - 1 */
+
+ for (string::iterator i = url.begin(); i != last; ) {
+
+ if (*i == '%') {
+
+ next = i;
+
+ url.erase (i);
+
+ i = next;
+ ++next;
+
+ if (isxdigit (*i) && isxdigit (*next)) {
+ /* replace first digit with char */
+ *i = int_from_hex (*i,*next);
+ ++i; /* points at 2nd of 2 digits */
+ url.erase (i);
+ }
+ } else {
+ ++i;
+ }
+ }
+}
+
+string
+get_font_for_style (string widgetname)
+{
+ Gtk::Label foobar;
+
+ foobar.set_name (widgetname);
+ foobar.ensure_style();
+
+ if (foobar.get_style() == 0 || foobar.get_style()->gtkobj()->rc_style == 0 || foobar.get_style()->gtkobj()->rc_style->font_name == 0) {
+ return "fixed";
+ }
+
+ string str = foobar.get_style()->gtkobj()->rc_style->font_name;
+
+ if (str.empty()) {
+ return "fixed"; // standard X Window fallback font
+ } else {
+ return str;
+ }
+}
+gint
+pane_handler (GdkEventButton* ev, Gtk::Paned* pane)
+{
+ if (ev->window != Gtkmmext::get_paned_handle (*pane)) {
+ return FALSE;
+ }
+
+ if (Keyboard::is_delete_event (ev)) {
+
+ gint pos;
+ gint cmp;
+
+ pos = Gtkmmext::gtk_paned_get_position (pane->gtkobj());
+
+ if (dynamic_cast<VPaned*>(pane)) {
+ cmp = pane->height();
+ } else {
+ cmp = pane->width();
+ }
+
+ /* we have to use approximations here because we can't predict the
+ exact position or sizes of the pane (themes, etc)
+ */
+
+ if (pos < 10 || abs (pos - cmp) < 10) {
+
+ /* already collapsed: restore it (note that this is cast from a pointer value to int, which is tricky on 64bit */
+
+ pane->set_position ((gint64) pane->get_data ("rpos"));
+
+ } else {
+
+ int collapse_direction;
+
+ /* store the current position */
+
+ pane->set_data ("rpos", (gpointer) pos);
+
+ /* collapse to show the relevant child in full */
+
+ collapse_direction = (gint64) pane->get_data ("collapse-direction");
+
+ if (collapse_direction) {
+ pane->set_position (1);
+ } else {
+ if (dynamic_cast<VPaned*>(pane)) {
+ pane->set_position (pane->height());
+ } else {
+ pane->set_position (pane->width());
+ }
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+uint32_t
+rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a)
+{
+ Gtk::Label foo;
+
+ foo.set_name (style);
+ foo.ensure_style ();
+
+ GtkRcStyle* waverc = foo.get_style()->gtkobj()->rc_style;
+
+ if (waverc) {
+ r = waverc->fg[GTK_STATE_NORMAL].red / 257;
+ g = waverc->fg[GTK_STATE_NORMAL].green / 257;
+ b = waverc->fg[GTK_STATE_NORMAL].blue / 257;
+
+ /* what a hack ... "a" is for "active" */
+
+ a = waverc->fg[GTK_STATE_ACTIVE].red / 257;
+
+ } else {
+ warning << compose (_("missing RGBA style for \"%1\""), style) << endl;
+ }
+
+ return (uint32_t) RGBA_TO_UINT(r,g,b,a);
+}
diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h
new file mode 100644
index 0000000000..bc0f5cfdec
--- /dev/null
+++ b/gtk2_ardour/utils.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2002 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_gtk_utils_h__
+#define __ardour_gtk_utils_h__
+
+#include <string>
+#include <vector>
+#include <cmath>
+#include <ardour/types.h>
+#include <gtk-canvas.h>
+#include <gdk--/types.h>
+
+namespace Gtk {
+ class Window;
+ class Combo;
+ class Paned;
+}
+
+static inline double
+gain_to_slider_position (ARDOUR::gain_t g)
+{
+ if (g == 0) return 0;
+ return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
+
+}
+
+static inline ARDOUR::gain_t
+slider_position_to_gain (double pos)
+{
+ /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
+ if (pos == 0.0) return 0;
+ return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
+}
+
+std::string short_version (std::string, std::string::size_type target_length);
+std::string fit_to_pixels (std::string, int32_t pixel_width, Gdk_Font&);
+
+int atoi (const std::string&);
+double atof (const std::string&);
+void strip_whitespace_edges (std::string& str);
+void url_decode (std::string&);
+gint just_hide_it (GdkEventAny*, Gtk::Window*);
+void allow_keyboard_focus (bool);
+
+unsigned char* xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h);
+unsigned char* xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h);
+
+GtkCanvasPoints* get_canvas_points (std::string who, uint32_t npoints);
+
+int channel_combo_get_channel_count (Gtk::Combo& combo);
+std::string get_font_for_style (std::string widgetname);
+
+gint pane_handler (GdkEventButton*, Gtk::Paned*);
+uint32_t rgba_from_style (std::string style, uint32_t, uint32_t, uint32_t, uint32_t);
+
+#endif /* __ardour_gtk_utils_h__ */
diff --git a/gtk2_ardour/visual_time_axis.cc b/gtk2_ardour/visual_time_axis.cc
new file mode 100644
index 0000000000..228a85b70b
--- /dev/null
+++ b/gtk2_ardour/visual_time_axis.cc
@@ -0,0 +1,491 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <cstdlib>
+#include <cmath>
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <pbd/error.h>
+#include <pbd/stl_delete.h>
+
+#include <gtkmmext/utils.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/gtk_ui.h>
+#include <gtkmmext/stop_signal.h>
+#include <gtkmmext/choice.h>
+
+#include <ardour/session.h>
+#include <ardour/utils.h>
+#include <ardour/insert.h>
+#include <ardour/location.h>
+
+#include "ardour_ui.h"
+#include "public_editor.h"
+#include "imageframe_time_axis.h"
+#include "canvas-simplerect.h"
+#include "imageframe_time_axis_view.h"
+#include "marker_time_axis_view.h"
+#include "imageframe_view.h"
+#include "marker_time_axis.h"
+#include "marker_view.h"
+#include "utils.h"
+#include "prompter.h"
+#include "rgb_macros.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace SigC;
+using namespace Gtk;
+
+//XXX should really have a common home...
+static const gchar* small_x_xpm[] = {
+ "11 11 2 1",
+ " c None",
+ ". c #000000",
+ " ",
+ " ",
+ " . . ",
+ " . . ",
+ " . . ",
+ " . ",
+ " . . ",
+ " . . ",
+ " . . ",
+ " ",
+ " "};
+
+
+/**
+ * Abstract Constructor for base visual time axis classes
+ *
+ * @param name the name/Id of thie TimeAxis
+ * @param ed the Ardour PublicEditor
+ * @param sess the current session
+ * @param canvas the parent canvas object
+ */
+VisualTimeAxis::VisualTimeAxis(std::string name, PublicEditor& ed, ARDOUR::Session& sess, Widget *canvas)
+ : AxisView(sess),
+ TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas),
+ visual_button (_("v")),
+ size_button (_("h"))
+{
+ time_axis_name = name ;
+ name_prompter = 0 ;
+ _color = unique_random_color() ;
+ _marked_for_display = true;
+
+ name_entry.activate.connect(slot(*this, &VisualTimeAxis::name_entry_changed)) ;
+ name_entry.focus_out_event.connect(slot(*this, &VisualTimeAxis::name_entry_focus_out_handler)) ;
+ name_entry.button_press_event.connect(slot(*this, &VisualTimeAxis::name_entry_button_press_handler)) ;
+ name_entry.button_release_event.connect(slot(*this, &VisualTimeAxis::name_entry_button_release_handler)) ;
+ name_entry.key_release_event.connect(slot(*this, &VisualTimeAxis::name_entry_key_release_handler)) ;
+
+ size_button.set_name("TrackSizeButton") ;
+ visual_button.set_name("TrackVisualButton") ;
+ hide_button.set_name("TrackRemoveButton") ;
+ hide_button.add(*(Gtk::manage(new Gtk::Pixmap(small_x_xpm)))) ;
+ size_button.button_release_event.connect (slot (*this, &VisualTimeAxis::size_click)) ;
+ visual_button.clicked.connect (slot (*this, &VisualTimeAxis::visual_click)) ;
+ hide_button.clicked.connect (slot (*this, &VisualTimeAxis::hide_click)) ;
+ ARDOUR_UI::instance()->tooltips().set_tip(size_button,_("Display Height")) ;
+ ARDOUR_UI::instance()->tooltips().set_tip(visual_button, _("Visual options")) ;
+ ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("Hide this track")) ;
+
+ 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);
+
+ /* remove focus from the buttons */
+ size_button.unset_flags(GTK_CAN_FOCUS) ;
+ hide_button.unset_flags(GTK_CAN_FOCUS) ;
+ visual_button.unset_flags(GTK_CAN_FOCUS) ;
+
+ set_height(Normal) ;
+}
+
+/**
+ * VisualTimeAxis Destructor
+ *
+ */
+VisualTimeAxis::~VisualTimeAxis()
+{
+ if(name_prompter)
+ {
+ delete name_prompter ;
+ name_prompter = 0 ;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Name/Id Accessors/Mutators
+
+void
+VisualTimeAxis::set_time_axis_name(std::string name, void* src)
+{
+ std::string old_name = time_axis_name ;
+
+ if(name != time_axis_name)
+ {
+ time_axis_name = name ;
+ label_view() ;
+ editor.route_name_changed(this) ;
+
+ NameChanged(time_axis_name, old_name, src) ; /* EMIT_SIGNAL */
+ }
+}
+
+std::string
+VisualTimeAxis::name() const
+{
+ return(time_axis_name) ;
+}
+
+
+//---------------------------------------------------------------------------------------//
+// ui methods & data
+
+/**
+ * Sets the height of this TrackView to one of the defined TrackHeghts
+ *
+ * @param h the TrackHeight value to set
+ */
+void
+VisualTimeAxis::set_height(TrackHeight h)
+{
+ TimeAxisView::set_height(h) ;
+
+ switch (height)
+ {
+ case Largest:
+ case Large:
+ case Larger:
+ case Normal:
+ {
+ name_label.hide() ;
+ name_entry.show() ;
+ other_button_hbox.show_all() ;
+ break;
+ }
+ case Smaller:
+ {
+ name_label.hide() ;
+ name_entry.show() ;
+ other_button_hbox.hide_all() ;
+ break;
+ }
+ case Small:
+ {
+ name_label.show() ;
+ name_entry.hide() ;
+ other_button_hbox.hide_all() ;
+ }
+ break;
+ }
+}
+
+/**
+ * Handle the visuals button click
+ *
+ */
+void
+VisualTimeAxis::visual_click()
+{
+ popup_display_menu(0);
+}
+
+
+/**
+ * Handle the hide buttons click
+ *
+ */
+void
+VisualTimeAxis::hide_click()
+{
+ editor.unselect_strip_in_display (*this);
+}
+
+
+/**
+ * Allows the selection of a new color for this TimeAxis
+ *
+ */
+void
+VisualTimeAxis::select_track_color ()
+{
+ if(choose_time_axis_color())
+ {
+ //Does nothing at this abstract point
+ }
+}
+
+/**
+ * Provides a color chooser for the selection of a new time axis color.
+ *
+ */
+bool
+VisualTimeAxis::choose_time_axis_color()
+{
+ bool picked ;
+ GdkColor color ;
+ gdouble current[4] ;
+
+ current[0] = _color.get_red() / 65535.0 ;
+ current[1] = _color.get_green() / 65535.0 ;
+ current[2] = _color.get_blue() / 65535.0 ;
+ current[3] = 1.0 ;
+
+ color = Gtkmmext::UI::instance()->get_color(_("ardour: color selection"),picked, current) ;
+
+ if (picked)
+ {
+ set_time_axis_color(color) ;
+ }
+ return(picked) ;
+}
+
+/**
+ * Sets the color of this TimeAxis to the specified color c
+ *
+ * @param c the new TimeAxis color
+ */
+void
+VisualTimeAxis::set_time_axis_color(Gdk_Color c)
+{
+ _color = c ;
+}
+
+void
+VisualTimeAxis::set_selected_regionviews (AudioRegionSelection& regions)
+{
+ // Not handled by purely visual TimeAxis
+}
+
+//---------------------------------------------------------------------------------------//
+// Handle time axis removal
+
+/**
+ * Handles the Removal of this VisualTimeAxis
+ *
+ * @param src the identity of the object that initiated the change
+ */
+void
+VisualTimeAxis::remove_this_time_axis(void* src)
+{
+ vector<string> choices;
+
+ std::string prompt = compose (_("Do you really want to remove track \"%1\" ?\n(cannot be undone)"), time_axis_name);
+
+ choices.push_back (_("Yes, remove it."));
+ choices.push_back (_("No, do nothing."));
+
+ Gtkmmext::Choice prompter (prompt, choices);
+
+ prompter.chosen.connect (Gtk::Main::quit.slot());
+ prompter.show_all ();
+
+ Gtk::Main::run ();
+
+ if (prompter.get_choice() == 0)
+ {
+ /*
+ defer to idle loop, otherwise we'll delete this object
+ while we're still inside this function ...
+ */
+ Gtk::Main::idle.connect(bind(slot(&VisualTimeAxis::idle_remove_this_time_axis), this, src));
+ }
+}
+
+/**
+ * Callback used to remove this time axis during the gtk idle loop
+ * This is used to avoid deleting the obejct while inside the remove_this_time_axis
+ * method
+ *
+ * @param ta the VisualTimeAxis to remove
+ * @param src the identity of the object that initiated the change
+ */
+gint
+VisualTimeAxis::idle_remove_this_time_axis(VisualTimeAxis* ta, void* src)
+{
+ ta->VisualTimeAxisRemoved(ta->name(), src) ; /* EMIT_SIGNAL */
+ delete ta ;
+ ta = 0 ;
+ return(false) ;
+}
+
+
+
+
+//---------------------------------------------------------------------------------------//
+// Handle TimeAxis rename
+
+/**
+ * Construct a new prompt to receive a new name for this TimeAxis
+ *
+ * @see finish_time_axis_rename()
+ */
+void
+VisualTimeAxis::start_time_axis_rename()
+{
+ if(name_prompter)
+ {
+ delete name_prompter ;
+ name_prompter = 0 ;
+ }
+
+ name_prompter = new ArdourPrompter() ;
+
+ name_prompter->set_prompt (_("new name: ")) ;
+ ARDOUR_UI::instance()->allow_focus(true) ;
+ name_prompter->done.connect (slot(*this, &VisualTimeAxis::finish_time_axis_rename)) ;
+ name_prompter->show_all() ;
+}
+
+/**
+ * Handles the new name for this TimeAxis from the name prompt
+ *
+ * @see start_time_axis_rename()
+ */
+void
+VisualTimeAxis::finish_time_axis_rename()
+{
+ name_prompter->hide_all () ;
+ ARDOUR_UI::instance()->allow_focus (false) ;
+
+ if (name_prompter->status == Gtkmmext::Prompter::cancelled)
+ {
+ return;
+ }
+
+ string result ;
+ name_prompter->get_result (result) ;
+ //time_axis_name = result ;
+
+ if (editor.get_named_time_axis(result) != 0) {
+ ARDOUR_UI::instance()->popup_error (_("A track already exists with that name"));
+ return ;
+ }
+
+ set_time_axis_name(result, this) ;
+
+ delete name_prompter ;
+ name_prompter = 0 ;
+ label_view() ;
+}
+
+/**
+ * Handle the (re-)displaying of the TimeAxis name label
+ *
+ */
+void
+VisualTimeAxis::label_view()
+{
+ name_label.set_text(time_axis_name) ;
+ name_entry.set_text(time_axis_name) ;
+ ARDOUR_UI::instance()->tooltips().set_tip(name_entry, time_axis_name) ;
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Handle name entry signals
+
+void
+VisualTimeAxis::name_entry_changed()
+{
+ ARDOUR_UI::generic_focus_out_event (0);
+
+ string x = name_entry.get_text ();
+
+ if (x == time_axis_name) {
+ return;
+ }
+
+ if (x.length() == 0) {
+ name_entry.set_text (time_axis_name);
+ return;
+ }
+
+ strip_whitespace_edges(x);
+
+ if (!editor.get_named_time_axis(x)) {
+ set_time_axis_name(x, this);
+ } else {
+ ARDOUR_UI::instance()->popup_error (_("a track already exists with that name"));
+ name_entry.set_text(time_axis_name);
+ }
+}
+
+gint
+VisualTimeAxis::name_entry_button_press_handler(GdkEventButton *ev)
+{
+ if (ev->button == 3) {
+ return stop_signal (name_entry, "button_press_event");
+ }
+ return FALSE;
+}
+
+gint
+VisualTimeAxis::name_entry_button_release_handler(GdkEventButton *ev)
+{
+ return FALSE;
+}
+
+gint
+VisualTimeAxis::name_entry_focus_out_handler(GdkEventFocus* ev)
+{
+ name_entry_changed();
+ return TRUE;
+}
+
+gint
+VisualTimeAxis::name_entry_key_release_handler(GdkEventKey* ev)
+{
+ switch (ev->keyval) {
+ case GDK_Tab:
+ case GDK_Up:
+ case GDK_Down:
+ name_entry_changed ();
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+
+//---------------------------------------------------------------------------------------//
+// Super class methods not handled by VisualTimeAxis
+
+void
+VisualTimeAxis::show_timestretch (jack_nframes_t start, jack_nframes_t end)
+{
+ // Not handled by purely visual TimeAxis
+}
+
+void
+VisualTimeAxis::hide_timestretch()
+{
+ // Not handled by purely visual TimeAxis
+}
+
+
diff --git a/gtk2_ardour/visual_time_axis.h b/gtk2_ardour/visual_time_axis.h
new file mode 100644
index 0000000000..6d9eb5cfb6
--- /dev/null
+++ b/gtk2_ardour/visual_time_axis.h
@@ -0,0 +1,277 @@
+/*
+ Copyright (C) 2003 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#ifndef __ardour_visual_time_axis_h__
+#define __ardour_visual_time_axis_h__
+
+#include <gtk--.h>
+#include <gtk-canvas.h>
+#include <gtkmmext/selector.h>
+#include <gtkmmext/popup_selector.h>
+
+#include "ardour_dialog.h"
+#include "route_ui.h"
+#include "enums.h"
+#include "time_axis_view.h"
+
+
+namespace ARDOUR
+{
+ class Session ;
+}
+
+class PublicEditor;
+class ImageFrameView;
+class ImageFrameTimeAxisView;
+class MarkersTimeAxisView;
+class TimeSelection;
+class AudioRegionSelection;
+class MarkerTimeAxis;
+class TimeAxisViewStrip;
+
+/**
+ * Base Abstact Class for TimeAxis views that operate purely within the visual domain.
+ *
+ * This class provides many of the common methods required for visual TimeAxis views. The aim is
+ * to provide an abstract layer during the developmnt of the visual based time axis'. Many of these
+ * methods have a better home further up the class heirarchy, and in fact some are replication of
+ * methods found within RouteUI. This, however, has been required due to various problems with previous
+ * versions of g++, mainly 2.95, which are not correctly handling virtual methods, virtual base classes,
+ * and virtual methods when used with Multiple Inheritance. Perhaps these could be combined once the
+ * compilers all agree on hos do to do stuff...
+ */
+class VisualTimeAxis : public TimeAxisView
+{
+ public:
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * VisualTimeAxis Destructor
+ *
+ */
+ virtual ~VisualTimeAxis() ;
+
+ //---------------------------------------------------------------------------------------//
+ // Name/Id Accessors/Mutators
+
+ /**
+ * Returns the name of this TimeAxis
+ *
+ * @return the name of this TimeAxis
+ */
+ virtual std::string name() const ;
+
+ /**
+ * Sets the name of this TimeAxis
+ *
+ * @param name the new name of this TimeAxis
+ * @param src the identity of the object that initiated the change
+ */
+ virtual void set_time_axis_name(std::string name, void* src) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods & data
+
+ /**
+ * Sets the height of this TrackView to one of the defined TrackHeghts
+ *
+ * @param h the TrackHeight value to set
+ */
+ virtual void set_height (TrackHeight h);
+
+ //---------------------------------------------------------------------------------------//
+ // Selection Methods
+ // selection methods are not handled by visual time axis object yet...
+
+ /**
+ * Not implemented
+ */
+ virtual void set_selected_regionviews(AudioRegionSelection&) ;
+
+
+ //---------------------------------------------------------------------------------//
+ // Emitted Signals
+
+ /**
+ * Emitted when we have changed the gui, and what we have shanged
+ */
+ SigC::Signal2<void,string,void*> gui_changed ;
+
+ /**
+ * Emitted when this Visual Time Axis has been removed
+ * This is different to the GoingAway signal in that this signal
+ * is emitted during the deletion of this Time Axis, and not during
+ * the destructor, this allows us to capture the source of the deletion
+ * event
+ */
+ SigC::Signal2<void,std::string,void*> VisualTimeAxisRemoved ;
+
+ /**
+ * Emitted when we have changed the name of this TimeAxis
+ */
+ SigC::Signal3<void,std::string,std::string,void*> NameChanged ;
+
+ /**
+ * Emitted when this time axis has been selected for removal
+ */
+ //SigC::Signal2<void,std::string,void*> VisualTimeAxisRemoved ;
+
+ //---------------------------------------------------------------------------------------//
+ // Constructor / Desctructor
+
+ /**
+ * Abstract Constructor for base visual time axis classes
+ *
+ * @param name the name/Id of thie TimeAxis
+ * @param ed the Ardour PublicEditor
+ * @param sess the current session
+ * @param canvas the parent canvas object
+ */
+ VisualTimeAxis(std::string name, PublicEditor& ed, ARDOUR::Session& sess, Gtk::Widget* canvas) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Handle time axis removal
+
+ /**
+ * Handles the Removal of this VisualTimeAxis
+ *
+ * @param src the identity of the object that initiated the change
+ */
+ virtual void remove_this_time_axis(void* src) ;
+
+ /**
+ * Callback used to remove this time axis during the gtk idle loop
+ * This is used to avoid deleting the obejct while inside the remove_this_time_axis
+ * method
+ *
+ * @param ta the VisualTimeAxis to remove
+ * @param src the identity of the object that initiated the change
+ */
+ static gint idle_remove_this_time_axis(VisualTimeAxis* ta, void* src) ;
+
+
+
+ //---------------------------------------------------------------------------------------//
+ // ui methods & data
+
+ /**
+ * Handle the visuals button click
+ *
+ */
+ void visual_click() ;
+
+ /**
+ * Handle the hide buttons click
+ *
+ */
+ void hide_click() ;
+
+ /**
+ * Allows the selection of a new color for this TimeAxis
+ *
+ */
+ virtual void select_track_color() ;
+
+ /**
+ * Provides a color chooser for the selection of a new time axis color.
+ *
+ */
+ bool choose_time_axis_color() ;
+
+ /**
+ * Sets the color of this TimeAxis to the specified color c
+ *
+ * @param c the new TimeAxis color
+ */
+ void set_time_axis_color(Gdk_Color c) ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Handle TimeAxis rename
+
+ /**
+ * Construct a new prompt to receive a new name for this TimeAxis
+ *
+ * @see finish_time_axis_rename()
+ */
+ void start_time_axis_rename() ;
+
+ /**
+ * Handles the new name for this TimeAxis from the name prompt
+ *
+ * @see start_time_axis_rename()
+ */
+ void finish_time_axis_rename() ;
+
+ /**
+ * Handle the (re-)displaying of the TimeAxis name label
+ *
+ */
+ virtual void label_view() ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Handle name entry signals
+
+ void name_entry_changed() ;
+ gint name_entry_focus_out_handler(GdkEventFocus*) ;
+ gint name_entry_key_release_handler(GdkEventKey*) ;
+ gint name_entry_button_release_handler(GdkEventButton*) ;
+ gint name_entry_button_press_handler(GdkEventButton*) ;
+
+ //---------------------------------------------------------------------------------------//
+ // VisualTimeAxis Widgets
+ Gtk::HBox other_button_hbox ;
+ Gtk::Button hide_button ;
+ Gtk::Button visual_button ;
+ Gtk::Button size_button ;
+
+ /** the name of this TimeAxis object */
+ std::string time_axis_name ;
+
+ /** used to get a new name for this TimeAxis */
+ ArdourPrompter* name_prompter ;
+
+
+ //---------------------------------------------------------------------------------------//
+ // Super class methods not handled by VisualTimeAxis
+
+ /**
+ * Not handled by purely Visual TimeAxis
+ *
+ * @todo should VisualTimeAxis handle this?
+ */
+ void show_timestretch (jack_nframes_t start, jack_nframes_t end);
+
+ /**
+ * Not handle by purely visual TimeAxis
+ * @see show_timestratch
+ */
+ virtual void hide_timestretch() ;
+
+ private:
+
+};
+
+#endif /* __ardour_visual_time_axis_h__ */
+
diff --git a/gtk2_ardour/vst_pluginui.cc b/gtk2_ardour/vst_pluginui.cc
new file mode 100644
index 0000000000..bdb7ecded8
--- /dev/null
+++ b/gtk2_ardour/vst_pluginui.cc
@@ -0,0 +1,124 @@
+/*
+ Copyright (C) 2004 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <fst.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+
+#include <ardour/insert.h>
+#include <ardour/vst_plugin.h>
+
+#include "plugin_ui.h"
+#include "prompter.h"
+
+#include "i18n.h"
+
+using namespace Gtk;
+using namespace ARDOUR;
+
+VSTPluginUI::VSTPluginUI (PluginInsert& pi, VSTPlugin& vp)
+ : PlugUIBase (pi),
+ vst (vp)
+{
+ fst_run_editor (vst.fst());
+
+ preset_box.pack_end (bypass_button, false, false, 10);
+ preset_box.pack_end (save_button, false, false);
+ preset_box.pack_end (combo, false, false);
+
+ bypass_button.set_active (!insert.active());
+
+ pack_start (preset_box, false, false);
+ pack_start (socket, true, true);
+}
+
+VSTPluginUI::~VSTPluginUI ()
+{
+ // nothing to do here - plugin destructor destroys the GUI
+}
+
+int
+VSTPluginUI::get_preferred_height ()
+{
+ return vst.fst()->height;
+}
+
+int
+VSTPluginUI::package (Gtk::Window& win)
+{
+ /* for GTK+2, remove this: you cannot add to a realized socket */
+
+ socket.realize ();
+
+ /* forward configure events to plugin window */
+
+ win.configure_event.connect (bind (slot (*this, &VSTPluginUI::configure_handler), socket.gtkobj()));
+
+ /* XXX in GTK2, use add_id() instead of steal, although add_id()
+ assumes that the window's owner understands the XEmbed protocol.
+ */
+
+ socket.steal (fst_get_XID (vst.fst()));
+
+ return 0;
+}
+
+gboolean
+VSTPluginUI::configure_handler (GdkEventConfigure* ev, GtkSocket *socket)
+{
+ XEvent event;
+
+ gint x, y;
+
+ if (socket->plug_window == NULL) {
+ return FALSE;
+ }
+
+ event.xconfigure.type = ConfigureNotify;
+ event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
+ event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
+
+ /* The ICCCM says that synthetic events should have root relative
+ * coordinates. We still aren't really ICCCM compliant, since
+ * we don't send events when the real toplevel is moved.
+ */
+ gdk_error_trap_push ();
+ gdk_window_get_origin (socket->plug_window, &x, &y);
+ gdk_error_trap_pop ();
+
+ event.xconfigure.x = x;
+ event.xconfigure.y = y;
+ event.xconfigure.width = GTK_WIDGET(socket)->allocation.width;
+ event.xconfigure.height = GTK_WIDGET(socket)->allocation.height;
+
+ event.xconfigure.border_width = 0;
+ event.xconfigure.above = None;
+ event.xconfigure.override_redirect = False;
+
+ gdk_error_trap_push ();
+ XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
+ GDK_WINDOW_XWINDOW (socket->plug_window),
+ False, StructureNotifyMask, &event);
+ // gdk_display_sync (GDK_WINDOW_XDISPLAY (socket->plug_window));
+ gdk_error_trap_pop ();
+
+ return FALSE;
+}
+