summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2007-10-11 22:07:47 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2007-10-11 22:07:47 +0000
commitf7f9d6fdc40248b190ec9c6e1a886261d55777ae (patch)
tree080723e9dc35a66013b37acbafc67a6afa929302 /gtk2_ardour
parentaa1f736a651376534acaa2268b65d42a3786fff7 (diff)
merge from 2.0-ongoing by hand, minus key binding editor
git-svn-id: svn://localhost/ardour2/trunk@2539 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/SConscript93
-rwxr-xr-xgtk2_ardour/ardbg2
-rwxr-xr-xgtk2_ardour/ardev2
-rw-r--r--gtk2_ardour/ardour.menus22
-rw-r--r--gtk2_ardour/ardour.sh.in2
-rw-r--r--gtk2_ardour/ardour2_ui_dark.rc.in144
-rw-r--r--gtk2_ardour/ardour2_ui_default.conf37
-rw-r--r--gtk2_ardour/ardour2_ui_light.rc.in111
-rw-r--r--gtk2_ardour/ardour_dialog.cc9
-rw-r--r--gtk2_ardour/ardour_dialog.h1
-rw-r--r--gtk2_ardour/ardour_ui.cc628
-rw-r--r--gtk2_ardour/ardour_ui.h43
-rw-r--r--gtk2_ardour/ardour_ui2.cc44
-rw-r--r--gtk2_ardour/ardour_ui_dependents.cc5
-rw-r--r--gtk2_ardour/ardour_ui_dialogs.cc19
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc89
-rw-r--r--gtk2_ardour/ardour_ui_options.cc50
-rwxr-xr-xgtk2_ardour/arprof2
-rwxr-xr-xgtk2_ardour/arval2
-rw-r--r--gtk2_ardour/audio_region_view.cc8
-rw-r--r--gtk2_ardour/audio_streamview.cc1
-rw-r--r--gtk2_ardour/axis_view.h6
-rw-r--r--gtk2_ardour/editing.h27
-rw-r--r--gtk2_ardour/editing_syms.h12
-rw-r--r--gtk2_ardour/editor.cc353
-rw-r--r--gtk2_ardour/editor.h90
-rw-r--r--gtk2_ardour/editor_actions.cc32
-rw-r--r--gtk2_ardour/editor_audio_import.cc534
-rw-r--r--gtk2_ardour/editor_audiotrack.cc28
-rw-r--r--gtk2_ardour/editor_canvas.cc39
-rw-r--r--gtk2_ardour/editor_keyboard.cc8
-rw-r--r--gtk2_ardour/editor_markers.cc47
-rw-r--r--gtk2_ardour/editor_mouse.cc219
-rw-r--r--gtk2_ardour/editor_ops.cc96
-rw-r--r--gtk2_ardour/editor_region_list.cc4
-rw-r--r--gtk2_ardour/editor_route_list.cc53
-rw-r--r--gtk2_ardour/editor_rulers.cc6
-rw-r--r--gtk2_ardour/engine_dialog.cc1126
-rw-r--r--gtk2_ardour/engine_dialog.h106
-rw-r--r--gtk2_ardour/enums.cc9
-rw-r--r--gtk2_ardour/keyboard.cc15
-rw-r--r--gtk2_ardour/keyboard.h1
-rw-r--r--gtk2_ardour/main.cc214
-rw-r--r--gtk2_ardour/mixer_strip.cc8
-rw-r--r--gtk2_ardour/mixer_ui.cc63
-rw-r--r--gtk2_ardour/mixer_ui.h7
-rw-r--r--gtk2_ardour/new_session_dialog.cc65
-rw-r--r--gtk2_ardour/new_session_dialog.h13
-rw-r--r--gtk2_ardour/option_editor.cc266
-rw-r--r--gtk2_ardour/option_editor.h25
-rw-r--r--gtk2_ardour/opts.cc49
-rw-r--r--gtk2_ardour/opts.h4
-rw-r--r--gtk2_ardour/processor_box.cc55
-rw-r--r--gtk2_ardour/processor_box.h3
-rw-r--r--gtk2_ardour/send_ui.cc2
-rw-r--r--gtk2_ardour/sfdb_ui.cc1218
-rw-r--r--gtk2_ardour/sfdb_ui.h162
-rw-r--r--gtk2_ardour/streamview.cc2
-rw-r--r--gtk2_ardour/utils.cc38
59 files changed, 5014 insertions, 1305 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
index b96498602e..12e3225f89 100644
--- a/gtk2_ardour/SConscript
+++ b/gtk2_ardour/SConscript
@@ -13,7 +13,7 @@ gtkmmtests = env.Copy()
# this defines the version number of the GTK interface to ardour
#
-domain = 'gtk_ardour'
+domain = 'gtk2_ardour'
gtkardour.Append(DOMAIN=domain, MAJOR=1,MINOR=0,MICRO=2)
gtkardour.Append(CCFLAGS="-DPACKAGE=\\\"" + domain + "\\\"")
@@ -24,6 +24,9 @@ gtkardour.Append(CPPPATH="#/") # for top level svn_revision.h
gtkardour.Append(PACKAGE=domain)
gtkardour.Append(POTFILE=domain + '.pot')
+if gtkardour['DIST_TARGET'] == 'panther' or gtkardour['DIST_TARGET'] == 'tiger':
+ gtkardour.Append (LINKFLAGS="-Xlinker -headerpad -Xlinker 2048")
+
gtkardour.Merge ([
libraries['ardour'],
libraries['ardour_cp'],
@@ -48,7 +51,8 @@ gtkardour.Merge ([
libraries['xslt'],
libraries['soundtouch'],
libraries['samplerate'],
- libraries['jack']
+ libraries['jack'],
+ libraries['sysaudio']
])
gtkmmtests.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
@@ -80,6 +84,15 @@ audiounit_files=Split("""
au_pluginui.cc
""")
+gtkosx_files=Split("""
+sync-menu.c
+cocoacarbon.c
+""")
+
+x11_files=Split("""
+x11.cc
+""")
+
gtkardour_files=Split("""
about.cc
actions.cc
@@ -143,6 +156,7 @@ editor_selection.cc
editor_selection_list.cc
editor_tempodisplay.cc
editor_timefx.cc
+engine_dialog.cc
export_dialog.cc
export_session_dialog.cc
export_region_dialog.cc
@@ -258,6 +272,12 @@ if env['CMT']:
extra_sources += cmt_files
gtkardour.Append (CCFLAGS="-DWITH_CMT")
+if gtkardour['GTKOSX']:
+ extra_sources += gtkosx_files
+ gtkardour.Append (CCFLAGS="-DTOP_MENUBAR -DGTKOSX")
+else:
+ extra_sources += x11_files
+
if gtkardour['AUDIOUNITS']:
extra_sources += audiounit_files
gtkardour.Append(CCFLAGS='-DHAVE_AUDIOUNITS')
@@ -292,41 +312,43 @@ if gtkardour['DIST_TARGET'] == 'panther' or gtkardour['DIST_TARGET'] == 'tiger':
#
# OS X font rendering is different even with X11
#
- my_font_dict['%FONT_TINY%'] = 'sans 7'
- my_font_dict['%FONT_SMALLER%'] = 'sans 9'
- my_font_dict['%FONT_SMALL%'] = 'sans 10'
- my_font_dict['%FONT_NORMAL%'] = 'sans 11'
- my_font_dict['%FONT_BIG%'] = 'sans 15'
- my_font_dict['%FONT_BIGGER%'] = 'sans 16'
- my_font_dict['%FONT_LARGE%'] = 'sans 20'
- my_font_dict['%FONT_LARGER%'] = 'sans 28'
- my_font_dict['%FONT_HUGER%'] = 'sans 36'
- my_font_dict['%FONT_MASSIVE%'] = 'sans 60'
- my_font_dict['%FONT_BOLD_TINY%'] = 'sans bold 7'
- my_font_dict['%FONT_BOLD_SMALLER%'] = 'sans bold 9'
- my_font_dict['%FONT_BOLD_SMALL%'] = 'sans bold 10'
- my_font_dict['%FONT_BOLD_NORMAL%'] = 'sans bold 11'
- my_font_dict['%FONT_BOLD_BIG%'] = 'sans bold 15'
- my_font_dict['%FONT_BOLD_BIGGER%'] = 'sans bold 16'
- my_font_dict['%FONT_BOLD_LARGE%'] = 'sans bold 20'
- my_font_dict['%FONT_BOLD_LARGER%'] = 'sans bold 28'
- my_font_dict['%FONT_BOLD_HUGER%'] = 'sans bold 36'
- my_font_dict['%FONT_BOLD_MASSIVE%'] = 'sans bold 60'
- my_font_dict['%FONT_ITALIC_TINY%'] = 'sans italic 7'
- my_font_dict['%FONT_ITALIC_SMALLER%'] = 'sans italic 9'
- my_font_dict['%FONT_ITALIC_SMALL%'] = 'sans italic 10'
- my_font_dict['%FONT_ITALIC_NORMAL%'] = 'sans italic 11'
- my_font_dict['%FONT_ITALIC_BIG%'] = 'sans italic 15'
- my_font_dict['%FONT_ITALIC_BIGGER%'] = 'sans italic 16'
- my_font_dict['%FONT_ITALIC_LARGE%'] = 'sans italic 20'
- my_font_dict['%FONT_ITALIC_LARGER%'] = 'sans italic 28'
- my_font_dict['%FONT_ITALIC_HUGER%'] = 'sans italic 36'
- my_font_dict['%FONT_ITALIC_MASSIVE%'] = 'sans italic 60'
+ my_font_dict['%FONT_TINY%'] = 'Lucida Grande 7'
+ my_font_dict['%FONT_SMALLERER%'] = 'Lucida Grande 8'
+ my_font_dict['%FONT_SMALLER%'] = 'Lucida Grande 9'
+ my_font_dict['%FONT_SMALL%'] = 'Lucida Grande 10'
+ my_font_dict['%FONT_NORMAL%'] = 'Lucida Grande 11'
+ my_font_dict['%FONT_BIG%'] = 'Lucida Grande 12'
+ my_font_dict['%FONT_BIGGER%'] = 'Lucida Grande 14'
+ my_font_dict['%FONT_LARGE%'] = 'Lucida Grande 18'
+ my_font_dict['%FONT_LARGER%'] = 'Lucida Grande 28'
+ my_font_dict['%FONT_HUGER%'] = 'Lucida Grande 36'
+ my_font_dict['%FONT_MASSIVE%'] = 'Lucida Grande 60'
+ my_font_dict['%FONT_BOLD_TINY%'] = 'Lucida Grande bold 7'
+ my_font_dict['%FONT_BOLD_SMALLER%'] = 'Lucida Grande bold 9'
+ my_font_dict['%FONT_BOLD_SMALL%'] = 'Lucida Grande bold 10'
+ my_font_dict['%FONT_BOLD_NORMAL%'] = 'Lucida Grande bold 11'
+ my_font_dict['%FONT_BOLD_BIG%'] = 'Lucida Grande bold 13'
+ my_font_dict['%FONT_BOLD_BIGGER%'] = 'Lucida Grande bold 14'
+ my_font_dict['%FONT_BOLD_LARGE%'] = 'Lucida Grande bold 20'
+ my_font_dict['%FONT_BOLD_LARGER%'] = 'Lucida Grande bold 25'
+ my_font_dict['%FONT_BOLD_HUGER%'] = 'Lucida Grande bold 36'
+ my_font_dict['%FONT_BOLD_MASSIVE%'] = 'Lucida Grande bold 60'
+ my_font_dict['%FONT_ITALIC_TINY%'] = 'Lucida Grande italic 7'
+ my_font_dict['%FONT_ITALIC_SMALLER%'] = 'Lucida Grande italic 9'
+ my_font_dict['%FONT_ITALIC_SMALL%'] = 'Lucida Grande italic 10'
+ my_font_dict['%FONT_ITALIC_NORMAL%'] = 'Lucida Grande italic 11'
+ my_font_dict['%FONT_ITALIC_BIG%'] = 'Lucida Grande italic 15'
+ my_font_dict['%FONT_ITALIC_BIGGER%'] = 'Lucida Grande italic 16'
+ my_font_dict['%FONT_ITALIC_LARGE%'] = 'Lucida Grande italic 20'
+ my_font_dict['%FONT_ITALIC_LARGER%'] = 'Lucida Grande italic 28'
+ my_font_dict['%FONT_ITALIC_HUGER%'] = 'Lucida Grande italic 36'
+ my_font_dict['%FONT_ITALIC_MASSIVE%'] = 'Lucida Grande italic 60'
else:
#
# Linux/X11 font rendering
#
my_font_dict['%FONT_TINY%'] = 'sans 4'
+ my_font_dict['%FONT_SMALLERER%'] = 'sans 6'
my_font_dict['%FONT_SMALLER%'] = 'sans 6'
my_font_dict['%FONT_SMALL%'] = 'sans 7'
my_font_dict['%FONT_NORMAL%'] = 'sans 8'
@@ -411,6 +433,7 @@ if env['NLS']:
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), ardour_dark_theme))
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), ardour_light_theme))
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour.menus'))
+env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour-sae.menus'))
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour.bindings'))
env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour2'), 'ardour2_ui_default.conf'))
# data files
@@ -428,7 +451,9 @@ env.Alias ('tarball', env.Distribute (env['DISTTREE'],
'ardev_common.sh.in',
'ardev', 'ardbg',
'ardour2_ui_dark.rc', 'ardour2_ui_light.rc', 'splash.png',
- 'ardour.menus', 'ardour.bindings.in', 'ardour2_ui_default.conf',
+ 'ardour.menus',
+ 'ardour-sae.menus',
+ 'ardour.bindings.in', 'ardour2_ui_default.conf',
'editor_xpms'
] +
gtkardour_files +
@@ -437,6 +462,8 @@ env.Alias ('tarball', env.Distribute (env['DISTTREE'],
icon_files +
skipped_files +
audiounit_files +
+ gtkosx_files +
+ x11_files +
fft_analysis_files +
glob.glob('po/*.po') + glob.glob('*.h')))
diff --git a/gtk2_ardour/ardbg b/gtk2_ardour/ardbg
index ab99296f45..063b2b1b6d 100755
--- a/gtk2_ardour/ardbg
+++ b/gtk2_ardour/ardbg
@@ -2,4 +2,4 @@
dir=`dirname "$0"`
. $dir/ardev_common.sh
LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
-exec gdb $EXECUTABLE $*
+exec gdb $EXECUTABLE "$@"
diff --git a/gtk2_ardour/ardev b/gtk2_ardour/ardev
index 5dd8fc9d13..7980c43d93 100755
--- a/gtk2_ardour/ardev
+++ b/gtk2_ardour/ardev
@@ -1,4 +1,4 @@
#!/bin/sh
. `dirname "$0"`/ardev_common.sh
LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
-exec $EXECUTABLE $*
+exec $EXECUTABLE "$@"
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus
index 24adba9f7f..128ca81c27 100644
--- a/gtk2_ardour/ardour.menus
+++ b/gtk2_ardour/ardour.menus
@@ -13,13 +13,7 @@
<separator/>
<menuitem action='AddTrackBus'/>
<separator/>
- <menu action='addExistingAudioFiles'>
- <menuitem action='addExternalAudioAsRegion'/>
- <menuitem action='addExternalAudioToTrack'/>
- <separator/>
- <menuitem action='addExternalAudioAsTrack'/>
- <menuitem action='addExternalAudioAsTapeTrack'/>
- </menu>
+ <menuitem action='addExistingAudioFiles'/>
<separator/>
<menu name='Export' action='Export'>
<menuitem action='ExportSession'/>
@@ -140,7 +134,6 @@
<menuitem action='set-mouse-mode-gain'/>
<menuitem action='set-mouse-mode-zoom'/>
<menuitem action='set-mouse-mode-timefx'/>
- <menuitem action='set-mouse-mode-note'/>
</menu>
</menu>
<menu name='View' action = 'View'>
@@ -215,7 +208,7 @@
<menuitem action='ToggleMeasureVisibility'/>
<separator/>
<menuitem action='show-editor-mixer'/>
- <menuitem action='show-editor-list'/>
+ <menuitem action='SyncEditorAndMixerTrackOrder'/>
</menu>
<menu name='JACK' action='JACK'>
<menuitem action='JACKDisconnect'/>
@@ -304,10 +297,6 @@
<menuitem action='UseSoftwareMonitoring'/>
<menuitem action='UseExternalMonitoring'/>
</menu>
- <menu action='Plugins'>
- <menuitem action='DisableAllPlugins'/>
- <menuitem action='ABAllPlugins'/>
- </menu>
<menu action='Metering'>
<menu action='MeteringFallOffRate'>
<menuitem action='MeterFalloffOff'/>
@@ -370,13 +359,15 @@
<menuitem action='GainReduceFastTransport'/>
<menuitem action='PrimaryClockDeltaEditCursor'/>
<menuitem action='SecondaryClockDeltaEditCursor'/>
+ <menuitem action='OnlyCopyImportedFiles'/>
+ <separator/>
</menu>
<menu name='Help' action='Help'>
<menuitem action='About'/>
</menu>
</menubar>
- <popup name='processormenu'>
+ <popup name='redirectmenu'>
<menuitem action='newplugin'/>
<menuitem action='newinsert'/>
<menuitem action='newsend'/>
@@ -399,9 +390,6 @@
<menuitem action='activate_all'/>
<menuitem action='deactivate_all'/>
<separator/>
- <menuitem action='deactivate_plugins'/>
- <menuitem action='a_b_plugins'/>
- <separator/>
<menuitem action='edit'/>
</popup>
diff --git a/gtk2_ardour/ardour.sh.in b/gtk2_ardour/ardour.sh.in
index beed436cbe..2f1092c3fe 100644
--- a/gtk2_ardour/ardour.sh.in
+++ b/gtk2_ardour/ardour.sh.in
@@ -15,6 +15,6 @@ fi
ulimit -c unlimited
-exec %INSTALL_PREFIX%/%LIBDIR%/ardour2/ardour-%VERSION% $*
+exec %INSTALL_PREFIX%/%LIBDIR%/ardour2/ardour-%VERSION% "$@"
diff --git a/gtk2_ardour/ardour2_ui_dark.rc.in b/gtk2_ardour/ardour2_ui_dark.rc.in
index 1420fc8660..ba8e5fe1e1 100644
--- a/gtk2_ardour/ardour2_ui_dark.rc.in
+++ b/gtk2_ardour/ardour2_ui_dark.rc.in
@@ -4,17 +4,17 @@
style "very_small_text"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
}
style "small_text"
{
- font_name = "%FONT_NORMAL%"
+ font_name = "%FONT_SMALL%"
}
style "small_bold_text"
{
- font_name = "%FONT_BOLD_NORMAL%"
+ font_name = "%FONT_BOLD_SMALL%"
}
style "medium_bold_text"
@@ -73,7 +73,7 @@ style "verbose_canvas_cursor"
style "marker_text"
{
- font_name = "%FONT_NORMAL%"
+ font_name = "%FONT_SMALL%"
}
style "time_axis_view_item_name"
@@ -159,7 +159,7 @@ style "default_buttons_menus"
style "very_small_button" = "default_buttons_menus"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
ythickness = 0
xthickness = 0
}
@@ -220,21 +220,21 @@ style "track_rec_enable_button_alternate" = "small_button"
style "mixer_track_rec_enable_button" = "track_rec_enable_button"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
xthickness = 0
ythickness = 0
}
style "mixer_track_rec_enable_button_alternate" = "track_rec_enable_button_alternate"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
xthickness = 0
ythickness = 0
}
style "mixer_track_rec_enable_button_active" = "track_rec_enable_button_active"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
xthickness = 0
ythickness = 0
}
@@ -272,20 +272,20 @@ style "solo_button_active" = "small_button"
style "mixer_solo_button" = "solo_button"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
style "mixer_solo_button_alternate" = "solo_button_alternate"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
style "mixer_solo_button_active" = "solo_button_active"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
@@ -323,21 +323,21 @@ style "mute_button_active" = "small_button"
style "mixer_mute_button" = "mute_button"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
style "mixer_mute_button_alternate" = "mute_button_alternate"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
style "mixer_mute_button_active" = "mute_button_active"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
@@ -351,7 +351,7 @@ style "multiline_combo" = "small_button"
style "mixer_mute_button" = "mute_button"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
xthickness = 0
ythickness = 0
}
@@ -454,7 +454,7 @@ style "ardour_progressbars" = "default_buttons_menus"
bg[PRELIGHT] = { 0.00, 0.36, 0.40 }
}
-style "options_window" = "default_base"
+style "preferences" = "default_base"
{
font_name = "%FONT_NORMAL%"
fg[PRELIGHT] = { 0.80, 0.80, 0.80 }
@@ -667,7 +667,7 @@ style "transport_clock_display_delta" = "transport_clock_display"
style "tempo_meter_clock_display"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
fg[NORMAL] = { 1.0, 1.0, 1.0 }
fg[ACTIVE] = { 1.0, 1.0, 0.0 }
fg[SELECTED] = { 1.0, 0, 0 }
@@ -694,31 +694,6 @@ style "editor_time_ruler" = "small_text"
bg[NORMAL] = { 0.09, 0.09, 0.09 }
}
-style "time_bar_label_base" = "default_base"
-{
- font_name = "sans 6"
- fg[NORMAL] = { 0.77, 0.77, 0.72 }
- bg[NORMAL] = { 0.28, 0.29, 0.34 }
- bg[ACTIVE] = { 0.30, 0.30, 0.34 }
- bg[PRELIGHT] = { 0.30, 0.30, 0.34 }
- bg[INSENSITIVE] = { 0.30, 0.30, 0.34 }
- bg[SELECTED] = { 0.30, 0.30, 0.34 }
-}
-
-style "time_bar_padding" = "default_base"
-{
- fg[NORMAL] = { 0.09, 0.09, 0.09 }
- fg[ACTIVE] = { 0.09, 0.09, 0.09 }
- fg[PRELIGHT] = { 0.09, 0.09, 0.09 }
- fg[INSENSITIVE] = { 0.09, 0.09, 0.09 }
- fg[SELECTED] = { 0.09, 0.09, 0.09 }
- bg[NORMAL] = { 0.09, 0.09, 0.09 }
- bg[ACTIVE] = { 0.09, 0.09, 0.09 }
- bg[PRELIGHT] = { 0.09, 0.09, 0.09 }
- bg[INSENSITIVE] = { 0.09, 0.09, 0.09 }
- bg[SELECTED] = { 0.09, 0.09, 0.09 }
-}
-
style "audio_bus_base"
{
font_name = "%FONT_SMALLER%"
@@ -758,6 +733,38 @@ style "midi_track_base" = "default_base"
bg[SELECTED] = { 0.20, 0.20, 0.20 }
}
+style "track_controls_inactive"
+{
+ bg[NORMAL] = { 0.60, 0.60, 0.66 }
+ bg[ACTIVE] = { 0.60, 0.60, 0.66 }
+ bg[INSENSITIVE] = { 0.60, 0.60, 0.66 }
+ bg[SELECTED] = { 0.60, 0.60, 0.66 }
+ bg[PRELIGHT] = { 0.60, 0.60, 0.66 }
+
+ #font_name = "sans 18"
+ fg[NORMAL] = { 0.7, 0.8, 0.2 }
+}
+
+style "audio_track_metrics" = "audio_track_base"
+{
+ font_name = "%FONT_TINY%"
+}
+
+style "audio_bus_metrics" = "audio_bus_base"
+{
+ font_name = "%FONT_TINY%"
+}
+
+style "audio_track_metrics_inactive" = "track_controls_inactive"
+{
+ font_name = "%FONT_TINY%"
+}
+
+style "audio_bus_metrics_inactive" = "track_controls_inactive"
+{
+ font_name = "%FONT_TINY%"
+}
+
style "track_name_display"
{
font_name = "%FONT_NORMAL%"
@@ -864,11 +871,11 @@ style "treeview_display" = "small_bold_text"
style "main_canvas_area"
{
- bg[NORMAL] = { 0.40, 0.40, 0.44 }
- bg[ACTIVE] = { 0.40, 0.40, 0.44 }
- bg[INSENSITIVE] = { 0.40, 0.40, 0.44 }
- bg[SELECTED] = { 0.40, 0.40, 0.44 }
- bg[PRELIGHT] = { 0.40, 0.40, 0.44 }
+ bg[NORMAL] = { 0.30, 0.30, 0.34 }
+ bg[ACTIVE] = { 0.30, 0.30, 0.34 }
+ bg[INSENSITIVE] = { 0.30, 0.30, 0.34 }
+ bg[SELECTED] = { 0.30, 0.30, 0.34 }
+ bg[PRELIGHT] = { 0.30, 0.30, 0.34 }
}
style "track_controls_inactive"
@@ -1123,12 +1130,6 @@ style "tearoff_arrow" = "medium_bold_entry"
bg[PRELIGHT] = { 0.80, 0.80, 0.80 }
}
-style "meter_metrics_strip" = "default_base"
-{
- font_name = "%FONT_TINY%"
- fg[NORMAL] = { 1.0, 0.8, 0.2 }
-}
-
style "location_row_button" = "default_buttons_menus"
{
font_name = "%FONT_BIG%"
@@ -1234,15 +1235,15 @@ widget "*MixerMonitorInputButton.*" style:highest "very_small_button"
widget "*MixerIOButton" style:highest "very_small_button"
widget "*MixerIOButtonLabel" style:highest "very_small_button"
widget "*AddRouteDialogSpinner" style:highest "ardour_adjusters"
-widget "*AddRouteDialogRadioButton*" style:highest "options_window"
-widget "*OptionsNotebook" style:highest "options_window"
-widget "*OptionEditorToggleButton*" style:highest "options_window"
-widget "*OptionsLabel" style:highest "options_window"
-widget "*OptionEditorAuditionerLabel" style:highest "options_window"
+widget "*AddRouteDialogRadioButton*" style:highest "preferences"
+widget "*OptionsNotebook" style:highest "preferences"
+widget "*OptionEditorToggleButton*" style:highest "preferences"
+widget "*OptionsLabel" style:highest "preferences"
+widget "*OptionEditorAuditionerLabel" style:highest "preferences"
widget "*OptionsEntry" style:highest "option_entry"
-widget "*InspectorNotebook" style:highest "options_window"
-widget "*NewSessionDialog" style:highest "options_window"
-widget "*NewSessionDialogButton*" style:highest "options_window"
+widget "*InspectorNotebook" style:highest "preferences"
+widget "*NewSessionDialog" style:highest "preferences"
+widget "*NewSessionDialogButton*" style:highest "preferences"
widget "*MixerSendSwitch*" style:highest "very_small_red_active_and_selected_button"
widget "*OptionEditorToggleButton" style:highest "small_red_active_and_selected_button"
widget "*NewSessionDialogButton" style:highest "small_red_active_and_selected_button"
@@ -1346,15 +1347,24 @@ widget "*BBTRuler" style:highest "editor_time_ruler"
widget "*FramesRuler" style:highest "editor_time_ruler"
widget "*MinSecRuler" style:highest "editor_time_ruler"
widget "*BaseFrame" style:highest "base_frame"
+
widget "*AudioTrackStripBase" style:highest "audio_track_base"
+widget "*AudioBusStripBase" style:highest "audio_bus_base"
widget "*MidiTrackStripBase" style:highest "midi_track_base"
-widget "*TimebarLabelBase" style:highest "time_bar_label_base"
-widget "*TimebarPadding" style:highest "time_bar_padding"
+widget "*AudioTrackStripBaseInactive" style:highest "track_controls_inactive"
+widget "*AudioBusStripBaseInactive" style:highest "track_controls_inactive"
+widget "*MidiTrackStripBaseInactive" style:highest "track_controls_inactive"
+widget "*FaderMetricsStrip" style:highest "audio_track_metrics"
+widget "*AudioTrackMetrics" style:highest "audio_track_metrics"
+widget "*AudioBusMetrics" style:highest "audio_bus_metrics"
+widget "*AudioTrackMetricsInactive" style:highest "audio_track_metrics_inactive"
+widget "*AudioBusMetricsInactive" style:highest "audio_bus_metrics_inactive"
+
widget "*TimeAxisViewControlsBaseUnselected" style:highest "audio_track_base"
widget "*AudioTrackControlsBaseUnselected" style:highest "audio_track_base"
widget "*MidiTrackControlsBaseUnselected" style:highest "midi_track_base"
widget "*AudioTrackFader" style:highest "gain_fader"
-widget "*AudioBusStripBase" style:highest "audio_bus_base"
+
widget "*BusControlsBaseUnselected" style:highest "audio_bus_base"
widget "*AudioBusFader" style:highest "gain_fader"
widget "*TrackSeparator" style:highest "track_separator"
@@ -1386,9 +1396,6 @@ widget "*AutomationTrackName" style:highest "automation_track_name"
widget "*AudioTrackControlsBaseInactiveSelected" style:highest "track_controls_inactive"
widget "*BusControlsBaseInactiveSelected" style:highest "track_controls_inactive"
widget "*AutomationTrackControlsBaseInactiveSelected" style:highest "track_controls_inactive"
-widget "*AudioTrackStripBaseInactive" style:highest "track_controls_inactive"
-widget "*MidiTrackStripBaseInactive" style:highest "track_controls_inactive"
-widget "*AudioBusStripBaseInactive" style:highest "track_controls_inactive"
widget "*AudioTrackControlsBaseSelected" style:highest "edit_controls_base_selected"
widget "*MidiTrackControlsBaseSelected" style:highest "edit_controls_base_selected"
widget "*BusControlsBaseSelected" style:highest "edit_controls_base_selected"
@@ -1485,8 +1492,7 @@ widget "*PluginSaveButton" style:highest "small_button"
widget "*PluginSaveButton*" style:highest "small_button"
widget "*PluginLoadButton" style:highest "small_button"
widget "*PluginLoadButton*" style:highest "small_button"
-widget "*FaderMetricsStrip" style:highest "meter_metrics_strip"
-widget "*MeterMetricsStrip" style:highest "meter_metrics_strip"
+
widget "*MetricDialogFrame" style:highest "base_frame"
widget "*MetricEntry" style:highest "medium_bold_entry"
widget "*MetricButton" style:highest "default_buttons_menus"
diff --git a/gtk2_ardour/ardour2_ui_default.conf b/gtk2_ardour/ardour2_ui_default.conf
index e0d6ea2773..034dd75b0f 100644
--- a/gtk2_ardour/ardour2_ui_default.conf
+++ b/gtk2_ardour/ardour2_ui_default.conf
@@ -3,21 +3,21 @@
<Canvas>
<Option name="waveform" value="000000cc"/>
<Option name="clipped waveform" value="ff0000e5"/>
- <Option name="region base" value="bfbfc172"/>
- <Option name="selected region base" value="b591a8d0"/>
- <Option name="audio track base" value="b6c3cb88"/>
- <Option name="audio bus base" value="cbc1de78"/>
- <Option name="midi track base" value="ffd0d850"/>
- <Option name="midi bus base" value="ffceea40"/>
+ <Option name="region base" value="bfbfc1aa"/>
+ <Option name="selected region base" value="b591a8ff"/>
+ <Option name="audio track base" value="c6d3d868"/>
+ <Option name="audio bus base" value="dbd1ea68"/>
+ <Option name="midi track base" value="ff8f8f3d"/>
+ <Option name="midi bus base" value="ff0000ee"/>
<Option name="time-stretch-fill" value="e2b5b596"/>
<Option name="time-stretch-outline" value="63636396"/>
<Option name="automation line" value="44bc59ff"/>
<Option name="processor automation line" value="7aa3f9ff"/>
- <Option name="control point fill" value="ffffff66"/>
- <Option name="control point outline" value="ffffffaa"/>
+ <Option name="control point fill" value="000000ff"/>
+ <Option name="control point outline" value="000000ff"/>
<Option name="entered control point outline" value="ff0000ee"/>
<Option name="entered control point selected" value="ff3535ff"/>
- <Option name="entered control point" value="ffffffaa"/>
+ <Option name="entered control point" value="000000cc"/>
<Option name="control point selected" value="00ff00ff"/>
<Option name="control point" value="ff0000ff"/>
<Option name="automation track fill" value="a0a0ce68"/>
@@ -40,7 +40,7 @@
<Option name="location punch" value="7c3a3aff"/>
<Option name="verbose canvas cursor" value="f4f214bc"/>
<Option name="marker label" value="000000ff"/>
- <Option name="marker bar separator" value="aaaaaa77"/>
+ <Option name="marker bar separator" value="30303088"/>
<Option name="tempo bar" value="72727fff"/>
<Option name="meterbar" value="666672ff"/>
<Option name="markerbar" value="7f7f8cff"/>
@@ -60,8 +60,8 @@
<Option name="EnteredMarker" value="dd6363ff"/>
<Option name="MeterMarker" value="f2425bff"/>
<Option name="TempoMarker" value="f2425bff"/>
- <Option name="MeasureLineBeat" value="b5b5b576"/>
- <Option name="MeasureLineBar" value="d9d9d99c"/>
+ <Option name="MeasureLineBeat" value="72727266"/>
+ <Option name="MeasureLineBar" value="8c8c988c"/>
<Option name="GhostTrackBase" value="44007c7f"/>
<Option name="GhostTrackWave" value="02fd004c"/>
<Option name="GhostTrackWaveClip" value="ff000000"/>
@@ -74,8 +74,8 @@
<Option name="RecordingRect" value="e5c6c6ff"/>
<Option name="SelectionRect" value="e8f4d377"/>
<Option name="Selection" value="636363b2"/>
- <Option name="VestigialFrame" value="0000000f"/>
- <Option name="TimeAxisFrame" value="0000000f"/>
+ <Option name="VestigialFrame" value="44007c0f"/>
+ <Option name="TimeAxisFrame" value="44007c0f"/>
<Option name="NameHighlightFill" value="0000ffff"/>
<Option name="NameHighlightOutline" value="7c00ff96"/>
<Option name="FrameHandle" value="7c00ff96"/>
@@ -83,15 +83,6 @@
<Option name="TrimHandle" value="1900ff44"/>
<Option name="EditCursor" value="0000ffff"/>
<Option name="PlayHead" value="ff0000ff"/>
- <Option name="MidiSelectRectOutline" value="5555ffff"/>
- <Option name="MidiSelectRectFill" value="8888ff88"/>
- <Option name="MidiNoteOutlineMin" value="22ff22b0"/>
- <Option name="MidiNoteOutlineMid" value="ffff22b0"/>
- <Option name="MidiNoteOutlineMax" value="ff2222b0"/>
- <Option name="MidiNoteFillMin" value="33ee338a"/>
- <Option name="MidiNoteFillMid" value="eeee338a"/>
- <Option name="MidiNoteFillMax" value="ee33338a"/>
- <Option name="MidiNoteSelectedOutline" value="5566ffee"/>
</Canvas>
</Ardour>
diff --git a/gtk2_ardour/ardour2_ui_light.rc.in b/gtk2_ardour/ardour2_ui_light.rc.in
index 4172b73a5b..b8c3683e91 100644
--- a/gtk2_ardour/ardour2_ui_light.rc.in
+++ b/gtk2_ardour/ardour2_ui_light.rc.in
@@ -4,17 +4,17 @@
style "very_small_text"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
}
style "small_text"
{
- font_name = "%FONT_NORMAL%"
+ font_name = "%FONT_SMALL%"
}
style "small_bold_text"
{
- font_name = "%FONT_BOLD_NORMAL%"
+ font_name = "%FONT_BOLD_SMALL%"
}
style "medium_bold_text"
@@ -162,7 +162,7 @@ style "default_buttons_menus"
style "very_small_button" = "default_buttons_menus"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
ythickness = 0
xthickness = 0
}
@@ -223,21 +223,21 @@ style "track_rec_enable_button_alternate" = "small_button"
style "mixer_track_rec_enable_button" = "track_rec_enable_button"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
xthickness = 0
ythickness = 0
}
style "mixer_track_rec_enable_button_alternate" = "track_rec_enable_button_alternate"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
xthickness = 0
ythickness = 0
}
style "mixer_track_rec_enable_button_active" = "track_rec_enable_button_active"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
xthickness = 0
ythickness = 0
}
@@ -275,20 +275,20 @@ style "solo_button_active" = "small_button"
style "mixer_solo_button" = "solo_button"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
style "mixer_solo_button_alternate" = "solo_button_alternate"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
style "mixer_solo_button_active" = "solo_button_active"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
@@ -326,21 +326,21 @@ style "mute_button_active" = "small_button"
style "mixer_mute_button" = "mute_button"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
style "mixer_mute_button_alternate" = "mute_button_alternate"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
style "mixer_mute_button_active" = "mute_button_active"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
@@ -354,7 +354,7 @@ style "multiline_combo" = "small_button"
style "mixer_mute_button" = "mute_button"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLERER%"
xthickness = 0
ythickness = 0
}
@@ -457,7 +457,7 @@ style "ardour_progressbars" = "default_buttons_menus"
bg[PRELIGHT] = { 0.00, 0.36, 0.40 }
}
-style "options_window" = "default_base"
+style "preferences" = "default_base"
{
font_name = "%FONT_NORMAL%"
fg[PRELIGHT] = { 0.80, 0.80, 0.80 }
@@ -672,7 +672,7 @@ style "transport_clock_display_delta" = "transport_clock_display"
style "tempo_meter_clock_display"
{
- font_name = "%FONT_SMALL%"
+ font_name = "%FONT_SMALLER%"
fg[NORMAL] = { 1.0, 1.0, 1.0 }
fg[ACTIVE] = { 1.0, 1.0, 0.0 }
fg[SELECTED] = { 1.0, 0, 0 }
@@ -737,6 +737,38 @@ style "midi_track_base" = "default_base"
bg[SELECTED] = { 0.70, 0.70, 0.80 }
}
+style "track_controls_inactive"
+{
+ bg[NORMAL] = { 0.60, 0.60, 0.66 }
+ bg[ACTIVE] = { 0.60, 0.60, 0.66 }
+ bg[INSENSITIVE] = { 0.60, 0.60, 0.66 }
+ bg[SELECTED] = { 0.60, 0.60, 0.66 }
+ bg[PRELIGHT] = { 0.60, 0.60, 0.66 }
+
+ #font_name = "sans 18"
+ fg[NORMAL] = { 0.7, 0.8, 0.2 }
+}
+
+style "audio_track_metrics" = "audio_track_base"
+{
+ font_name = "%FONT_TINY%"
+}
+
+style "audio_bus_metrics" = "audio_bus_base"
+{
+ font_name = "%FONT_TINY%"
+}
+
+style "audio_track_metrics_inactive" = "track_controls_inactive"
+{
+ font_name = "%FONT_TINY%"
+}
+
+style "audio_bus_metrics_inactive" = "track_controls_inactive"
+{
+ font_name = "%FONT_TINY%"
+}
+
style "track_name_display"
{
font_name = "%FONT_NORMAL%"
@@ -1102,15 +1134,9 @@ style "tearoff_arrow" = "medium_bold_entry"
bg[PRELIGHT] = { 0.30, 0.30, 0.30 }
}
-style "meter_metrics_strip" = "default_base"
-{
- font_name = "%FONT_TINY%"
- fg[NORMAL] = { 1.0, 0.8, 0.2 }
-}
-
style "location_row_button" = "default_buttons_menus"
{
- font_name = "%FONT_BIG%"
+ font_name = "%FONT_SMALL%"
}
style "location_rows_clock" = "default_clock_display"
@@ -1213,15 +1239,15 @@ widget "*MixerMonitorInputButton.*" style:highest "very_small_button"
widget "*MixerIOButton" style:highest "very_small_button"
widget "*MixerIOButtonLabel" style:highest "very_small_button"
widget "*AddRouteDialogSpinner" style:highest "ardour_adjusters"
-widget "*AddRouteDialogRadioButton*" style:highest "options_window"
-widget "*OptionsNotebook" style:highest "options_window"
-widget "*OptionEditorToggleButton*" style:highest "options_window"
-widget "*OptionsLabel" style:highest "options_window"
-widget "*OptionEditorAuditionerLabel" style:highest "options_window"
+widget "*AddRouteDialogRadioButton*" style:highest "preferences"
+widget "*OptionsNotebook" style:highest "preferences"
+widget "*OptionEditorToggleButton*" style:highest "preferences"
+widget "*OptionsLabel" style:highest "preferences"
+widget "*OptionEditorAuditionerLabel" style:highest "preferences"
widget "*OptionsEntry" style:highest "option_entry"
-widget "*InspectorNotebook" style:highest "options_window"
-widget "*NewSessionDialog" style:highest "options_window"
-widget "*NewSessionDialogButton*" style:highest "options_window"
+widget "*InspectorNotebook" style:highest "preferences"
+widget "*NewSessionDialog" style:highest "preferences"
+widget "*NewSessionDialogButton*" style:highest "preferences"
widget "*MixerSendSwitch*" style:highest "very_small_red_active_and_selected_button"
widget "*OptionEditorToggleButton" style:highest "small_red_active_and_selected_button"
widget "*NewSessionDialogButton" style:highest "small_red_active_and_selected_button"
@@ -1325,11 +1351,24 @@ widget "*BBTRuler" style:highest "editor_time_ruler"
widget "*FramesRuler" style:highest "editor_time_ruler"
widget "*MinSecRuler" style:highest "editor_time_ruler"
widget "*BaseFrame" style:highest "base_frame"
-widget "*AudioTrackStripBase*" style:highest "audio_track_base"
+
+widget "*AudioTrackStripBase" style:highest "audio_track_base"
+widget "*AudioBusStripBase" style:highest "audio_bus_base"
+widget "*MidiTrackStripBase" style:highest "midi_track_base"
+widget "*AudioTrackStripBaseInactive" style:highest "track_controls_inactive"
+widget "*AudioBusStripBaseInactive" style:highest "track_controls_inactive"
+widget "*MidiTrackStripBaseInactive" style:highest "track_controls_inactive"
+widget "*FaderMetricsStrip" style:highest "audio_track_metrics"
+widget "*AudioTrackMetrics" style:highest "audio_track_metrics"
+widget "*AudioBusMetrics" style:highest "audio_bus_metrics"
+widget "*AudioTrackMetricsInactive" style:highest "audio_track_metrics_inactive"
+widget "*AudioBusMetricsInactive" style:highest "audio_bus_metrics_inactive"
+
widget "*TimeAxisViewControlsBaseUnselected" style:highest "audio_track_base"
widget "*AudioTrackControlsBaseUnselected" style:highest "audio_track_base"
+widget "*MidiTrackControlsBaseUnselected" style:highest "midi_track_base"
widget "*AudioTrackFader" style:highest "gain_fader"
-widget "*AudioBusStripBase" style:highest "audio_bus_base"
+
widget "*BusControlsBaseUnselected" style:highest "audio_bus_base"
widget "*AudioBusFader" style:highest "gain_fader"
widget "*TrackSeparator" style:highest "track_separator"
@@ -1361,9 +1400,8 @@ widget "*AutomationTrackName" style:highest "automation_track_name"
widget "*AudioTrackControlsBaseInactiveSelected" style:highest "track_controls_inactive"
widget "*BusControlsBaseInactiveSelected" style:highest "track_controls_inactive"
widget "*AutomationTrackControlsBaseInactiveSelected" style:highest "track_controls_inactive"
-widget "*AudioTrackStripBaseInactive" style:highest "track_controls_inactive"
-widget "*AudioBusStripBaseInactive" style:highest "track_controls_inactive"
widget "*AudioTrackControlsBaseSelected" style:highest "edit_controls_base_selected"
+widget "*MidiTrackControlsBaseSelected" style:highest "edit_controls_base_selected"
widget "*BusControlsBaseSelected" style:highest "edit_controls_base_selected"
widget "*AutomationTrackControlsBase" style:highest "automation_track_controls_base"
widget "*AutomationTrackControlsBaseSelected" style:highest "edit_controls_base_selected"
@@ -1458,8 +1496,7 @@ widget "*PluginSaveButton" style:highest "small_button"
widget "*PluginSaveButton*" style:highest "small_button"
widget "*PluginLoadButton" style:highest "small_button"
widget "*PluginLoadButton*" style:highest "small_button"
-widget "*FaderMetricsStrip" style:highest "meter_metrics_strip"
-widget "*MeterMetricsStrip" style:highest "meter_metrics_strip"
+
widget "*MetricDialogFrame" style:highest "base_frame"
widget "*MetricEntry" style:highest "medium_bold_entry"
widget "*MetricButton" style:highest "default_buttons_menus"
diff --git a/gtk2_ardour/ardour_dialog.cc b/gtk2_ardour/ardour_dialog.cc
index c5162919d4..795b924075 100644
--- a/gtk2_ardour/ardour_dialog.cc
+++ b/gtk2_ardour/ardour_dialog.cc
@@ -34,6 +34,15 @@ ArdourDialog::ArdourDialog (string title, bool modal, bool use_seperator)
set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG);
}
+ArdourDialog::ArdourDialog (Gtk::Window& parent, string title, bool modal, bool use_seperator)
+ : Dialog (title, parent, modal, use_seperator)
+{
+ session = 0;
+
+ set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG);
+ set_position (Gtk::WIN_POS_CENTER_ON_PARENT);
+}
+
ArdourDialog::~ArdourDialog ()
{
}
diff --git a/gtk2_ardour/ardour_dialog.h b/gtk2_ardour/ardour_dialog.h
index 069768c143..13248e14de 100644
--- a/gtk2_ardour/ardour_dialog.h
+++ b/gtk2_ardour/ardour_dialog.h
@@ -37,6 +37,7 @@ class ArdourDialog : public Gtk::Dialog
{
public:
ArdourDialog (std::string title, bool modal = false, bool use_separator = false);
+ ArdourDialog (Gtk::Window& parent, std::string title, bool modal = false, bool use_separator = false);
~ArdourDialog();
bool on_enter_notify_event (GdkEventCrossing*);
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index cac63dc752..962ada5035 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -36,6 +36,7 @@
#include <gtkmm/accelmap.h>
#include <pbd/error.h>
+#include <pbd/misc.h>
#include <pbd/compose.h>
#include <pbd/failed_constructor.h>
#include <pbd/enumwriter.h>
@@ -50,8 +51,7 @@
#include <gtkmm2ext/popup.h>
#include <gtkmm2ext/window_title.h>
-#include <midi++/port.h>
-#include <midi++/mmc.h>
+#include <midi++/manager.h>
#include <ardour/ardour.h>
#include <ardour/profile.h>
@@ -157,12 +157,18 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
auditioning_alert_button (_("AUDITION")),
solo_alert_button (_("SOLO")),
- shown_flag (false)
+ shown_flag (false),
+ error_log_button (_("Errors"))
+
{
using namespace Gtk::Menu_Helpers;
Gtkmm2ext::init();
+
+#ifdef TOP_MENUBAR
+ _auto_display_errors = false;
+#endif
about = 0;
if (theArdourUI == 0) {
@@ -180,6 +186,9 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
session_selector_window = 0;
last_key_press_time = 0;
connection_editor = 0;
+ _will_create_new_session_automatically = false;
+ new_session_dialog = 0;
+ loading_dialog = 0;
add_route_dialog = 0;
route_params = 0;
option_editor = 0;
@@ -190,7 +199,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
session_loaded = false;
last_speed_displayed = -1.0f;
ab_direction = true;
-
+
sys::path key_bindings_file;
find_file_in_search_path (ardour_search_path() + system_config_search_path(),
@@ -225,31 +234,80 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
ARDOUR::Session::AskAboutPendingState.connect (mem_fun(*this, &ARDOUR_UI::pending_state_dialog));
- /* have to wait for AudioEngine and Configuration before proceeding */
+ /* lets get this party started */
+
+ try {
+ ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization);
+ setup_gtk_ardour_enums ();
+ Config->set_current_owner (ConfigVariableBase::Interface);
+ setup_profile ();
+
+ } catch (failed_constructor& err) {
+ error << _("could not initialize Ardour.") << endmsg;
+ // pass it on up
+ throw err;
+ }
+
+ /* we like keyboards */
+
+ keyboard = new Keyboard;
+
+ starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
+ stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
+
+ platform_specific ();
}
-void
-ARDOUR_UI::set_engine (AudioEngine& e)
+int
+ARDOUR_UI::create_engine ()
{
- engine = &e;
+ // this gets called every time by new_session()
+
+ if (engine) {
+ return 0;
+ }
+
+ try {
+ engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
+
+ } catch (...) {
+
+ return -1;
+ }
engine->Stopped.connect (mem_fun(*this, &ARDOUR_UI::engine_stopped));
engine->Running.connect (mem_fun(*this, &ARDOUR_UI::engine_running));
engine->Halted.connect (mem_fun(*this, &ARDOUR_UI::engine_halted));
engine->SampleRateChanged.connect (mem_fun(*this, &ARDOUR_UI::update_sample_rate));
- ActionManager::init ();
- new_session_dialog = new NewSessionDialog();
+ post_engine ();
- _tooltips.enable();
+ return 0;
+}
- keyboard = new Keyboard;
+void
+ARDOUR_UI::post_engine ()
+{
+ extern int setup_midi ();
+
+ /* Things to be done once we create the AudioEngine
+ */
+
+ MIDI::Manager::instance()->set_api_data (engine->jack());
+ setup_midi ();
+
+ check_memory_locking();
+
+ ActionManager::init ();
+ _tooltips.enable();
if (setup_windows ()) {
throw failed_constructor ();
}
- if (GTK_ARDOUR::show_key_actions) {
+ /* this is the first point at which all the keybindings are available */
+
+ if (ARDOUR_COMMAND_LINE::show_key_actions) {
vector<string> names;
vector<string> paths;
vector<string> keys;
@@ -266,9 +324,6 @@ ARDOUR_UI::set_engine (AudioEngine& e)
exit (0);
}
- /* start with timecode, metering enabled
- */
-
blink_timeout_tag = -1;
/* the global configuration object is now valid */
@@ -287,15 +342,26 @@ ARDOUR_UI::set_engine (AudioEngine& e)
/* start the time-of-day-clock */
+#ifndef GTKOSX
+ /* OS X provides an always visible wallclock, so don't be stupid */
update_wall_clock ();
Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
+#endif
update_disk_space ();
update_cpu_load ();
update_sample_rate (engine->frame_rate());
- starting.connect (mem_fun(*this, &ARDOUR_UI::startup));
- stopping.connect (mem_fun(*this, &ARDOUR_UI::shutdown));
+ /* now start and maybe save state */
+
+ if (do_engine_start () == 0) {
+ if (session && _session_is_new) {
+ /* we need to retain initial visual
+ settings for a new session
+ */
+ session->save_state ("");
+ }
+ }
}
ARDOUR_UI::~ARDOUR_UI ()
@@ -317,6 +383,11 @@ ARDOUR_UI::~ARDOUR_UI ()
if (add_route_dialog) {
delete add_route_dialog;
}
+
+
+ if (new_session_dialog) {
+ delete new_session_dialog;
+ }
}
gint
@@ -436,7 +507,7 @@ ARDOUR_UI::save_ardour_state ()
if (session) {
session->add_instant_xml (enode);
- session->add_instant_xml (mnode);
+ session->add_instant_xml (mnode);
} else {
Config->add_instant_xml (enode);
Config->add_instant_xml (mnode);
@@ -479,9 +550,151 @@ ARDOUR_UI::update_autosave ()
}
void
+ARDOUR_UI::backend_audio_error (bool we_set_params, Gtk::Window* toplevel)
+{
+ string title;
+ if (we_set_params) {
+ title = _("Ardour could not start JACK");
+ } else {
+ title = _("Ardour could not connect to JACK.");
+ }
+
+ MessageDialog win (title,
+ false,
+ Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_NONE);
+
+ if (we_set_params) {
+ win.set_secondary_text(_("There are several possible reasons:\n\
+\n\
+1) You requested audio parameters that are not supported..\n\
+2) JACK is running as another user.\n\
+\n\
+Please consider the possibilities, and perhaps try different parameters."));
+ } else {
+ win.set_secondary_text(_("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."));
+ }
+
+ if (toplevel) {
+ win.set_transient_for (*toplevel);
+ }
+
+ if (we_set_params) {
+ win.add_button (Stock::OK, RESPONSE_CLOSE);
+ } else {
+ win.add_button (Stock::QUIT, RESPONSE_CLOSE);
+ }
+
+ win.set_default_response (RESPONSE_CLOSE);
+
+ win.show_all ();
+ win.set_position (Gtk::WIN_POS_CENTER);
+
+ if (!ARDOUR_COMMAND_LINE::no_splash) {
+ hide_splash ();
+ }
+
+ /* we just don't care about the result, but we want to block */
+
+ win.run ();
+}
+
+void
ARDOUR_UI::startup ()
{
- check_memory_locking();
+ string name, path;
+ bool isnew;
+
+ new_session_dialog = new NewSessionDialog();
+
+ /* If no session name is given: we're not loading a session yet, nor creating a new one */
+
+ if (ARDOUR_COMMAND_LINE::session_name.length()) {
+
+ /* Load session or start the new session dialog */
+
+ if (find_session (ARDOUR_COMMAND_LINE::session_name, path, name, isnew)) {
+ error << string_compose(_("could not load command line session \"%1\""),
+ ARDOUR_COMMAND_LINE::session_name) << endmsg;
+ return;
+ }
+
+ if (!ARDOUR_COMMAND_LINE::new_session) {
+
+ /* Supposed to be loading an existing session, but the session doesn't exist */
+
+ if (isnew) {
+ error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
+ "To create it from the command line, start ardour as \"ardour --new %1"), path)
+ << endmsg;
+ return;
+ }
+ }
+
+ new_session_dialog->set_session_name (name);
+ new_session_dialog->set_session_folder (Glib::path_get_basename (path));
+ _session_is_new = isnew;
+ }
+
+ hide_splash ();
+
+ bool have_backend = EngineControl::engine_running();
+ bool need_nsd;
+ bool load_needed = false;
+
+ if (have_backend) {
+
+ /* backend audio is working */
+
+ if (ARDOUR_COMMAND_LINE::session_name.empty() || ARDOUR_COMMAND_LINE::new_session) {
+ /* need NSD to get session name and other info */
+ need_nsd = true;
+ } else {
+ need_nsd = false;
+ }
+
+ } else {
+
+ XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
+
+ if (audio_setup) {
+ new_session_dialog->engine_control.set_state (*audio_setup);
+ }
+
+ /* no backend audio, must bring up NSD to check configuration */
+
+ need_nsd = true;
+ }
+
+ if (need_nsd) {
+
+ if (!get_session_parameters (ARDOUR_COMMAND_LINE::session_name, have_backend, ARDOUR_COMMAND_LINE::new_session)) {
+ return;
+ }
+
+ } else {
+
+ if (create_engine ()) {
+ backend_audio_error (false);
+ exit (1);
+ }
+
+ load_needed = true;
+ }
+
+ if (load_needed) {
+ if (load_session (ARDOUR_COMMAND_LINE::session_name, name)) {
+ return;
+ }
+ }
+
+ show ();
}
void
@@ -679,6 +892,8 @@ ARDOUR_UI::every_point_one_seconds ()
gint
ARDOUR_UI::every_point_zero_one_seconds ()
{
+ // august 2007: actual update frequency: 40Hz, not 100Hz
+
SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
return TRUE;
}
@@ -1001,6 +1216,7 @@ ARDOUR_UI::open_session ()
open_session_selector = new Gtk::FileChooserDialog (_("open session"), FILE_CHOOSER_ACTION_OPEN);
open_session_selector->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
open_session_selector->add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_ACCEPT);
+ open_session_selector->set_default_response(Gtk::RESPONSE_ACCEPT);
FileFilter session_filter;
session_filter.add_pattern ("*.ardour");
@@ -1524,21 +1740,6 @@ ARDOUR_UI::setup_theme ()
theme_manager->setup_theme();
}
-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 ("");
- }
- }
-
- return FALSE;
-}
-
void
ARDOUR_UI::update_clocks ()
{
@@ -1832,30 +2033,34 @@ ARDOUR_UI::save_template ()
}
bool
-ARDOUR_UI::new_session (std::string predetermined_path)
+ARDOUR_UI::get_session_parameters (Glib::ustring predetermined_path, bool have_engine, bool should_be_new)
{
string session_name;
string session_path;
+ string template_name;
- if (!check_audioengine()) {
- return false;
+ if (!loading_dialog) {
+ loading_dialog = new MessageDialog (*new_session_dialog,
+ "",
+ false,
+ Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_NONE);
}
-
+
int response = Gtk::RESPONSE_NONE;
new_session_dialog->set_modal(true);
new_session_dialog->set_name (predetermined_path);
new_session_dialog->reset_recent();
- new_session_dialog->show();
+ new_session_dialog->set_position (WIN_POS_CENTER);
new_session_dialog->set_current_page (0);
do {
- response = new_session_dialog->run ();
+ new_session_dialog->set_have_engine (have_engine);
- if (!check_audioengine()) {
- new_session_dialog->hide ();
- return false;
- }
+ new_session_dialog->show();
+ new_session_dialog->present ();
+ response = new_session_dialog->run ();
_session_is_new = false;
@@ -1869,65 +2074,119 @@ ARDOUR_UI::new_session (std::string predetermined_path)
} else if (response == Gtk::RESPONSE_NONE) {
- /* Clear was pressed */
- new_session_dialog->reset();
+ /* Clear was pressed */
+ new_session_dialog->reset();
+ continue;
+ }
- } else if (response == Gtk::RESPONSE_YES) {
+ /* first things first ... if we're here to help set up audio parameters
+ this is where want to do that.
+ */
- /* YES == OPEN, but there's no enum for that */
+ if (!have_engine) {
+ if (new_session_dialog->engine_control.setup_engine ()) {
+ new_session_dialog->hide ();
+ return false;
+ }
+ }
- session_name = new_session_dialog->session_name();
+#ifdef GTKOSX
+ /* X11 users will always have fontconfig info around, but new GTK-OSX users
+ may not and it can take a while to build it. Warn them.
+ */
+ Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
+
+ if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
+ MessageDialog msg (*new_session_dialog,
+ _("Welcome to Ardour.\n\n"
+ "The program will take a bit longer to start up\n"
+ "while the system fonts are checked.\n\n"
+ "This will only be done once, and you will\n"
+ "not see this message again\n"),
+ true,
+ Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK);
+ msg.show_all ();
+ msg.present ();
+ msg.run ();
+ }
+#endif
+ loading_dialog->set_message (_("Starting audio engine"));
+ loading_dialog->show_all ();
+ flush_pending ();
+
+ if (create_engine ()) {
+ backend_audio_error (!have_engine, new_session_dialog);
+ loading_dialog->hide ();
+ flush_pending ();
+ /* audio setup page */
+ new_session_dialog->set_current_page (2);
+ /* try again */
+ response = Gtk::RESPONSE_NONE;
+ continue;
+ }
+
+ have_engine = true;
+
+ /* now handle possible affirmative responses */
+
+ if (response == Gtk::RESPONSE_YES) {
+
+ /* YES == OPEN from the session selector */
+
+ session_name = new_session_dialog->session_name();
+
if (session_name.empty()) {
response = Gtk::RESPONSE_NONE;
continue;
}
if (session_name[0] == '/' ||
- (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
- (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+ (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+ (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
load_session (Glib::path_get_dirname (session_name), session_name);
} else {
session_path = new_session_dialog->session_folder();
load_session (session_path, session_name);
}
-
+
} else if (response == Gtk::RESPONSE_OK) {
- session_name = new_session_dialog->session_name();
-
- if (!new_session_dialog->on_new_session_page ()) {
-
- /* XXX this is a bit of a hack..
- i really want the new sesion dialog to return RESPONSE_YES
- if we're on page 1 (the load page)
- Unfortunately i can't see how atm..
- */
+ /* OK == OPEN button */
- if (session_name.empty()) {
- response = Gtk::RESPONSE_NONE;
- continue;
- }
+ session_name = new_session_dialog->session_name();
+
+ if (session_name.empty()) {
+ response = Gtk::RESPONSE_NONE;
+ continue;
+ }
+
+ switch (new_session_dialog->get_current_page()) {
+ case 1: /* recent session selector */
+ case 2: /* audio engine control */
if (session_name[0] == '/' ||
- (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
- (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+ (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+ (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
load_session (Glib::path_get_dirname (session_name), session_name);
} else {
session_path = new_session_dialog->session_folder();
load_session (session_path, session_name);
}
+ break;
- } else {
+ case 0: /* nominally the "new" session creator, but could be in use for an old session */
- if (session_name.empty()) {
- response = Gtk::RESPONSE_NONE;
- continue;
- }
+ if (new_session_dialog->get_current_page() == 0 && ARDOUR_COMMAND_LINE::session_name.empty()) {
+ should_be_new = true;
+ }
+
+ /* handle what appear to be paths rather than just a name */
if (session_name[0] == '/' ||
- (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
- (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
+ (session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
+ (session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
session_path = Glib::path_get_dirname (session_name);
session_name = Glib::path_get_basename (session_name);
@@ -1937,108 +2196,144 @@ ARDOUR_UI::new_session (std::string predetermined_path)
session_path = new_session_dialog->session_folder();
}
-
+
//XXX This is needed because session constructor wants a
//non-existant path. hopefully this will be fixed at some point.
-
+
session_path = Glib::build_filename (session_path, session_name);
+
+ if (!should_be_new) {
- if (g_file_test (session_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
+ load_session (session_path, session_name);
+ continue; /* leaves while() loop because response != NONE */
+
+ } else if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
Glib::ustring str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
MessageDialog msg (str,
- false,
- Gtk::MESSAGE_WARNING,
- Gtk::BUTTONS_YES_NO,
- true);
+ false,
+ Gtk::MESSAGE_WARNING,
+ Gtk::BUTTONS_YES_NO,
+ true);
msg.set_name (X_("CleanupDialog"));
msg.set_wmclass (X_("existing_session"), "Ardour");
msg.set_position (Gtk::WIN_POS_MOUSE);
-
+
switch (msg.run()) {
- case RESPONSE_YES:
- load_session (session_path, session_name);
- goto done;
- break;
- default:
- response = RESPONSE_NONE;
- new_session_dialog->reset ();
- continue;
+ case RESPONSE_YES:
+ new_session_dialog->hide ();
+ goto_editor_window ();
+ flush_pending ();
+ load_session (session_path, session_name);
+ goto done;
+ break;
+ default:
+ response = RESPONSE_NONE;
+ new_session_dialog->reset ();
+ continue;
}
- }
+ }
- _session_is_new = true;
+ _session_is_new = true;
+
+ if (new_session_dialog->use_session_template()) {
- std::string template_name = new_session_dialog->session_template_name();
+ template_name = new_session_dialog->session_template_name();
- if (new_session_dialog->use_session_template()) {
+ new_session_dialog->hide ();
+ goto_editor_window ();
+ flush_pending ();
load_session (session_path, session_name, &template_name);
-
+
} else {
uint32_t cchns;
uint32_t mchns;
AutoConnectOption iconnect;
AutoConnectOption oconnect;
+ uint32_t nphysin;
+ uint32_t nphysout;
+
+ if (Profile->get_sae()) {
- if (new_session_dialog->create_control_bus()) {
- cchns = (uint32_t) new_session_dialog->control_channel_count();
- } else {
cchns = 0;
- }
+ mchns = 2;
+ iconnect = AutoConnectPhysical;
+ oconnect = AutoConnectMaster;
+ nphysin = 0; // use all available
+ nphysout = 0; // use all available
- if (new_session_dialog->create_master_bus()) {
- mchns = (uint32_t) new_session_dialog->master_channel_count();
} else {
- mchns = 0;
- }
- if (new_session_dialog->connect_inputs()) {
- iconnect = AutoConnectPhysical;
- } else {
- iconnect = AutoConnectOption (0);
+ /* get settings from advanced section of NSD */
+
+ if (new_session_dialog->create_control_bus()) {
+ cchns = (uint32_t) new_session_dialog->control_channel_count();
+ } else {
+ cchns = 0;
+ }
+
+ if (new_session_dialog->create_master_bus()) {
+ mchns = (uint32_t) new_session_dialog->master_channel_count();
+ } else {
+ mchns = 0;
+ }
+
+ if (new_session_dialog->connect_inputs()) {
+ iconnect = AutoConnectPhysical;
+ } else {
+ iconnect = AutoConnectOption (0);
+ }
+
+ /// @todo some minor tweaks.
+
+ if (new_session_dialog->connect_outs_to_master()) {
+ oconnect = AutoConnectMaster;
+ } else if (new_session_dialog->connect_outs_to_physical()) {
+ oconnect = AutoConnectPhysical;
+ } else {
+ oconnect = AutoConnectOption (0);
+ }
+
+ nphysin = (uint32_t) new_session_dialog->input_limit_count();
+ nphysout = (uint32_t) new_session_dialog->output_limit_count();
}
- /// @todo some minor tweaks.
-
- if (new_session_dialog->connect_outs_to_master()) {
- oconnect = AutoConnectMaster;
- } else if (new_session_dialog->connect_outs_to_physical()) {
- oconnect = AutoConnectPhysical;
- } else {
- oconnect = AutoConnectOption (0);
- }
-
- uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
- uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
-
- if (!build_session (session_path,
- session_name,
- cchns,
- mchns,
- iconnect,
- oconnect,
- nphysin,
- nphysout,
- engine->frame_rate() * 60 * 5)) {
-
+ new_session_dialog->hide ();
+ goto_editor_window ();
+ flush_pending ();
+
+ if (build_session (session_path,
+ session_name,
+ cchns,
+ mchns,
+ iconnect,
+ oconnect,
+ nphysin,
+ nphysout,
+ engine->frame_rate() * 60 * 5)) {
+
response = Gtk::RESPONSE_NONE;
new_session_dialog->reset ();
continue;
}
}
+ break;
+
+ default:
+ break;
}
}
-
+
} while (response == Gtk::RESPONSE_NONE);
done:
show();
- new_session_dialog->get_window()->set_cursor();
+ loading_dialog->hide ();
new_session_dialog->hide();
return true;
}
@@ -2050,21 +2345,32 @@ ARDOUR_UI::close_session()
return;
}
- unload_session();
- new_session ();
+ unload_session (true);
+
+ get_session_parameters ("", true, false);
}
int
ARDOUR_UI::load_session (const string & path, const string & snap_name, string* mix_template)
{
Session *new_session;
+ int unload_status;
+ int retval = -1;
+
session_loaded = false;
-
+
if (!check_audioengine()) {
return -1;
}
- if(!unload_session ()) return -1;
+ unload_status = unload_session ();
+
+ if (unload_status < 0) {
+ goto out;
+ } else if (unload_status > 0) {
+ retval = 0;
+ goto out;
+ }
/* if it already exists, we must have write access */
@@ -2072,17 +2378,23 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string*
MessageDialog msg (*editor, _("You do not have write access to this session.\n"
"This prevents the session from being loaded."));
msg.run ();
- return -1;
+ goto out;
+ }
+
+ if (loading_dialog) {
+ loading_dialog->set_markup (_("Please wait while Ardour loads your session"));
+ flush_pending ();
}
+ disable_screen_updates ();
+
try {
new_session = new Session (*engine, path, snap_name, mix_template);
}
catch (...) {
-
error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
- return -1;
+ goto out;
}
connect_to_session (new_session);
@@ -2098,10 +2410,15 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string*
}
editor->edit_cursor_position (true);
- return 0;
+ enable_screen_updates ();
+ flush_pending ();
+ retval = 0;
+
+ out:
+ return retval;
}
-bool
+int
ARDOUR_UI::build_session (const string & path, const string & snap_name,
uint32_t control_channels,
uint32_t master_channels,
@@ -2112,14 +2429,21 @@ ARDOUR_UI::build_session (const string & path, const string & snap_name,
nframes_t initial_length)
{
Session *new_session;
+ int x;
if (!check_audioengine()) {
- return false;
+ return -1;
}
session_loaded = false;
- if (!unload_session ()) return false;
+ x = unload_session ();
+
+ if (x < 0) {
+ return -1;
+ } else if (x > 0) {
+ return 0;
+ }
_session_is_new = true;
@@ -2132,13 +2456,13 @@ ARDOUR_UI::build_session (const string & path, const string & snap_name,
MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
msg.run ();
- return false;
+ return -1;
}
connect_to_session (new_session);
session_loaded = true;
- return true;
+ return 0;
}
void
@@ -2616,8 +2940,10 @@ ARDOUR_UI::cmdline_new_session (string path)
path = str;
}
- new_session (path);
-
+ get_session_parameters (path, false, true);
+
+ _will_create_new_session_automatically = false; /* done it */
+
return FALSE; /* don't call it again */
}
@@ -2868,6 +3194,12 @@ ARDOUR_UI::setup_profile ()
if (gdk_screen_width() < 1200) {
Profile->set_small_screen ();
}
+
+
+ if (getenv ("ARDOUR_SAE")) {
+ Profile->set_sae ();
+ Profile->set_single_package ();
+ }
}
void
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 39bd8db4a6..427d40dffe 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -50,6 +50,7 @@
#include <gtkmm/togglebutton.h>
#include <gtkmm/treeview.h>
#include <gtkmm/menubar.h>
+#include <gtkmm/textbuffer.h>
#include <gtkmm/adjustment.h>
#include <gtkmm2ext/gtk_ui.h>
#include <gtkmm2ext/click_box.h>
@@ -111,8 +112,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
int load_session (const string & path, const string & snapshot, string* mix_template = 0);
bool session_loaded;
- /// @return true if building the session was successful
- bool build_session (const string & path, const string & snapshot,
+ /// @return zero if building the session was successful
+ int build_session (const string & path, const string & snapshot,
uint32_t ctl_chns,
uint32_t master_chns,
ARDOUR::AutoConnectOption input_connect,
@@ -124,11 +125,20 @@ class ARDOUR_UI : public Gtkmm2ext::UI
ARDOUR::Session* the_session() { return session; }
- bool new_session(std::string path = string());
+ 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;
+ }
+
+ bool get_session_parameters (Glib::ustring path, bool have_engine = false, bool should_be_new = false);
+
gint cmdline_new_session (string path);
/// @return true if session was successfully unloaded.
- bool unload_session ();
+ int unload_session (bool hide_stuff = false);
void close_session();
int save_state_canfail (string state_name = "");
@@ -204,8 +214,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
session_add_midi_route (false);
}*/
- void set_engine (ARDOUR::AudioEngine&);
- gint start_engine ();
+ int create_engine ();
+ void post_engine ();
gint exit_on_main_window_close (GdkEventAny *);
@@ -221,6 +231,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void setup_profile ();
void setup_theme ();
+ void set_shuttle_fract (double);
+
protected:
friend class PublicEditor;
@@ -293,6 +305,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
static ARDOUR_UI *theArdourUI;
+ void backend_audio_error (bool we_set_params, Gtk::Window* toplevel = 0);
void startup ();
void shutdown ();
@@ -438,7 +451,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
gint shuttle_box_expose (GdkEventExpose*);
gint mouse_shuttle (double x, bool force);
void use_shuttle_fract (bool force);
- void set_shuttle_fract (double);
bool shuttle_grabbed;
double shuttle_fract;
@@ -507,6 +519,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
Gtk::EventBox menu_bar_base;
Gtk::HBox menu_hbox;
+ void use_menubar_as_top_menubar ();
void build_menu_bar ();
void build_control_surface_menu ();
@@ -541,6 +554,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
gint session_menu (GdkEventButton *);
+ bool _will_create_new_session_automatically;
+
NewSessionDialog* new_session_dialog;
void open_session ();
@@ -683,6 +698,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void set_remote_model (ARDOUR::RemoteModel);
void set_denormal_model (ARDOUR::DenormalModel);
+ void toggle_sync_order_keys ();
void toggle_StopPluginsWithTransport();
void toggle_DoNotRunPluginsWhileRecording();
void toggle_VerifyRemoveLastCapture();
@@ -696,16 +712,19 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_RegionEquivalentsOverlap ();
void toggle_PrimaryClockDeltaEditCursor ();
void toggle_SecondaryClockDeltaEditCursor ();
+ void toggle_only_copy_imported_files ();
void mtc_port_changed ();
void map_solo_model ();
void map_monitor_model ();
void map_denormal_model ();
+ void map_denormal_protection ();
void map_remote_model ();
void map_file_header_format ();
void map_file_data_format ();
void map_input_auto_connect ();
void map_output_auto_connect ();
+ void map_only_copy_imported_files ();
void parameter_changed (const char*);
void set_meter_hold (ARDOUR::MeterHold);
@@ -725,6 +744,16 @@ class ARDOUR_UI : public Gtkmm2ext::UI
bool ab_direction;
void disable_all_plugins ();
void ab_all_plugins ();
+
+ void audioengine_setup ();
+
+ void display_message (const char *prefix, gint prefix_len,
+ Glib::RefPtr<Gtk::TextBuffer::Tag> ptag, Glib::RefPtr<Gtk::TextBuffer::Tag> mtag, const char *msg);
+ Gtk::Label status_bar_label;
+ Gtk::ToggleButton error_log_button;
+ Gtk::MessageDialog* loading_dialog;
+
+ void platform_specific ();
};
#endif /* __ardour_gui_h__ */
diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc
index 489728286c..8f755a3d93 100644
--- a/gtk2_ardour/ardour_ui2.cc
+++ b/gtk2_ardour/ardour_ui2.cc
@@ -78,14 +78,54 @@ ARDOUR_UI::setup_windows ()
theme_manager->signal_unmap().connect (bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleThemeManager")));
- top_packer.pack_start (menu_bar_base, false, false);
- top_packer.pack_start (transport_frame, false, false);
+ top_packer.pack_start (transport_frame, false, false);
+
+#ifdef TOP_MENUBAR
+ HBox* status_bar_packer = manage (new HBox);
+
+ status_bar_label.set_size_request (300, -1);
+ status_bar_packer->pack_start (status_bar_label, true, true, 6);
+ status_bar_packer->pack_start (error_log_button, false, false);
+
+ error_log_button.signal_clicked().connect (mem_fun (*this, &UI::toggle_errors));
+
+ editor->get_status_bar_packer().pack_start (*status_bar_packer, true, true);
+ editor->get_status_bar_packer().pack_start (menu_bar_base, false, false, 6);
+#else
+ top_packer.pack_start (menu_bar_base, false, false);
+#endif
editor->add_toplevel_controls (top_packer);
return 0;
}
+ void
+ARDOUR_UI::display_message (const char *prefix, gint prefix_len, RefPtr<TextBuffer::Tag> ptag, RefPtr<TextBuffer::Tag> mtag, const char *msg)
+{
+ ustring text;
+
+ UI::display_message (prefix, prefix_len, ptag, mtag, msg);
+#ifdef TOP_MENUBAR
+
+ if (strcmp (prefix, _("[ERROR]: ")) == 0) {
+ text = "<span color=\"red\" weight=\"bold\">";
+ } else if (strcmp (prefix, _("[WARNING]: ")) == 0) {
+ text = "<span color=\"yellow\" weight=\"bold\">";
+ } else if (strcmp (prefix, _("[INFO]: ")) == 0) {
+ text = "<span color=\"green\" weight=\"bold\">";
+ } else {
+ text = "<span color=\"blue\" weight=\"bold\">???";
+ }
+
+ text += prefix;
+ text += "</span>";
+ text += msg;
+
+ status_bar_label.set_markup (text);
+#endif
+}
+
void
ARDOUR_UI::transport_stopped ()
{
diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc
index 725180e0ab..6464c52967 100644
--- a/gtk2_ardour/ardour_ui_dependents.cc
+++ b/gtk2_ardour/ardour_ui_dependents.cc
@@ -47,7 +47,8 @@ void
ARDOUR_UI::shutdown ()
{
if (session) {
- delete session;
+ /* we're exiting cleanly, so remove any auto-save data */
+ session->remove_pending_capture_state ();
session = 0;
}
@@ -109,11 +110,13 @@ void
ARDOUR_UI::goto_editor_window ()
{
editor->show_window ();
+ editor->present ();
}
void
ARDOUR_UI::goto_mixer_window ()
{
mixer->show_window ();
+ mixer->present ();
}
gint
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
index c6353df782..9a71443489 100644
--- a/gtk2_ardour/ardour_ui_dialogs.cc
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -162,21 +162,26 @@ ARDOUR_UI::connect_to_session (Session *s)
point_zero_one_second_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::every_point_zero_one_seconds), 40);
}
-bool
-ARDOUR_UI::unload_session ()
+int
+ARDOUR_UI::unload_session (bool hide_stuff)
{
if (session && session->dirty()) {
switch (ask_about_saving_session (_("close"))) {
case -1:
// cancel
- return false;
+ return 1;
case 1:
session->save_state ("");
break;
}
}
- editor->hide ();
+
+ if (hide_stuff) {
+ editor->hide ();
+ mixer->hide ();
+ }
+
second_connection.disconnect ();
point_one_second_connection.disconnect ();
point_oh_five_second_connection.disconnect ();
@@ -204,16 +209,12 @@ ARDOUR_UI::unload_session ()
option_editor->set_session (0);
}
- if (mixer) {
- mixer->hide ();
- }
-
delete session;
session = 0;
update_buffer_load ();
- return true;
+ return 0;
}
int
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index a043128700..c850d72048 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -34,8 +34,10 @@
#include "ardour_ui.h"
#include "public_editor.h"
#include "audio_clock.h"
+#include "engine_dialog.h"
#include "editor.h"
#include "actions.h"
+#include "sync-menu.h"
#include <ardour/session.h>
#include <ardour/profile.h>
@@ -80,6 +82,8 @@ ARDOUR_UI::install_actions ()
/* menus + submenus that need action items */
ActionManager::register_action (main_actions, X_("Session"), _("Session"));
+ ActionManager::register_action (main_actions, X_("Files"), _("Files"));
+ ActionManager::register_action (main_actions, X_("Regions"), _("Regions"));
ActionManager::register_action (main_actions, X_("Cleanup"), _("Cleanup"));
ActionManager::register_action (main_actions, X_("Sync"), _("Sync"));
ActionManager::register_action (main_actions, X_("Options"), _("Options"));
@@ -98,7 +102,7 @@ ARDOUR_UI::install_actions ()
/* the real actions */
- act = ActionManager::register_action (main_actions, X_("New"), _("New"), hide_return (bind (mem_fun(*this, &ARDOUR_UI::new_session), string ())));
+ act = ActionManager::register_action (main_actions, X_("New"), _("New"), hide_return (bind (mem_fun(*this, &ARDOUR_UI::get_session_parameters), string (), true, true)));
ActionManager::register_action (main_actions, X_("Open"), _("Open"), mem_fun(*this, &ARDOUR_UI::open_session));
ActionManager::register_action (main_actions, X_("Recent"), _("Recent"), mem_fun(*this, &ARDOUR_UI::open_recent_session));
@@ -191,7 +195,7 @@ ARDOUR_UI::install_actions ()
ActionManager::register_action (common_actions, X_("goto-editor"), _("Show Editor"), mem_fun(*this, &ARDOUR_UI::goto_editor_window));
ActionManager::register_action (common_actions, X_("goto-mixer"), _("Show Mixer"), mem_fun(*this, &ARDOUR_UI::goto_mixer_window));
- ActionManager::register_toggle_action (common_actions, X_("ToggleOptionsEditor"), _("Options Editor"), mem_fun(*this, &ARDOUR_UI::toggle_options_window));
+ ActionManager::register_toggle_action (common_actions, X_("ToggleOptionsEditor"), _("Preferences"), mem_fun(*this, &ARDOUR_UI::toggle_options_window));
act = ActionManager::register_toggle_action (common_actions, X_("ToggleInspector"), _("Track/Bus Inspector"), mem_fun(*this, &ARDOUR_UI::toggle_route_params_window));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (common_actions, X_("ToggleConnections"), _("Connections"), mem_fun(*this, &ARDOUR_UI::toggle_connection_editor));
@@ -200,7 +204,6 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (common_actions, X_("ToggleBigClock"), _("Big Clock"), mem_fun(*this, &ARDOUR_UI::toggle_big_clock_window));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (common_actions, X_("About"), _("About"), mem_fun(*this, &ARDOUR_UI::show_splash));
act = ActionManager::register_toggle_action (common_actions, X_("ToggleThemeManager"), _("Theme Manager"), mem_fun(*this, &ARDOUR_UI::toggle_theme_manager));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal, 1));
@@ -216,6 +219,8 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_action (common_actions, X_("RemoveLastCapture"), _("Remove Last Capture"), mem_fun(*this, &ARDOUR_UI::remove_last_capture));
ActionManager::session_sensitive_actions.push_back (act);
+ ActionManager::register_action (common_actions, X_("About"), _("About"), mem_fun(*this, &ARDOUR_UI::show_splash));
+
Glib::RefPtr<ActionGroup> transport_actions = ActionGroup::create (X_("Transport"));
/* do-nothing action for the "transport" menu bar item */
@@ -402,6 +407,7 @@ ARDOUR_UI::install_actions ()
act->set_sensitive (false);
#endif
+ ActionManager::register_toggle_action (option_actions, X_("SyncEditorAndMixerTrackOrder"), _("Sync Editor and Mixer track order"), mem_fun (*this, &ARDOUR_UI::toggle_sync_order_keys));
ActionManager::register_toggle_action (option_actions, X_("StopPluginsWithTransport"), _("Stop plugins with transport"), mem_fun (*this, &ARDOUR_UI::toggle_StopPluginsWithTransport));
ActionManager::register_toggle_action (option_actions, X_("VerifyRemoveLastCapture"), _("Verify remove last capture"), mem_fun (*this, &ARDOUR_UI::toggle_VerifyRemoveLastCapture));
ActionManager::register_toggle_action (option_actions, X_("PeriodicSafetyBackups"), _("Make periodic safety backups"), mem_fun (*this, &ARDOUR_UI::toggle_PeriodicSafetyBackups));
@@ -412,26 +418,45 @@ ARDOUR_UI::install_actions ()
ActionManager::register_toggle_action (option_actions, X_("RegionEquivalentsOverlap"), _("Region equivalents overlap"), mem_fun (*this, &ARDOUR_UI::toggle_RegionEquivalentsOverlap));
ActionManager::register_toggle_action (option_actions, X_("PrimaryClockDeltaEditCursor"), _("Primary Clock delta to edit cursor"), mem_fun (*this, &ARDOUR_UI::toggle_PrimaryClockDeltaEditCursor));
ActionManager::register_toggle_action (option_actions, X_("SecondaryClockDeltaEditCursor"), _("Secondary Clock delta to edit cursor"), mem_fun (*this, &ARDOUR_UI::toggle_SecondaryClockDeltaEditCursor));
+ ActionManager::register_toggle_action (option_actions, X_("OnlyCopyImportedFiles"), _("Always copy imported files"), mem_fun (*this, &ARDOUR_UI::toggle_only_copy_imported_files));
RadioAction::Group denormal_group;
ActionManager::register_toggle_action (option_actions, X_("DenormalProtection"), _("Use DC bias"), mem_fun (*this, &ARDOUR_UI::toggle_denormal_protection));
-
- FPU fpu;
-
ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalNone"), _("No processor handling"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalNone));
- act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZ"), _("Use FlushToZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZ));
- if (!fpu.has_flush_to_zero()) {
+ // as of September 10th 2007, Valgrind cannot handle various FPU flag setting instructions
+ // so avoid them
+
+ if (getenv ("ARDOUR_RUNNING_UNDER_VALGRIND")) {
+
+ /* we still need these actions to exist, but make them all insensitive */
+
+ act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZ"), _("Use FlushToZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZ));
act->set_sensitive (false);
- }
- act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalDAZ"), _("Use DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalDAZ));
- if (!fpu.has_denormals_are_zero()) {
+ act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalDAZ"), _("Use DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalDAZ));
act->set_sensitive (false);
- }
- act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZDAZ"), _("Use FlushToZero & DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZDAZ));
- if (!fpu.has_flush_to_zero() || !fpu.has_denormals_are_zero()) {
+ act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZDAZ"), _("Use FlushToZero & DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZDAZ));
act->set_sensitive (false);
+
+ } else {
+
+ FPU fpu;
+
+ act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZ"), _("Use FlushToZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZ));
+ if (!fpu.has_flush_to_zero()) {
+ act->set_sensitive (false);
+ }
+
+ act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalDAZ"), _("Use DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalDAZ));
+ if (!fpu.has_denormals_are_zero()) {
+ act->set_sensitive (false);
+ }
+
+ act = ActionManager::register_radio_action (option_actions, denormal_group, X_("DenormalFTZDAZ"), _("Use FlushToZero & DenormalsAreZero"), bind (mem_fun (*this, &ARDOUR_UI::set_denormal_model), DenormalFTZDAZ));
+ if (!fpu.has_flush_to_zero() || !fpu.has_denormals_are_zero()) {
+ act->set_sensitive (false);
+ }
}
act = ActionManager::register_toggle_action (option_actions, X_("DoNotRunPluginsWhileRecording"), _("Do not run plugins while recording"), mem_fun (*this, &ARDOUR_UI::toggle_DoNotRunPluginsWhileRecording));
@@ -696,7 +721,9 @@ ARDOUR_UI::build_control_surface_menu ()
void
ARDOUR_UI::build_menu_bar ()
{
- build_control_surface_menu ();
+ if (!Profile->get_sae()) {
+ build_control_surface_menu ();
+ }
menu_bar = dynamic_cast<MenuBar*> (ActionManager::get_widget (X_("/Main")));
menu_bar->set_name ("MainMenuBar");
@@ -731,11 +758,20 @@ ARDOUR_UI::build_menu_bar ()
sample_rate_box.set_name ("SampleRate");
sample_rate_label.set_name ("SampleRate");
- menu_hbox.pack_start (*menu_bar, true, true);
- if (!Profile->get_small_screen()) {
- menu_hbox.pack_end (wall_clock_box, false, false, 2);
- menu_hbox.pack_end (disk_space_box, false, false, 4);
+#ifndef TOP_MENUBAR
+ menu_hbox.pack_start (*menu_bar, true, true);
+#else
+ use_menubar_as_top_menubar ();
+#endif
+
+ if (!Profile->get_small_screen()) {
+#ifndef GTKOSX
+ // OSX provides its own wallclock, thank you very much
+ menu_hbox.pack_end (wall_clock_box, false, false, 2);
+#endif
+ menu_hbox.pack_end (disk_space_box, false, false, 4);
}
+
menu_hbox.pack_end (cpu_load_box, false, false, 4);
menu_hbox.pack_end (buffer_load_box, false, false, 4);
menu_hbox.pack_end (sample_rate_box, false, false, 4);
@@ -745,12 +781,23 @@ ARDOUR_UI::build_menu_bar ()
}
void
+ARDOUR_UI::use_menubar_as_top_menubar ()
+{
+#ifdef GTKOSX
+ ige_mac_menu_set_menu_bar ((GtkMenuShell*) menu_bar->gobj());
+ // ige_mac_menu_set_quit_menu_item (some_item->gobj());
+#endif
+}
+
+
+void
ARDOUR_UI::setup_clock ()
{
ARDOUR_UI::Clock.connect (bind (mem_fun (big_clock, &AudioClock::set), false));
big_clock_window = new Window (WINDOW_TOPLEVEL);
+ big_clock_window->set_keep_above (true);
big_clock_window->set_border_width (0);
big_clock_window->add (big_clock);
@@ -761,9 +808,5 @@ ARDOUR_UI::setup_clock ()
big_clock_window->signal_realize().connect (bind (sigc::ptr_fun (set_decoration), big_clock_window, (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH)));
big_clock_window->signal_unmap().connect (bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleBigClock")));
- if (editor) {
- editor->ensure_float (*big_clock_window);
- }
-
manage_window (*big_clock_window);
}
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index 4a6bef6b5f..d013f98e5b 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -82,6 +82,13 @@ ARDOUR_UI::toggle_denormal_protection ()
}
void
+ARDOUR_UI::toggle_only_copy_imported_files ()
+{
+ ActionManager::toggle_config_state ("options", "OnlyCopyImportedFiles", &Configuration::set_only_copy_imported_files, &Configuration::get_only_copy_imported_files);
+}
+
+
+void
ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
{
const char *action = 0;
@@ -459,6 +466,12 @@ ARDOUR_UI::toggle_StopRecordingOnXrun()
}
void
+ARDOUR_UI::toggle_sync_order_keys ()
+{
+ ActionManager::toggle_config_state ("options", "SyncEditorAndMixerTrackOrder", &Configuration::set_sync_all_route_ordering, &Configuration::get_sync_all_route_ordering);
+}
+
+void
ARDOUR_UI::toggle_StopTransportAtEndOfSession()
{
ActionManager::toggle_config_state ("options", "StopTransportAtEndOfSession", &Configuration::set_stop_at_session_end, &Configuration::get_stop_at_session_end);
@@ -577,6 +590,19 @@ ARDOUR_UI::map_monitor_model ()
}
void
+ARDOUR_UI::map_denormal_protection ()
+{
+ Glib::RefPtr<Action> act = ActionManager::get_action ("options", X_("DenormalProtection"));
+ if (act) {
+ Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+
+ if (tact && !tact->get_active()) {
+ tact->set_active (Config->get_denormal_protection());
+ }
+ }
+}
+
+void
ARDOUR_UI::map_denormal_model ()
{
const char* on = 0;
@@ -762,6 +788,21 @@ ARDOUR_UI::map_output_auto_connect ()
}
void
+ARDOUR_UI::map_only_copy_imported_files ()
+{
+ Glib::RefPtr<Action> act = ActionManager::get_action ("options", X_("OnlyCopyImportedFiles"));
+ if (act) {
+ Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+
+ if (tact && !tact->get_active()) {
+ tact->set_active (Config->get_only_copy_imported_files());
+ }
+ }
+
+}
+
+
+void
ARDOUR_UI::map_meter_falloff ()
{
const char* action = X_("MeterFalloffMedium");
@@ -995,12 +1036,16 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
ActionManager::map_some_state ("options", "PeriodicSafetyBackups", &Configuration::get_periodic_safety_backups);
} else if (PARAM_IS ("stop-recording-on-xrun")) {
ActionManager::map_some_state ("options", "StopRecordingOnXrun", &Configuration::get_stop_recording_on_xrun);
+ } else if (PARAM_IS ("sync-all-route-ordering")) {
+ ActionManager::map_some_state ("options", "SyncEditorAndMixerTrackOrder", &Configuration::get_sync_all_route_ordering);
} else if (PARAM_IS ("stop-at-session-end")) {
ActionManager::map_some_state ("options", "StopTransportAtEndOfSession", &Configuration::get_stop_at_session_end);
} else if (PARAM_IS ("monitoring-model")) {
map_monitor_model ();
} else if (PARAM_IS ("denormal-model")) {
map_denormal_model ();
+ } else if (PARAM_IS ("denormal-protection")) {
+ map_denormal_protection ();
} else if (PARAM_IS ("remote-model")) {
map_remote_model ();
} else if (PARAM_IS ("use-video-sync")) {
@@ -1062,8 +1107,9 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
ActionManager::map_some_state ("options", "PrimaryClockDeltaEditCursor", &Configuration::get_primary_clock_delta_edit_cursor);
} else if (PARAM_IS ("secondary-clock-delta-edit-cursor")) {
ActionManager::map_some_state ("options", "SecondaryClockDeltaEditCursor", &Configuration::get_secondary_clock_delta_edit_cursor);
- }
-
+ } else if (PARAM_IS ("only-copy-imported-files")) {
+ map_only_copy_imported_files ();
+ }
#undef PARAM_IS
}
diff --git a/gtk2_ardour/arprof b/gtk2_ardour/arprof
index 05a469cb17..47c11cdb99 100755
--- a/gtk2_ardour/arprof
+++ b/gtk2_ardour/arprof
@@ -6,4 +6,4 @@ if [ gprofhelper.c -nt gprofhelper.so ] ; then
fi
. ardev_common.sh
-LDPRELOAD=./gprofhelper.so $EXECUTABLE $*
+LDPRELOAD=./gprofhelper.so $EXECUTABLE "$@"
diff --git a/gtk2_ardour/arval b/gtk2_ardour/arval
index 920e7cb1a8..5661b4cd11 100755
--- a/gtk2_ardour/arval
+++ b/gtk2_ardour/arval
@@ -1,4 +1,4 @@
#!/bin/sh
. ardev_common.sh
export ARDOUR_RUNNING_UNDER_VALGRIND=TRUE
-exec valgrind --num-callers=50 --tool=memcheck $EXECUTABLE --novst $*
+exec valgrind --num-callers=50 --tool=memcheck $EXECUTABLE --novst "$@"
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index dc6de8d0f6..4bc10e93ec 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -28,6 +28,8 @@
#include <ardour/audioregion.h>
#include <ardour/audiosource.h>
#include <ardour/audio_diskstream.h>
+#include <ardour/profile.h>
+
#include <pbd/memento_command.h>
#include <pbd/stacktrace.h>
@@ -177,7 +179,9 @@ AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
line_name += ':';
line_name += "gain";
- gain_line = new AudioRegionGainLine (line_name, trackview.session(), *this, *group, audio_region()->envelope());
+ if (!Profile->get_sae()) {
+ gain_line = new AudioRegionGainLine (line_name, trackview.session(), *this, *group, audio_region()->envelope());
+ }
if (!(_flags & EnvelopeVisible)) {
gain_line->hide ();
@@ -814,6 +818,8 @@ AudioRegionView::create_waves ()
if (audio_region()->audio_source(n)->peaks_ready (bind (mem_fun(*this, &AudioRegionView::peaks_ready_handler), n), data_ready_connection)) {
create_one_wave (n, true);
} else {
+ // we'll get a PeaksReady signal from the source in the future
+ // and will call create_one_wave(n) then.
}
} else {
create_one_wave (n, true);
diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc
index bbe573dab2..22f8fa6239 100644
--- a/gtk2_ardour/audio_streamview.cc
+++ b/gtk2_ardour/audio_streamview.cc
@@ -74,6 +74,7 @@ AudioStreamView::AudioStreamView (AudioTimeAxisView& tv)
use_rec_regions = tv.editor.show_waveforms_recording ();
+
}
AudioStreamView::~AudioStreamView ()
diff --git a/gtk2_ardour/axis_view.h b/gtk2_ardour/axis_view.h
index 51f744c4e5..e64ef99b16 100644
--- a/gtk2_ardour/axis_view.h
+++ b/gtk2_ardour/axis_view.h
@@ -62,6 +62,9 @@ class AxisView : public virtual Selectable
sigc::signal<void> Hiding;
sigc::signal<void> GoingAway;
+ void set_old_order_key (uint32_t ok) { _old_order_key = ok; }
+ uint32_t old_order_key() const { return _old_order_key; }
+
protected:
AxisView (ARDOUR::Session& sess);
@@ -84,7 +87,8 @@ class AxisView : public virtual Selectable
Gtk::Label name_label;
bool _marked_for_display;
-
+ uint32_t _old_order_key;
+
}; /* class AxisView */
#endif /* __ardour_gtk_axis_view_h__ */
diff --git a/gtk2_ardour/editing.h b/gtk2_ardour/editing.h
index d7f8f6ece8..93bbb603ee 100644
--- a/gtk2_ardour/editing.h
+++ b/gtk2_ardour/editing.h
@@ -34,6 +34,8 @@
#define ZOOMFOCUS(a) /*empty*/
#define DISPLAYCONTROL(a) /*empty*/
#define IMPORTMODE(a) /*empty*/
+#define IMPORTPOSITION(a)
+#define IMPORTDISPOSITION(a)
namespace Editing {
@@ -135,6 +137,7 @@ DisplayControl str2displaycontrol (const std::string &);
#undef DISPLAYCONTROL
#define DISPLAYCONTROL(a) /*empty*/
+
// IMPORTMODE
#undef IMPORTMODE
#define IMPORTMODE(a) a,
@@ -142,13 +145,29 @@ enum ImportMode {
#include "editing_syms.h"
};
-extern const char *importmodestrs[];
-inline const char* enum2str(ImportMode m) {return importmodestrs[m];}
-ImportMode str2importmode (const std::string &);
-
#undef IMPORTMODE
#define IMPORTMODE(a) /*empty*/
+// IMPORTPOSITION
+#undef IMPORTPOSITION
+#define IMPORTPOSITION(a) a,
+enum ImportPosition {
+ #include "editing_syms.h"
+};
+
+#undef IMPORTPOSITION
+#define IMPORTPOSITION(a) /*empty*/
+
+// IMPORTDISPOSITION
+#undef IMPORTDISPOSITION
+#define IMPORTDISPOSITION(a) a,
+enum ImportDisposition {
+ #include "editing_syms.h"
+};
+
+#undef IMPORTDISPOSITION
+#define IMPORTDISPOSITION(a) /*empty*/
+
/////////////////////
// These don't need their state saved. yet...
enum CutCopyOp {
diff --git a/gtk2_ardour/editing_syms.h b/gtk2_ardour/editing_syms.h
index a057f6dd64..a520b0d318 100644
--- a/gtk2_ardour/editing_syms.h
+++ b/gtk2_ardour/editing_syms.h
@@ -83,3 +83,15 @@ IMPORTMODE(ImportAsRegion=0)
IMPORTMODE(ImportToTrack=1)
IMPORTMODE(ImportAsTrack=2)
IMPORTMODE(ImportAsTapeTrack=3)
+
+// if this is changed, remember to update the string table in sfdb_ui.cc
+IMPORTPOSITION(ImportAtTimestamp=0)
+IMPORTPOSITION(ImportAtEditCursor=1)
+IMPORTPOSITION(ImportAtPlayhead=2)
+IMPORTPOSITION(ImportAtStart=3)
+
+// if this is changed, remember to update the string table in sfdb_ui.cc
+IMPORTDISPOSITION(ImportDistinctFiles=0)
+IMPORTDISPOSITION(ImportMergeFiles=1)
+IMPORTDISPOSITION(ImportSerializeFiles=2)
+IMPORTDISPOSITION(ImportDistinctChannels=3)
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 031262c41e..f0a2bfa809 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -25,6 +25,8 @@
#include <string>
#include <algorithm>
+#include <boost/none.hpp>
+
#include <sigc++/bind.h>
#include <pbd/convert.h>
@@ -56,6 +58,7 @@
#include <ardour/session_state_utils.h>
#include <ardour/tempo.h>
#include <ardour/utils.h>
+#include <ardour/profile.h>
#include <control_protocol/control_protocol.h>
@@ -77,6 +80,7 @@
#include "crossfade_edit.h"
#include "canvas_impl.h"
#include "actions.h"
+#include "sfdb_ui.h"
#include "gui_thread.h"
#ifdef FFT_ANALYSIS
@@ -139,8 +143,8 @@ static const gchar *_zoom_focus_strings[] = {
N_("Left"),
N_("Right"),
N_("Center"),
- N_("Play"),
- N_("Edit"),
+ N_("Playhead"),
+ N_("Edit Cursor"),
0
};
@@ -267,6 +271,7 @@ Editor::Editor ()
autoscroll_active = false;
autoscroll_timeout_tag = -1;
interthread_progress_window = 0;
+ logo_item = 0;
#ifdef FFT_ANALYSIS
analysis_window = 0;
@@ -278,6 +283,7 @@ Editor::Editor ()
_show_waveforms_recording = true;
first_action_message = 0;
export_dialog = 0;
+ export_range_markers_dialog = 0;
show_gain_after_trim = false;
ignore_route_list_reorder = false;
no_route_list_redisplay = false;
@@ -302,6 +308,8 @@ Editor::Editor ()
new_transport_marker_menu = 0;
editor_mixer_strip_width = Wide;
show_editor_mixer_when_tracks_arrive = false;
+ region_edit_menu_split_multichannel_item = 0;
+ region_edit_menu_split_item = 0;
temp_location = 0;
leftmost_frame = 0;
ignore_mouse_mode_toggle = false;
@@ -321,6 +329,17 @@ Editor::Editor ()
_dragging_playhead = false;
_dragging_hscrollbar = false;
+ _scrubbing = false;
+ mouse_direction = 1;
+ mouse_speed_update = -1;
+ mouse_speed_size = 16;
+ mouse_speed = new double[mouse_speed_size];
+ memset (mouse_speed, 0, sizeof(double) * mouse_speed_size);
+ mouse_speed_entries = 0;
+
+ sfbrowser = 0;
+ ignore_route_order_sync = false;
+
location_marker_color = ARDOUR_UI::config()->canvasvar_LocationMarker.get();
location_range_color = ARDOUR_UI::config()->canvasvar_LocationRange.get();
location_cd_marker_color = ARDOUR_UI::config()->canvasvar_LocationCDMarker.get();
@@ -345,7 +364,7 @@ Editor::Editor ()
edit_controls_vbox.set_spacing (0);
horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
- vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
+ vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling), true);
track_canvas.set_hadjustment (horizontal_adjustment);
track_canvas.set_vadjustment (vertical_adjustment);
@@ -688,6 +707,9 @@ Editor::Editor ()
set_name ("EditorWindow");
add_accel_group (ActionManager::ui_manager->get_accel_group());
+ status_bar_hpacker.show ();
+
+ vpacker.pack_end (status_bar_hpacker, false, false);
vpacker.pack_end (global_hpacker, true, true);
/* register actions now so that set_state() can find them and set toggles/checks etc */
@@ -756,6 +778,7 @@ Editor::Editor ()
ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll));
Config->ParameterChanged.connect (mem_fun (*this, &Editor::parameter_changed));
+ Route::SyncOrderKeys.connect (mem_fun (*this, &Editor::sync_order_keys));
constructed = true;
instant_save ();
@@ -854,9 +877,27 @@ void
Editor::tie_vertical_scrolling ()
{
double y1 = vertical_adjustment.get_value();
+
+ playhead_cursor->set_y_axis (y1);
+ edit_cursor->set_y_axis (y1);
+ if (logo_item) {
+ logo_item->property_y() = y1;
+ }
+
controls_layout.get_vadjustment()->set_value (y1);
- playhead_cursor->set_y_axis(y1);
- edit_cursor->set_y_axis(y1);
+
+#ifdef GTKOSX
+ /* the way idle updates and immediate window flushing work on GTK-Quartz
+ requires that we force an immediate redraw right here. The controls
+ layout will do the same all by itself, as does the canvas widget, but
+ most of the time, the canvas itself hasn't updated itself because its
+ idle handler hasn't run. consequently, the call that its layout makes
+ to gdk_window_process_updates() finds nothing to do. here, we force
+ the update to happen, then request a flush of the new window state.
+ */
+ track_canvas.update_now ();
+ gdk_window_process_updates (GTK_LAYOUT(track_canvas.gobj())->bin_window, true);
+#endif
}
void
@@ -912,40 +953,65 @@ Editor::control_scroll (float fraction)
}
double step = fraction * current_page_frames();
- nframes_t target;
- if ((fraction < 0.0f) && (session->transport_frame() < (nframes_t) fabs(step))) {
- target = 0;
- } else if ((fraction > 0.0f) && (max_frames - session->transport_frame() < step)) {
- target = (max_frames - (current_page_frames()*2)); // allow room for slop in where the PH is on the screen
+ /*
+ _control_scroll_target is an optional<T>
+
+ it acts like a pointer to an nframes_t, with
+ a operator conversion to boolean to check
+ that it has a value could possibly use
+ playhead_cursor->current_frame to store the
+ value and a boolean in the class to know
+ when it's out of date
+ */
+
+ if (!_control_scroll_target) {
+ _control_scroll_target = session->transport_frame();
+ _dragging_playhead = true;
+ }
+
+ if ((fraction < 0.0f) && (*_control_scroll_target < (nframes_t) fabs(step))) {
+ *_control_scroll_target = 0;
+ } else if ((fraction > 0.0f) && (max_frames - *_control_scroll_target < step)) {
+ *_control_scroll_target = max_frames - (current_page_frames()*2); // allow room for slop in where the PH is on the screen
} else {
- target = (session->transport_frame() + (nframes_t) floor ((fraction * current_page_frames())));
+ *_control_scroll_target += (nframes_t) floor (step);
}
/* move visuals, we'll catch up with it later */
- playhead_cursor->set_position (target);
-
- if (target > (current_page_frames() / 2)) {
+ playhead_cursor->set_position (*_control_scroll_target);
+ UpdateAllTransportClocks (*_control_scroll_target);
+
+ if (*_control_scroll_target > (current_page_frames() / 2)) {
/* try to center PH in window */
- reset_x_origin (target - (current_page_frames()/2));
+ reset_x_origin (*_control_scroll_target - (current_page_frames()/2));
} else {
reset_x_origin (0);
}
- /* cancel the existing */
+ /*
+ Now we do a timeout to actually bring the session to the right place
+ according to the playhead. This is to avoid reading disk buffers on every
+ call to control_scroll, which is driven by ScrollTimeline and therefore
+ probably by a control surface wheel which can generate lots of events.
+ */
+ /* cancel the existing timeout */
control_scroll_connection.disconnect ();
- /* add the next one */
+ /* add the next timeout */
- control_scroll_connection = Glib::signal_timeout().connect (bind (mem_fun (*this, &Editor::deferred_control_scroll), target), 50);
+ control_scroll_connection = Glib::signal_timeout().connect (bind (mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
}
bool
Editor::deferred_control_scroll (nframes_t target)
{
- session->request_locate (target);
+ session->request_locate (*_control_scroll_target, session->transport_rolling());
+ // reset for next stream
+ _control_scroll_target = boost::none;
+ _dragging_playhead = false;
return false;
}
@@ -1153,6 +1219,10 @@ Editor::connect_to_session (Session *t)
session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
+ if (sfbrowser) {
+ sfbrowser->set_session (session);
+ }
+
handle_new_duration ();
redisplay_regions ();
@@ -1271,12 +1341,18 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
}
items.push_back (SeparatorElem());
-
- items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Linear)));
- items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Fast)));
- items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogB)));
- items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogA)));
- items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Slow)));
+
+ if (Profile->get_sae()) {
+ items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Linear)));
+ items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Fast)));
+ } else {
+ items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Linear)));
+ items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Fast)));
+ items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogB)));
+ items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogA)));
+ items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Slow)));
+ }
+
break;
case FadeOutItem:
@@ -1289,11 +1365,16 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear)));
- items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
- items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogA)));
- items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogB)));
- items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Fast)));
+ if (Profile->get_sae()) {
+ items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear)));
+ items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
+ } else {
+ items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear)));
+ items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
+ items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogA)));
+ items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogB)));
+ items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Fast)));
+ }
break;
@@ -1486,6 +1567,7 @@ void
Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
{
using namespace Menu_Helpers;
+ sigc::connection fooc;
Menu *region_menu = manage (new Menu);
MenuList& items = region_menu->items();
region_menu->set_name ("ArdourContextMenu");
@@ -1515,14 +1597,52 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Lock"), bind (mem_fun (*this, &Editor::set_region_lock), true)));
- items.push_back (MenuElem (_("Unlock"), bind (mem_fun (*this, &Editor::set_region_lock), false)));
- items.push_back (MenuElem (_("Lock Position"), bind (mem_fun (*this, &Editor::set_region_position_lock), true)));
- items.push_back (MenuElem (_("Unlock Position"), bind (mem_fun (*this, &Editor::set_region_position_lock), false)));
- items.push_back (MenuElem (_("Mute"), bind (mem_fun (*this, &Editor::set_region_mute), true)));
- items.push_back (MenuElem (_("Unmute"), bind (mem_fun (*this, &Editor::set_region_mute), false)));
- items.push_back (MenuElem (_("Opaque"), bind (mem_fun (*this, &Editor::set_region_opaque), true)));
- items.push_back (MenuElem (_("Transparent"), bind (mem_fun (*this, &Editor::set_region_opaque), false)));
+ items.push_back (CheckMenuElem (_("Lock")));
+ region_lock_item = static_cast<CheckMenuItem*>(&items.back());
+ fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
+
+#if FIXUP_REGION_MENU
+ if (region->locked()) {
+ fooc.block (true);
+ region_lock_item->set_active();
+ fooc.block (false);
+ }
+#endif
+
+ items.push_back (CheckMenuElem (_("Lock Position")));
+ region_lock_position_item = static_cast<CheckMenuItem*>(&items.back());
+ fooc = region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_position_lock));
+#if FIXUP_REGION_MENU
+ if (region->locked()) {
+ fooc.block (true);
+ region_lock_position_item->set_active();
+ fooc.block (false);
+ }
+#endif
+
+ items.push_back (CheckMenuElem (_("Mute")));
+ region_mute_item = static_cast<CheckMenuItem*>(&items.back());
+ fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
+#if FIXUP_REGION_MENU
+ if (region->muted()) {
+ fooc.block (true);
+ region_mute_item->set_active();
+ fooc.block (false);
+ }
+#endif
+
+ if (!Profile->get_sae()) {
+ items.push_back (CheckMenuElem (_("Opaque")));
+ region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
+ fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
+#if FIXUP_REGION_MENU
+ if (region->opaque()) {
+ fooc.block (true);
+ region_opaque_item->set_active();
+ fooc.block (false);
+ }
+#endif
+ }
/* We allow "Original position" if at least one region is not at its
natural position
@@ -1549,16 +1669,48 @@ Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items)
MenuList& envelopes_items = envelopes_menu->items();
envelopes_menu->set_name ("ArdourContextMenu");
- envelopes_items.push_back (MenuElem (_("Reset"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
- envelopes_items.push_back (MenuElem (_("Visible"), bind (mem_fun (*this, &Editor::set_gain_envelope_visibility), true)));
- envelopes_items.push_back (MenuElem (_("Invisible"), bind (mem_fun (*this, &Editor::set_gain_envelope_visibility), false)));
- envelopes_items.push_back (MenuElem (_("Active"), bind (mem_fun (*this, &Editor::set_gain_envelope_active), true)));
- envelopes_items.push_back (MenuElem (_("Inactive"), bind (mem_fun (*this, &Editor::set_gain_envelope_active), false)));
+#if FIXUP_REGION_MENU
+
+ XXX NEED TO RESOLVE ONE v. MANY REGION ISSUE
+
+ RegionView* rv = sv->find_view (ar);
+ AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
+
+ if (!Profile->get_sae()) {
+ envelopes_items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
+
+ envelopes_items.push_back (CheckMenuElem (_("Envelope Visible")));
+ region_envelope_visible_item = static_cast<CheckMenuItem*> (&items.back());
+ fooc = region_envelope_visible_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_visibility));
+ if (arv->envelope_visible()) {
+ fooc.block (true);
+ region_envelope_visible_item->set_active (true);
+ fooc.block (false);
+ }
+
+ envelopes_items.push_back (CheckMenuElem (_("Envelope Active")));
+ region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back());
+ fooc = region_envelope_active_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_active));
+
+ if (ar->envelope_active()) {
+ fooc.block (true);
+ region_envelope_active_item->set_active (true);
+ fooc.block (false);
+ }
+
+ items.push_back (SeparatorElem());
+ }
+#endif
items.push_back (MenuElem (_("Envelopes"), *envelopes_menu));
- items.push_back (MenuElem (_("Denormalize"), mem_fun (*this, &Editor::denormalize_regions)));
- items.push_back (MenuElem (_("Normalize"), mem_fun (*this, &Editor::normalize_regions)));
+#if FIXUP_REGION_MENU
+ if (ar->scale_amplitude() != 1.0f) {
+ items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_regions)));
+ } else {
+ items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_regions)));
+ }
+#endif
}
/* Find out if we have a selected MIDI region */
@@ -1631,7 +1783,7 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
selection_menu->set_name ("ArdourContextMenu");
items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
- items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
+ items.push_back (MenuElem (_("Loop range"), bind (mem_fun(*this, &Editor::set_loop_from_selection), true)));
#ifdef FFT_ANALYSIS
items.push_back (SeparatorElem());
@@ -1639,15 +1791,22 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
#endif
items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Separate range to track"), mem_fun(*this, &Editor::separate_region_from_selection)));
- items.push_back (MenuElem (_("Separate range to region list"), mem_fun(*this, &Editor::new_region_from_selection)));
+ items.push_back (MenuElem (_("Extend Range to End of Region"), bind (mem_fun(*this, &Editor::extend_selection_to_end_of_region), false)));
+ items.push_back (MenuElem (_("Extend Range to Start of Region"), bind (mem_fun(*this, &Editor::extend_selection_to_start_of_region), false)));
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Convert to region in-place"), mem_fun(*this, &Editor::separate_region_from_selection)));
+ items.push_back (MenuElem (_("Convert to region in region list"), mem_fun(*this, &Editor::new_region_from_selection)));
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Select all in range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
+
+ items.push_back (SeparatorElem());
+ items.push_back (MenuElem (_("Set loop from selection"), bind (mem_fun(*this, &Editor::set_loop_from_selection), false)));
+ items.push_back (MenuElem (_("Set punch from selection"), mem_fun(*this, &Editor::set_punch_from_selection)));
+
items.push_back (SeparatorElem());
- items.push_back (MenuElem (_("Add range markers"), mem_fun (*this, &Editor::add_location_from_selection)));
- items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
- items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
+ items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_selection)));
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Crop region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
items.push_back (MenuElem (_("Fill range with region"), mem_fun(*this, &Editor::region_fill_selection)));
@@ -1656,9 +1815,6 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection)));
-
- edit_items.push_back (MenuElem (_("Range"), *selection_menu));
- edit_items.push_back (SeparatorElem());
}
/** Add context menu items relevant to busses or audio tracks.
@@ -2685,8 +2841,10 @@ Editor::convert_drop_to_paths (vector<ustring>& paths,
vector<ustring> uris = data.get_uris();
+ cerr << "there were " << uris.size() << " in that drag data\n";
+
if (uris.empty()) {
-
+
/* This is seriously fucked up. Nautilus doesn't say that its URI lists
are actually URI lists. So do it by hand.
*/
@@ -2736,10 +2894,34 @@ Editor::convert_drop_to_paths (vector<ustring>& paths,
}
for (vector<ustring>::iterator i = uris.begin(); i != uris.end(); ++i) {
+
if ((*i).substr (0,7) == "file://") {
- string p = *i;
+
+ ustring p = *i;
PBD::url_decode (p);
- paths.push_back (p.substr (7));
+
+ // scan forward past three slashes
+
+ ustring::size_type slashcnt = 0;
+ ustring::size_type n = 0;
+ ustring::iterator x = p.begin();
+
+ while (slashcnt < 3 && x != p.end()) {
+ if ((*x) == '/') {
+ slashcnt++;
+ } else if (slashcnt == 3) {
+ break;
+ }
+ ++n;
+ ++x;
+ }
+
+ if (slashcnt != 3 || x == p.end()) {
+ error << _("malformed URL passed to drag-n-drop code") << endmsg;
+ continue;
+ }
+
+ paths.push_back (p.substr (n - 1));
}
}
@@ -3838,3 +4020,60 @@ Editor::edit_cursor_position(bool sync)
return edit_cursor->current_frame;
}
+
+void
+Editor::set_loop_range (nframes_t start, nframes_t end, string cmd)
+{
+ if (!session) return;
+
+ begin_reversible_command (cmd);
+
+ Location* tll;
+
+ if ((tll = transport_loop_location()) == 0) {
+ Location* loc = new Location (start, end, _("Loop"), Location::IsAutoLoop);
+ XMLNode &before = session->locations()->get_state();
+ session->locations()->add (loc, true);
+ session->set_auto_loop_location (loc);
+ XMLNode &after = session->locations()->get_state();
+ session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
+ }
+ else {
+ XMLNode &before = tll->get_state();
+ tll->set_hidden (false, this);
+ tll->set (start, end);
+ XMLNode &after = tll->get_state();
+ session->add_command (new MementoCommand<Location>(*tll, &before, &after));
+ }
+
+ commit_reversible_command ();
+}
+
+void
+Editor::set_punch_range (nframes_t start, nframes_t end, string cmd)
+{
+ if (!session) return;
+
+ begin_reversible_command (cmd);
+
+ Location* tpl;
+
+ if ((tpl = transport_punch_location()) == 0) {
+ Location* loc = new Location (start, end, _("Loop"), Location::IsAutoPunch);
+ XMLNode &before = session->locations()->get_state();
+ session->locations()->add (loc, true);
+ session->set_auto_loop_location (loc);
+ XMLNode &after = session->locations()->get_state();
+ session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
+ }
+ else {
+ XMLNode &before = tpl->get_state();
+ tpl->set_hidden (false, this);
+ tpl->set (start, end);
+ XMLNode &after = tpl->get_state();
+ session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
+ }
+
+ commit_reversible_command ();
+}
+
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 976ad68188..63cbc042ac 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -26,9 +26,14 @@
#include <string>
#include <sys/time.h>
+#include <glibmm/ustring.h>
+
+#include <boost/optional.hpp>
+
#include <libgnomecanvasmm/canvas.h>
#include <libgnomecanvasmm/group.h>
#include <libgnomecanvasmm/line.h>
+#include <libgnomecanvasmm/pixbuf.h>
#include <cmath>
@@ -100,6 +105,7 @@ class MixerStrip;
class StreamView;
class AudioStreamView;
class ControlPoint;
+class SoundFileOmega;
#ifdef FFT_ANALYSIS
class AnalysisWindow;
#endif
@@ -249,6 +255,7 @@ class Editor : public PublicEditor
void add_toplevel_controls (Gtk::Container&);
+ Gtk::HBox& get_status_bar_packer() { return status_bar_hpacker; }
void set_zoom_focus (Editing::ZoomFocus);
Editing::ZoomFocus get_zoom_focus () const { return zoom_focus; }
@@ -298,6 +305,7 @@ class Editor : public PublicEditor
void toggle_waveform_visibility ();
void toggle_waveforms_while_recording ();
void toggle_measure_visibility ();
+ void toggle_logo_visibility ();
/* SMPTE timecode & video sync */
@@ -346,6 +354,8 @@ class Editor : public PublicEditor
void reposition_and_zoom (nframes_t, double);
nframes_t edit_cursor_position(bool);
+ bool update_mouse_speed ();
+ bool decelerate_mouse_speed ();
protected:
void map_transport_state ();
@@ -360,6 +370,9 @@ class Editor : public PublicEditor
ARDOUR::Session *session;
bool constructed;
+ // to keep track of the playhead position for control_scroll
+ boost::optional<nframes_t> _control_scroll_target;
+
PlaylistSelector* _playlist_selector;
void set_frames_per_unit (double);
@@ -464,6 +477,9 @@ class Editor : public PublicEditor
void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set);
void collect_new_region_view (RegionView *);
+ Gtk::MenuItem* region_edit_menu_split_item;
+ Gtk::MenuItem* region_edit_menu_split_multichannel_item;
+
void popup_track_context_menu (int, int, nframes_t);
Gtk::Menu* build_track_context_menu (nframes_t);
void add_bus_or_audio_track_context_items (Gtk::Menu_Helpers::MenuList&);
@@ -507,6 +523,7 @@ class Editor : public PublicEditor
Gtk::Frame time_button_frame;
ArdourCanvas::Group *minsec_group;
+ ArdourCanvas::Pixbuf *logo_item;
ArdourCanvas::Group *bbt_group;
ArdourCanvas::Group *smpte_group;
ArdourCanvas::Group *frame_group;
@@ -671,6 +688,7 @@ class Editor : public PublicEditor
Gtk::VBox track_canvas_vbox;
Gtk::VBox time_canvas_vbox;
Gtk::VBox edit_controls_vbox;
+ Gtk::HBox edit_controls_hbox;
void control_scroll (float);
bool deferred_control_scroll (nframes_t);
@@ -728,6 +746,7 @@ class Editor : public PublicEditor
Gtk::Menu *region_list_menu;
Gtk::ScrolledWindow region_list_scroller;
+ Gtk::Frame region_list_frame;
bool region_list_display_key_press (GdkEventKey *);
bool region_list_display_key_release (GdkEventKey *);
@@ -868,10 +887,10 @@ class Editor : public PublicEditor
/* EDITING OPERATIONS */
void reset_point_selection ();
- void set_region_mute (bool);
- void set_region_lock (bool);
- void set_region_position_lock (bool);
- void set_region_opaque (bool);
+ void toggle_region_mute ();
+ void toggle_region_lock ();
+ void toggle_region_opaque ();
+ void toggle_region_position_lock ();
void raise_region_to_top ();
void lower_region_to_bottom ();
void split_region ();
@@ -951,15 +970,32 @@ class Editor : public PublicEditor
void insert_region_list_drag (boost::shared_ptr<ARDOUR::Region>, int x, int y);
void insert_region_list_selection (float times);
+ /* import & embed */
+
void add_external_audio_action (Editing::ImportMode);
+ void external_audio_dialog ();
+ bool check_multichannel_status (const std::vector<Glib::ustring>& paths);
+
+ SoundFileOmega* sfbrowser;
+
+ void bring_in_external_audio (Editing::ImportMode mode, nframes64_t& pos);
+ void do_import (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t&);
+
+ void _do_embed (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, nframes64_t&);
+ void do_embed (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, nframes64_t&);
+ bool idle_do_embed (vector<Glib::ustring> paths, Editing::ImportDisposition, Editing::ImportMode mode, nframes64_t&);
- void bring_in_external_audio (Editing::ImportMode mode, ARDOUR::AudioTrack*, nframes_t& pos, bool prompt);
- void do_import (vector<Glib::ustring> paths, bool split, Editing::ImportMode mode, ARDOUR::AudioTrack*, nframes_t&, bool);
- void do_embed (vector<Glib::ustring> paths, bool split, Editing::ImportMode mode, ARDOUR::AudioTrack*, nframes_t&, bool);
- int import_sndfile (vector<Glib::ustring> paths, Editing::ImportMode mode, ARDOUR::AudioTrack* track, nframes_t& pos);
- int embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_files, bool& check_sample_rate, Editing::ImportMode mode,
- ARDOUR::AudioTrack* track, nframes_t& pos, bool prompt);
- int finish_bringing_in_audio (boost::shared_ptr<ARDOUR::AudioRegion> region, uint32_t, uint32_t, ARDOUR::AudioTrack* track, nframes_t& pos, Editing::ImportMode mode);
+ int import_sndfiles (vector<Glib::ustring> paths, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t& pos,
+ int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::AudioTrack>&);
+ int embed_sndfiles (vector<Glib::ustring> paths, bool multiple_files, bool& check_sample_rate, Editing::ImportMode mode,
+ nframes64_t& pos, int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::AudioTrack>&);
+
+ int add_sources (vector<Glib::ustring> paths, ARDOUR::SourceList& sources, nframes64_t& pos, Editing::ImportMode,
+ int target_regions, int target_tracks, boost::shared_ptr<ARDOUR::AudioTrack>&, bool add_channel_suffix);
+ int finish_bringing_in_audio (boost::shared_ptr<ARDOUR::AudioRegion> region, uint32_t, uint32_t, nframes64_t& pos, Editing::ImportMode mode,
+ boost::shared_ptr<ARDOUR::AudioTrack>& existing_track);
+
+ boost::shared_ptr<ARDOUR::AudioTrack> get_nth_selected_audio_track (int nth) const;
/* generic interthread progress window */
@@ -1030,7 +1066,11 @@ class Editor : public PublicEditor
void add_location_from_audio_region ();
void add_location_from_selection ();
- void set_route_loop_selection ();
+ void set_loop_from_selection (bool play);
+ void set_punch_from_selection ();
+
+ void set_loop_range (nframes_t start, nframes_t end, std::string cmd);
+ void set_punch_range (nframes_t start, nframes_t end, std::string cmd);
void add_location_from_playhead_cursor ();
@@ -1040,6 +1080,18 @@ class Editor : public PublicEditor
void start_scrolling ();
void stop_scrolling ();
+ bool _scrubbing;
+ bool have_full_mouse_speed;
+ nframes64_t last_scrub_frame;
+ double last_scrub_time;
+ int mouse_speed_update;
+ double mouse_direction;
+ double compute_mouse_speed ();
+ void add_mouse_speed (double, double);
+ double* mouse_speed;
+ size_t mouse_speed_entries;
+ size_t mouse_speed_size;
+
void keyboard_selection_begin ();
void keyboard_selection_finish (bool add);
bool have_pending_keyboard_selection;
@@ -1488,10 +1540,12 @@ class Editor : public PublicEditor
add (text);
add (visible);
add (tv);
+ add (route);
}
Gtk::TreeModelColumn<Glib::ustring> text;
Gtk::TreeModelColumn<bool> visible;
Gtk::TreeModelColumn<TimeAxisView*> tv;
+ Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Route> > route;
};
RouteDisplayModelColumns route_display_columns;
@@ -1502,11 +1556,16 @@ class Editor : public PublicEditor
Gtk::ScrolledWindow route_list_scroller;
Gtk::Menu* route_list_menu;
+ void sync_order_keys ();
+ bool ignore_route_order_sync;
+
bool route_list_display_button_press (GdkEventButton*);
bool route_list_selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
void route_list_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&);
void route_list_delete (const Gtk::TreeModel::Path&);
+ void track_list_reorder (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order);
+
void initial_route_list_display ();
void redisplay_route_list();
void route_list_reordered (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* what);
@@ -1858,14 +1917,15 @@ class Editor : public PublicEditor
bool _new_regionviews_show_envelope;
- void set_gain_envelope_visibility (bool);
- void set_gain_envelope_active (bool);
+ void toggle_gain_envelope_visibility ();
+ void toggle_gain_envelope_active ();
void reset_region_gain_envelopes ();
Gtk::CheckMenuItem* region_envelope_visible_item;
Gtk::CheckMenuItem* region_envelope_active_item;
Gtk::CheckMenuItem* region_mute_item;
Gtk::CheckMenuItem* region_lock_item;
+ Gtk::CheckMenuItem* region_lock_position_item;
Gtk::CheckMenuItem* region_opaque_item;
bool on_key_press_event (GdkEventKey*);
@@ -1876,6 +1936,8 @@ class Editor : public PublicEditor
Glib::RefPtr<Gtk::Action> redo_action;
void history_changed ();
+
+ Gtk::HBox status_bar_hpacker;
};
#endif /* __ardour_editor_h__ */
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 7fe0de9aae..051af2c898 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -66,7 +66,6 @@ Editor::register_actions ()
/* add named actions for the editor */
-
act = ActionManager::register_toggle_action (editor_actions, "show-editor-mixer", _("Show Editor Mixer"), mem_fun (*this, &Editor::editor_mixer_button_toggled));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_toggle_action (editor_actions, "show-editor-list", _("Show Editor List"), mem_fun (*this, &Editor::editor_list_button_toggled));
@@ -385,19 +384,17 @@ Editor::register_actions ()
act = ActionManager::register_action (editor_actions, X_("addExternalAudioToRegionList"), _("Add External Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, X_("addExternalAudioAsRegion"), _("as Region(s)"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion));
- ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, X_("addExternalAudioAsTrack"), _("as Tracks"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsTrack));
- ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, X_("addExternalAudioAsTapeTrack"), _("as Tape Tracks"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportAsTapeTrack));
- ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, X_("addExternalAudioToTrack"), _("to Tracks"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack));
- ActionManager::session_sensitive_actions.push_back (act);
ActionManager::register_toggle_action (editor_actions, X_("ToggleWaveformVisibility"), _("Show Waveforms"), mem_fun (*this, &Editor::toggle_waveform_visibility));
ActionManager::register_toggle_action (editor_actions, X_("ToggleWaveformsWhileRecording"), _("Show Waveforms While Recording"), mem_fun (*this, &Editor::toggle_waveforms_while_recording));
act = ActionManager::register_toggle_action (editor_actions, X_("ToggleMeasureVisibility"), _("Show Measures"), mem_fun (*this, &Editor::toggle_measure_visibility));
+ /* if there is a logo in the editor canvas, its always visible at startup */
+
+ act = ActionManager::register_toggle_action (editor_actions, X_("ToggleLogoVisibility"), _("Show Logo"), mem_fun (*this, &Editor::toggle_logo_visibility));
+ Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+ tact->set_active (true);
+
RadioAction::Group layer_model_group;
ActionManager::register_radio_action (editor_actions, layer_model_group, X_("LayerLaterHigher"), _("Later is Higher"), bind (mem_fun (*this, &Editor::set_layer_model), LaterHigher));
@@ -474,6 +471,23 @@ Editor::toggle_measure_visibility ()
}
void
+Editor::toggle_logo_visibility ()
+{
+ Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleLogoVisibility"));
+
+ if (act) {
+ Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+ if (logo_item) {
+ if (tact->get_active()) {
+ logo_item->show ();
+ } else {
+ logo_item->hide ();
+ }
+ }
+ }
+}
+
+void
Editor::set_crossfade_model (CrossfadeModel model)
{
RefPtr<Action> act;
diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc
index 263ac0c31f..0dc0d707c0 100644
--- a/gtk2_ardour/editor_audio_import.cc
+++ b/gtk2_ardour/editor_audio_import.cc
@@ -19,9 +19,12 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
+#include <sndfile.h>
+
#include <pbd/pthread_utils.h>
#include <pbd/basename.h>
#include <pbd/shortpath.h>
@@ -63,166 +66,307 @@ using Glib::ustring;
/* Functions supporting the incorporation of external (non-captured) audio material into ardour */
void
-Editor::add_external_audio_action (ImportMode mode)
+Editor::add_external_audio_action (ImportMode mode_hint)
{
- nframes_t& pos = edit_cursor->current_frame;
- boost::shared_ptr<AudioTrack> track;
-
- if (!selection->tracks.empty()) {
- AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front());
- if (atv) {
- track = atv->audio_track();
- }
+ if (session == 0) {
+ MessageDialog msg (0, _("You can't import or embed an audiofile until you have a session loaded."));
+ msg.run ();
+ return;
+ }
+
+ if (sfbrowser == 0) {
+ sfbrowser = new SoundFileOmega (*this, _("Add existing audio"), session, 0, true, mode_hint);
+ } else {
+ sfbrowser->set_mode (mode_hint);
}
- bring_in_external_audio (mode, track.get(), pos, false);
+ external_audio_dialog ();
}
void
-Editor::bring_in_external_audio (ImportMode mode, AudioTrack* track, nframes_t& pos, bool prompt)
+Editor::external_audio_dialog ()
{
+ vector<Glib::ustring> paths;
+ uint32_t track_cnt;
+
if (session == 0) {
MessageDialog msg (0, _("You can't import or embed an audiofile until you have a session loaded."));
msg.run ();
return;
}
+
+ track_cnt = 0;
- SoundFileOmega sfdb (_("Add existing audio to session"), session);
- sfdb.set_mode (mode);
+ for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) {
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*x);
+
+ if (!atv) {
+ continue;
+ } else if (atv->is_audio_track()) {
+ track_cnt++;
+ }
+ }
+
+ if (sfbrowser == 0) {
+ sfbrowser = new SoundFileOmega (*this, _("Add existing audio"), session, track_cnt, true);
+ } else {
+ sfbrowser->reset (track_cnt);
+ }
+
+ sfbrowser->show_all ();
+
+ again:
+ int response = sfbrowser->run ();
- switch (sfdb.run()) {
- case SoundFileOmega::ResponseImport:
- do_import (sfdb.get_paths(), sfdb.get_split(), sfdb.get_mode(), track, pos, prompt);
+ switch (response) {
+ case RESPONSE_APPLY:
+ // leave the dialog open
break;
-
- case SoundFileOmega::ResponseEmbed:
- do_embed (sfdb.get_paths(), sfdb.get_split(), sfdb.get_mode(), track, pos, prompt);
+
+ case RESPONSE_OK:
+ sfbrowser->hide ();
break;
default:
+ // cancel from the browser - we are done
+ sfbrowser->hide ();
+ return;
+ }
+
+ /* lets do it */
+
+ paths = sfbrowser->get_paths ();
+
+ ImportPosition pos = sfbrowser->get_position ();
+ ImportMode mode = sfbrowser->get_mode ();
+ ImportDisposition chns = sfbrowser->get_channel_disposition ();
+ nframes64_t where;
+
+ switch (pos) {
+ case ImportAtEditCursor:
+ where = edit_cursor->current_frame;
+ break;
+ case ImportAtTimestamp:
+ where = -1;
+ break;
+ case ImportAtPlayhead:
+ where = playhead_cursor->current_frame;
break;
+ case ImportAtStart:
+ where = session->current_start_frame();
+ break;
+ }
+
+ SrcQuality quality = sfbrowser->get_src_quality();
+
+ if (sfbrowser->copy_files_btn.get_active()) {
+ do_import (paths, chns, mode, quality, where);
+ } else {
+ do_embed (paths, chns, mode, where);
+ }
+
+ if (response == RESPONSE_APPLY) {
+ sfbrowser->clear_selection ();
+ goto again;
}
}
-void
-Editor::do_import (vector<ustring> paths, bool split, ImportMode mode, AudioTrack* track, nframes_t& pos, bool prompt)
+boost::shared_ptr<AudioTrack>
+Editor::get_nth_selected_audio_track (int nth) const
{
- /* SFDB sets "multichan" to true to indicate "split channels"
- so reverse the setting to match the way libardour
- interprets it.
- */
+ AudioTimeAxisView* atv;
+ TrackSelection::iterator x;
- import_status.multichan = !split;
+ for (x = selection->tracks.begin(); nth > 0 && x != selection->tracks.end(); ++x) {
- if (interthread_progress_window == 0) {
- build_interthread_progress_window ();
+ atv = dynamic_cast<AudioTimeAxisView*>(*x);
+
+ if (!atv) {
+ continue;
+ } else if (atv->is_audio_track()) {
+ --nth;
+ }
}
+
+ if (x == selection->tracks.end()) {
+ atv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.back());
+ } else {
+ atv = dynamic_cast<AudioTimeAxisView*>(*x);
+ }
+
+ if (!atv || !atv->is_audio_track()) {
+ return boost::shared_ptr<AudioTrack>();
+ }
+
+ return atv->audio_track();
+}
+void
+Editor::do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mode, SrcQuality quality, nframes64_t& pos)
+{
+ boost::shared_ptr<AudioTrack> track;
vector<ustring> to_import;
+ bool ok = false;
+ int nth = 0;
- for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
-
- to_import.clear ();
- to_import.push_back (*a);
-
- import_sndfile (to_import, mode, track, pos);
+ if (interthread_progress_window == 0) {
+ build_interthread_progress_window ();
}
- interthread_progress_window->hide_all ();
-}
+ switch (chns) {
+ case Editing::ImportDistinctFiles:
+ for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
-void
-Editor::do_embed (vector<ustring> paths, bool split, ImportMode mode, AudioTrack* track, nframes_t& pos, bool prompt)
-{
- bool multiple_files = paths.size() > 1;
- bool check_sample_rate = true;
- vector<ustring>::iterator a;
+ to_import.clear ();
+ to_import.push_back (*a);
- for (a = paths.begin(); a != paths.end(); ) {
+ if (mode == Editing::ImportToTrack) {
+ track = get_nth_selected_audio_track (nth++);
+ }
+
+ if (import_sndfiles (to_import, mode, quality, pos, 1, -1, track)) {
+ goto out;
+ }
- cerr << "Considering embed of " << (*a) << endl;
-
- Glib::ustring path = *a;
- Glib::ustring pair_base;
- vector<ustring> to_embed;
+ }
+ break;
- to_embed.push_back (path);
- a = paths.erase (a);
+ case Editing::ImportDistinctChannels:
+ for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
- if (path_is_paired (path, pair_base)) {
+ to_import.clear ();
+ to_import.push_back (*a);
- ustring::size_type len = pair_base.length();
+ if (import_sndfiles (to_import, mode, quality, pos, -1, -1, track)) {
+ goto out;
+ }
- for (vector<Glib::ustring>::iterator b = paths.begin(); b != paths.end(); ) {
+ }
+ break;
- if (((*b).substr (0, len) == pair_base) && ((*b).length() == path.length())) {
+ case Editing::ImportMergeFiles:
+ /* create 1 region from all paths, add to 1 track,
+ ignore "track"
+ */
+ if (import_sndfiles (paths, mode, quality, pos, 1, 1, track)) {
+ goto out;
+ }
+ break;
- to_embed.push_back (*b);
-
- /* don't process this one again */
+ case Editing::ImportSerializeFiles:
+ for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
- b = paths.erase (b);
- break;
+ to_import.clear ();
+ to_import.push_back (*a);
+
+ /* create 1 region from this path, add to 1 track,
+ reuse "track" across paths
+ */
- } else {
- ++b;
- }
+ if (import_sndfiles (to_import, mode, quality, pos, 1, 1, track)) {
+ goto out;
}
+
}
+ break;
+ }
- if (to_embed.size() > 1) {
+ ok = true;
+
+ out:
+ if (ok) {
+ session->save_state ("");
+ }
- vector<string> choices;
+ interthread_progress_window->hide_all ();
+}
- choices.push_back (string_compose (_("Import as a %1 region"),
- to_embed.size() > 2 ? _("multichannel") : _("stereo")));
- choices.push_back (_("Import as multiple regions"));
-
- Choice chooser (string_compose (_("Paired files detected (%1, %2 ...).\nDo you want to:"),
- to_embed[0],
- to_embed[1]),
- choices);
-
- if (chooser.run () == 0) {
-
- /* keep them paired */
+bool
+Editor::idle_do_embed (vector<ustring> paths, ImportDisposition chns, ImportMode mode, nframes64_t& pos)
+{
+ _do_embed (paths, chns, mode, pos);
+ return false;
+}
- if (embed_sndfile (to_embed, split, multiple_files, check_sample_rate, mode, track, pos, prompt) < -1) {
- break;
- }
+void
+Editor::do_embed (vector<ustring> paths, ImportDisposition chns, ImportMode mode, nframes64_t& pos)
+{
+#ifdef GTKOSX
+ Glib::signal_idle().connect (bind (mem_fun (*this, &Editor::idle_do_embed), paths, chns, mode, pos));
+#else
+ _do_embed (paths, chns, mode, pos);
+#endif
+}
- } else {
+void
+Editor::_do_embed (vector<ustring> paths, ImportDisposition chns, ImportMode mode, nframes64_t& pos)
+{
+ boost::shared_ptr<AudioTrack> track;
+ bool check_sample_rate = true;
+ bool ok = false;
+ vector<ustring> to_embed;
+ bool multi = paths.size() > 1;
+ int nth = 0;
- /* one thing per file */
+ switch (chns) {
+ case Editing::ImportDistinctFiles:
+ for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
- vector<ustring> foo;
+ to_embed.clear ();
+ to_embed.push_back (*a);
- for (vector<ustring>::iterator x = to_embed.begin(); x != to_embed.end(); ++x) {
+ if (mode == Editing::ImportToTrack) {
+ track = get_nth_selected_audio_track (nth++);
+ }
- foo.clear ();
- foo.push_back (*x);
+ if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, 1, -1, track) < -1) {
+ goto out;
+ }
+ }
+ break;
+
+ case Editing::ImportDistinctChannels:
+ for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
- if (embed_sndfile (foo, split, multiple_files, check_sample_rate, mode, track, pos, prompt) < -1) {
- break;
- }
- }
+ to_embed.clear ();
+ to_embed.push_back (*a);
+
+ if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, -1, -1, track) < -1) {
+ goto out;
}
+ }
+ break;
- } else {
-
- if (embed_sndfile (to_embed, split, multiple_files, check_sample_rate, mode, track, pos, prompt) < -1) {
- break;
+ case Editing::ImportMergeFiles:
+ if (embed_sndfiles (paths, multi, check_sample_rate, mode, pos, 1, 1, track) < -1) {
+ goto out;
+ }
+ break;
+
+ case Editing::ImportSerializeFiles:
+ for (vector<ustring>::iterator a = paths.begin(); a != paths.end(); ++a) {
+
+ to_embed.clear ();
+ to_embed.push_back (*a);
+
+ if (embed_sndfiles (to_embed, multi, check_sample_rate, mode, pos, 1, 1, track) < -1) {
+ goto out;
}
}
+ break;
}
+
+ ok = true;
- if (a == paths.end()) {
+ out:
+ if (ok) {
session->save_state ("");
}
}
int
-Editor::import_sndfile (vector<ustring> paths, ImportMode mode, AudioTrack* track, nframes_t& pos)
+Editor::import_sndfiles (vector<ustring> paths, ImportMode mode, SrcQuality quality, nframes64_t& pos,
+ int target_regions, int target_tracks, boost::shared_ptr<AudioTrack>& track)
{
WindowTitle title = string_compose (_("importing %1"), paths.front());
@@ -238,7 +382,8 @@ Editor::import_sndfile (vector<ustring> paths, ImportMode mode, AudioTrack* trac
import_status.cancel = false;
import_status.freeze = false;
import_status.done = 0.0;
-
+ import_status.quality = quality;
+
interthread_progress_connection = Glib::signal_timeout().connect
(bind (mem_fun(*this, &Editor::import_progress_timeout), (gpointer) 0), 100);
@@ -262,28 +407,31 @@ Editor::import_sndfile (vector<ustring> paths, ImportMode mode, AudioTrack* trac
interthread_progress_connection.disconnect ();
/* import thread finished - see if we should build a new track */
+
+ boost::shared_ptr<AudioRegion> r;
- if (!import_status.new_regions.empty()) {
- boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion>(import_status.new_regions.front());
- finish_bringing_in_audio (region, region->n_channels(), region->n_channels(), track, pos, mode);
+ if (import_status.cancel || import_status.sources.empty()) {
+ goto out;
+ }
+
+ if (add_sources (paths, import_status.sources, pos, mode, target_regions, target_tracks, track, false) == 0) {
+ session->save_state ("");
}
+ out:
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
return 0;
}
int
-Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_files, bool& check_sample_rate, ImportMode mode,
- AudioTrack* track, nframes_t& pos, bool prompt)
+Editor::embed_sndfiles (vector<Glib::ustring> paths, bool multifile,
+ bool& check_sample_rate, ImportMode mode, nframes64_t& pos, int target_regions, int target_tracks,
+ boost::shared_ptr<AudioTrack>& track)
{
boost::shared_ptr<AudioFileSource> source;
SourceList sources;
- boost::shared_ptr<AudioRegion> region;
string linked_path;
SoundFileInfo finfo;
- ustring region_name;
- uint32_t input_chan = 0;
- uint32_t output_chan = 0;
int ret = 0;
track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
@@ -294,10 +442,8 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
ustring path = *p;
/* lets see if we can link it into the session */
-
- sys::path tmp = session->session_directory().sound_path();
-
- tmp /= Glib::path_get_basename(path);
+
+ sys::path tmp = session->session_directory().sound_path() / Glib::path_get_basename(path);
linked_path = tmp.to_string();
if (link (path.c_str(), linked_path.c_str()) == 0) {
@@ -323,22 +469,21 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
}
}
}
-
}
/* note that we temporarily truncated _id at the colon */
string error_msg;
-
+
if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) {
- error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), selection, error_msg ) << endmsg;
+ error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), path, error_msg ) << endmsg;
goto out;
}
if (check_sample_rate && (finfo.samplerate != (int) session->frame_rate())) {
vector<string> choices;
- if (multiple_files) {
+ if (multifile) {
choices.push_back (_("Cancel entire import"));
choices.push_back (_("Don't embed it"));
choices.push_back (_("Embed all without questions"));
@@ -390,14 +535,8 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
}
track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
- ARDOUR_UI::instance()->flush_pending ();
-
- /* make the proper number of channels in the region */
-
- input_chan += finfo.channels;
- for (int n = 0; n < finfo.channels; ++n)
- {
+ for (int n = 0; n < finfo.channels; ++n) {
try {
/* check if we have this thing embedded already */
@@ -409,7 +548,8 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
(DataType::AUDIO, *session, path, n,
(mode == ImportAsTapeTrack ?
AudioFileSource::Destructive :
- AudioFileSource::Flag (0))));
+ AudioFileSource::Flag (0)),
+ true, true));
} else {
source = boost::dynamic_pointer_cast<AudioFileSource> (s);
}
@@ -430,14 +570,74 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
goto out;
}
- if (sources[0]->natural_position() != 0) {
- pos = sources[0]->natural_position();
- }
+ ret = add_sources (paths, sources, pos, mode, target_regions, target_tracks, track, true);
- region_name = region_name_from_path (paths.front(), (sources.size() > 1));
-
- region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, 0, sources[0]->length(), region_name, 0,
- Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)));
+ out:
+ track_canvas.get_window()->set_cursor (*current_canvas_cursor);
+ return ret;
+}
+
+int
+Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64_t& pos, ImportMode mode,
+ int target_regions, int target_tracks, boost::shared_ptr<AudioTrack>& track, bool add_channel_suffix)
+{
+ vector<boost::shared_ptr<AudioRegion> > regions;
+ ustring region_name;
+ uint32_t input_chan = 0;
+ uint32_t output_chan = 0;
+
+ if (pos == -1) { // "use timestamp"
+ if (sources[0]->natural_position() != 0) {
+ pos = sources[0]->natural_position();
+ } else {
+ // XXX is this the best alternative ?
+ pos = edit_cursor->current_frame;
+ }
+ }
+
+ if (target_regions == 1) {
+
+ /* take all the sources we have and package them up as a region */
+
+ region_name = region_name_from_path (paths.front(), (sources.size() > 1), false);
+
+ regions.push_back (boost::dynamic_pointer_cast<AudioRegion>
+ (RegionFactory::create (sources, 0, sources[0]->length(), region_name, 0,
+ Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External))));
+
+ } else if (target_regions == -1) {
+
+ /* take each source and create a region for each one */
+
+ SourceList just_one;
+ SourceList::iterator x;
+ uint32_t n;
+
+ for (n = 0, x = sources.begin(); x != sources.end(); ++x, ++n) {
+
+ just_one.clear ();
+ just_one.push_back (*x);
+
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (*x);
+
+ region_name = region_name_from_path (afs->path(), false, true, sources.size(), n);
+
+ regions.push_back (boost::dynamic_pointer_cast<AudioRegion>
+ (RegionFactory::create (just_one, 0, (*x)->length(), region_name, 0,
+ Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External))));
+
+ }
+ }
+
+ if (target_regions == 1) {
+ input_chan = regions.front()->n_channels();
+ } else {
+ if (target_tracks == 1) {
+ input_chan = regions.size();
+ } else {
+ input_chan = 1;
+ }
+ }
if (Config->get_output_auto_connect() & AutoConnectMaster) {
output_chan = (session->master_out() ? session->master_out()->n_inputs().n_audio() : input_chan);
@@ -445,15 +645,31 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
output_chan = input_chan;
}
- finish_bringing_in_audio (region, input_chan, output_chan, track, pos, mode);
-
- out:
- track_canvas.get_window()->set_cursor (*current_canvas_cursor);
- return ret;
-}
+ int n = 0;
+
+ for (vector<boost::shared_ptr<AudioRegion> >::iterator r = regions.begin(); r != regions.end(); ++r, ++n) {
+
+ finish_bringing_in_audio (*r, input_chan, output_chan, pos, mode, track);
+ if (target_tracks != 1) {
+ track.reset ();
+ } else {
+ pos += (*r)->length();
+ }
+ }
+
+ /* setup peak file building in another thread */
+
+ for (SourceList::iterator x = sources.begin(); x != sources.end(); ++x) {
+ SourceFactory::setup_peakfile (*x, true);
+ }
+
+ return 0;
+}
+
int
-Editor::finish_bringing_in_audio (boost::shared_ptr<AudioRegion> region, uint32_t in_chans, uint32_t out_chans, AudioTrack* track, nframes_t& pos, ImportMode mode)
+Editor::finish_bringing_in_audio (boost::shared_ptr<AudioRegion> region, uint32_t in_chans, uint32_t out_chans, nframes64_t& pos,
+ ImportMode mode, boost::shared_ptr<AudioTrack>& existing_track)
{
switch (mode) {
case ImportAsRegion:
@@ -461,38 +677,52 @@ Editor::finish_bringing_in_audio (boost::shared_ptr<AudioRegion> region, uint32_
break;
case ImportToTrack:
- if (track) {
- boost::shared_ptr<Playlist> playlist = track->diskstream()->playlist();
-
- boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
- begin_reversible_command (_("insert sndfile"));
- XMLNode &before = playlist->get_state();
- playlist->add_region (copy, pos);
- session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
- commit_reversible_command ();
+ {
+ if (!existing_track) {
+
+ existing_track = get_nth_selected_audio_track (0);
- pos += region->length();
+ if (!existing_track) {
+ return -1;
+ }
}
+
+ boost::shared_ptr<Playlist> playlist = existing_track->diskstream()->playlist();
+ boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
+ begin_reversible_command (_("insert sndfile"));
+ XMLNode &before = playlist->get_state();
+ playlist->add_region (copy, pos);
+ session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
+ commit_reversible_command ();
break;
-
+ }
+
case ImportAsTrack:
{
- list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Normal, 1));
- if (!at.empty()) {
- boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
- at.front()->diskstream()->playlist()->add_region (copy, pos);
- at.front()->set_name(short_path(copy->name(), 32));
+ if (!existing_track) {
+ list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Normal, 1));
+
+ if (at.empty()) {
+ return -1;
+ }
+
+ existing_track = at.front();
+ existing_track->set_name (region->name());
}
+
+ boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
+ existing_track->diskstream()->playlist()->add_region (copy, pos);
break;
}
+
case ImportAsTapeTrack:
{
list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Destructive));
if (!at.empty()) {
boost::shared_ptr<AudioRegion> copy (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (region)));
+ at.front()->set_name (basename_nosuffix (copy->name()));
at.front()->diskstream()->playlist()->add_region (copy, pos);
- at.front()->set_name(short_path(copy->name(), 32));
}
break;
}
diff --git a/gtk2_ardour/editor_audiotrack.cc b/gtk2_ardour/editor_audiotrack.cc
index cdcbb43f76..87fa8a06b8 100644
--- a/gtk2_ardour/editor_audiotrack.cc
+++ b/gtk2_ardour/editor_audiotrack.cc
@@ -26,11 +26,13 @@
#include "audio_region_view.h"
#include "selection.h"
+#include "i18n.h"
+
using namespace ARDOUR;
using namespace PBD;
void
-Editor::set_route_loop_selection ()
+Editor::set_loop_from_selection (bool play)
{
if (session == 0 || selection->time.empty()) {
return;
@@ -38,18 +40,26 @@ Editor::set_route_loop_selection ()
nframes_t start = selection->time[clicked_selection].start;
nframes_t end = selection->time[clicked_selection].end;
+
+ set_loop_range (start, end, _("set loop range from selection"));
- Location* loc = transport_loop_location();
-
- if (loc) {
-
- loc->set (start, end);
-
- // enable looping, reposition and start rolling
+ if (play) {
session->request_play_loop (true);
- session->request_locate (loc->start(), true);
+ session->request_locate (start, true);
+ }
+}
+
+void
+Editor::set_punch_from_selection ()
+{
+ if (session == 0 || selection->time.empty()) {
+ return;
}
+ nframes_t start = selection->time[clicked_selection].start;
+ nframes_t end = selection->time[clicked_selection].end;
+
+ set_punch_range (start, end, _("set punch range from selection"));
}
void
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index c5a8695158..86beec387e 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -22,6 +22,7 @@
#include <gtkmm2ext/utils.h>
#include <ardour/audioregion.h>
+#include <ardour/profile.h>
#include "ardour_ui.h"
#include "editor.h"
@@ -143,11 +144,21 @@ Editor::initialize_canvas ()
verbose_cursor_visible = false;
- cursor_group = new ArdourCanvas::Group (*track_canvas.root(), 0.0, 0.0);
+ if (Profile->get_sae()) {
+ Image img (::get_icon (X_("saelogo")));
+ logo_item = new ArdourCanvas::Pixbuf (*track_canvas.root(), 0.0, 0.0, img.get_pixbuf());
+ // logo_item->property_height_in_pixels() = true;
+ // logo_item->property_width_in_pixels() = true;
+ // logo_item->property_height_set() = true;
+ // logo_item->property_width_set() = true;
+ logo_item->show ();
+ }
+
+ /* a group to hold time (measure) lines */
time_line_group = new ArdourCanvas::Group (*track_canvas.root(), 0.0, 0.0);
tempo_lines = new TempoLines(track_canvas, time_line_group);
-
+ cursor_group = new ArdourCanvas::Group (*track_canvas.root(), 0.0, 0.0);
time_canvas.set_name ("EditorTimeCanvas");
time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
time_canvas.set_flags (CAN_FOCUS);
@@ -257,6 +268,10 @@ Editor::initialize_canvas ()
initial_ruler_update_required = true;
track_canvas.signal_size_allocate().connect (mem_fun(*this, &Editor::track_canvas_allocate));
+ if (logo_item) {
+ logo_item->lower_to_bottom ();
+ }
+
ColorsChanged.connect (mem_fun (*this, &Editor::color_handler));
color_handler();
@@ -348,6 +363,11 @@ Editor::track_canvas_size_allocated ()
update_fixed_rulers();
redisplay_tempo (true);
+
+ if (logo_item) {
+ // logo_item->property_height() = canvas_height;
+ // logo_item->property_width() = canvas_width;
+ }
Resized (); /* EMIT_SIGNAL */
@@ -455,7 +475,7 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
vector<ustring> paths;
string spath;
GdkEvent ev;
- nframes_t frame;
+ nframes64_t frame;
if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
goto out;
@@ -483,15 +503,18 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
/* drop onto canvas background: create new tracks */
- nframes_t pos = 0;
- do_embed (paths, false, ImportAsTrack, 0, pos, false);
+ do_embed (paths, Editing::ImportDistinctFiles, ImportAsTrack, frame);
} else if ((tv = dynamic_cast<RouteTimeAxisView*>(tvp)) != 0) {
/* check that its an audio track, not a bus */
+ /* check that its an audio track, not a bus */
+
if (tv->get_diskstream()) {
- do_embed (paths, false, ImportToTrack, tv->audio_track().get(), frame, true);
+ /* select the track, then embed */
+ selection->set (tv);
+ do_embed (paths, Editing::ImportDistinctFiles, ImportToTrack, frame);
}
}
@@ -697,6 +720,10 @@ Editor::canvas_horizontally_scrolled ()
reset_scrolling_region ();
}
+ if (logo_item) {
+ logo_item->property_x() = horizontal_adjustment.get_value ();
+ }
+
update_fixed_rulers ();
redisplay_tempo (!_dragging_hscrollbar);
diff --git a/gtk2_ardour/editor_keyboard.cc b/gtk2_ardour/editor_keyboard.cc
index 4b0088f075..28b86f53fc 100644
--- a/gtk2_ardour/editor_keyboard.cc
+++ b/gtk2_ardour/editor_keyboard.cc
@@ -43,6 +43,14 @@ Editor::kbd_driver (sigc::slot<void,GdkEvent*> theslot, bool use_track_canvas, b
doit = true;
}
+ /* any use of "keyboard mouse buttons" invalidates an existing grab
+ */
+
+ if (drag_info.item) {
+ drag_info.item->ungrab (GDK_CURRENT_TIME);
+ drag_info.item = 0;
+ }
+
if (doit) {
if (entered_regionview && can_select) {
diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc
index 29a212f2f5..724ff2c31a 100644
--- a/gtk2_ardour/editor_markers.cc
+++ b/gtk2_ardour/editor_markers.cc
@@ -909,56 +909,13 @@ Editor::new_transport_marker_menu_popdown (GdkEventAny *ev)
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);
- XMLNode &before = session->locations()->get_state();
- session->locations()->add (loc, true);
- session->set_auto_loop_location (loc);
- XMLNode &after = session->locations()->get_state();
- session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
- }
- else {
- XMLNode &before = tll->get_state();
- tll->set_hidden (false, this);
- tll->set (temp_location->start(), temp_location->end());
- XMLNode &after = tll->get_state();
- session->add_command (new MementoCommand<Location>(*tll, &before, &after));
- }
-
- commit_reversible_command ();
+ set_loop_range (temp_location->start(), temp_location->end(), _("set loop range"));
}
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);
- XMLNode &before = session->locations()->get_state();
- session->locations()->add (tpl, true);
- session->set_auto_punch_location (tpl);
- XMLNode &after = session->locations()->get_state();
- session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
- } else {
- XMLNode &before = tpl->get_state();
- tpl->set_hidden(false, this);
- tpl->set(temp_location->start(), temp_location->end());
- XMLNode &after = tpl->get_state();
- session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
- }
-
- commit_reversible_command ();
+ set_punch_range (temp_location->start(), temp_location->end(), _("set punch range"));
}
void
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index e8bc98a73c..da95d50d95 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -442,8 +442,23 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
switch (item_type) {
case RegionItem:
- case RegionViewNameHighlight:
- case RegionViewName:
+ if (mouse_mode != MouseRange) {
+ commit = set_selected_regionview_from_click (press, op, true);
+ } else if (event->type == GDK_BUTTON_PRESS) {
+ commit = set_selected_track_from_click (press, op, false);
+ }
+ break;
+
+ case RegionViewNameHighlight:
+ case RegionViewName:
+ if (mouse_mode != MouseRange) {
+ commit = set_selected_regionview_from_click (press, op, true);
+ } else if (event->type == GDK_BUTTON_PRESS) {
+ commit = set_selected_track_from_click (press, op, false);
+ }
+ break;
+
+
case FadeInHandleItem:
case FadeInItem:
case FadeOutHandleItem:
@@ -754,7 +769,12 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
break;
case MouseAudition:
- /* handled in release */
+ _scrubbing = true;
+ last_scrub_frame = 0;
+ last_scrub_time = 0;
+ have_full_mouse_speed = false;
+ memset (mouse_speed, 0, sizeof (double) * mouse_speed_size);
+ /* rest handled in motion & release */
break;
default:
@@ -906,10 +926,19 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
case StreamItem:
+ popup_track_context_menu (1, event->button.time, where);
+ break;
+
case RegionItem:
case RegionViewNameHighlight:
case RegionViewName:
+ popup_track_context_menu (1, event->button.time, where);
+ break;
+
case SelectionItem:
+ popup_track_context_menu (1, event->button.time, where);
+ break;
+
case AutomationTrackItem:
case CrossfadeViewItem:
popup_track_context_menu (1, event->button.time, where);
@@ -1073,13 +1102,20 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
break;
case MouseAudition:
- switch (item_type) {
- case RegionItem:
- audition_selected_region ();
- break;
- default:
- break;
- }
+ _scrubbing = false;
+ if (last_scrub_frame == 0) {
+ /* no drag, just a click */
+ switch (item_type) {
+ case RegionItem:
+ audition_selected_region ();
+ break;
+ default:
+ break;
+ }
+ } else {
+ /* make sure we stop */
+ session->request_transport_speed (0.0);
+ }
break;
default:
@@ -1424,6 +1460,12 @@ Editor::left_automation_track ()
return false;
}
+static gboolean
+_update_mouse_speed (void *arg)
+{
+ return static_cast<Editor*>(arg)->update_mouse_speed ();
+}
+
bool
Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type, bool from_autoscroll)
{
@@ -1455,6 +1497,66 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item
drag_info.current_pointer_frame = event_frame (event, &drag_info.current_pointer_x,
&drag_info.current_pointer_y);
+ switch (mouse_mode) {
+ case MouseAudition:
+ if (_scrubbing) {
+ struct timeval tmnow;
+
+ if (last_scrub_frame == 0) {
+
+ /* first motion, just set up the variables */
+
+ last_scrub_frame = (nframes64_t) drag_info.current_pointer_frame;
+ gettimeofday (&tmnow, 0);
+ last_scrub_time = tmnow.tv_sec * 1000000.0 + tmnow.tv_usec;
+ session->request_locate (last_scrub_frame, true);
+
+ } else {
+ /* how fast is the mouse moving ? */
+
+ double speed;
+ nframes_t distance;
+ double time;
+ double dir;
+
+#if 1
+ if (last_scrub_frame < (nframes64_t) drag_info.current_pointer_frame) {
+ distance = (nframes64_t) drag_info.current_pointer_frame - last_scrub_frame;
+ dir = 1.0;
+ } else {
+ distance = last_scrub_frame - (nframes64_t) drag_info.current_pointer_frame;
+ dir = -1.0;
+ }
+#else
+ if (drag_info.grab_x < drag_info.current_pointer_x) {
+ distance = drag_info.current_pointer_x - drag_info.grab_x;
+ dir = -1.0;
+ } else {
+ distance = drag_info.grab_x - drag_info.current_pointer_x;
+ dir = 1.0;
+ }
+#endif
+
+ gettimeofday (&tmnow, 0);
+ time = (tmnow.tv_sec * 1000000.0 + tmnow.tv_usec) - last_scrub_time;
+ last_scrub_frame = drag_info.current_pointer_frame;
+ last_scrub_time = (tmnow.tv_sec * 1000000.0) + tmnow.tv_usec;
+ speed = ((double)distance/session->frame_rate()) / (time/1000000.0); // frames/sec
+
+ add_mouse_speed (speed, dir);
+
+ if (mouse_speed_update < 0) {
+ mouse_speed_update = g_timeout_add (10, _update_mouse_speed, this);
+ update_mouse_speed ();
+ }
+ }
+ }
+
+ default:
+ break;
+ }
+
+
if (!from_autoscroll && drag_info.item) {
/* item != 0 is the best test i can think of for dragging.
*/
@@ -3469,6 +3571,10 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
rtv->reveal_dependent_views (*latest_regionview);
selection->add (latest_regionview);
}
+
+ /* if the original region was locked, we don't care for the new one */
+
+ newregion->set_locked (false);
} else {
@@ -4832,6 +4938,11 @@ Editor::end_time_fx (ArdourCanvas::Item* item, GdkEvent* event)
if (drag_info.first_move) {
return;
}
+
+ if (drag_info.last_pointer_frame < clicked_regionview->region()->position()) {
+ /* backwards drag of the left edge - not usable */
+ return;
+ }
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;
@@ -4909,3 +5020,91 @@ Editor::track_height_step_timeout ()
}
return true;
}
+
+
+void
+Editor::add_mouse_speed (double speed, double dir)
+{
+ size_t index;
+
+ mouse_direction = dir;
+
+ index = mouse_speed_entries;
+
+ if (++index >= mouse_speed_size) {
+ index = 0;
+ have_full_mouse_speed = true;
+ }
+
+ mouse_speed[index] = speed;
+ mouse_speed_entries = index;
+}
+
+double
+Editor::compute_mouse_speed ()
+{
+ double total = 0;
+
+ if (!have_full_mouse_speed) {
+
+ /* partial speed buffer, just use whatever we have so far */
+
+ if (mouse_speed_entries == 0 ) {
+ return 0.0;
+ }
+
+ for (size_t n = 0; n < mouse_speed_entries; ++n) {
+ total += mouse_speed[n];
+ }
+
+ return mouse_direction * total/mouse_speed_entries;
+ }
+
+ /* compute the average (effectively low-pass filtering) mouse speed
+ across the entire buffer.
+ */
+
+ for (size_t n = 0; n < mouse_speed_size; ++n) {
+ total += mouse_speed[n];
+ }
+
+
+ return mouse_direction * total/mouse_speed_size;
+}
+
+bool
+Editor::update_mouse_speed ()
+{
+ double speed;
+
+ if (!_scrubbing) {
+ session->request_transport_speed (0.0);
+ mouse_speed_update = -1;
+ return false;
+ }
+
+ speed = compute_mouse_speed ();
+
+ struct timeval tmnow;
+
+ gettimeofday (&tmnow, 0);
+ double now = (tmnow.tv_sec * 1000000.0) + tmnow.tv_usec;
+
+ if (now - last_scrub_time > 250000) {
+
+ // 0.25 seconds since last mouse motion, start to brake
+
+ if (fabs (speed) < 0.1) {
+ /* don't asymptotically approach zero */
+ memset (mouse_speed, 0, sizeof (double) * mouse_speed_size);
+ speed = 0.0;
+ } else if (fabs (speed) < 0.25) {
+ add_mouse_speed (fabs (speed * 0.2), mouse_direction);
+ } else {
+ add_mouse_speed (fabs (speed * 0.6), mouse_direction);
+ }
+ }
+
+ session->request_transport_speed (speed);
+ return _scrubbing;
+}
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 8906837031..ca2d7039ad 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -119,7 +119,22 @@ Editor::split_regions_at (nframes_t where, RegionSelection& regions)
{
begin_reversible_command (_("split"));
- snap_to (where);
+ // if splitting a single region, and snap-to is using
+ // region boundaries, don't pay attention to them
+
+ if (regions.size() == 1) {
+ switch (snap_type) {
+ case SnapToRegionStart:
+ case SnapToRegionSync:
+ case SnapToRegionEnd:
+ break;
+ default:
+ snap_to (where);
+ }
+ } else {
+ snap_to (where);
+ }
+
for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
RegionSelection::iterator tmp;
@@ -178,16 +193,17 @@ Editor::remove_selected_regions ()
/* XXX: should be called remove regions if we're removing more than one */
begin_reversible_command (_("remove region"));
+
while (!selection->regions.empty()) {
boost::shared_ptr<Region> region = selection->regions.front()->region ();
boost::shared_ptr<Playlist> playlist = region->playlist ();
-
+
XMLNode &before = playlist->get_state();
playlist->remove_region (region);
XMLNode &after = playlist->get_state();
session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
}
-
+
commit_reversible_command ();
}
@@ -497,12 +513,13 @@ Editor::build_region_boundary_cache ()
for (vector<RegionPoint>::iterator p = interesting_points.begin(); p != interesting_points.end(); ++p) {
if ((r = find_next_region (pos, *p, 1, tlist, &ontrack)) == 0) {
- at_end = true;
+ if (*p == interesting_points.back()) {
+ at_end = true;
+ }
/* move to next point type */
continue;
}
-
switch (*p) {
case Start:
rpos = r->first_frame();
@@ -3423,73 +3440,94 @@ Editor::reset_region_gain_envelopes ()
session->commit_reversible_command ();
}
-/** Set whether or not gain envelopes are visible for the selected regions.
- * @param yn true to make visible, false to make invisible.
- */
void
-Editor::set_gain_envelope_visibility (bool yn)
+Editor::toggle_gain_envelope_visibility ()
{
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
- if (arv->envelope_visible() != yn) {
- arv->set_envelope_visible (yn);
+ bool x = region_envelope_visible_item->get_active();
+ if (x != arv->envelope_visible()) {
+ arv->set_envelope_visible (x);
}
}
}
}
-/** Set whether or not gain envelopes are active for the selected regions.
- * @param yn true to make active, false to make inactive.
- */
void
-Editor::set_gain_envelope_active (bool yn)
+Editor::toggle_gain_envelope_active ()
{
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
if (arv) {
- if (arv->audio_region()->envelope_active() != yn) {
- arv->audio_region()->set_envelope_active (yn);
+ bool x = region_envelope_active_item->get_active();
+ if (x != arv->audio_region()->envelope_active()) {
+ arv->audio_region()->set_envelope_active (x);
}
}
}
}
-/** Set the locked state of all selected regions to a particular value.
+/** Set the position-locked state of all selected regions to a particular value.
* @param yn true to make locked, false to make unlocked.
*/
void
-Editor::set_region_lock (bool yn)
+Editor::toggle_region_position_lock ()
{
+ bool x = region_lock_position_item->get_active();
+
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
- (*i)->region()->set_locked (yn);
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+ if (arv) {
+ if (x != arv->audio_region()->locked()) {
+ arv->audio_region()->set_position_locked (x);
+ }
+ }
}
}
-/** Set the position-locked state of all selected regions to a particular value.
- * @param yn true to make locked, false to make unlocked.
- */
void
-Editor::set_region_position_lock (bool yn)
+Editor::toggle_region_lock ()
{
+ bool x = region_lock_item->get_active();
+
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
- (*i)->region()->set_position_locked (yn);
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+ if (arv) {
+ if (x != arv->audio_region()->locked()) {
+ arv->audio_region()->set_locked (x);
+ }
+ }
}
}
void
-Editor::set_region_mute (bool yn)
+Editor::toggle_region_mute ()
{
+ bool x = region_mute_item->get_active();
+
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
- (*i)->region()->set_muted (yn);
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+ if (arv) {
+ if (x != arv->audio_region()->muted()) {
+ arv->audio_region()->set_muted (x);
+ }
+ }
}
}
void
-Editor::set_region_opaque (bool yn)
+Editor::toggle_region_opaque ()
{
+ bool x = region_opaque_item->get_active();
+
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
- (*i)->region()->set_opaque (yn);
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
+ if (arv) {
+ if (x != arv->audio_region()->opaque()) {
+ arv->audio_region()->set_opaque (x);
+ }
+ }
}
}
diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc
index a9df928222..f1001cb8e4 100644
--- a/gtk2_ardour/editor_region_list.cc
+++ b/gtk2_ardour/editor_region_list.cc
@@ -626,8 +626,8 @@ Editor::region_list_display_drag_data_received (const RefPtr<Gdk::DragContext>&
vector<ustring> paths;
if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) {
- nframes_t pos = 0;
- do_embed (paths, false, ImportAsRegion, 0, pos, true);
+ nframes64_t pos = 0;
+ do_embed (paths, Editing::ImportDistinctFiles, ImportAsRegion, pos);
context->drag_finish (true, false, time);
}
}
diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc
index e11738f65b..5e10a578f5 100644
--- a/gtk2_ardour/editor_route_list.cc
+++ b/gtk2_ardour/editor_route_list.cc
@@ -53,6 +53,10 @@ Editor::handle_new_route (Session::RouteList& routes)
TreeModel::Row parent;
TreeModel::Row row;
+ ignore_route_list_reorder = true;
+ ignore_route_order_sync = true;
+ no_route_list_redisplay = true;
+
for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
boost::shared_ptr<Route> route = (*x);
@@ -100,6 +104,7 @@ Editor::handle_new_route (Session::RouteList& routes)
row[route_display_columns.text] = route->name();
row[route_display_columns.visible] = tv->marked_for_display();
row[route_display_columns.tv] = tv;
+ row[route_display_columns.route] = route;
track_views.push_back (tv);
@@ -114,11 +119,18 @@ Editor::handle_new_route (Session::RouteList& routes)
ignore_route_list_reorder = false;
+ tv->set_old_order_key (route_display_model->children().size() - 1);
route->gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes));
tv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), tv));
}
+ ignore_route_list_reorder = false;
+ ignore_route_order_sync = false;
+ no_route_list_redisplay = false;
+
+ redisplay_route_list ();
+
if (show_editor_mixer_when_tracks_arrive) {
show_editor_mixer (true);
}
@@ -234,6 +246,33 @@ Editor::route_list_reordered (const TreeModel::Path& path,const TreeModel::itera
redisplay_route_list ();
}
+
+void
+Editor::sync_order_keys ()
+{
+ vector<int> neworder;
+ TreeModel::Children rows = route_display_model->children();
+ TreeModel::Children::iterator ri;
+
+ if (ignore_route_order_sync || !session || (session->state_of_the_state() & Session::Loading) || rows.empty()) {
+ return;
+ }
+
+ for (ri = rows.begin(); ri != rows.end(); ++ri) {
+ neworder.push_back (0);
+ }
+
+ for (ri = rows.begin(); ri != rows.end(); ++ri) {
+ TimeAxisView* tv = (*ri)[route_display_columns.tv];
+ boost::shared_ptr<Route> route = (*ri)[route_display_columns.route];
+ neworder[route->order_key (X_("editor"))] = tv->old_order_key ();
+ }
+
+ ignore_route_list_reorder = true;
+ route_display_model->reorder (neworder);
+ ignore_route_list_reorder = false;
+}
+
void
Editor::redisplay_route_list ()
{
@@ -288,6 +327,13 @@ Editor::redisplay_route_list ()
cursor_group->raise_to_top ();
reset_scrolling_region ();
+
+ if (Config->get_sync_all_route_ordering() && !ignore_route_list_reorder) {
+ ignore_route_order_sync = true;
+ Route::SyncOrderKeys (); // EMIT SIGNAL
+ ignore_route_order_sync = false;
+ }
+
}
void
@@ -524,6 +570,13 @@ Editor::initial_route_list_display ()
}
void
+Editor::track_list_reorder (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter, int* new_order)
+{
+ session->set_remote_control_ids();
+ redisplay_route_list ();
+}
+
+void
Editor::route_list_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter)
{
session->set_remote_control_ids();
diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc
index cfc7157510..88ff3a0c1e 100644
--- a/gtk2_ardour/editor_rulers.cc
+++ b/gtk2_ardour/editor_rulers.cc
@@ -152,14 +152,14 @@ Editor::ruler_button_press (GdkEventButton* ev)
switch (ev->button) {
case 1:
- // Since we are about to move the playhead, cancel any running
+ // Since we will locate the playhead on button release, cancel any running
// auditions.
if (session->is_auditioning()) {
session->cancel_audition ();
}
- /* transport playhead */
+ /* playhead cursor */
snap_to (where);
- session->request_locate (where);
+ playhead_cursor->set_position (where);
_dragging_playhead = true;
break;
diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc
new file mode 100644
index 0000000000..5be28e9226
--- /dev/null
+++ b/gtk2_ardour/engine_dialog.cc
@@ -0,0 +1,1126 @@
+#include <vector>
+#include <cmath>
+#include <fstream>
+
+#include <glibmm.h>
+#include <pbd/xml++.h>
+
+#ifdef __APPLE__
+#include <CoreAudio/CoreAudio.h>
+#include <CoreFoundation/CFString.h>
+#include <sys/param.h>
+#include <mach-o/dyld.h>
+#else
+#include <alsa/asoundlib.h>
+#endif
+
+#include <ardour/profile.h>
+#include <jack/jack.h>
+
+#include <gtkmm/stock.h>
+#include <gtkmm2ext/utils.h>
+
+#include <pbd/convert.h>
+#include <pbd/error.h>
+
+#ifdef __APPLE
+#include <CFBundle.h>
+#endif
+
+#include "engine_dialog.h"
+#include "i18n.h"
+
+using namespace std;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+using namespace PBD;
+using namespace Glib;
+
+EngineControl::EngineControl ()
+ : periods_adjustment (2, 2, 16, 1, 2),
+ periods_spinner (periods_adjustment),
+ priority_adjustment (60, 10, 90, 1, 10),
+ priority_spinner (priority_adjustment),
+ ports_adjustment (128, 8, 1024, 1, 16),
+ ports_spinner (ports_adjustment),
+ realtime_button (_("Realtime")),
+ no_memory_lock_button (_("Do not lock memory")),
+ unlock_memory_button (_("Unlock memory")),
+ soft_mode_button (_("No zombies")),
+ monitor_button (_("Provide monitor ports")),
+ force16bit_button (_("Force 16 bit")),
+ hw_monitor_button (_("H/W monitoring")),
+ hw_meter_button (_("H/W metering")),
+ verbose_output_button (_("Verbose output")),
+ start_button (_("Start")),
+ stop_button (_("Stop")),
+#ifdef __APPLE__
+ basic_packer (5, 2),
+ options_packer (4, 2),
+ device_packer (4, 2)
+#else
+ basic_packer (8, 2),
+ options_packer (14, 2),
+ device_packer (6, 2)
+#endif
+{
+ using namespace Notebook_Helpers;
+ Label* label;
+ vector<string> strings;
+ int row = 0;
+
+ _used = false;
+
+ strings.push_back (_("8000Hz"));
+ strings.push_back (_("22050Hz"));
+ strings.push_back (_("44100Hz"));
+ strings.push_back (_("48000Hz"));
+ strings.push_back (_("88200Hz"));
+ strings.push_back (_("96000Hz"));
+ strings.push_back (_("192000Hz"));
+ set_popdown_strings (sample_rate_combo, strings);
+ sample_rate_combo.set_active_text ("48000Hz");
+
+ strings.clear ();
+ strings.push_back ("32");
+ strings.push_back ("64");
+ strings.push_back ("128");
+ strings.push_back ("256");
+ strings.push_back ("512");
+ strings.push_back ("1024");
+ strings.push_back ("2048");
+ strings.push_back ("4096");
+ strings.push_back ("8192");
+ set_popdown_strings (period_size_combo, strings);
+ period_size_combo.set_active_text ("1024");
+
+ strings.clear ();
+ strings.push_back (_("None"));
+ strings.push_back (_("Triangular"));
+ strings.push_back (_("Rectangular"));
+ strings.push_back (_("Shaped"));
+ set_popdown_strings (dither_mode_combo, strings);
+ dither_mode_combo.set_active_text (_("None"));
+
+ /* basic parameters */
+
+ basic_packer.set_spacings (6);
+
+ strings.clear ();
+#ifdef __APPLE__
+ strings.push_back (X_("CoreAudio"));
+#else
+ strings.push_back (X_("ALSA"));
+ strings.push_back (X_("OSS"));
+ strings.push_back (X_("FFADO"));
+#endif
+ strings.push_back (X_("NetJACK"));
+ strings.push_back (X_("Dummy"));
+ set_popdown_strings (driver_combo, strings);
+ driver_combo.set_active_text (strings.front());
+
+ /* figure out available devices and set up interface_combo */
+
+ enumerate_devices ();
+ driver_combo.signal_changed().connect (mem_fun (*this, &EngineControl::driver_changed));
+ driver_changed ();
+
+ strings.clear ();
+ strings.push_back (_("Playback/Recording on 1 Device"));
+ strings.push_back (_("Playback/Recording on 2 Devices"));
+ strings.push_back (_("Playback only"));
+ strings.push_back (_("Recording only"));
+ set_popdown_strings (audio_mode_combo, strings);
+ audio_mode_combo.set_active_text (strings.front());
+
+ audio_mode_combo.signal_changed().connect (mem_fun (*this, &EngineControl::audio_mode_changed));
+ audio_mode_changed ();
+
+ row = 0;
+
+ label = manage (new Label (_("Driver")));
+ basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ basic_packer.attach (driver_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ row++;
+
+ label = manage (new Label (_("Interface")));
+ basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ basic_packer.attach (interface_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ row++;
+
+ label = manage (new Label (_("Sample Rate")));
+ basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ row++;
+
+ label = manage (new Label (_("Buffer size")));
+ basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ basic_packer.attach (period_size_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ row++;
+
+#ifndef __APPLE__
+ label = manage (new Label (_("Number of buffers")));
+ basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ basic_packer.attach (periods_spinner, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ periods_spinner.set_value (2);
+ row++;
+#endif
+
+ label = manage (new Label (_("Approximate latency")));
+ label->set_alignment (0.0, 0.5);
+ basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ basic_packer.attach (latency_label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ row++;
+
+ sample_rate_combo.signal_changed().connect (mem_fun (*this, &EngineControl::redisplay_latency));
+ periods_adjustment.signal_value_changed().connect (mem_fun (*this, &EngineControl::redisplay_latency));
+ period_size_combo.signal_changed().connect (mem_fun (*this, &EngineControl::redisplay_latency));
+ redisplay_latency();
+ row++;
+ /* no audio mode with CoreAudio, its duplex or nuthin' */
+
+#ifndef __APPLE__
+ label = manage (new Label (_("Audio Mode")));
+ basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ basic_packer.attach (audio_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ row++;
+#endif
+
+ interface_combo.set_size_request (125, -1);
+ input_device_combo.set_size_request (125, -1);
+ output_device_combo.set_size_request (125, -1);
+
+ /*
+
+ if (engine_running()) {
+ start_button.set_sensitive (false);
+ } else {
+ stop_button.set_sensitive (false);
+ }
+
+ start_button.signal_clicked().connect (mem_fun (*this, &EngineControl::start_engine));
+ stop_button.signal_clicked().connect (mem_fun (*this, &EngineControl::start_engine));
+ */
+
+ button_box.pack_start (start_button, false, false);
+ button_box.pack_start (stop_button, false, false);
+
+ // basic_packer.attach (button_box, 0, 2, 8, 9, FILL|EXPAND, (AttachOptions) 0);
+
+ /* options */
+
+ options_packer.set_spacings (6);
+ row = 0;
+
+ options_packer.attach (realtime_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+
+ realtime_button.signal_toggled().connect (mem_fun (*this, &EngineControl::realtime_changed));
+ realtime_changed ();
+
+#ifndef __APPLE__
+ label = manage (new Label (_("Realtime Priority")));
+ label->set_alignment (1.0, 0.5);
+ options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ options_packer.attach (priority_spinner, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ priority_spinner.set_value (60);
+
+ options_packer.attach (no_memory_lock_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ options_packer.attach (unlock_memory_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ options_packer.attach (soft_mode_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ options_packer.attach (monitor_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ options_packer.attach (force16bit_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ options_packer.attach (hw_monitor_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ options_packer.attach (hw_meter_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+#else
+ options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+#endif
+
+ strings.clear ();
+ strings.push_back (_("Ignore"));
+ strings.push_back ("500 msec");
+ strings.push_back ("1 sec");
+ strings.push_back ("2 sec");
+ strings.push_back ("10 sec");
+ set_popdown_strings (timeout_combo, strings);
+ timeout_combo.set_active_text (strings.front ());
+
+ label = manage (new Label (_("Client timeout")));
+ label->set_alignment (1.0, 0.5);
+ options_packer.attach (timeout_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
+ options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+
+ label = manage (new Label (_("Number of ports")));
+ label->set_alignment (1.0, 0.5);
+ options_packer.attach (ports_spinner, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
+ options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+
+#ifndef __APPLE__
+ label = manage (new Label (_("Dither")));
+ label->set_alignment (1.0, 0.5);
+ options_packer.attach (dither_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
+ options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+#endif
+
+ find_jack_servers (server_strings);
+
+ if (server_strings.empty()) {
+ fatal << _("No JACK server found anywhere on this system. Please install JACK and restart") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ set_popdown_strings (serverpath_combo, server_strings);
+ serverpath_combo.set_active_text (server_strings.front());
+
+ if (server_strings.size() > 1) {
+ label = manage (new Label (_("Server:")));
+ options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ label->set_alignment (0.0, 0.5);
+ options_packer.attach (serverpath_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ }
+
+ /* device settings */
+
+ device_packer.set_spacings (6);
+ row = 0;
+
+#ifndef __APPLE__
+ label = manage (new Label (_("Input device")));
+ label->set_alignment (1.0, 0.5);
+ device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ device_packer.attach (input_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ label = manage (new Label (_("Output device")));
+ label->set_alignment (1.0, 0.5);
+ device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ device_packer.attach (output_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+#endif
+ label = manage (new Label (_("Input channels")));
+ label->set_alignment (1.0, 0.5);
+ device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ device_packer.attach (input_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ label = manage (new Label (_("Output channels")));
+ label->set_alignment (1.0, 0.5);
+ device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ device_packer.attach (output_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ label = manage (new Label (_("Hardware input latency (samples)")));
+ label->set_alignment (1.0, 0.5);
+ device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ device_packer.attach (input_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+ label = manage (new Label (_("Hardware output latency (samples)")));
+ label->set_alignment (1.0, 0.5);
+ device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ device_packer.attach (output_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
+ ++row;
+
+ basic_hbox.pack_start (basic_packer, false, false);
+ options_hbox.pack_start (options_packer, false, false);
+
+ device_packer.set_border_width (12);
+ options_packer.set_border_width (12);
+ basic_packer.set_border_width (12);
+
+ notebook.pages().push_back (TabElem (basic_hbox, _("Device")));
+ notebook.pages().push_back (TabElem (options_hbox, _("Options")));
+ notebook.pages().push_back (TabElem (device_packer, _("Advanced")));
+ notebook.set_border_width (12);
+
+ set_border_width (12);
+ pack_start (notebook);
+}
+
+EngineControl::~EngineControl ()
+{
+
+}
+
+void
+EngineControl::build_command_line (vector<string>& cmd)
+{
+ string str;
+ string driver;
+ bool using_oss = false;
+ bool using_alsa = false;
+ bool using_coreaudio = false;
+ bool using_netjack = false;
+ bool using_ffado = false;
+
+ /* first, path to jackd */
+
+ cmd.push_back (serverpath_combo.get_active_text ());
+
+ /* now jackd arguments */
+
+ str = timeout_combo.get_active_text ();
+ if (str != _("Ignore")) {
+ double secs;
+ uint32_t msecs;
+ atof (str);
+ msecs = (uint32_t) floor (secs * 1000.0);
+ cmd.push_back ("-t");
+ cmd.push_back (to_string (msecs, std::dec));
+ }
+
+ if (no_memory_lock_button.get_active()) {
+ cmd.push_back ("-m"); /* no munlock */
+ }
+
+ cmd.push_back ("-p"); /* port max */
+ cmd.push_back (to_string ((uint32_t) floor (ports_spinner.get_value()), std::dec));
+
+ if (realtime_button.get_active()) {
+ cmd.push_back ("-R");
+ cmd.push_back ("-P");
+ cmd.push_back (to_string ((uint32_t) floor (priority_spinner.get_value()), std::dec));
+ }
+
+ if (unlock_memory_button.get_active()) {
+ cmd.push_back ("-u");
+ }
+
+ if (verbose_output_button.get_active()) {
+ cmd.push_back ("-v");
+ }
+
+ /* now add fixed arguments (not user-selectable) */
+
+ cmd.push_back ("-T"); // temporary */
+
+ /* next the driver */
+
+ cmd.push_back ("-d");
+
+ driver = driver_combo.get_active_text ();
+ if (driver == X_("ALSA")) {
+ using_alsa = true;
+ cmd.push_back ("alsa");
+ } else if (driver == X_("OSS")) {
+ using_oss = true;
+ cmd.push_back ("oss");
+ } else if (driver == X_("CoreAudio")) {
+ using_coreaudio = true;
+ cmd.push_back ("coreaudio");
+ } else if (driver == X_("NetJACK")) {
+ using_netjack = true;
+ cmd.push_back ("netjack");
+ } else if (driver == X_("FFADO")) {
+ using_ffado = true;
+ cmd.push_back ("ffado");
+ }
+
+ /* driver arguments */
+
+ if (!using_coreaudio) {
+ str = audio_mode_combo.get_active_text();
+
+ if (str == _("Playback/Recording on 1 Device")) {
+
+ /* relax */
+
+ } else if (str == _("Playback/Recording on 2 Devices")) {
+
+ cmd.push_back ("-C");
+ cmd.push_back (get_device_name (driver, input_device_combo.get_active_text()));
+ cmd.push_back ("-P");
+ cmd.push_back (get_device_name (driver, output_device_combo.get_active_text()));
+
+ } else if (str == _("Playback only")) {
+ cmd.push_back ("-P");
+ } else if (str == _("Recording only")) {
+ cmd.push_back ("-C");
+ }
+
+ cmd.push_back ("-n");
+ cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec));
+ }
+
+ cmd.push_back ("-r");
+ cmd.push_back (to_string (get_rate(), std::dec));
+
+ cmd.push_back ("-p");
+ cmd.push_back (period_size_combo.get_active_text());
+
+ if (using_alsa) {
+
+ if (audio_mode_combo.get_active_text() != _("Playback/Recording on 2 Devices")) {
+ cmd.push_back ("-d");
+ cmd.push_back (get_device_name (driver, interface_combo.get_active_text()));
+ }
+
+ if (hw_meter_button.get_active()) {
+ cmd.push_back ("-M");
+ }
+
+ if (hw_monitor_button.get_active()) {
+ cmd.push_back ("-H");
+ }
+
+ str = dither_mode_combo.get_active_text();
+
+ if (str == _("None")) {
+ } else if (str == _("Triangular")) {
+ cmd.push_back ("-z triangular");
+ } else if (str == _("Rectangular")) {
+ cmd.push_back ("-z rectangular");
+ } else if (str == _("Shaped")) {
+ cmd.push_back ("-z shaped");
+ }
+
+ if (force16bit_button.get_active()) {
+ cmd.push_back ("-S");
+ }
+
+ if (soft_mode_button.get_active()) {
+ cmd.push_back ("-s");
+ }
+
+ } else if (using_coreaudio) {
+
+#ifdef __APPLE__
+ // note: older versions of the CoreAudio JACK backend use -n instead of -d here
+ cmd.push_back ("-d");
+ cmd.push_back (get_device_name (driver, interface_combo.get_active_text()));
+#endif
+
+ } else if (using_oss) {
+
+ } else if (using_netjack) {
+
+ }
+}
+
+bool
+EngineControl::engine_running ()
+{
+ jack_status_t status;
+ jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
+
+ if (status == 0) {
+ jack_client_close (c);
+ return true;
+ }
+ return false;
+}
+
+int
+EngineControl::setup_engine ()
+{
+ vector<string> args;
+ std::string cwd = "/tmp";
+
+ build_command_line (args);
+
+ Glib::ustring jackdrc_path = Glib::get_home_dir();
+ jackdrc_path += "/.jackdrc";
+
+ ofstream jackdrc (jackdrc_path.c_str());
+ if (!jackdrc) {
+ error << string_compose (_("cannot open JACK rc file %1 to store parameters"), jackdrc_path) << endmsg;
+ return -1;
+ }
+
+ for (vector<string>::iterator i = args.begin(); i != args.end(); ++i) {
+ jackdrc << (*i) << ' ';
+ }
+ jackdrc << endl;
+ jackdrc.close ();
+
+ _used = true;
+
+ return 0;
+}
+
+void
+EngineControl::realtime_changed ()
+{
+#ifndef __APPLE__
+ priority_spinner.set_sensitive (realtime_button.get_active());
+#endif
+}
+
+void
+EngineControl::enumerate_devices ()
+{
+ /* note: case matters for the map keys */
+
+#ifdef __APPLE__
+ devices["CoreAudio"] = enumerate_coreaudio_devices ();
+#else
+ devices["ALSA"] = enumerate_alsa_devices ();
+ devices["FFADO"] = enumerate_ffado_devices ();
+ devices["OSS"] = enumerate_oss_devices ();
+ devices["Dummy"] = enumerate_dummy_devices ();
+ devices["NetJACK"] = enumerate_netjack_devices ();
+#endif
+}
+
+#ifdef __APPLE__
+static OSStatus
+getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize)
+{
+ UInt32 size = sizeof(CFStringRef);
+ CFStringRef UI;
+ OSStatus res = AudioDeviceGetProperty(id, 0, false,
+ kAudioDevicePropertyDeviceUID, &size, &UI);
+ if (res == noErr)
+ CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding());
+ CFRelease(UI);
+ return res;
+}
+
+vector<string>
+EngineControl::enumerate_coreaudio_devices ()
+{
+ vector<string> devs;
+
+ // Find out how many Core Audio devices are there, if any...
+ // (code snippet gently "borrowed" from St?hane Letz jackdmp;)
+ OSStatus err;
+ Boolean isWritable;
+ size_t outSize = sizeof(isWritable);
+
+ backend_devs.clear ();
+
+ err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
+ &outSize, &isWritable);
+ if (err == noErr) {
+ // Calculate the number of device available...
+ int numCoreDevices = outSize / sizeof(AudioDeviceID);
+ // Make space for the devices we are about to get...
+ AudioDeviceID *coreDeviceIDs = new AudioDeviceID [numCoreDevices];
+ err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
+ &outSize, (void *) coreDeviceIDs);
+ if (err == noErr) {
+ // Look for the CoreAudio device name...
+ char coreDeviceName[256];
+ size_t nameSize;
+ for (int i = 0; i < numCoreDevices; i++) {
+
+ nameSize = sizeof (coreDeviceName);
+
+ err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
+ 0, true, kAudioDevicePropertyDeviceName,
+ &outSize, &isWritable);
+ if (err == noErr) {
+ err = AudioDeviceGetProperty(coreDeviceIDs[i],
+ 0, true, kAudioDevicePropertyDeviceName,
+ &nameSize, (void *) coreDeviceName);
+ if (err == noErr) {
+ char drivername[128];
+
+ // this returns the unique id for the device
+ // that must be used on the commandline for jack
+
+ if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) {
+ devs.push_back (coreDeviceName);
+ backend_devs.push_back (drivername);
+ }
+ }
+ }
+ }
+ }
+ delete [] coreDeviceIDs;
+ }
+
+ return devs;
+}
+#else
+vector<string>
+EngineControl::enumerate_alsa_devices ()
+{
+ vector<string> devs;
+
+ snd_ctl_t *handle;
+ snd_ctl_card_info_t *info;
+ snd_pcm_info_t *pcminfo;
+ snd_ctl_card_info_alloca(&info);
+ snd_pcm_info_alloca(&pcminfo);
+ string devname;
+ int cardnum = -1;
+ int device = -1;
+
+ backend_devs.clear ();
+
+ while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
+
+ devname = "hw:";
+ devname += to_string (cardnum, std::dec);
+
+ if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) {
+
+ while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
+
+ bool have_playback = false;
+ bool have_capture = false;
+
+ /* find duplex devices only */
+
+ snd_pcm_info_set_device (pcminfo, device);
+ snd_pcm_info_set_subdevice (pcminfo, 0);
+ snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_CAPTURE);
+
+ if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
+ have_capture = true;
+ }
+
+ snd_pcm_info_set_device (pcminfo, device);
+ snd_pcm_info_set_subdevice (pcminfo, 0);
+ snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK);
+
+ if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
+ have_playback = true;
+ }
+
+ if (have_capture && have_playback) {
+ devs.push_back (snd_pcm_info_get_name (pcminfo));
+ devname += ',';
+ devname += to_string (device, std::dec);
+ backend_devs.push_back (devname);
+ }
+ }
+
+ snd_ctl_close(handle);
+ }
+ }
+
+ return devs;
+}
+
+vector<string>
+EngineControl::enumerate_ffado_devices ()
+{
+ vector<string> devs;
+ return devs;
+}
+vector<string>
+EngineControl::enumerate_oss_devices ()
+{
+ vector<string> devs;
+ return devs;
+}
+vector<string>
+EngineControl::enumerate_dummy_devices ()
+{
+ vector<string> devs;
+ return devs;
+}
+vector<string>
+EngineControl::enumerate_netjack_devices ()
+{
+ vector<string> devs;
+ return devs;
+}
+#endif
+
+void
+EngineControl::driver_changed ()
+{
+ string driver = driver_combo.get_active_text();
+ vector<string>& strings = devices[driver];
+ string::size_type maxlen = 0;
+ int maxindex = -1;
+ int n = 0;
+
+ for (vector<string>::iterator i = strings.begin(); i != strings.end(); ++i, ++n) {
+ if ((*i).length() > maxlen) {
+ maxlen = (*i).length();
+ maxindex = n;
+ }
+ }
+
+ set_popdown_strings (interface_combo, strings);
+ set_popdown_strings (input_device_combo, strings);
+ set_popdown_strings (output_device_combo, strings);
+
+ if (!strings.empty()) {
+ interface_combo.set_active_text (strings.front());
+ input_device_combo.set_active_text (strings.front());
+ output_device_combo.set_active_text (strings.front());
+ }
+
+ if (driver == "ALSA") {
+ soft_mode_button.set_sensitive (true);
+ force16bit_button.set_sensitive (true);
+ hw_monitor_button.set_sensitive (true);
+ hw_meter_button.set_sensitive (true);
+ monitor_button.set_sensitive (true);
+ } else {
+ soft_mode_button.set_sensitive (false);
+ force16bit_button.set_sensitive (false);
+ hw_monitor_button.set_sensitive (false);
+ hw_meter_button.set_sensitive (false);
+ monitor_button.set_sensitive (false);
+ }
+}
+
+uint32_t
+EngineControl::get_rate ()
+{
+ return atoi (sample_rate_combo.get_active_text ());
+}
+
+void
+EngineControl::redisplay_latency ()
+{
+ uint32_t rate = get_rate();
+#ifdef __APPLE_
+ float periods = 2;
+#else
+ float periods = periods_adjustment.get_value();
+#endif
+ float period_size = atof (period_size_combo.get_active_text());
+
+ char buf[32];
+ snprintf (buf, sizeof(buf), "%.1fmsec", (periods * period_size) / (rate/1000.0));
+
+ latency_label.set_text (buf);
+}
+
+void
+EngineControl::audio_mode_changed ()
+{
+ Glib::ustring str = audio_mode_combo.get_active_text();
+
+ if (str == _("Playback/Recording on 1 Device")) {
+ input_device_combo.set_sensitive (false);
+ output_device_combo.set_sensitive (false);
+ } else if (str == _("Playback/Recording on 2 Devices")) {
+ input_device_combo.set_sensitive (true);
+ output_device_combo.set_sensitive (true);
+ } else if (str == _("Playback only")) {
+ output_device_combo.set_sensitive (true);
+ } else if (str == _("Recording only")) {
+ input_device_combo.set_sensitive (true);
+ }
+}
+
+void
+EngineControl::find_jack_servers (vector<string>& strings)
+{
+#ifdef __APPLE__
+ /* this magic lets us finds the path to the OSX bundle, and then
+ we infer JACK's location from there
+ */
+
+ char execpath[MAXPATHLEN+1];
+ uint32_t pathsz = sizeof (execpath);
+
+ _NSGetExecutablePath (execpath, &pathsz);
+
+ cerr << " execpath = " << execpath << endl;
+
+ Glib::ustring path (Glib::path_get_dirname (execpath));
+ path += "/jackd";
+
+ if (Glib::file_test (path, FILE_TEST_EXISTS)) {
+ strings.push_back (path);
+ cerr << "Found jack in " << path << endl;
+ }
+
+ if (getenv ("ARDOUR_WITH_JACK")) {
+ /* no other options - only use the JACK we supply */
+ if (strings.empty()) {
+ fatal << _("JACK appears to be missing from the Ardour bundle") << endmsg;
+ /*NOTREACHED*/
+ }
+ return;
+ }
+#endif
+
+ if (Glib::file_test ("/usr/bin/jackd", FILE_TEST_EXISTS)) {
+ strings.push_back ("/usr/bin/jackd");
+ }
+ if (Glib::file_test ("/usr/local/bin/jackd", FILE_TEST_EXISTS)) {
+ strings.push_back ("/usr/local/bin/jackd");
+ }
+ if (Glib::file_test ("/opt/bin/jackd", FILE_TEST_EXISTS)) {
+ strings.push_back ("/opt/bin/jackd");
+ }
+ if (Glib::file_test ("/usr/bin/jackdmp", FILE_TEST_EXISTS)) {
+ strings.push_back ("/usr/bin/jackd");
+ }
+ if (Glib::file_test ("/usr/local/bin/jackdmp", FILE_TEST_EXISTS)) {
+ strings.push_back ("/usr/local/bin/jackd");
+ }
+ if (Glib::file_test ("/opt/bin/jackdmp", FILE_TEST_EXISTS)) {
+ strings.push_back ("/opt/bin/jackd");
+ }
+
+}
+
+string
+EngineControl::get_device_name (const string& driver, const string& human_readable)
+{
+ vector<string>::iterator n;
+ vector<string>::iterator i;
+
+ if (backend_devs.empty()) {
+ return human_readable;
+ }
+
+ for (i = devices[driver].begin(), n = backend_devs.begin(); i != devices[driver].end(); ++i, ++n) {
+ if (human_readable == (*i)) {
+ return (*n);
+ }
+ }
+
+ if (i == devices[driver].end()) {
+ fatal << string_compose (_("programming error: %1"), "true hardware name for ID missing") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ /* keep gcc happy */
+
+ return string();
+}
+
+XMLNode&
+EngineControl::get_state ()
+{
+ XMLNode* root = new XMLNode ("AudioSetup");
+ XMLNode* child;
+ Glib::ustring path;
+
+ child = new XMLNode ("periods");
+ child->add_property ("val", to_string (periods_adjustment.get_value(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("priority");
+ child->add_property ("val", to_string (priority_adjustment.get_value(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("ports");
+ child->add_property ("val", to_string (ports_adjustment.get_value(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("inchannels");
+ child->add_property ("val", to_string (input_channels.get_value(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("outchannels");
+ child->add_property ("val", to_string (output_channels.get_value(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("inlatency");
+ child->add_property ("val", to_string (input_latency.get_value(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("outlatency");
+ child->add_property ("val", to_string (output_latency.get_value(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("realtime");
+ child->add_property ("val", to_string (realtime_button.get_active(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("nomemorylock");
+ child->add_property ("val", to_string (no_memory_lock_button.get_active(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("unlockmemory");
+ child->add_property ("val", to_string (unlock_memory_button.get_active(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("softmode");
+ child->add_property ("val", to_string (soft_mode_button.get_active(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("force16bit");
+ child->add_property ("val", to_string (force16bit_button.get_active(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("hwmonitor");
+ child->add_property ("val", to_string (hw_monitor_button.get_active(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("hwmeter");
+ child->add_property ("val", to_string (hw_meter_button.get_active(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("verbose");
+ child->add_property ("val", to_string (verbose_output_button.get_active(), std::dec));
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("samplerate");
+ child->add_property ("val", sample_rate_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("periodsize");
+ child->add_property ("val", period_size_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("serverpath");
+ child->add_property ("val", serverpath_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("driver");
+ child->add_property ("val", driver_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("interface");
+ child->add_property ("val", interface_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("timeout");
+ child->add_property ("val", timeout_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("dither");
+ child->add_property ("val", dither_mode_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("audiomode");
+ child->add_property ("val", audio_mode_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("inputdevice");
+ child->add_property ("val", input_device_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ child = new XMLNode ("outputdevice");
+ child->add_property ("val", output_device_combo.get_active_text());
+ root->add_child_nocopy (*child);
+
+ return *root;
+}
+
+void
+EngineControl::set_state (const XMLNode& root)
+{
+ XMLNodeList clist;
+ XMLNodeConstIterator citer;
+ XMLNode* child;
+ XMLProperty* prop;
+
+ int val;
+ string strval;
+
+ clist = root.children();
+
+ for (citer = clist.begin(); citer != clist.end(); ++citer) {
+
+ child = *citer;
+
+ prop = child->property ("val");
+
+ if (!prop || prop->value().empty()) {
+ error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg;
+ continue;
+ }
+
+ strval = prop->value();
+
+ /* adjustments/spinners */
+
+ if (child->name() == "periods") {
+ val = atoi (strval);
+ periods_adjustment.set_value(val);
+ } else if (child->name() == "priority") {
+ val = atoi (strval);
+ priority_adjustment.set_value(val);
+ } else if (child->name() == "ports") {
+ val = atoi (strval);
+ ports_adjustment.set_value(val);
+ } else if (child->name() == "inchannels") {
+ val = atoi (strval);
+ input_channels.set_value(val);
+ } else if (child->name() == "outchannels") {
+ val = atoi (strval);
+ output_channels.set_value(val);
+ } else if (child->name() == "inlatency") {
+ val = atoi (strval);
+ input_latency.set_value(val);
+ } else if (child->name() == "outlatency") {
+ val = atoi (strval);
+ output_latency.set_value(val);
+ }
+
+ /* buttons */
+
+ else if (child->name() == "realtime") {
+ val = atoi (strval);
+ realtime_button.set_active(val);
+ } else if (child->name() == "nomemorylock") {
+ val = atoi (strval);
+ no_memory_lock_button.set_active(val);
+ } else if (child->name() == "unlockmemory") {
+ val = atoi (strval);
+ unlock_memory_button.set_active(val);
+ } else if (child->name() == "softmode") {
+ val = atoi (strval);
+ soft_mode_button.set_active(val);
+ } else if (child->name() == "force16bit") {
+ val = atoi (strval);
+ force16bit_button.set_active(val);
+ } else if (child->name() == "hwmonitor") {
+ val = atoi (strval);
+ hw_monitor_button.set_active(val);
+ } else if (child->name() == "hwmeter") {
+ val = atoi (strval);
+ hw_meter_button.set_active(val);
+ } else if (child->name() == "verbose") {
+ val = atoi (strval);
+ verbose_output_button.set_active(val);
+ }
+
+ /* combos */
+
+ else if (child->name() == "samplerate") {
+ sample_rate_combo.set_active_text(strval);
+ } else if (child->name() == "periodsize") {
+ period_size_combo.set_active_text(strval);
+ } else if (child->name() == "serverpath") {
+ /* do not allow us to use a server path that doesn't
+ exist on this system. this handles cases where
+ the user has an RC file listing a serverpath
+ from some other machine.
+ */
+ vector<string>::iterator x;
+ for (x = server_strings.begin(); x != server_strings.end(); ++x) {
+ if (*x == strval) {
+ break;
+ }
+ }
+ if (x != server_strings.end()) {
+ serverpath_combo.set_active_text (strval);
+ } else {
+ warning << string_compose (_("configuration files contain a JACK server path that doesn't exist (%1)"),
+ strval)
+ << endmsg;
+ }
+ } else if (child->name() == "driver") {
+ driver_combo.set_active_text(strval);
+ } else if (child->name() == "interface") {
+ interface_combo.set_active_text(strval);
+ } else if (child->name() == "timeout") {
+ timeout_combo.set_active_text(strval);
+ } else if (child->name() == "dither") {
+ dither_mode_combo.set_active_text(strval);
+ } else if (child->name() == "audiomode") {
+ audio_mode_combo.set_active_text(strval);
+ } else if (child->name() == "inputdevice") {
+ input_device_combo.set_active_text(strval);
+ } else if (child->name() == "outputdevice") {
+ output_device_combo.set_active_text(strval);
+ }
+ }
+}
diff --git a/gtk2_ardour/engine_dialog.h b/gtk2_ardour/engine_dialog.h
new file mode 100644
index 0000000000..925d12acbb
--- /dev/null
+++ b/gtk2_ardour/engine_dialog.h
@@ -0,0 +1,106 @@
+#ifndef __gtk2_ardour_engine_dialog_h__
+#define __gtk2_ardour_engine_dialog_h__
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include <gtkmm/checkbutton.h>
+#include <gtkmm/spinbutton.h>
+#include <gtkmm/notebook.h>
+#include <gtkmm/comboboxtext.h>
+#include <gtkmm/table.h>
+#include <gtkmm/expander.h>
+#include <gtkmm/box.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/button.h>
+
+class EngineControl : public Gtk::VBox {
+ public:
+ EngineControl ();
+ ~EngineControl ();
+
+ static bool engine_running ();
+ int setup_engine ();
+
+ bool was_used() const { return _used; }
+ XMLNode& get_state ();
+ void set_state (const XMLNode&);
+
+ private:
+ Gtk::Adjustment periods_adjustment;
+ Gtk::SpinButton periods_spinner;
+ Gtk::Adjustment priority_adjustment;
+ Gtk::SpinButton priority_spinner;
+ Gtk::Adjustment ports_adjustment;
+ Gtk::SpinButton ports_spinner;
+ Gtk::SpinButton input_channels;
+ Gtk::SpinButton output_channels;
+ Gtk::SpinButton input_latency;
+ Gtk::SpinButton output_latency;
+ Gtk::Label latency_label;
+
+ Gtk::CheckButton realtime_button;
+ Gtk::CheckButton no_memory_lock_button;
+ Gtk::CheckButton unlock_memory_button;
+ Gtk::CheckButton soft_mode_button;
+ Gtk::CheckButton monitor_button;
+ Gtk::CheckButton force16bit_button;
+ Gtk::CheckButton hw_monitor_button;
+ Gtk::CheckButton hw_meter_button;
+ Gtk::CheckButton verbose_output_button;
+
+ Gtk::Button start_button;
+ Gtk::Button stop_button;
+ Gtk::HButtonBox button_box;
+
+ Gtk::ComboBoxText sample_rate_combo;
+ Gtk::ComboBoxText period_size_combo;
+
+ Gtk::ComboBoxText preset_combo;
+ Gtk::ComboBoxText serverpath_combo;
+ Gtk::ComboBoxText driver_combo;
+ Gtk::ComboBoxText interface_combo;
+ Gtk::ComboBoxText timeout_combo;
+ Gtk::ComboBoxText dither_mode_combo;
+ Gtk::ComboBoxText audio_mode_combo;
+ Gtk::ComboBoxText input_device_combo;
+ Gtk::ComboBoxText output_device_combo;
+
+ Gtk::Table basic_packer;
+ Gtk::Table options_packer;
+ Gtk::Table device_packer;
+ Gtk::HBox basic_hbox;
+ Gtk::HBox options_hbox;
+ Gtk::HBox device_hbox;
+ Gtk::Notebook notebook;
+
+ bool _used;
+
+ void realtime_changed ();
+ void driver_changed ();
+ void build_command_line (std::vector<std::string>&);
+
+ std::map<std::string,std::vector<std::string> > devices;
+ std::vector<std::string> backend_devs;
+ void enumerate_devices ();
+
+#ifdef __APPLE__
+ std::vector<std::string> enumerate_coreaudio_devices ();
+#else
+ std::vector<std::string> enumerate_alsa_devices ();
+ std::vector<std::string> enumerate_oss_devices ();
+ std::vector<std::string> enumerate_netjack_devices ();
+ std::vector<std::string> enumerate_ffado_devices ();
+ std::vector<std::string> enumerate_dummy_devices ();
+#endif
+
+ void redisplay_latency ();
+ uint32_t get_rate();
+ void audio_mode_changed ();
+ std::vector<std::string> server_strings;
+ void find_jack_servers (std::vector<std::string>&);
+ std::string get_device_name (const std::string& driver, const std::string& human_readable_name);
+};
+
+#endif /* __gtk2_ardour_engine_dialog_h__ */
diff --git a/gtk2_ardour/enums.cc b/gtk2_ardour/enums.cc
index e6c81598fb..c33b2965c3 100644
--- a/gtk2_ardour/enums.cc
+++ b/gtk2_ardour/enums.cc
@@ -20,11 +20,13 @@
#include <pbd/enumwriter.h>
#include "audio_clock.h"
+#include "editing.h"
#include "enums.h"
using namespace std;
using namespace PBD;
using namespace ARDOUR;
+using namespace Editing;
void
setup_gtk_ardour_enums ()
@@ -35,6 +37,7 @@ setup_gtk_ardour_enums ()
AudioClock::Mode clock_mode;
Width width;
+ ImportMode import_mode;
#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
@@ -51,4 +54,10 @@ setup_gtk_ardour_enums ()
REGISTER_ENUM (Wide);
REGISTER_ENUM (Narrow);
REGISTER (width);
+
+ REGISTER_ENUM (ImportAsTrack);
+ REGISTER_ENUM (ImportToTrack);
+ REGISTER_ENUM (ImportAsRegion);
+ REGISTER_ENUM (ImportAsTapeTrack);
+ REGISTER (import_mode);
}
diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc
index 90fea321de..e6eaffefcb 100644
--- a/gtk2_ardour/keyboard.cc
+++ b/gtk2_ardour/keyboard.cc
@@ -48,14 +48,14 @@ uint32_t Keyboard::Shift = GDK_SHIFT_MASK;
uint32_t Keyboard::Alt = GDK_MOD1_MASK;
uint32_t Keyboard::Meta;
-Keyboard* Keyboard::_the_keyboard = 0;
+Keyboard* Keyboard::_the_keyboard = 0;
+Gtk::Window* Keyboard::current_window = 0;
+bool Keyboard::_some_magic_widget_has_focus = false;
/* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
GdkModifierType Keyboard::RelevantModifierKeyMask;
-bool Keyboard::_some_magic_widget_has_focus = false;
-
void
Keyboard::magic_widget_grab_focus ()
{
@@ -199,6 +199,13 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
}
+ if (event->type == GDK_KEY_RELEASE && event->keyval == GDK_w && modifier_state_equals (event->state, Control)) {
+ if (current_window) {
+ current_window->hide ();
+ current_window = 0;
+ }
+ }
+
return false;
}
@@ -211,6 +218,7 @@ Keyboard::key_is_down (uint32_t keyval)
bool
Keyboard::enter_window (GdkEventCrossing *ev, Gtk::Window* win)
{
+ current_window = win;
return false;
}
@@ -236,6 +244,7 @@ Keyboard::leave_window (GdkEventCrossing *ev, Gtk::Window* win)
cerr << "clearing current target\n";
}
state.clear ();
+ current_window = 0;
}
return false;
diff --git a/gtk2_ardour/keyboard.h b/gtk2_ardour/keyboard.h
index 3d9e1c9f41..fb22f2eca9 100644
--- a/gtk2_ardour/keyboard.h
+++ b/gtk2_ardour/keyboard.h
@@ -105,6 +105,7 @@ class Keyboard : public sigc::trackable, PBD::Stateful
static guint delete_but;
static guint delete_mod;
static guint snap_mod;
+ static Gtk::Window* current_window;
static gint _snooper (GtkWidget*, GdkEventKey*, gpointer);
gint snooper (GtkWidget*, GdkEventKey*);
diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
index 67e59d4b80..1e9b27d8a7 100644
--- a/gtk2_ardour/main.cc
+++ b/gtk2_ardour/main.cc
@@ -47,7 +47,7 @@
#include "i18n.h"
using namespace Gtk;
-using namespace GTK_ARDOUR;
+using namespace ARDOUR_COMMAND_LINE;
using namespace ARDOUR;
using namespace PBD;
using namespace sigc;
@@ -57,6 +57,7 @@ TextReceiver text_receiver ("ardour");
extern int curvetest (string);
static ARDOUR_UI *ui = 0;
+static char* localedir = LOCALEDIR;
gint
show_ui_callback (void *arg)
@@ -98,65 +99,129 @@ Please consider the possibilities, and perhaps (re)start JACK."));
win.run ();
}
-static bool
-maybe_load_session ()
-{
- /* If no session name is given: we're not loading a session yet, nor creating a new one */
- if (!session_name.length()) {
- ui->hide_splash ();
- if (!Config->get_no_new_session_dialog()) {
- if (!ui->new_session ()) {
- return false;
- }
- }
- return true;
+#ifdef __APPLE__
+
+#include <mach-o/dyld.h>
+#include <sys/param.h>
+#include <fstream>
+
+void
+fixup_bundle_environment ()
+{
+ if (!getenv ("ARDOUR_BUNDLED")) {
+ return;
}
- /* Load session or start the new session dialog */
- string name, path;
+ char execpath[MAXPATHLEN+1];
+ uint32_t pathsz = sizeof (execpath);
- bool isnew;
+ _NSGetExecutablePath (execpath, &pathsz);
- if (find_session (session_name, path, name, isnew)) {
- error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
- return false;
+ Glib::ustring exec_path (execpath);
+ Glib::ustring dir_path = Glib::path_get_dirname (exec_path);
+ Glib::ustring path;
+ const char *cstr = getenv ("PATH");
+
+ /* ensure that we find any bundled executables (e.g. JACK) */
+
+ path = dir_path;
+ if (cstr) {
+ path += ':';
+ path += cstr;
}
+ setenv ("PATH", path.c_str(), 1);
+
+ path = dir_path;
+ path += "/../Resources";
+ path += dir_path;
+ path += "/../Resources/Surfaces";
+ path += dir_path;
+ path += "/../Resources/Panners";
+
+ setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
+
+ path = dir_path;
+ path += "/../Resources/icons:";
+ path += dir_path;
+ path += "/../Resources/pixmaps:";
+ path += dir_path;
+ path += "/../Resources/share:";
+ path += dir_path;
+ path += "/../Resources";
+
+ setenv ("ARDOUR_PATH", path.c_str(), 1);
+ setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
+ setenv ("ARDOUR_DATA_PATH", path.c_str(), 1);
+
+ cstr = getenv ("LADSPA_PATH");
+ if (cstr) {
+ path = cstr;
+ path += ':';
+ }
+ path = dir_path;
+ path += "/../Plugins";
+
+ setenv ("LADSPA_PATH", path.c_str(), 1);
- if (!new_session) {
-
- /* Loading a session, but the session doesn't exist */
- if (isnew) {
- error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
- "To create it from the command line, start ardour as \"ardour --new %1"), path)
- << endmsg;
- return false;
- }
+ path = dir_path;
+ path += "/../Frameworks/clearlooks";
- if (ui->load_session (path, name)) {
- /* it failed */
- return false;
- }
+ setenv ("GTK_PATH", path.c_str(), 1);
- } else {
+ path = dir_path;
+ path += "/../Resources/locale";
+
+ localedir = strdup (path.c_str());
+
+ /* write a pango.rc file and tell pango to use it */
- /* TODO: This bit of code doesn't work properly yet
- Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
- ui->set_will_create_new_session_automatically (true);
- */
+ path = dir_path;
+ path += "/../Resources/pango.rc";
+
+ std::ofstream pangorc (path.c_str());
+ if (!pangorc) {
+ error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
+ } else {
+ pangorc << "[Pango]\nModuleFiles=";
+ Glib::ustring mpath = dir_path;
+ mpath += "/../Resources/pango.modules";
+ pangorc << mpath << endl;
- /* Show the NSD */
- ui->hide_splash ();
- if (!Config->get_no_new_session_dialog()) {
- if (!ui->new_session ()) {
- return false;
- }
- }
+ pangorc.close ();
+ setenv ("PANGO_RC_FILE", path.c_str(), 1);
}
- return true;
+ // gettext charset aliases
+
+ setenv ("CHARSETALIASDIR", path.c_str(), 1);
+
+ // font config
+
+ path = dir_path;
+ path += "/../Resources/fonts.conf";
+
+ setenv ("FONTCONFIG_FILE", path.c_str(), 1);
+
+ // GDK Pixbuf loader module file
+
+ path = dir_path;
+ path += "/../Resources/gdk-pixbuf.loaders";
+
+ setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
+
+ if (getenv ("ARDOUR_WITH_JACK")) {
+ // JACK driver dir
+
+ path = dir_path;
+ path += "/../Frameworks";
+
+ setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
+ }
}
+#endif
+
#ifdef VST_SUPPORT
/* this is called from the entry point of a wine-compiled
executable that is linked against gtk2_ardour built
@@ -167,15 +232,17 @@ int ardour_main (int argc, char *argv[])
#else
int main (int argc, char *argv[])
#endif
-
{
- ARDOUR::AudioEngine *engine = NULL;
vector<Glib::ustring> null_file_list;
- Glib::thread_init();
+#ifdef __APPLE__
+ fixup_bundle_environment ();
+#endif
+
+ Glib::thread_init();
gtk_set_locale ();
- (void) bindtextdomain (PACKAGE, LOCALEDIR);
+ (void) bindtextdomain (PACKAGE, localedir);
/* our i18n translations are all in UTF-8, so make sure
that even if the user locale doesn't specify UTF-8,
we use that when handling them.
@@ -229,17 +296,13 @@ int main (int argc, char *argv[])
PBD::ID::init ();
- try {
+ try {
ui = new ARDOUR_UI (&argc, &argv);
} catch (failed_constructor& err) {
error << _("could not create ARDOUR GUI") << endmsg;
exit (1);
}
- if (!keybindings_path.empty()) {
- ui->set_keybindings_path (keybindings_path);
- }
-
if (!no_splash) {
ui->show_splash ();
if (session_name.length()) {
@@ -247,50 +310,17 @@ int main (int argc, char *argv[])
}
}
- try {
- ARDOUR::init (use_vst, try_hw_optimization);
- setup_gtk_ardour_enums ();
- Config->set_current_owner (ConfigVariableBase::Interface);
- ui->setup_profile ();
-
- try {
- engine = new ARDOUR::AudioEngine (jack_client_name);
- } catch (AudioEngine::NoBackendAvailable& err) {
- gui_jack_error ();
- error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
- return -1;
- }
-
- ARDOUR::setup_midi(*engine);
-
- ui->set_engine (*engine);
-
- } catch (failed_constructor& err) {
- error << _("could not initialize Ardour.") << endmsg;
- return -1;
- }
-
- ui->start_engine ();
-
- if (maybe_load_session ()) {
- ui->run (text_receiver);
- ui = 0;
+ if (!keybindings_path.empty()) {
+ ui->set_keybindings_path (keybindings_path);
}
- delete engine;
- ARDOUR::cleanup ();
+ ui->run (text_receiver);
+ ui = 0;
- if (ui) {
- ui->kill();
- }
-
+ ARDOUR::cleanup ();
pthread_cancel_all ();
-
- exit (0);
-
return 0;
}
#ifdef VST_SUPPORT
} // end of extern C block
#endif
-
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index dfe5a268fa..f791314d75 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -1227,19 +1227,19 @@ MixerStrip::route_active_changed ()
} else if (is_audio_track()) {
if (_route->active()) {
set_name ("AudioTrackStripBase");
- gpm.set_meter_strip_name ("AudioTrackStripBase");
+ gpm.set_meter_strip_name ("AudioTrackMetrics");
} else {
set_name ("AudioTrackStripBaseInactive");
- gpm.set_meter_strip_name ("AudioTrackStripBaseInactive");
+ gpm.set_meter_strip_name ("AudioTrackMetricsInactive");
}
gpm.set_fader_name ("AudioTrackFader");
} else {
if (_route->active()) {
set_name ("AudioBusStripBase");
- gpm.set_meter_strip_name ("AudioBusStripBase");
+ gpm.set_meter_strip_name ("AudioBusMetrics");
} else {
set_name ("AudioBusStripBaseInactive");
- gpm.set_meter_strip_name ("AudioBusStripBaseInactive");
+ gpm.set_meter_strip_name ("AudioBusMetricsInactive");
}
gpm.set_fader_name ("AudioBusFader");
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
index 89d7ef5cc4..e3f6cae6ac 100644
--- a/gtk2_ardour/mixer_ui.cc
+++ b/gtk2_ardour/mixer_ui.cc
@@ -61,12 +61,17 @@ using PBD::atoi;
Mixer_UI::Mixer_UI ()
: Window (Gtk::WINDOW_TOPLEVEL)
{
+ session = 0;
_strip_width = Wide;
track_menu = 0;
mix_group_context_menu = 0;
no_track_list_redisplay = false;
in_group_row_change = false;
_visible = false;
+ ignore_route_reorder = false;
+ ignore_sync = false;
+
+ Route::SyncOrderKeys.connect (mem_fun (*this, &Mixer_UI::sync_order_keys));
scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
scroller_base.set_name ("MixerWindow");
@@ -92,6 +97,7 @@ Mixer_UI::Mixer_UI ()
track_model->signal_row_deleted().connect (mem_fun (*this, &Mixer_UI::track_list_delete));
track_model->signal_row_changed().connect (mem_fun (*this, &Mixer_UI::track_list_change));
+ track_model->signal_rows_reordered().connect (mem_fun (*this, &Mixer_UI::track_list_reorder));
CellRendererToggle* track_list_visible_cell = dynamic_cast<CellRendererToggle*>(track_display.get_column_cell_renderer (1));
track_list_visible_cell->property_activatable() = true;
@@ -318,6 +324,8 @@ Mixer_UI::add_strip (Session::RouteList& routes)
row[track_columns.route] = route;
row[track_columns.strip] = strip;
+ strip->set_old_order_key (track_model->children().size() - 1);
+
no_track_list_redisplay = false;
redisplay_track_list ();
@@ -349,6 +357,42 @@ Mixer_UI::remove_strip (MixerStrip* strip)
}
}
+const char*
+Mixer_UI::get_order_key()
+{
+ if (Config->get_sync_all_route_ordering()) {
+ return X_("editor");
+ } else {
+ return X_("signal");
+ }
+}
+
+void
+Mixer_UI::sync_order_keys ()
+{
+ vector<int> neworder;
+ TreeModel::Children rows = track_model->children();
+ TreeModel::Children::iterator ri;
+
+ if (ignore_sync || !session || (session->state_of_the_state() & Session::Loading) || rows.empty()) {
+ return;
+ }
+
+ for (ri = rows.begin(); ri != rows.end(); ++ri) {
+ neworder.push_back (0);
+ }
+
+ for (ri = rows.begin(); ri != rows.end(); ++ri) {
+ boost::shared_ptr<Route> route = (*ri)[track_columns.route];
+ MixerStrip* strip = (*ri)[track_columns.strip];
+ neworder[route->order_key (get_order_key())] = strip->old_order_key ();
+ }
+
+ ignore_route_reorder = true;
+ track_model->reorder (neworder);
+ ignore_route_reorder = false;
+}
+
void
Mixer_UI::follow_strip_selection ()
{
@@ -594,6 +638,13 @@ Mixer_UI::hide_all_audiotracks ()
}
void
+Mixer_UI::track_list_reorder (const TreeModel::Path& path, const TreeModel::iterator& iter, int* new_order)
+{
+ session->set_remote_control_ids();
+ redisplay_track_list ();
+}
+
+void
Mixer_UI::track_list_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter)
{
session->set_remote_control_ids();
@@ -632,6 +683,10 @@ Mixer_UI::redisplay_track_list ()
strip->set_marked_for_display (true);
strip->route()->set_order_key (N_("signal"), order);
+ if (!ignore_route_reorder) {
+ strip->route()->set_order_key (get_order_key(), order);
+ }
+
if (strip->packed()) {
if (strip->route()->is_master() || strip->route()->is_control()) {
@@ -663,12 +718,18 @@ Mixer_UI::redisplay_track_list ()
}
}
}
+
+ if (Config->get_sync_all_route_ordering() && !ignore_route_reorder) {
+ ignore_sync = true;
+ Route::SyncOrderKeys (); // EMIT SIGNAL
+ ignore_sync = false;
+ }
}
struct SignalOrderRouteSorter {
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
/* use of ">" forces the correct sort order */
- return a->order_key ("signal") < b->order_key ("signal");
+ return a->order_key (Mixer_UI::get_order_key()) < b->order_key (Mixer_UI::get_order_key());
}
};
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
index 3c9355efb7..5d00acff5b 100644
--- a/gtk2_ardour/mixer_ui.h
+++ b/gtk2_ardour/mixer_ui.h
@@ -77,6 +77,8 @@ class Mixer_UI : public Gtk::Window
void ensure_float (Gtk::Window&);
RouteRedirectSelection& selection() { return _selection; }
+
+ static const char* get_order_key();
private:
ARDOUR::Session *session;
@@ -148,6 +150,7 @@ class Mixer_UI : public Gtk::Window
void track_list_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&);
void track_list_delete (const Gtk::TreeModel::Path&);
+ void track_list_reorder (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order);
void initial_track_display ();
void show_track_list_menu ();
@@ -234,6 +237,10 @@ class Mixer_UI : public Gtk::Window
Width _strip_width;
+ void sync_order_keys ();
+ bool ignore_route_reorder;
+ bool ignore_sync;
+
static const int32_t default_width = 478;
static const int32_t default_height = 765;
};
diff --git a/gtk2_ardour/new_session_dialog.cc b/gtk2_ardour/new_session_dialog.cc
index 132af4a86c..ebf520fba7 100644
--- a/gtk2_ardour/new_session_dialog.cc
+++ b/gtk2_ardour/new_session_dialog.cc
@@ -23,6 +23,8 @@
#include <ardour/recent_sessions.h>
#include <ardour/session_state_utils.h>
#include <ardour/template_utils.h>
+#include <ardour/session.h>
+#include <ardour/profile.h>
#include <gtkmm/entry.h>
#include <gtkmm/filechooserbutton.h>
@@ -44,9 +46,10 @@ using namespace PBD;
NewSessionDialog::NewSessionDialog()
: ArdourDialog ("session control")
{
+ in_destructor = false;
session_name_label = Gtk::manage(new class Gtk::Label(_("Name :")));
m_name = Gtk::manage(new class Gtk::Entry());
- m_name->set_text(GTK_ARDOUR::session_name);
+ m_name->set_text(ARDOUR_COMMAND_LINE::session_name);
chan_count_label_1 = Gtk::manage(new class Gtk::Label(_("channels")));
chan_count_label_2 = Gtk::manage(new class Gtk::Label(_("channels")));
@@ -308,8 +311,11 @@ NewSessionDialog::NewSessionDialog()
new_session_table->attach(*m_folder, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0);
new_session_table->attach(*session_template_label, 0, 1, 2, 3, Gtk::FILL, Gtk::FILL, 0, 0);
new_session_table->attach(*m_template, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::FILL, 0, 0);
- new_session_table->attach(*advanced_expander, 0, 2, 3, 4, Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 6);
+ if (!ARDOUR::Profile->get_sae()) {
+ new_session_table->attach(*advanced_expander, 0, 2, 3, 4, Gtk::FILL, Gtk::EXPAND|Gtk::FILL, 0, 6);
+ }
+
open_session_hbox->pack_start(*open_session_file_label, false, false, 12);
open_session_hbox->pack_start(*m_open_filechooser, true, true, 12);
m_treeview->set_flags(Gtk::CAN_FOCUS);
@@ -358,7 +364,7 @@ NewSessionDialog::NewSessionDialog()
// add_button(Gtk::Stock::HELP, Gtk::RESPONSE_HELP);
add_button(Gtk::Stock::QUIT, Gtk::RESPONSE_CANCEL);
add_button(Gtk::Stock::CLEAR, Gtk::RESPONSE_NONE);
- m_okbutton = add_button(Gtk::Stock::NEW, Gtk::RESPONSE_OK);
+ m_okbutton = add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
recent_model = Gtk::TreeStore::create (recent_columns);
m_treeview->set_model (recent_model);
@@ -401,7 +407,7 @@ NewSessionDialog::NewSessionDialog()
set_default_response (Gtk::RESPONSE_OK);
- if (!GTK_ARDOUR::session_name.length()) {
+ if (!ARDOUR_COMMAND_LINE::session_name.length()) {
set_response_sensitive (Gtk::RESPONSE_OK, false);
set_response_sensitive (Gtk::RESPONSE_NONE, false);
} else {
@@ -426,12 +432,39 @@ NewSessionDialog::NewSessionDialog()
m_name->grab_focus();
}
+NewSessionDialog::~NewSessionDialog()
+{
+ in_destructor = true;
+}
+
+void
+NewSessionDialog::set_have_engine (bool yn)
+{
+ if (yn) {
+ m_notebook->remove_page (engine_control);
+ } else {
+ // XXX this is a bit of crude hack. if we ever add or remove
+ // pages from the notebook, this is going to break.
+ if (m_notebook->get_n_pages () != 3) {
+ m_notebook->append_page (engine_control, _("Audio Setup"));
+ m_notebook->show_all_children();
+ }
+ }
+}
+
+
void
NewSessionDialog::set_session_name(const Glib::ustring& name)
{
m_name->set_text(name);
}
+void
+NewSessionDialog::set_session_folder(const Glib::ustring& dir)
+{
+ // XXX DO SOMETHING
+}
+
std::string
NewSessionDialog::session_name() const
{
@@ -450,7 +483,7 @@ NewSessionDialog::session_name() const
}
*/
- if (on_new_session_page ()) {
+ if (on_newable_page()) {
return Glib::filename_from_utf8(m_name->get_text());
} else {
if (m_treeview->get_selection()->count_selected_rows() == 0) {
@@ -464,10 +497,9 @@ NewSessionDialog::session_name() const
std::string
NewSessionDialog::session_folder() const
{
- if (on_new_session_page ()) {
+ if (on_newable_page()) {
return Glib::filename_from_utf8(m_folder->get_filename());
} else {
-
if (m_treeview->get_selection()->count_selected_rows() == 0) {
std::string str = Glib::filename_from_utf8(m_open_filechooser->get_filename());
return Glib::path_get_dirname(str);
@@ -563,9 +595,16 @@ NewSessionDialog::connect_outs_to_physical() const
}
bool
-NewSessionDialog::on_new_session_page() const
+NewSessionDialog::on_newable_page() const
{
- return (m_notebook->get_current_page() == 0);
+ return (m_notebook->get_current_page() == 0 ||
+ m_notebook->get_current_page() == 2);
+}
+
+int
+NewSessionDialog::get_current_page() const
+{
+ return m_notebook->get_current_page();
}
void
@@ -595,7 +634,11 @@ NewSessionDialog::on_new_session_name_entry_changed ()
void
NewSessionDialog::notebook_page_changed (GtkNotebookPage* np, uint pagenum)
{
- if (!on_new_session_page ()) {
+ if (in_destructor) {
+ return;
+ }
+
+ if (!on_newable_page ()) {
m_okbutton->set_label(_("Open"));
set_response_sensitive (Gtk::RESPONSE_NONE, false);
m_okbutton->set_image (*(new Gtk::Image (Gtk::Stock::OPEN, Gtk::ICON_SIZE_BUTTON)));
@@ -635,7 +678,7 @@ NewSessionDialog::treeview_selection_changed ()
void
NewSessionDialog::file_chosen ()
{
- if (on_new_session_page ()) return;
+ if (on_newable_page ()) return;
m_treeview->get_selection()->unselect_all();
diff --git a/gtk2_ardour/new_session_dialog.h b/gtk2_ardour/new_session_dialog.h
index 2a2081e56a..53ec3eabf2 100644
--- a/gtk2_ardour/new_session_dialog.h
+++ b/gtk2_ardour/new_session_dialog.h
@@ -38,6 +38,7 @@
#include <glibmm/refptr.h>
#include "ardour_dialog.h"
+#include "engine_dialog.h"
namespace Gtk {
class Entry;
@@ -54,8 +55,10 @@ class NewSessionDialog : public ArdourDialog
public:
NewSessionDialog();
+ ~NewSessionDialog ();
void set_session_name(const Glib::ustring& name);
+ void set_session_folder(const Glib::ustring& folder);
std::string session_name() const;
std::string session_folder() const;
@@ -82,14 +85,17 @@ public:
bool connect_outs_to_master() const;
bool connect_outs_to_physical() const ;
- bool on_new_session_page () const;
-
+ bool on_newable_page() const;
+ int get_current_page () const;
void set_current_page (int);
void reset_recent();
// reset everything to default values.
void reset();
+ EngineControl engine_control;
+ void set_have_engine (bool yn);
+
protected:
void reset_name();
@@ -173,6 +179,8 @@ protected:
RecentSessionModelColumns recent_columns;
Glib::RefPtr<Gtk::TreeStore> recent_model;
+ bool in_destructor;
+
void recent_session_selection_changed ();
void nsd_redisplay_recent_sessions();
void nsd_recent_session_row_activated (const Gtk::TreePath& path, Gtk::TreeViewColumn* col);
@@ -194,6 +202,7 @@ protected:
void master_bus_button_clicked ();
void monitor_bus_button_clicked ();
+ bool have_engine;
};
#endif // NEW_SESSION_DIALOG_H
diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc
index 513e46448e..e49b410668 100644
--- a/gtk2_ardour/option_editor.cc
+++ b/gtk2_ardour/option_editor.cc
@@ -27,7 +27,6 @@
#include <ardour/crossfade.h>
#include <midi++/manager.h>
#include <midi++/factory.h>
-#include <midi++/port_request.h>
#include <gtkmm2ext/stop_signal.h>
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/window_title.h>
@@ -43,6 +42,7 @@
#include "editing.h"
#include "option_editor.h"
#include "midi_port_dialog.h"
+#include "gui_thread.h"
#include "i18n.h"
@@ -56,7 +56,7 @@ using namespace std;
static vector<string> positional_sync_strings;
OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
- : Dialog ("options editor"),
+ : ArdourDialog ("options editor", false),
ui (uip),
editor (ed),
mixer (mixui),
@@ -64,24 +64,33 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
/* Paths */
path_table (11, 2),
- /* Fades */
+ /* misc */
short_xfade_adjustment (0, 1.0, 500.0, 5.0, 100.0),
short_xfade_slider (short_xfade_adjustment),
destructo_xfade_adjustment (1.0, 1.0, 500.0, 1.0, 100.0),
destructo_xfade_slider (destructo_xfade_adjustment),
+ history_depth (20, -1, 100, 1.0, 10.0),
+ saved_history_depth (20, 0, 100, 1.0, 10.0),
+ history_depth_spinner (history_depth),
+ saved_history_depth_spinner (saved_history_depth),
+ limit_history_button (_("Limit undo history")),
+ save_history_button (_("Save undo history")),
/* Sync */
smpte_offset_clock (X_("smpteoffset"), false, X_("SMPTEOffsetClock"), true, true),
smpte_offset_negative_button (_("SMPTE offset is negative")),
+ synced_timecode_button (_("Timecode source is sample-clock synced")),
/* MIDI */
+ midi_port_table (4, 11),
mmc_receive_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
mmc_receive_device_id_spinner (mmc_receive_device_id_adjustment),
mmc_send_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
mmc_send_device_id_spinner (mmc_send_device_id_adjustment),
+ add_midi_port_button (_("Add new MIDI port")),
/* Click */
@@ -105,13 +114,13 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
session = 0;
WindowTitle title(Glib::get_application_name());
- title += _("Options Editor");
+ title += _("Preferences");
set_title(title.get_string());
set_default_size (300, 300);
- set_wmclass (X_("ardour_option_editor"), "Ardour");
+ set_wmclass (X_("ardour_preferences"), "Ardour");
- set_name ("OptionsWindow");
+ set_name ("Preferences");
add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
VBox *vbox = get_vbox();
@@ -128,7 +137,7 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
setup_sync_options();
setup_path_options();
- setup_fade_options ();
+ setup_misc_options ();
setup_keyboard_options ();
setup_auditioner_editor ();
@@ -137,15 +146,16 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
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 (misc_packer, _("Misc")));
- if (!MIDI::Manager::instance()->get_midi_ports().empty()) {
- setup_midi_options ();
- notebook.pages().push_back (TabElem (midi_packer, _("MIDI")));
- }
+ setup_midi_options ();
+ notebook.pages().push_back (TabElem (midi_packer, _("MIDI")));
set_session (0);
show_all_children();
+
+ Config->map_parameters (mem_fun (*this, &OptionEditor::parameter_changed));
+ Config->ParameterChanged.connect (mem_fun (*this, &OptionEditor::parameter_changed));
}
void
@@ -182,27 +192,7 @@ OptionEditor::set_session (Session *s)
smpte_offset_negative_button.set_active (session->smpte_offset_negative());
- /* set up port assignments */
-
- std::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);
- }
- }
+ redisplay_midi_ports ();
setup_click_editor ();
connect_audition_editor ();
@@ -260,7 +250,7 @@ OptionEditor::add_session_paths ()
}
void
-OptionEditor::setup_fade_options ()
+OptionEditor::setup_misc_options ()
{
Gtk::HBox* hbox;
@@ -272,7 +262,7 @@ OptionEditor::setup_fade_options ()
hbox->set_spacing (10);
hbox->pack_start (*label, false, false);
hbox->pack_start (short_xfade_slider, true, true);
- fade_packer.pack_start (*hbox, false, false);
+ misc_packer.pack_start (*hbox, false, false);
short_xfade_adjustment.signal_value_changed().connect (mem_fun(*this, &OptionEditor::short_xfade_adjustment_changed));
@@ -284,16 +274,94 @@ OptionEditor::setup_fade_options ()
hbox->set_spacing (10);
hbox->pack_start (*label, false, false);
hbox->pack_start (destructo_xfade_slider, true, true);
- fade_packer.pack_start (*hbox, false, false);
+ misc_packer.pack_start (*hbox, false, false);
+
destructo_xfade_adjustment.signal_value_changed().connect (mem_fun(*this, &OptionEditor::destructo_xfade_adjustment_changed));
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (limit_history_button, false, false);
+ misc_packer.pack_start (*hbox, false, false);
+
+ label = manage (new Label (_("History depth (commands)")));
+ label->set_name ("OptionsLabel");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (*label, false, false);
+ hbox->pack_start (history_depth_spinner, false, false);
+ misc_packer.pack_start (*hbox, false, false);
+
+ history_depth.signal_value_changed().connect (mem_fun (*this, &OptionEditor::history_depth_changed));
+ saved_history_depth.signal_value_changed().connect (mem_fun (*this, &OptionEditor::saved_history_depth_changed));
+ save_history_button.signal_toggled().connect (mem_fun (*this, &OptionEditor::save_history_toggled));
+ limit_history_button.signal_toggled().connect (mem_fun (*this, &OptionEditor::limit_history_toggled));
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (save_history_button, false, false);
+ misc_packer.pack_start (*hbox, false, false);
+
+ label = manage (new Label (_("Saved history depth (commands)")));
+ label->set_name ("OptionsLabel");
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (5);
+ hbox->set_spacing (10);
+ hbox->pack_start (*label, false, false);
+ hbox->pack_start (saved_history_depth_spinner, false, false);
+ misc_packer.pack_start (*hbox, false, false);
+
short_xfade_slider.set_update_policy (UPDATE_DISCONTINUOUS);
destructo_xfade_slider.set_update_policy (UPDATE_DISCONTINUOUS);
destructo_xfade_adjustment.set_value (Config->get_destructive_xfade_msecs());
- fade_packer.show_all ();
+ misc_packer.show_all ();
+}
+
+void
+OptionEditor::limit_history_toggled ()
+{
+ bool x = limit_history_button.get_active();
+
+ if (!x) {
+ Config->set_history_depth (0);
+ history_depth_spinner.set_sensitive (false);
+ } else {
+ if (Config->get_history_depth() == 0) {
+ /* get back to a sane default */
+ Config->set_history_depth (20);
+ }
+ history_depth_spinner.set_sensitive (true);
+ }
+}
+
+void
+OptionEditor::save_history_toggled ()
+{
+ bool x = save_history_button.get_active();
+
+ if (x != Config->get_save_history()) {
+ Config->set_save_history (x);
+ saved_history_depth_spinner.set_sensitive (x);
+ }
+}
+
+void
+OptionEditor::history_depth_changed()
+{
+ Config->set_history_depth ((int32_t) floor (history_depth.get_value()));
+}
+
+void
+OptionEditor::saved_history_depth_changed()
+{
+ Config->set_saved_history_depth ((int32_t) floor (saved_history_depth.get_value()));
}
void
@@ -347,8 +415,10 @@ OptionEditor::setup_sync_options ()
hbox->pack_start (smpte_offset_negative_button, false, false);
sync_packer.pack_start (*hbox, false, false);
+ sync_packer.pack_start (synced_timecode_button, false, false);
smpte_offset_negative_button.signal_clicked().connect (mem_fun(*this, &OptionEditor::smpte_offset_negative_clicked));
+ synced_timecode_button.signal_toggled().connect (mem_fun(*this, &OptionEditor::synced_timecode_toggled));
}
void
@@ -360,6 +430,17 @@ OptionEditor::smpte_offset_negative_clicked ()
}
void
+OptionEditor::synced_timecode_toggled ()
+{
+ bool x;
+
+ if ((x = synced_timecode_button.get_active()) != Config->get_timecode_source_is_synced()) {
+ Config->set_timecode_source_is_synced (x);
+ Config->save_state();
+ }
+}
+
+void
OptionEditor::smpte_offset_chosen()
{
if (session) {
@@ -368,6 +449,7 @@ OptionEditor::smpte_offset_chosen()
}
}
+
void
OptionEditor::setup_midi_options ()
{
@@ -379,6 +461,9 @@ OptionEditor::setup_midi_options ()
redisplay_midi_ports ();
+ mmc_receive_device_id_adjustment.set_value (Config->get_mmc_receive_device_id());
+ mmc_send_device_id_adjustment.set_value (Config->get_mmc_send_device_id());
+
mmc_receive_device_id_adjustment.signal_value_changed().connect (mem_fun (*this, &OptionEditor::mmc_receive_device_id_adjusted));
mmc_send_device_id_adjustment.signal_value_changed().connect (mem_fun (*this, &OptionEditor::mmc_send_device_id_adjusted));
@@ -396,7 +481,9 @@ OptionEditor::setup_midi_options ()
label = (manage (new Label (_("Inbound MMC Device ID"))));
hbox->pack_start (mmc_receive_device_id_spinner, false, false);
hbox->pack_start (*label, false, false);
- midi_packer.pack_start (*hbox, false, false);
+ midi_packer.pack_start (*hbox, false, false);
+
+ mmc_receive_device_id_spinner.set_value(Config->get_mmc_receive_device_id ());
hbox = manage (new HBox);
hbox->set_border_width (6);
@@ -406,6 +493,8 @@ OptionEditor::setup_midi_options ()
hbox->pack_start (*label, false, false);
midi_packer.pack_start (*hbox, false, false);
+ mmc_send_device_id_spinner.set_value(Config->get_mmc_send_device_id ());
+
add_midi_port_button.signal_clicked().connect (mem_fun (*this, &OptionEditor::add_midi_port));
}
@@ -624,12 +713,15 @@ OptionEditor::add_midi_port ()
smod = "duplex";
}
- MIDI::PortRequest req (X_("ardour"),
- dialog.port_name.get_text(),
- smod,
- MIDI::PortFactory::default_port_type());
- if (MIDI::Manager::instance()->add_port (req) != 0) {
+ XMLNode node (X_("MIDI-port"));
+
+ node.add_property ("tag", dialog.port_name.get_text());
+ node.add_property ("device", X_("ardour")); // XXX this can't be right for all types
+ node.add_property ("type", MIDI::PortFactory::default_port_type());
+ node.add_property ("mode", smod);
+
+ if (MIDI::Manager::instance()->add_port (node) != 0) {
redisplay_midi_ports ();
}
}
@@ -696,23 +788,27 @@ OptionEditor::port_online_toggled (MIDI::Port* port, ToggleButton* tb)
{
bool wanted = tb->get_active();
- if (wanted != port->input()->offline()) {
- port->input()->set_offline (wanted);
- }
+ if (port->input()) {
+ if (wanted != port->input()->offline()) {
+ port->input()->set_offline (wanted);
+ }
+ }
}
void
OptionEditor::map_port_online (MIDI::Port* port, ToggleButton* tb)
{
bool bstate = tb->get_active ();
-
- if (bstate != port->input()->offline()) {
- if (port->input()->offline()) {
- tb->set_label (_("offline"));
- tb->set_active (false);
- } else {
- tb->set_label (_("online"));
- tb->set_active (true);
+
+ if (port->input()) {
+ if (bstate != port->input()->offline()) {
+ if (port->input()->offline()) {
+ tb->set_label (_("offline"));
+ tb->set_active (false);
+ } else {
+ tb->set_label (_("online"));
+ tb->set_active (true);
+ }
}
}
}
@@ -721,20 +817,14 @@ void
OptionEditor::mmc_receive_device_id_adjusted ()
{
uint8_t id = (uint8_t) mmc_receive_device_id_spinner.get_value();
-
- if (id != Config->get_mmc_receive_device_id()) {
- Config->set_mmc_receive_device_id (id);
- }
+ Config->set_mmc_receive_device_id (id);
}
void
OptionEditor::mmc_send_device_id_adjusted ()
{
uint8_t id = (uint8_t) mmc_send_device_id_spinner.get_value();
-
- if (id != Config->get_mmc_send_device_id()) {
- Config->set_mmc_send_device_id (id);
- }
+ Config->set_mmc_send_device_id (id);
}
void
@@ -742,8 +832,10 @@ OptionEditor::port_trace_in_toggled (MIDI::Port* port, ToggleButton* tb)
{
bool trace = tb->get_active();
- if (port->input()->tracing() != trace) {
- port->input()->trace (trace, &cerr, string (port->name()) + string (" input: "));
+ if (port->input()) {
+ if (port->input()->tracing() != trace) {
+ port->input()->trace (trace, &cerr, string (port->name()) + string (" input: "));
+ }
}
}
@@ -752,8 +844,10 @@ OptionEditor::port_trace_out_toggled (MIDI::Port* port, ToggleButton* tb)
{
bool trace = tb->get_active();
- if (port->output()->tracing() != trace) {
- port->output()->trace (trace, &cerr, string (port->name()) + string (" output: "));
+ if (port->output()) {
+ if (port->output()->tracing() != trace) {
+ port->output()->trace (trace, &cerr, string (port->name()) + string (" output: "));
+ }
}
}
@@ -784,10 +878,13 @@ OptionEditor::raid_path_changed ()
void
OptionEditor::click_browse_clicked ()
{
- SoundFileChooser sfdb (_("Choose Click"), session);
+ SoundFileChooser sfdb (*this, _("Choose Click"), session);
- int result = sfdb.run ();
+ sfdb.show_all ();
+ sfdb.present ();
+ int result = sfdb.run ();
+
if (result == Gtk::RESPONSE_OK) {
click_chosen(sfdb.get_filename());
}
@@ -803,7 +900,10 @@ OptionEditor::click_chosen (const string & path)
void
OptionEditor::click_emphasis_browse_clicked ()
{
- SoundFileChooser sfdb (_("Choose Click Emphasis"), session);
+ SoundFileChooser sfdb (*this, _("Choose Click Emphasis"), session);
+
+ sfdb.show_all ();
+ sfdb.present ();
int result = sfdb.run ();
@@ -1167,3 +1267,31 @@ OptionEditor::fixup_combo_size (Gtk::ComboBoxText& combo, vector<string>& string
set_size_request_to_display_given_text (combo, maxstring.c_str(), 10 + FUDGE, 10);
}
+void
+OptionEditor::parameter_changed (const char* parameter_name)
+{
+ ENSURE_GUI_THREAD (bind (mem_fun (*this, &OptionEditor::parameter_changed), parameter_name));
+
+#define PARAM_IS(x) (!strcmp (parameter_name, (x)))
+
+ if (PARAM_IS ("timecode-source-is-synced")) {
+ synced_timecode_button.set_active (Config->get_timecode_source_is_synced());
+ } else if (PARAM_IS ("history-depth")) {
+ int32_t depth = Config->get_history_depth();
+
+ history_depth.set_value (depth);
+ history_depth_spinner.set_sensitive (depth != 0);
+ limit_history_button.set_active (depth != 0);
+
+ } else if (PARAM_IS ("saved-history-depth")) {
+
+ saved_history_depth.set_value (Config->get_saved_history_depth());
+
+ } else if (PARAM_IS ("save-history")) {
+
+ bool x = Config->get_save_history();
+
+ save_history_button.set_active (x);
+ saved_history_depth_spinner.set_sensitive (x);
+ }
+}
diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h
index a234f1d752..82bb4db79b 100644
--- a/gtk2_ardour/option_editor.h
+++ b/gtk2_ardour/option_editor.h
@@ -45,7 +45,7 @@ class IOSelector;
class GainMeter;
class PannerUI;
-class OptionEditor : public Gtk::Dialog
+class OptionEditor : public ArdourDialog
{
public:
OptionEditor (ARDOUR_UI&, PublicEditor&, Mixer_UI&);
@@ -66,6 +66,7 @@ class OptionEditor : public Gtk::Dialog
gint wm_close (GdkEventAny *);
bool focus_out_event_handler (GdkEventFocus*, void (OptionEditor::*pmf)());
+ void parameter_changed (const char* name);
/* paths */
@@ -77,18 +78,32 @@ class OptionEditor : public Gtk::Dialog
void remove_session_paths ();
void raid_path_changed ();
- /* fades */
+ /* misc */
+
+ Gtk::VBox misc_packer;
- Gtk::VBox fade_packer;
Gtk::Adjustment short_xfade_adjustment;
Gtk::HScale short_xfade_slider;
Gtk::Adjustment destructo_xfade_adjustment;
Gtk::HScale destructo_xfade_slider;
- void setup_fade_options();
+ void setup_misc_options();
+
void short_xfade_adjustment_changed ();
void destructo_xfade_adjustment_changed ();
+ Gtk::Adjustment history_depth;
+ Gtk::Adjustment saved_history_depth;
+ Gtk::SpinButton history_depth_spinner;
+ Gtk::SpinButton saved_history_depth_spinner;
+ Gtk::CheckButton limit_history_button;
+ Gtk::CheckButton save_history_button;
+
+ void history_depth_changed();
+ void saved_history_depth_changed();
+ void save_history_toggled ();
+ void limit_history_toggled ();
+
/* Sync */
Gtk::VBox sync_packer;
@@ -96,11 +111,13 @@ class OptionEditor : public Gtk::Dialog
Gtk::ComboBoxText slave_type_combo;
AudioClock smpte_offset_clock;
Gtk::CheckButton smpte_offset_negative_button;
+ Gtk::CheckButton synced_timecode_button;
void setup_sync_options ();
void smpte_offset_chosen ();
void smpte_offset_negative_clicked ();
+ void synced_timecode_toggled ();
/* MIDI */
diff --git a/gtk2_ardour/opts.cc b/gtk2_ardour/opts.cc
index 608f684fc9..8da0fb9ca1 100644
--- a/gtk2_ardour/opts.cc
+++ b/gtk2_ardour/opts.cc
@@ -27,18 +27,19 @@
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 = true;
-string GTK_ARDOUR::keybindings_path = ""; /* empty means use builtin default */
-
-using namespace GTK_ARDOUR;
+string ARDOUR_COMMAND_LINE::session_name = "";
+string ARDOUR_COMMAND_LINE::jack_client_name = "ardour";
+bool ARDOUR_COMMAND_LINE::show_key_actions = false;
+bool ARDOUR_COMMAND_LINE::no_splash = true;
+bool ARDOUR_COMMAND_LINE::just_version = false;
+bool ARDOUR_COMMAND_LINE::use_vst = true;
+bool ARDOUR_COMMAND_LINE::new_session = false;
+char* ARDOUR_COMMAND_LINE::curvetest_file = 0;
+bool ARDOUR_COMMAND_LINE::try_hw_optimization = true;
+string ARDOUR_COMMAND_LINE::keybindings_path = ""; /* empty means use builtin default */
+Glib::ustring ARDOUR_COMMAND_LINE::menus_file = "ardour.menus";
+
+using namespace ARDOUR_COMMAND_LINE;
int
print_help (const char *execname)
@@ -49,9 +50,10 @@ print_help (const char *execname)
<< _(" -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")
+ << _(" -m, --menus file Use \"file\" for Ardour menus\n")
<< _(" -N, --new session-name Create a new session from the command line\n")
<< _(" -O, --no-hw-optimizations Disable h/w specific optimizations\n")
- << _(" -S, --sync Draw the gui synchronously \n")
+ << _(" -S, --sync Draw the gui synchronously \n")
#ifdef VST_SUPPORT
<< _(" -V, --novst Do not use VST support\n")
#endif
@@ -64,12 +66,16 @@ print_help (const char *execname)
}
int
-GTK_ARDOUR::parse_opts (int argc, char *argv[])
+ARDOUR_COMMAND_LINE::parse_opts (int argc, char *argv[])
{
- const char *optstring = "U:hSbvVnOc:C:N:k:";
+ const char *optstring = "U:hSbvVnOc:C:m:N:k:";
const char *execname = strrchr (argv[0], '/');
+ if (getenv ("ARDOUR_SAE")) {
+ menus_file = "ardour-sae.menus";
+ }
+
if (execname == 0) {
execname = argv[0];
} else {
@@ -81,11 +87,12 @@ GTK_ARDOUR::parse_opts (int argc, char *argv[])
{ "help", 0, 0, 'h' },
{ "bindings", 0, 0, 'b' },
{ "show-splash", 0, 0, 'n' },
+ { "menus", 1, 0, 'm' },
{ "name", 1, 0, 'c' },
{ "novst", 0, 0, 'V' },
{ "new", 1, 0, 'N' },
{ "no-hw-optimizations", 0, 0, 'O' },
- { "sync", 0, 0, 'O' },
+ { "sync", 0, 0, 'S' },
{ "curvetest", 1, 0, 'C' },
{ 0, 0, 0, 0 }
};
@@ -116,6 +123,11 @@ GTK_ARDOUR::parse_opts (int argc, char *argv[])
show_key_actions = true;
break;
+
+ case 'm':
+ menus_file = optarg;
+ break;
+
case 'n':
no_splash = false;
break;
@@ -133,6 +145,11 @@ GTK_ARDOUR::parse_opts (int argc, char *argv[])
try_hw_optimization = false;
break;
+
+ case 'p':
+ //undocumented OS X finder -psn_XXXXX argument
+ break;
+
case 'V':
#ifdef VST_SUPPORT
use_vst = false;
diff --git a/gtk2_ardour/opts.h b/gtk2_ardour/opts.h
index fb780fc8aa..c1b3f062d4 100644
--- a/gtk2_ardour/opts.h
+++ b/gtk2_ardour/opts.h
@@ -21,10 +21,11 @@
#define __ardour_opts_h__
#include <string>
+#include <glibmm/ustring.h>
using std::string;
-namespace GTK_ARDOUR {
+namespace ARDOUR_COMMAND_LINE {
extern string session_name;
extern bool show_key_actions;
@@ -37,6 +38,7 @@ extern char* curvetest_file;
extern bool try_hw_optimization;
extern bool use_gtk_theme;
extern string keybindings_path;
+extern Glib::ustring menus_file;
extern int32_t parse_opts (int argc, char *argv[]);
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index d093fda99f..12e30e59c0 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -338,7 +338,7 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev)
show_processor_menu(ev->time);
ret = true;
- } else if (processor && (ev->button == 2) && (ev->state == Gdk::BUTTON2_MASK)) {
+ } else if (processor && (ev->button == 2) && (Keyboard::no_modifier_keys_pressed (ev) && ((ev->state & Gdk::BUTTON2_MASK) == Gdk::BUTTON2_MASK))) {
processor->set_active (!processor->active());
ret = true;
@@ -394,13 +394,13 @@ ProcessorBox::processor_plugin_chosen (boost::shared_ptr<Plugin> plugin)
boost::shared_ptr<Processor> processor (new PluginInsert (_session, plugin, _placement));
- processor->ActiveChanged.connect (bind (mem_fun (*this, &ProcessorBox::show_processor_active), boost::weak_ptr<Processor>(processor)));
-
Route::ProcessorStreams err;
if (_route->add_processor (processor, &err)) {
weird_plugin_dialog (*plugin, err, _route);
// XXX SHAREDPTR delete plugin here .. do we even need to care?
+ } else {
+ processor->ActiveChanged.connect (bind (mem_fun (*this, &ProcessorBox::show_processor_active), boost::weak_ptr<Processor>(processor)));
}
}
}
@@ -482,36 +482,39 @@ ProcessorBox::choose_send ()
boost::shared_ptr<Send> send (new Send (_session, _placement));
//send->set_default_type(_route->default_type());
- /* XXX need redirect lock on route */
+ ChanCount outs;
+
+ /* make an educated guess at the initial number of outputs for the send */
+
+ if (_session.master_out()) {
+ outs = _session.master_out()->n_outputs();
+ } else {
+ outs = _route->n_outputs();
+ }
+
+ send->io()->ensure_io (ChanCount::ZERO, outs, false, this);
- // This will be set properly in route->add_processor
- send->configure_io (_route->max_processor_outs(), _route->max_processor_outs());
+ SendUIWindow* gui = new SendUIWindow (send, _session);
- IOSelectorWindow *ios = new IOSelectorWindow (_session, send->io(), false, true);
+ /* let the user adjust the output setup (number and connections) before passing
+ it along to the Route
+ */
- ios->show_all ();
+ gui->show_all ();
+ gui->present ();
- ios->selector().Finished.connect (bind (mem_fun(*this, &ProcessorBox::send_io_finished), send, ios));
+ /* pass shared_ptr, it will go out of scope when the GUI is deleted */
+ /* also, connect it *before* existing handlers so that its definitely executed */
+
+ gui->signal_delete_event().connect (bind (mem_fun(*this, &ProcessorBox::send_io_finished), send, gui), false);
}
-void
-ProcessorBox::send_io_finished (IOSelector::Result r, boost::shared_ptr<Send> send, IOSelectorWindow* ios)
+bool
+ProcessorBox::send_io_finished (GdkEventAny* ev, boost::shared_ptr<Send> send, SendUIWindow* sui)
{
- if (!send) {
- return;
- }
-
- switch (r) {
- case IOSelector::Cancelled:
- // send will go away when all shared_ptrs to it vanish
- break;
-
- case IOSelector::Accepted:
- _route->add_processor (send);
- break;
- }
-
- delete_when_idle (ios);
+ _route->add_processor (send);
+ delete sui;
+ return false;
}
void
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index 1ed0bcb39e..b6bb3ae3d7 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -50,6 +50,7 @@ class MotionController;
class PluginSelector;
class PluginUIWindow;
class RouteRedirectSelection;
+class SendUIWindow;
namespace ARDOUR {
class Bundle;
@@ -142,7 +143,7 @@ class ProcessorBox : public Gtk::HBox
void show_processor_menu (gint arg);
void choose_send ();
- void send_io_finished (IOSelector::Result, boost::shared_ptr<ARDOUR::Send>, IOSelectorWindow*);
+ bool send_io_finished (GdkEventAny*,boost::shared_ptr<ARDOUR::Send>, SendUIWindow*);
void choose_processor ();
void choose_plugin ();
void processor_plugin_chosen (boost::shared_ptr<ARDOUR::Plugin>);
diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc
index 7dda653894..c91068f97c 100644
--- a/gtk2_ardour/send_ui.cc
+++ b/gtk2_ardour/send_ui.cc
@@ -54,7 +54,7 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
_send->set_metering (true);
- _send->io()->output_changed.connect (mem_fun (*this, &SendUI::ins_changed));
+ _send->io()->input_changed.connect (mem_fun (*this, &SendUI::ins_changed));
_send->io()->output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
panners.set_width (Wide);
diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
index 5415cd70cb..67bedb6182 100644
--- a/gtk2_ardour/sfdb_ui.cc
+++ b/gtk2_ardour/sfdb_ui.cc
@@ -21,90 +21,181 @@
#include <cerrno>
#include <sstream>
+#include <unistd.h>
#include <sys/stat.h>
+#include <sys/param.h>
#include <gtkmm/box.h>
#include <gtkmm/stock.h>
+#include <glibmm/fileutils.h>
#include <pbd/convert.h>
#include <pbd/tokenizer.h>
+#include <pbd/enumwriter.h>
#include <gtkmm2ext/utils.h>
#include <ardour/audio_library.h>
+#include <ardour/auditioner.h>
#include <ardour/audioregion.h>
#include <ardour/audiofilesource.h>
#include <ardour/region_factory.h>
#include <ardour/source_factory.h>
+#include <ardour/session.h>
+#include <ardour/session_directory.h>
+#include <ardour/profile.h>
#include "ardour_ui.h"
#include "editing.h"
#include "gui_thread.h"
#include "prompter.h"
#include "sfdb_ui.h"
+#include "editing.h"
#include "utils.h"
+#include "gain_meter.h"
#include "i18n.h"
using namespace ARDOUR;
using namespace PBD;
using namespace std;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+using namespace Editing;
+
+using Glib::ustring;
-Glib::ustring SoundFileBrowser::persistent_folder;
+ustring SoundFileBrowser::persistent_folder;
-SoundFileBox::SoundFileBox ()
- :
- _session(0),
- current_pid(0),
- main_box (false, 3),
- bottom_box (true, 4),
- play_btn(_("Play")),
- stop_btn(_("Stop")),
- apply_btn(_("Apply"))
+static ImportMode
+string2importmode (string str)
{
- set_name (X_("SoundFileBox"));
+ if (str == "as new tracks") {
+ return ImportAsTrack;
+ } else if (str == "to selected tracks") {
+ return ImportToTrack;
+ } else if (str == "to region list") {
+ return ImportAsRegion;
+ } else if (str == "as new tape tracks") {
+ return ImportAsTapeTrack;
+ }
+
+ warning << string_compose (_("programming error: unknown import mode string %1"), str) << endmsg;
- set_size_request (250, 500);
+ return ImportAsTrack;
+}
+
+static string
+importmode2string (ImportMode mode)
+{
+ switch (mode) {
+ case ImportAsTrack:
+ return _("as new tracks");
+ case ImportToTrack:
+ return _("to selected tracks");
+ case ImportAsRegion:
+ return _("to region list");
+ case ImportAsTapeTrack:
+ return _("as new tape tracks");
+ }
+ /*NOTREACHED*/
+ return _("as new tracks");
+}
+
+SoundFileBox::SoundFileBox (bool persistent)
+ : _session(0),
+ table (6, 2),
+ length_clock ("sfboxLengthClock", !persistent, "EditCursorClock", false, true, false),
+ timecode_clock ("sfboxTimecodeClock", !persistent, "EditCursorClock", false, false, false),
+ main_box (false, 6),
+ autoplay_btn (_("Auto-play"))
- border_frame.set_label (_("Soundfile Info"));
+{
+ HBox* hbox;
+ VBox* vbox;
+
+ set_name (X_("SoundFileBox"));
+ set_size_request (300, -1);
+
+ preview_label.set_markup (_("<b>Soundfile Info</b>"));
+
+ border_frame.set_label_widget (preview_label);
border_frame.add (main_box);
- Gtk::Label* tag_label = manage(new Gtk::Label(_("comma seperated tags")));
+ pack_start (border_frame, true, true);
+ set_border_width (6);
- pack_start (border_frame);
- set_border_width (4);
+ main_box.set_border_width (6);
+ main_box.set_spacing (12);
- main_box.set_border_width (4);
+ length.set_text (_("Length:"));
+ timecode.set_text (_("Timestamp:"));
+ format.set_text (_("Format:"));
+ channels.set_text (_("Channels:"));
+ samplerate.set_text (_("Sample rate:"));
- 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);
- main_box.pack_start(timecode, false, false);
- main_box.pack_start(*tag_label, false, false);
- main_box.pack_start(tags_entry, false, false);
- main_box.pack_start(apply_btn, false, false);
- main_box.pack_start(bottom_box, false, false);
+ table.set_col_spacings (6);
+ table.set_homogeneous (false);
+ table.set_row_spacings (6);
+
+ table.attach (channels, 0, 1, 0, 1, FILL|EXPAND, (AttachOptions) 0);
+ table.attach (samplerate, 0, 1, 1, 2, FILL|EXPAND, (AttachOptions) 0);
+ table.attach (format, 0, 1, 2, 4, FILL|EXPAND, (AttachOptions) 0);
+ table.attach (length, 0, 1, 4, 5, FILL|EXPAND, (AttachOptions) 0);
+ table.attach (timecode, 0, 1, 5, 6, FILL|EXPAND, (AttachOptions) 0);
+
+ table.attach (channels_value, 1, 2, 0, 1, FILL, (AttachOptions) 0);
+ table.attach (samplerate_value, 1, 2, 1, 2, FILL, (AttachOptions) 0);
+ table.attach (format_text, 1, 2, 2, 4, FILL, AttachOptions (0));
+ table.attach (length_clock, 1, 2, 4, 5, FILL, (AttachOptions) 0);
+ table.attach (timecode_clock, 1, 2, 5, 6, FILL, (AttachOptions) 0);
+
+ length_clock.set_mode (ARDOUR_UI::instance()->secondary_clock.mode());
+ timecode_clock.set_mode (AudioClock::SMPTE);
+
+ hbox = manage (new HBox);
+ hbox->pack_start (table, false, false);
+ main_box.pack_start (*hbox, false, false);
- bottom_box.set_homogeneous(true);
- bottom_box.pack_start(play_btn);
- bottom_box.pack_start(stop_btn);
+ tags_entry.set_editable (true);
+ tags_entry.signal_focus_out_event().connect (mem_fun (*this, &SoundFileBox::tags_entry_left));
+ hbox = manage (new HBox);
+ hbox->pack_start (tags_entry, true, true);
- play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::play_btn_clicked));
- stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_btn_clicked));
- apply_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::apply_btn_clicked));
- tags_entry.signal_activate().connect (mem_fun (*this, &SoundFileBox::apply_btn_clicked));
+ vbox = manage (new VBox);
- length.set_alignment (0.0f, 0.0f);
- format.set_alignment (0.0f, 0.0f);
- channels.set_alignment (0.0f, 0.0f);
- samplerate.set_alignment (0.0f, 0.0f);
- timecode.set_alignment (0.0f, 0.0f);
+ Label* label = manage (new Label (_("Tags:")));
+ label->set_alignment (0.0f, 0.5f);
+ vbox->set_spacing (6);
+ vbox->pack_start(*label, false, false);
+ vbox->pack_start(*hbox, true, true);
- stop_btn.set_no_show_all (true);
- stop_btn.hide();
+ main_box.pack_start(*vbox, true, true);
+ main_box.pack_start(bottom_box, false, false);
+
+ play_btn.set_image (*(manage (new Image (Stock::MEDIA_PLAY, ICON_SIZE_BUTTON))));
+ play_btn.set_label (_("Play (double click)"));
+
+ stop_btn.set_image (*(manage (new Image (Stock::MEDIA_STOP, ICON_SIZE_BUTTON))));
+ stop_btn.set_label (_("Stop"));
- show_all();
+ bottom_box.set_homogeneous (false);
+ bottom_box.set_spacing (6);
+ bottom_box.pack_start(play_btn, true, true);
+ bottom_box.pack_start(stop_btn, true, true);
+ bottom_box.pack_start(autoplay_btn, false, false);
+
+ play_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::audition));
+ stop_btn.signal_clicked().connect (mem_fun (*this, &SoundFileBox::stop_audition));
+
+ length.set_alignment (0.0f, 0.5f);
+ format.set_alignment (0.0f, 0.5f);
+ channels.set_alignment (0.0f, 0.5f);
+ samplerate.set_alignment (0.0f, 0.5f);
+ timecode.set_alignment (0.0f, 0.5f);
+
+ channels_value.set_alignment (0.0f, 0.5f);
+ samplerate_value.set_alignment (0.0f, 0.5f);
}
void
@@ -113,41 +204,66 @@ SoundFileBox::set_session(Session* s)
_session = s;
if (!_session) {
- play_btn.set_sensitive(false);
- } else {
- _session->AuditionActive.connect(mem_fun (*this, &SoundFileBox::audition_status_changed));
- }
+ play_btn.set_sensitive (false);
+ stop_btn.set_sensitive (false);
+ }
+
+
+ length_clock.set_session (s);
+ timecode_clock.set_session (s);
}
bool
-SoundFileBox::setup_labels (string filename)
+SoundFileBox::setup_labels (const ustring& filename)
{
+ if (!path.empty()) {
+ // save existing tags
+ tags_changed ();
+ }
+
path = filename;
string error_msg;
if(!AudioFileSource::get_soundfile_info (filename, sf_info, error_msg)) {
- length.set_text (_("Length: n/a"));
- format.set_text (_("Format: n/a"));
- channels.set_text (_("Channels: n/a"));
- samplerate.set_text (_("Samplerate: n/a"));
- timecode.set_text (_("Timecode: n/a"));
- tags_entry.set_text ("");
+
+ preview_label.set_markup (_("<b>Soundfile Info</b>"));
+ format_text.set_text (_("n/a"));
+ channels_value.set_text (_("n/a"));
+ samplerate_value.set_text (_("n/a"));
+ tags_entry.get_buffer()->set_text ("");
+
+ length_clock.set (0);
+ timecode_clock.set (0);
tags_entry.set_sensitive (false);
play_btn.set_sensitive (false);
- apply_btn.set_sensitive (false);
return false;
}
- length.set_text (string_compose(_("Length: %1"), length2string(sf_info.length, sf_info.samplerate)));
- format.set_text (sf_info.format_name);
- channels.set_text (string_compose(_("Channels: %1"), sf_info.channels));
- samplerate.set_text (string_compose(_("Samplerate: %1"), sf_info.samplerate));
- timecode.set_text (string_compose (_("Timecode: %1"), length2string(sf_info.timecode, sf_info.samplerate)));
+ preview_label.set_markup (string_compose ("<b>%1</b>", Glib::path_get_basename (filename)));
+ format_text.set_text (sf_info.format_name);
+ channels_value.set_text (to_string (sf_info.channels, std::dec));
+
+ if (_session && sf_info.samplerate != _session->frame_rate()) {
+ samplerate.set_markup (string_compose ("<b>%1</b>", _("Sample rate:")));
+ samplerate_value.set_markup (string_compose (X_("<b>%1 Hz</b>"), sf_info.samplerate));
+ samplerate_value.set_name ("NewSessionSR1Label");
+ samplerate.set_name ("NewSessionSR1Label");
+ } else {
+ samplerate.set_text (_("Sample rate:"));
+ samplerate_value.set_text (string_compose (X_("%1 Hz"), sf_info.samplerate));
+ samplerate_value.set_name ("NewSessionSR2Label");
+ samplerate.set_name ("NewSessionSR2Label");
+ }
+
+ length_clock.set (sf_info.length, true);
+ timecode_clock.set (sf_info.timecode, true);
+
+ // this is a hack that is fixed in trunk, i think (august 26th, 2007)
- vector<string> tags = Library->get_tags (filename);
+ vector<string> tags = Library->get_tags (string ("//") + filename);
stringstream tag_string;
for (vector<string>::iterator i = tags.begin(); i != tags.end(); ++i) {
@@ -156,158 +272,164 @@ SoundFileBox::setup_labels (string filename)
}
tag_string << *i;
}
- tags_entry.set_text (tag_string.str());
+ tags_entry.get_buffer()->set_text (tag_string.str());
tags_entry.set_sensitive (true);
if (_session) {
play_btn.set_sensitive (true);
}
- apply_btn.set_sensitive (true);
return true;
}
bool
-SoundFileBox::tags_entry_left (GdkEventFocus* event)
-{
- apply_btn_clicked ();
-
- return true;
+SoundFileBox::autoplay() const
+{
+ return autoplay_btn.get_active();
+}
+
+bool
+SoundFileBox::audition_oneshot()
+{
+ audition ();
+ return false;
}
void
-SoundFileBox::play_btn_clicked ()
+SoundFileBox::audition ()
{
if (!_session) {
return;
}
-
+
_session->cancel_audition();
- if (access(path.c_str(), R_OK)) {
+ if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
warning << string_compose(_("Could not read file: %1 (%2)."), path, strerror(errno)) << endmsg;
return;
}
- typedef std::map<string, boost::shared_ptr<AudioRegion> > RegionCache;
- static RegionCache region_cache;
- RegionCache::iterator the_region;
+ boost::shared_ptr<Region> r;
+ SourceList srclist;
+ boost::shared_ptr<AudioFileSource> afs;
+ bool old_sbp = AudioSource::get_build_peakfiles ();
- if ((the_region = region_cache.find (path)) == region_cache.end()) {
- SourceList srclist;
- boost::shared_ptr<AudioFileSource> afs;
-
- for (int n = 0; n < sf_info.channels; ++n) {
- try {
- afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path, n, AudioFileSource::Flag (0)));
- srclist.push_back(afs);
-
- } catch (failed_constructor& err) {
- error << _("Could not access soundfile: ") << path << endmsg;
- return;
- }
- }
+ /* don't even think of building peakfiles for these files */
+
+ AudioSource::set_build_peakfiles (false);
- if (srclist.empty()) {
+ for (int n = 0; n < sf_info.channels; ++n) {
+ try {
+ afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path,
+ n, AudioFileSource::Flag (0), false));
+
+ srclist.push_back(afs);
+
+ } catch (failed_constructor& err) {
+ error << _("Could not access soundfile: ") << path << endmsg;
+ AudioSource::set_build_peakfiles (old_sbp);
return;
}
-
- string rname;
-
- _session->region_name (rname, Glib::path_get_basename(srclist[0]->name()), false);
-
- pair<string,boost::shared_ptr<AudioRegion> > newpair;
- pair<RegionCache::iterator,bool> res;
-
- newpair.first = path;
- newpair.second = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
-
- res = region_cache.insert (newpair);
- the_region = res.first;
}
- play_btn.hide();
- stop_btn.show();
-
- boost::shared_ptr<Region> r = boost::static_pointer_cast<Region> (the_region->second);
+ AudioSource::set_build_peakfiles (old_sbp);
+
+ if (srclist.empty()) {
+ return;
+ }
+
+ afs = boost::dynamic_pointer_cast<AudioFileSource> (srclist[0]);
+ string rname = region_name_from_path (afs->path(), false);
+ r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, 0, srclist[0]->length(), rname, 0, Region::DefaultFlags, false));
_session->audition_region(r);
}
void
-SoundFileBox::stop_btn_clicked ()
+SoundFileBox::stop_audition ()
{
if (_session) {
_session->cancel_audition();
- play_btn.show();
- stop_btn.hide();
}
}
+bool
+SoundFileBox::tags_entry_left (GdkEventFocus *ev)
+{
+ tags_changed ();
+ return false;
+}
+
void
-SoundFileBox::apply_btn_clicked ()
+SoundFileBox::tags_changed ()
{
- string tag_string = tags_entry.get_text ();
+ string tag_string = tags_entry.get_buffer()->get_text ();
+
+ if (tag_string.empty()) {
+ return;
+ }
vector<string> tags;
- if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
+ if (!PBD::tokenize (tag_string, string(",\n"), std::back_inserter (tags), true)) {
warning << _("SoundFileBox: Could not tokenize string: ") << tag_string << endmsg;
return;
}
-
- Library->set_tags (path, tags);
- Library->save_changes ();
+
+ save_tags (tags);
}
void
-SoundFileBox::audition_status_changed (bool active)
+SoundFileBox::save_tags (const vector<string>& tags)
{
- ENSURE_GUI_THREAD(bind (mem_fun (*this, &SoundFileBox::audition_status_changed), active));
-
- if (!active) {
- stop_btn_clicked ();
- }
+ Library->set_tags (string ("//") + path, tags);
+ Library->save_changes ();
}
-// this needs to be kept in sync with the ImportMode enum defined in editing.h and editing_syms.h.
-static const char *import_mode_strings[] = {
- N_("Add to Region list"),
- N_("Add to selected Track(s)"),
- N_("Add as new Track(s)"),
- N_("Add as new Tape Track(s)"),
- 0
-};
-
-SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
- : ArdourDialog (title, false),
- chooser (Gtk::FILE_CHOOSER_ACTION_OPEN),
- found_list (Gtk::ListStore::create(found_list_columns)),
+SoundFileBrowser::SoundFileBrowser (Gtk::Window& parent, string title, ARDOUR::Session* s, bool persistent)
+ : ArdourDialog (parent, title, false, false),
+ found_list (ListStore::create(found_list_columns)),
+ chooser (FILE_CHOOSER_ACTION_OPEN),
found_list_view (found_list),
+ preview (persistent),
found_search_btn (_("Search"))
+
{
- set_default_size (700, 500);
- Gtk::HBox* hbox = manage(new Gtk::HBox);
- hbox->pack_start(notebook);
- hbox->pack_start(preview, Gtk::PACK_SHRINK);
- get_vbox()->pack_start(*hbox);
+ VBox* vbox;
+ HBox* hbox;
+
+ gm = 0;
+
+ set_session (s);
+ resetting_ourselves = false;
+
+ hpacker.set_spacing (6);
+ hpacker.pack_start (notebook, true, true);
+ hpacker.pack_start (preview, false, false);
+
+ get_vbox()->pack_start (hpacker, true, true);
- hbox = manage(new Gtk::HBox);
+ hbox = manage(new HBox);
hbox->pack_start (found_entry);
hbox->pack_start (found_search_btn);
- Gtk::VBox* vbox = manage(new Gtk::VBox);
- vbox->pack_start (*hbox, Gtk::PACK_SHRINK);
+ vbox = manage(new VBox);
+ vbox->pack_start (*hbox, PACK_SHRINK);
vbox->pack_start (found_list_view);
found_list_view.append_column(_("Paths"), found_list_columns.pathname);
- notebook.append_page (chooser, _("Files"));
- notebook.append_page (*vbox, _("Tags"));
+ chooser.set_border_width (12);
+
+ notebook.append_page (chooser, _("Browse Files"));
+ notebook.append_page (*vbox, _("Search Tags"));
- found_list_view.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
+ notebook.set_size_request (500, -1);
- custom_filter.add_custom (Gtk::FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_custom));
- custom_filter.set_name (_("Probable audio files"));
+ found_list_view.get_selection()->set_mode (SELECTION_MULTIPLE);
+ found_list_view.signal_row_activated().connect (mem_fun (*this, &SoundFileBrowser::found_list_view_activated));
+
+ custom_filter.add_custom (FILE_FILTER_FILENAME, mem_fun(*this, &SoundFileBrowser::on_custom));
+ custom_filter.set_name (_("Audio files"));
matchall_filter.add_pattern ("*.*");
matchall_filter.set_name (_("All files"));
@@ -316,6 +438,7 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
chooser.add_filter (matchall_filter);
chooser.set_select_multiple (true);
chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
+ chooser.signal_file_activated().connect (mem_fun (*this, &SoundFileBrowser::chooser_file_activated));
if (!persistent_folder.empty()) {
chooser.set_current_folder (persistent_folder);
@@ -325,10 +448,11 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
found_entry.signal_activate().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
+
+ add_button (Stock::CANCEL, RESPONSE_CANCEL);
+ add_button (Stock::APPLY, RESPONSE_APPLY);
+ add_button (Stock::OK, RESPONSE_OK);
- show_all ();
-
- set_session (s);
}
SoundFileBrowser::~SoundFileBrowser ()
@@ -336,37 +460,129 @@ SoundFileBrowser::~SoundFileBrowser ()
persistent_folder = chooser.get_current_folder();
}
+
+void
+SoundFileBrowser::on_show ()
+{
+ ArdourDialog::on_show ();
+ start_metering ();
+}
+
+void
+SoundFileBrowser::clear_selection ()
+{
+ chooser.unselect_all ();
+ found_list_view.get_selection()->unselect_all ();
+}
+
+void
+SoundFileBrowser::chooser_file_activated ()
+{
+ preview.audition ();
+}
+
+void
+SoundFileBrowser::found_list_view_activated (const TreeModel::Path& path, TreeViewColumn* col)
+{
+ preview.audition ();
+}
+
void
SoundFileBrowser::set_session (Session* s)
{
- preview.set_session(s);
+ ArdourDialog::set_session (s);
+ preview.set_session (s);
+ if (s) {
+ add_gain_meter ();
+ } else {
+ remove_gain_meter ();
+ }
+}
+
+void
+SoundFileBrowser::add_gain_meter ()
+{
+ if (gm) {
+ delete gm;
+ }
+
+ gm = new GainMeter (session->the_auditioner(), *session);
+
+ meter_packer.set_border_width (12);
+ meter_packer.pack_start (*gm, false, true);
+ hpacker.pack_end (meter_packer, false, false);
+ meter_packer.show_all ();
+ start_metering ();
+}
+
+void
+SoundFileBrowser::remove_gain_meter ()
+{
+ if (gm) {
+ meter_packer.remove (*gm);
+ hpacker.remove (meter_packer);
+ delete gm;
+ gm = 0;
+ }
+}
+
+void
+SoundFileBrowser::start_metering ()
+{
+ metering_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun(*this, &SoundFileBrowser::meter));
+}
+
+void
+SoundFileBrowser::stop_metering ()
+{
+ metering_connection.disconnect();
+}
+
+void
+SoundFileBrowser::meter ()
+{
+ if (is_mapped () && session && gm) {
+ gm->update_meters ();
+ }
}
bool
-SoundFileBrowser::on_custom (const Gtk::FileFilter::Info& filter_info)
+SoundFileBrowser::on_custom (const FileFilter::Info& filter_info)
{
- return AudioFileSource::safe_file_extension(filter_info.filename);
+ return AudioFileSource::safe_file_extension (filter_info.filename);
}
void
SoundFileBrowser::update_preview ()
{
- preview.setup_labels(chooser.get_filename());
+ preview.setup_labels (chooser.get_filename());
+
+ if (preview.autoplay()) {
+ Glib::signal_idle().connect (mem_fun (preview, &SoundFileBox::audition_oneshot));
+ }
}
void
SoundFileBrowser::found_list_view_selected ()
{
- string file;
-
- Gtk::TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
-
- if (!rows.empty()) {
- Gtk::TreeIter iter = found_list->get_iter(*rows.begin());
- file = (*iter)[found_list_columns.pathname];
- chooser.set_filename (file);
+ if (!reset_options ()) {
+ set_response_sensitive (RESPONSE_OK, false);
+ } else {
+ ustring file;
+
+ TreeView::Selection::ListHandle_Path rows = found_list_view.get_selection()->get_selected_rows ();
+
+ if (!rows.empty()) {
+ TreeIter iter = found_list->get_iter(*rows.begin());
+ file = (*iter)[found_list_columns.pathname];
+ chooser.set_filename (file);
+ set_response_sensitive (RESPONSE_OK, true);
+ } else {
+ set_response_sensitive (RESPONSE_OK, false);
+ }
+
+ preview.setup_labels (file);
}
- preview.setup_labels (file);
}
void
@@ -376,194 +592,608 @@ SoundFileBrowser::found_search_clicked ()
vector<string> tags;
- if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
+ if (!PBD::tokenize (tag_string, string(","), std::back_inserter (tags), true)) {
warning << _("SoundFileBrowser: Could not tokenize string: ") << tag_string << endmsg;
return;
}
-
+
vector<string> results;
Library->search_members_and (results, tags);
found_list->clear();
for (vector<string>::iterator i = results.begin(); i != results.end(); ++i) {
- Gtk::TreeModel::iterator new_row = found_list->append();
- Gtk::TreeModel::Row row = *new_row;
- row[found_list_columns.pathname] = *i;
+ TreeModel::iterator new_row = found_list->append();
+ TreeModel::Row row = *new_row;
+ string path = Glib::filename_from_uri (string ("file:") + *i);
+ row[found_list_columns.pathname] = path;
}
}
-SoundFileChooser::SoundFileChooser (string title, ARDOUR::Session* s)
- :
- SoundFileBrowser(title, s)
+vector<ustring>
+SoundFileBrowser::get_paths ()
{
- add_button (Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
- add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ vector<ustring> results;
- chooser.set_select_multiple (false);
- found_list_view.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
- show_all ();
+ int n = notebook.get_current_page ();
+
+ if (n == 0) {
+ vector<ustring> filenames = chooser.get_filenames();
+ vector<ustring>::iterator i;
+
+ for (i = filenames.begin(); i != filenames.end(); ++i) {
+ struct stat buf;
+ if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
+ results.push_back (*i);
+ }
+ }
+
+ } else {
+
+ typedef TreeView::Selection::ListHandle_Path ListPath;
+
+ ListPath rows = found_list_view.get_selection()->get_selected_rows ();
+ for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
+ TreeIter iter = found_list->get_iter(*i);
+ ustring str = (*iter)[found_list_columns.pathname];
+
+ results.push_back (str);
+ }
+ }
+
+ return results;
}
-string
-SoundFileChooser::get_filename ()
+void
+SoundFileOmega::reset_options_noret ()
{
- Gtk::TreeModel::iterator iter;
- Gtk::TreeModel::Row row;
-
- string filename;
- switch (notebook.get_current_page()) {
- case 0:
- filename = chooser.get_filename();
- case 1:
- iter = found_list_view.get_selection()->get_selected();
- row = *iter;
- filename = row[found_list_columns.pathname];
- default:
- /* NOT REACHED */
- return "";
+ if (!resetting_ourselves) {
+ (void) reset_options ();
}
-
- struct stat buf;
- if (stat (filename.c_str(), &buf) || !S_ISREG(buf.st_mode)) {
- return "";
- }
-
- return filename;
}
-vector<string> SoundFileOmega::mode_strings;
-
-SoundFileOmega::SoundFileOmega (string title, ARDOUR::Session* s)
- : SoundFileBrowser (title, s),
- split_check (_("Split Channels"))
+bool
+SoundFileOmega::reset_options ()
{
- ARDOUR_UI::instance()->tooltips().set_tip(split_check,
- _("Create a region for each channel"));
+ vector<ustring> paths = get_paths ();
- Gtk::Button* btn = add_button (_("Embed"), ResponseEmbed);
- ARDOUR_UI::instance()->tooltips().set_tip(*btn,
- _("Link to an external file"));
+ if (paths.empty()) {
- btn = add_button (_("Import"), ResponseImport);
- ARDOUR_UI::instance()->tooltips().set_tip(*btn,
- _("Copy a file to the session folder"));
+ channel_combo.set_sensitive (false);
+ action_combo.set_sensitive (false);
+ where_combo.set_sensitive (false);
+ copy_files_btn.set_sensitive (false);
- add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
+ return false;
+
+ } else {
+
+ channel_combo.set_sensitive (true);
+ action_combo.set_sensitive (true);
+ where_combo.set_sensitive (true);
+
+ /* if we get through this function successfully, this may be
+ reset at the end, once we know if we can use hard links
+ to do embedding
+ */
+
+ if (Config->get_only_copy_imported_files()) {
+ copy_files_btn.set_sensitive (false);
+ } else {
+ copy_files_btn.set_sensitive (false);
+ }
+ }
+
+ bool same_size;
+ bool src_needed;
+ bool selection_includes_multichannel;
+ bool selection_can_be_embedded_with_links = check_link_status (*session, paths);
+ ImportMode mode;
+
+ if (check_info (paths, same_size, src_needed, selection_includes_multichannel)) {
+ Glib::signal_idle().connect (mem_fun (*this, &SoundFileOmega::bad_file_message));
+ return false;
+ }
+
+ ustring existing_choice;
+ vector<string> action_strings;
+
+ if (selected_track_cnt > 0) {
+ if (channel_combo.get_active_text().length()) {
+ ImportDisposition id = get_channel_disposition();
+
+ switch (id) {
+ case Editing::ImportDistinctFiles:
+ if (selected_track_cnt == paths.size()) {
+ action_strings.push_back (importmode2string (ImportToTrack));
+ }
+ break;
+
+ case Editing::ImportDistinctChannels:
+ /* XXX it would be nice to allow channel-per-selected track
+ but its too hard we don't want to deal with all the
+ different per-file + per-track channel configurations.
+ */
+ break;
+
+ default:
+ action_strings.push_back (importmode2string (ImportToTrack));
+ break;
+ }
+ }
+ }
+
+ action_strings.push_back (importmode2string (ImportAsTrack));
+ action_strings.push_back (importmode2string (ImportAsRegion));
+ action_strings.push_back (importmode2string (ImportAsTapeTrack));
+
+ resetting_ourselves = true;
+
+ existing_choice = action_combo.get_active_text();
+
+ set_popdown_strings (action_combo, action_strings);
+
+ /* preserve any existing choice, if possible */
+
+
+ if (existing_choice.length()) {
+ vector<string>::iterator x;
+ for (x = action_strings.begin(); x != action_strings.end(); ++x) {
+ if (*x == existing_choice) {
+ action_combo.set_active_text (existing_choice);
+ break;
+ }
+ }
+ if (x == action_strings.end()) {
+ action_combo.set_active_text (action_strings.front());
+ }
+ } else {
+ action_combo.set_active_text (action_strings.front());
+ }
+
+ resetting_ourselves = false;
+
+ if ((mode = get_mode()) == ImportAsRegion) {
+ where_combo.set_sensitive (false);
+ } else {
+ where_combo.set_sensitive (true);
+ }
+
+ vector<string> channel_strings;
- if (mode_strings.empty()) {
- mode_strings = I18N (import_mode_strings);
+ if (mode == ImportAsTrack || mode == ImportAsTapeTrack || mode == ImportToTrack) {
+ channel_strings.push_back (_("one track per file"));
+
+ if (selection_includes_multichannel) {
+ channel_strings.push_back (_("one track per channel"));
+ }
+
+ if (paths.size() > 1) {
+ /* tape tracks are a single region per track, so we cannot
+ sequence multiple files.
+ */
+ if (mode != ImportAsTapeTrack) {
+ channel_strings.push_back (_("sequence files"));
+ }
+ if (same_size) {
+ channel_strings.push_back (_("all files in one region"));
+ }
+
+ }
+
+ } else {
+ channel_strings.push_back (_("one region per file"));
+
+ if (selection_includes_multichannel) {
+ channel_strings.push_back (_("one region per channel"));
+ }
+
+ if (paths.size() > 1) {
+ if (same_size) {
+ channel_strings.push_back (_("all files in one region"));
+ }
+ }
+ }
+
+ existing_choice = channel_combo.get_active_text();
+
+ set_popdown_strings (channel_combo, channel_strings);
+
+ /* preserve any existing choice, if possible */
+
+ if (existing_choice.length()) {
+ vector<string>::iterator x;
+ for (x = channel_strings.begin(); x != channel_strings.end(); ++x) {
+ if (*x == existing_choice) {
+ channel_combo.set_active_text (existing_choice);
+ break;
+ }
+ }
+ if (x == channel_strings.end()) {
+ channel_combo.set_active_text (channel_strings.front());
+ }
+ } else {
+ channel_combo.set_active_text (channel_strings.front());
}
- Gtkmm2ext::set_popdown_strings (mode_combo, mode_strings);
- set_mode (Editing::ImportAsRegion);
+ if (src_needed) {
+ src_combo.set_sensitive (true);
+ } else {
+ src_combo.set_sensitive (false);
+ }
+
+ if (Config->get_only_copy_imported_files()) {
- get_action_area()->pack_start (split_check);
- get_action_area()->pack_start (mode_combo);
+ if (selection_can_be_embedded_with_links) {
+ copy_files_btn.set_sensitive (true);
+ } else {
+ copy_files_btn.set_sensitive (false);
+ }
- mode_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::mode_changed));
+ } else {
+
+ copy_files_btn.set_sensitive (true);
+ }
- show_all ();
+ return true;
+}
+
+
+bool
+SoundFileOmega::bad_file_message()
+{
+ MessageDialog msg (*this,
+ _("One or more of the selected files\ncannot be used by Ardour"),
+ true,
+ Gtk::MESSAGE_INFO,
+ Gtk::BUTTONS_OK);
+ msg.run ();
+ resetting_ourselves = true;
+ chooser.unselect_uri (chooser.get_preview_uri());
+ resetting_ourselves = false;
+
+ return false;
}
bool
-SoundFileOmega::get_split ()
+SoundFileOmega::check_info (const vector<ustring>& paths, bool& same_size, bool& src_needed, bool& multichannel)
{
- return split_check.get_active();
+ SNDFILE* sf;
+ SF_INFO info;
+ nframes64_t sz = 0;
+ bool err = false;
+
+ same_size = true;
+ src_needed = false;
+ multichannel = false;
+
+ for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+
+ info.format = 0; // libsndfile says to clear this before sf_open().
+
+ if ((sf = sf_open ((char*) (*i).c_str(), SFM_READ, &info)) != 0) {
+ sf_close (sf);
+
+ if (info.channels > 1) {
+ multichannel = true;
+ }
+
+ if (sz == 0) {
+ sz = info.frames;
+ } else {
+ if (sz != info.frames) {
+ same_size = false;
+ }
+ }
+
+ if ((nframes_t) info.samplerate != session->frame_rate()) {
+ src_needed = true;
+ }
+
+ } else {
+ err = true;
+ }
+ }
+
+ return err;
}
-vector<Glib::ustring>
-SoundFileOmega::get_paths ()
+
+bool
+SoundFileOmega::check_link_status (const Session& s, const vector<ustring>& paths)
{
- vector<Glib::ustring> results;
-
- int n = notebook.get_current_page ();
+ sys::path path = s.session_directory().sound_path() / "linktest";
+ string tmpdir = path.to_string();
+ bool ret = false;
+
+ if (mkdir (tmpdir.c_str(), 0744)) {
+ if (errno != EEXIST) {
+ return false;
+ }
+ }
- if (n == 0) {
- vector<Glib::ustring> filenames = chooser.get_filenames();
- vector<Glib::ustring>::iterator i;
- for (i = filenames.begin(); i != filenames.end(); ++i) {
- struct stat buf;
- if ((!stat((*i).c_str(), &buf)) && S_ISREG(buf.st_mode)) {
- results.push_back (*i);
- }
+ for (vector<ustring>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+
+ char tmpc[MAXPATHLEN+1];
+
+ snprintf (tmpc, sizeof(tmpc), "%s/%s", tmpdir.c_str(), Glib::path_get_basename (*i).c_str());
+
+ /* can we link ? */
+
+ if (link ((*i).c_str(), tmpc)) {
+ goto out;
}
- return results;
-
- } else {
- typedef Gtk::TreeView::Selection::ListHandle_Path ListPath;
-
- ListPath rows = found_list_view.get_selection()->get_selected_rows ();
- for (ListPath::iterator i = rows.begin() ; i != rows.end(); ++i) {
- Gtk::TreeIter iter = found_list->get_iter(*i);
- string str = (*iter)[found_list_columns.pathname];
-
- results.push_back (str);
- }
- return results;
+ unlink (tmpc);
}
+
+ ret = true;
+
+ out:
+ rmdir (tmpdir.c_str());
+ return ret;
+}
+
+SoundFileChooser::SoundFileChooser (Gtk::Window& parent, string title, ARDOUR::Session* s)
+ : SoundFileBrowser (parent, title, s, false)
+{
+ set_size_request (780, 300);
+ chooser.set_select_multiple (false);
+ found_list_view.get_selection()->set_mode (SELECTION_SINGLE);
}
void
-SoundFileOmega::set_mode (Editing::ImportMode mode)
+SoundFileChooser::on_hide ()
{
- mode_combo.set_active_text (mode_strings[(int)mode]);
+ ArdourDialog::on_hide();
+ stop_metering ();
- switch (mode) {
- case Editing::ImportAsRegion:
- split_check.set_sensitive (true);
- break;
- case Editing::ImportAsTrack:
- split_check.set_sensitive (true);
- break;
- case Editing::ImportToTrack:
- split_check.set_sensitive (false);
- break;
- case Editing::ImportAsTapeTrack:
- split_check.set_sensitive (true);
- break;
- }
-}
-
-Editing::ImportMode
-SoundFileOmega::get_mode ()
-{
- vector<string>::iterator i;
- uint32_t n;
- string str = mode_combo.get_active_text ();
-
- for (n = 0, i = mode_strings.begin (); i != mode_strings.end(); ++i, ++n) {
- if (str == (*i)) {
- break;
- }
+ if (session) {
+ session->cancel_audition();
+ }
+}
+
+ustring
+SoundFileChooser::get_filename ()
+{
+ vector<ustring> paths;
+
+ paths = get_paths ();
+
+ if (paths.empty()) {
+ return ustring ();
+ }
+
+ if (!Glib::file_test (paths.front(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+ return ustring();
}
- if (i == mode_strings.end()) {
- fatal << string_compose (_("programming error: %1"), X_("unknown import mode string")) << endmsg;
+ return paths.front();
+}
+
+SoundFileOmega::SoundFileOmega (Gtk::Window& parent, string title, ARDOUR::Session* s, int selected_tracks, bool persistent,
+ Editing::ImportMode mode_hint)
+ : SoundFileBrowser (parent, title, s, persistent),
+ copy_files_btn ( _("Copy files to session")),
+ selected_track_cnt (selected_tracks)
+{
+ VBox* vbox;
+ HBox* hbox;
+ vector<string> str;
+
+ set_size_request (-1, 450);
+
+ block_two.set_border_width (12);
+ block_three.set_border_width (12);
+ block_four.set_border_width (12);
+
+ options.set_spacing (12);
+
+ str.clear ();
+ str.push_back (_("use file timestamp"));
+ str.push_back (_("at edit cursor"));
+ str.push_back (_("at playhead"));
+ str.push_back (_("at session start"));
+ set_popdown_strings (where_combo, str);
+ where_combo.set_active_text (str.front());
+
+ Label* l = manage (new Label);
+ l->set_text (_("Add files:"));
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (12);
+ hbox->set_spacing (6);
+ hbox->pack_start (*l, false, false);
+ hbox->pack_start (action_combo, false, false);
+ vbox = manage (new VBox);
+ vbox->pack_start (*hbox, false, false);
+ options.pack_start (*vbox, false, false);
+
+ /* dummy entry for action combo so that it doesn't look odd if we
+ come up with no tracks selected.
+ */
+
+ str.clear ();
+ str.push_back (importmode2string (mode_hint));
+ set_popdown_strings (action_combo, str);
+ action_combo.set_active_text (str.front());
+ action_combo.set_sensitive (false);
+
+ l = manage (new Label);
+ l->set_text (_("Insert:"));
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (12);
+ hbox->set_spacing (6);
+ hbox->pack_start (*l, false, false);
+ hbox->pack_start (where_combo, false, false);
+ vbox = manage (new VBox);
+ vbox->pack_start (*hbox, false, false);
+ options.pack_start (*vbox, false, false);
+
+
+ l = manage (new Label);
+ l->set_text (_("Mapping:"));
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (12);
+ hbox->set_spacing (6);
+ hbox->pack_start (*l, false, false);
+ hbox->pack_start (channel_combo, false, false);
+ vbox = manage (new VBox);
+ vbox->pack_start (*hbox, false, false);
+ options.pack_start (*vbox, false, false);
+
+ str.clear ();
+ str.push_back (_("one track per file"));
+ set_popdown_strings (channel_combo, str);
+ channel_combo.set_active_text (str.front());
+ channel_combo.set_sensitive (false);
+
+ l = manage (new Label);
+ l->set_text (_("Conversion Quality:"));
+
+ hbox = manage (new HBox);
+ hbox->set_border_width (12);
+ hbox->set_spacing (6);
+ hbox->pack_start (*l, false, false);
+ hbox->pack_start (src_combo, false, false);
+ vbox = manage (new VBox);
+ vbox->pack_start (*hbox, false, false);
+ options.pack_start (*vbox, false, false);
+
+ str.clear ();
+ str.push_back (_("Best"));
+ str.push_back (_("Good"));
+ str.push_back (_("Quick"));
+ str.push_back (_("Fast"));
+ str.push_back (_("Fastest"));
+
+ set_popdown_strings (src_combo, str);
+ src_combo.set_active_text (str.front());
+ src_combo.set_sensitive (false);
+
+ reset_options ();
+
+ action_combo.signal_changed().connect (mem_fun (*this, &SoundFileOmega::reset_options_noret));
+
+ copy_files_btn.set_active (true);
+
+ block_four.pack_start (copy_files_btn, false, false);
+
+ options.pack_start (block_four, false, false);
+
+ get_vbox()->pack_start (options, false, false);
+
+ /* setup disposition map */
+
+ disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per file"), ImportDistinctFiles));
+ disposition_map.insert (pair<ustring,ImportDisposition>(_("one track per channel"), ImportDistinctChannels));
+ disposition_map.insert (pair<ustring,ImportDisposition>(_("merge files"), ImportMergeFiles));
+ disposition_map.insert (pair<ustring,ImportDisposition>(_("sequence files"), ImportSerializeFiles));
+
+ disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per file"), ImportDistinctFiles));
+ disposition_map.insert (pair<ustring,ImportDisposition>(_("one region per channel"), ImportDistinctChannels));
+ disposition_map.insert (pair<ustring,ImportDisposition>(_("all files in one region"), ImportMergeFiles));
+
+ chooser.signal_selection_changed().connect (mem_fun (*this, &SoundFileOmega::file_selection_changed));
+}
+
+void
+SoundFileOmega::set_mode (ImportMode mode)
+{
+ action_combo.set_active_text (importmode2string (mode));
+}
+
+ImportMode
+SoundFileOmega::get_mode () const
+{
+ return string2importmode (action_combo.get_active_text());
+}
+
+void
+SoundFileOmega::on_hide ()
+{
+ ArdourDialog::on_hide();
+ if (session) {
+ session->cancel_audition();
+ }
+}
+
+ImportPosition
+SoundFileOmega::get_position() const
+{
+ ustring str = where_combo.get_active_text();
+
+ if (str == _("use file timestamp")) {
+ return ImportAtTimestamp;
+ } else if (str == _("at edit cursor")) {
+ return ImportAtEditCursor;
+ } else if (str == _("at playhead")) {
+ return ImportAtPlayhead;
+ } else {
+ return ImportAtStart;
+ }
+}
+
+SrcQuality
+SoundFileOmega::get_src_quality() const
+{
+ ustring str = where_combo.get_active_text();
+
+ if (str == _("Best")) {
+ return SrcBest;
+ } else if (str == _("Good")) {
+ return SrcGood;
+ } else if (str == _("Quick")) {
+ return SrcQuick;
+ } else if (str == _("Fast")) {
+ return SrcFast;
+ } else {
+ return SrcFastest;
+ }
+}
+
+ImportDisposition
+SoundFileOmega::get_channel_disposition () const
+{
+ /* we use a map here because the channel combo can contain different strings
+ depending on the state of the other combos. the map contains all possible strings
+ and the ImportDisposition enum that corresponds to it.
+ */
+
+ ustring str = channel_combo.get_active_text();
+ DispositionMap::const_iterator x = disposition_map.find (str);
+
+ if (x == disposition_map.end()) {
+ fatal << string_compose (_("programming error: %1 (%2)"), "unknown string for import disposition", str) << endmsg;
/*NOTREACHED*/
}
- return (Editing::ImportMode) (n);
+ return x->second;
}
void
-SoundFileOmega::mode_changed ()
+SoundFileOmega::reset (int selected_tracks)
{
- Editing::ImportMode mode = get_mode();
+ selected_track_cnt = selected_tracks;
+ reset_options ();
+}
- switch (mode) {
- case Editing::ImportAsRegion:
- split_check.set_sensitive (true);
- break;
- case Editing::ImportAsTrack:
- split_check.set_sensitive (true);
- break;
- case Editing::ImportToTrack:
- split_check.set_sensitive (false);
- break;
- case Editing::ImportAsTapeTrack:
- split_check.set_sensitive (true);
- break;
+void
+SoundFileOmega::file_selection_changed ()
+{
+ if (resetting_ourselves) {
+ return;
+ }
+
+ if (!reset_options ()) {
+ set_response_sensitive (RESPONSE_OK, false);
+ } else {
+ if (chooser.get_filenames().size() > 0) {
+ set_response_sensitive (RESPONSE_OK, true);
+ } else {
+ set_response_sensitive (RESPONSE_OK, false);
+ }
}
}
diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h
index 34c3f558bb..43f76a9ea2 100644
--- a/gtk2_ardour/sfdb_ui.h
+++ b/gtk2_ardour/sfdb_ui.h
@@ -22,6 +22,8 @@
#include <string>
#include <vector>
+#include <map>
+#include <glibmm/ustring.h>
#include <sigc++/signal.h>
@@ -41,32 +43,50 @@
#include "ardour_dialog.h"
#include "editing.h"
+namespace ARDOUR {
+ class Session;
+};
+
+class GainMeter;
+
class SoundFileBox : public Gtk::VBox
{
public:
- SoundFileBox ();
+ SoundFileBox (bool persistent);
virtual ~SoundFileBox () {};
void set_session (ARDOUR::Session* s);
- bool setup_labels (std::string filename);
+ bool setup_labels (const Glib::ustring& filename);
+
+ void audition();
+ bool audition_oneshot();
+ bool autoplay () const;
protected:
ARDOUR::Session* _session;
- std::string path;
+ Glib::ustring path;
ARDOUR::SoundFileInfo sf_info;
- pid_t current_pid;
+ Gtk::Table table;
Gtk::Label length;
Gtk::Label format;
Gtk::Label channels;
Gtk::Label samplerate;
Gtk::Label timecode;
+
+ Gtk::Label channels_value;
+ Gtk::Label samplerate_value;
+ Gtk::Label format_text;
+ AudioClock length_clock;
+ AudioClock timecode_clock;
+
Gtk::Frame border_frame;
-
- Gtk::Entry tags_entry;
+ Gtk::Label preview_label;
+
+ Gtk::TextView tags_entry;
Gtk::VBox main_box;
Gtk::VBox path_box;
@@ -74,91 +94,137 @@ class SoundFileBox : public Gtk::VBox
Gtk::Button play_btn;
Gtk::Button stop_btn;
+ Gtk::CheckButton autoplay_btn;
Gtk::Button apply_btn;
-
+
bool tags_entry_left (GdkEventFocus* event);
- void play_btn_clicked ();
- void stop_btn_clicked ();
- void apply_btn_clicked ();
-
- void audition_status_changed (bool state);
+ void tags_changed ();
+ void save_tags (const std::vector<std::string>&);
+ void stop_audition ();
};
class SoundFileBrowser : public ArdourDialog
{
+ private:
+ class FoundTagColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ Gtk::TreeModelColumn<Glib::ustring> pathname;
+
+ FoundTagColumns() { add(pathname); }
+ };
+
+ FoundTagColumns found_list_columns;
+ Glib::RefPtr<Gtk::ListStore> found_list;
+
public:
- SoundFileBrowser (std::string title, ARDOUR::Session* _s = 0);
+ SoundFileBrowser (Gtk::Window& parent, std::string title, ARDOUR::Session* _s, bool persistent);
virtual ~SoundFileBrowser ();
virtual void set_session (ARDOUR::Session*);
+ std::vector<Glib::ustring> get_paths ();
+
+ void clear_selection ();
- protected:
Gtk::FileChooserWidget chooser;
+ Gtk::TreeView found_list_view;
+
+ protected:
+ bool resetting_ourselves;
+
Gtk::FileFilter custom_filter;
Gtk::FileFilter matchall_filter;
SoundFileBox preview;
+ Gtk::HBox hpacker;
static Glib::ustring persistent_folder;
- class FoundTagColumns : public Gtk::TreeModel::ColumnRecord
- {
- public:
- Gtk::TreeModelColumn<string> pathname;
-
- FoundTagColumns() { add(pathname); }
- };
-
- FoundTagColumns found_list_columns;
- Glib::RefPtr<Gtk::ListStore> found_list;
- Gtk::TreeView found_list_view;
Gtk::Entry found_entry;
Gtk::Button found_search_btn;
-
Gtk::Notebook notebook;
-
+
+ GainMeter* gm;
+ Gtk::VBox meter_packer;
+ void add_gain_meter ();
+ void remove_gain_meter ();
+ void meter ();
+ void start_metering ();
+ void stop_metering ();
+ sigc::connection metering_connection;
+
void update_preview ();
void found_list_view_selected ();
+ void found_list_view_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*);
void found_search_clicked ();
+
+ void chooser_file_activated ();
bool on_custom (const Gtk::FileFilter::Info& filter_info);
+
+ virtual bool reset_options() { return true; }
+
+ protected:
+ void on_show();
+
};
class SoundFileChooser : public SoundFileBrowser
{
public:
- SoundFileChooser (std::string title, ARDOUR::Session* _s = 0);
+ SoundFileChooser (Gtk::Window& parent, std::string title, ARDOUR::Session* _s = 0);
virtual ~SoundFileChooser () {};
- std::string get_filename ();
+ Glib::ustring get_filename ();
+
+ protected:
+ void on_hide();
};
class SoundFileOmega : public SoundFileBrowser
{
+
public:
- SoundFileOmega (std::string title, ARDOUR::Session* _s);
- virtual ~SoundFileOmega () {};
-
- /* these are returned by the Dialog::run() method. note
- that builtin GTK responses are all negative, leaving
- positive values for application-defined responses.
- */
-
- const static int ResponseImport = 1;
- const static int ResponseEmbed = 2;
+ SoundFileOmega (Gtk::Window& parent, std::string title, ARDOUR::Session* _s, int selected_tracks, bool persistent,
+ Editing::ImportMode mode_hint = Editing::ImportAsTrack);
- std::vector<Glib::ustring> get_paths ();
- bool get_split ();
+ void reset (int selected_tracks);
+ Gtk::ComboBoxText action_combo;
+ Gtk::ComboBoxText where_combo;
+ Gtk::ComboBoxText channel_combo;
+ Gtk::ComboBoxText src_combo;
+
+ Gtk::CheckButton copy_files_btn;
+
void set_mode (Editing::ImportMode);
- Editing::ImportMode get_mode ();
+ Editing::ImportMode get_mode() const;
+ Editing::ImportPosition get_position() const;
+ Editing::ImportDisposition get_channel_disposition() const;
+ ARDOUR::SrcQuality get_src_quality() const;
protected:
- Gtk::CheckButton split_check;
- Gtk::ComboBoxText mode_combo;
-
- void mode_changed ();
-
- static std::vector<std::string> mode_strings;
+ void on_hide();
+
+ private:
+ uint32_t selected_track_cnt;
+
+ typedef std::map<Glib::ustring,Editing::ImportDisposition> DispositionMap;
+ DispositionMap disposition_map;
+
+ Gtk::HBox options;
+ Gtk::VBox block_two;
+ Gtk::VBox block_three;
+ Gtk::VBox block_four;
+
+ bool check_info (const std::vector<Glib::ustring>& paths,
+ bool& same_size, bool& src_needed, bool& multichannel);
+
+ static bool check_link_status (const ARDOUR::Session&, const std::vector<Glib::ustring>& paths);
+
+ void file_selection_changed ();
+ bool reset_options ();
+ void reset_options_noret ();
+ bool bad_file_message ();
};
#endif // __ardour_sfdb_ui_h__
diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc
index 560dcd503f..1a3fb9a084 100644
--- a/gtk2_ardour/streamview.cc
+++ b/gtk2_ardour/streamview.cc
@@ -153,6 +153,8 @@ StreamView::set_samples_per_unit (gdouble spp)
void
StreamView::add_region_view (boost::shared_ptr<Region> r)
{
+ // ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r));
+
add_region_view_internal (r, true);
}
diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc
index 83a95fb71f..570a481c11 100644
--- a/gtk2_ardour/utils.cc
+++ b/gtk2_ardour/utils.cc
@@ -337,6 +337,12 @@ set_color (Gdk::Color& c, int rgb)
c.set_rgb((rgb >> 16)*256, ((rgb & 0xff00) >> 8)*256, (rgb & 0xff)*256);
}
+#ifdef GTKOSX
+extern "C" {
+ gboolean gdk_quartz_possibly_forward (GdkEvent*);
+}
+#endif
+
bool
key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
{
@@ -348,7 +354,6 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
#ifdef DEBUG_ACCELERATOR_HANDLING
bool debug = (getenv ("ARDOUR_DEBUG_ACCELERATOR_HANDLING") != 0);
#endif
-
if (focus) {
if (GTK_IS_ENTRY(focus) || Keyboard::some_magic_widget_has_focus()) {
special_handling_of_unmodified_accelerators = true;
@@ -444,6 +449,11 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
cerr << "\tactivate, then propagate\n";
}
#endif
+#ifdef GTKOSX
+ if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
+ return true;
+ }
+#endif
if (!gtk_window_activate_key (win, ev)) {
return gtk_window_propagate_key_event (win, ev);
} else {
@@ -469,6 +479,11 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
cerr << "\tpropagation didn't handle, so activate\n";
}
#endif
+#ifdef GTKOSX
+ if (gdk_quartz_possibly_forward ((GdkEvent*) ev)) {
+ return true;
+ }
+#endif
return gtk_window_activate_key (win, ev);
} else {
#ifdef DEBUG_ACCELERATOR_HANDLING
@@ -490,23 +505,18 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev)
Glib::RefPtr<Gdk::Pixbuf>
get_xpm (std::string name)
{
- if (!xpm_map[name]) {
-
- SearchPath spath(ARDOUR::ardour_search_path());
- spath += ARDOUR::system_data_search_path();
-
- spath.add_subdirectory_to_paths("pixmaps");
+ SearchPath spath(ARDOUR::ardour_search_path());
+ spath += ARDOUR::system_data_search_path();
- sys::path data_file_path;
+ spath.add_subdirectory_to_paths("pixmaps");
- if(!find_file_in_search_path (spath, name, data_file_path)) {
- fatal << string_compose (_("cannot find pixmap %1"), name) << endmsg;
- }
+ sys::path data_file_path;
- xpm_map[name] = Gdk::Pixbuf::create_from_file (data_file_path.to_string());
+ if(!find_file_in_search_path (spath, name, data_file_path)) {
+ fatal << string_compose (_("cannot find XPM file for %1"), name) << endmsg;
}
-
- return (xpm_map[name]);
+
+ return Gdk::Pixbuf::create_from_file (data_file_path.to_string());
}
Glib::RefPtr<Gdk::Pixbuf>