summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--SConstruct42
-rw-r--r--ardour.dox13
-rw-r--r--gtk2_ardour/SConscript11
-rw-r--r--gtk2_ardour/about.cc6
-rw-r--r--gtk2_ardour/about.h1
-rw-r--r--gtk2_ardour/actions.cc1
-rw-r--r--gtk2_ardour/add_route_dialog.cc3
-rw-r--r--gtk2_ardour/analysis_window.cc1
-rwxr-xr-xgtk2_ardour/ardbg1
-rwxr-xr-xgtk2_ardour/ardev1
-rw-r--r--gtk2_ardour/ardour.bindings.in (renamed from gtk2_ardour/ardour.bindings)14
-rw-r--r--gtk2_ardour/ardour.colors3
-rw-r--r--gtk2_ardour/ardour.menus10
-rw-r--r--gtk2_ardour/ardour2_ui.rc874
-rw-r--r--gtk2_ardour/ardour_image_compositor_socket.h1
-rw-r--r--gtk2_ardour/ardour_message.cc64
-rw-r--r--gtk2_ardour/ardour_ui.cc515
-rw-r--r--gtk2_ardour/ardour_ui.h109
-rw-r--r--gtk2_ardour/ardour_ui2.cc134
-rw-r--r--gtk2_ardour/ardour_ui_dependents.cc1
-rw-r--r--gtk2_ardour/ardour_ui_dialogs.cc18
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc77
-rw-r--r--gtk2_ardour/ardour_ui_mixer.cc4
-rw-r--r--gtk2_ardour/ardour_ui_options.cc107
-rw-r--r--gtk2_ardour/audio_clock.cc1
-rw-r--r--gtk2_ardour/audio_clock.h1
-rw-r--r--gtk2_ardour/audio_region_editor.cc1
-rw-r--r--gtk2_ardour/audio_region_editor.h1
-rw-r--r--gtk2_ardour/audio_region_view.cc38
-rw-r--r--gtk2_ardour/audio_region_view.h6
-rw-r--r--gtk2_ardour/audio_time_axis.cc25
-rw-r--r--gtk2_ardour/audio_time_axis.h2
-rw-r--r--gtk2_ardour/automation_gain_line.cc1
-rw-r--r--gtk2_ardour/automation_line.cc2
-rw-r--r--gtk2_ardour/automation_line.h1
-rw-r--r--gtk2_ardour/automation_pan_line.cc1
-rw-r--r--gtk2_ardour/axis_view.cc1
-rw-r--r--gtk2_ardour/axis_view.h1
-rw-r--r--gtk2_ardour/canvas-imageframe.h8
-rw-r--r--gtk2_ardour/canvas-simplerect.c87
-rw-r--r--gtk2_ardour/canvas-waveview.c5
-rw-r--r--gtk2_ardour/colors.h3
-rw-r--r--gtk2_ardour/connection_editor.cc1
-rw-r--r--gtk2_ardour/connection_editor.h1
-rw-r--r--gtk2_ardour/crossfade_edit.cc35
-rw-r--r--gtk2_ardour/crossfade_edit.h5
-rw-r--r--gtk2_ardour/crossfade_view.cc1
-rw-r--r--gtk2_ardour/crossfade_view.h1
-rw-r--r--gtk2_ardour/editor.cc74
-rw-r--r--gtk2_ardour/editor.h25
-rw-r--r--gtk2_ardour/editor_actions.cc4
-rw-r--r--gtk2_ardour/editor_audio_import.cc27
-rw-r--r--gtk2_ardour/editor_audiotrack.cc2
-rw-r--r--gtk2_ardour/editor_canvas.cc48
-rw-r--r--gtk2_ardour/editor_canvas_events.cc6
-rw-r--r--gtk2_ardour/editor_cursors.cc4
-rw-r--r--gtk2_ardour/editor_edit_groups.cc1
-rw-r--r--gtk2_ardour/editor_export_audio.cc1
-rw-r--r--gtk2_ardour/editor_hscroller.cc8
-rw-r--r--gtk2_ardour/editor_imageframe.cc1
-rw-r--r--gtk2_ardour/editor_keyboard.cc1
-rw-r--r--gtk2_ardour/editor_keys.cc12
-rw-r--r--gtk2_ardour/editor_markers.cc20
-rw-r--r--gtk2_ardour/editor_mixer.cc57
-rw-r--r--gtk2_ardour/editor_mouse.cc633
-rw-r--r--gtk2_ardour/editor_nudge.cc1
-rw-r--r--gtk2_ardour/editor_ops.cc7
-rw-r--r--gtk2_ardour/editor_region_list.cc16
-rw-r--r--gtk2_ardour/editor_route_list.cc12
-rw-r--r--gtk2_ardour/editor_rulers.cc3
-rw-r--r--gtk2_ardour/editor_selection.cc6
-rw-r--r--gtk2_ardour/editor_selection_list.cc2
-rw-r--r--gtk2_ardour/editor_tempodisplay.cc28
-rw-r--r--gtk2_ardour/editor_timefx.cc1
-rw-r--r--gtk2_ardour/export_dialog.cc20
-rw-r--r--gtk2_ardour/export_dialog.h7
-rw-r--r--gtk2_ardour/export_range_markers_dialog.cc39
-rw-r--r--gtk2_ardour/export_range_markers_dialog.h4
-rw-r--r--gtk2_ardour/export_region_dialog.cc3
-rw-r--r--gtk2_ardour/export_session_dialog.cc3
-rw-r--r--gtk2_ardour/gain_automation_time_axis.cc1
-rw-r--r--gtk2_ardour/gain_meter.cc35
-rw-r--r--gtk2_ardour/gain_meter.h5
-rw-r--r--gtk2_ardour/ghostregion.h1
-rw-r--r--gtk2_ardour/icons/crossfade_in_constant.pngbin0 -> 693 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_in_dipped.pngbin0 -> 667 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_in_fast-cut.pngbin0 -> 686 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_in_slow-cut.pngbin0 -> 723 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_in_slow-fade.pngbin0 -> 730 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_in_transition.pngbin0 -> 692 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_out_constant.pngbin0 -> 720 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_out_dipped.pngbin0 -> 831 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_out_fast-cut.pngbin0 -> 737 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_out_slow-cut.pngbin0 -> 770 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_out_slow-fade.pngbin0 -> 798 bytes
-rw-r--r--gtk2_ardour/icons/crossfade_out_transition.pngbin0 -> 737 bytes
-rw-r--r--gtk2_ardour/imageframe.cc1
-rw-r--r--gtk2_ardour/imageframe.h1
-rw-r--r--gtk2_ardour/imageframe_socket_handler.cc1
-rw-r--r--gtk2_ardour/imageframe_socket_handler.h1
-rw-r--r--gtk2_ardour/imageframe_time_axis.cc1
-rw-r--r--gtk2_ardour/imageframe_time_axis.h1
-rw-r--r--gtk2_ardour/imageframe_time_axis_group.cc1
-rw-r--r--gtk2_ardour/imageframe_time_axis_group.h1
-rw-r--r--gtk2_ardour/imageframe_time_axis_view.cc1
-rw-r--r--gtk2_ardour/imageframe_time_axis_view.h1
-rw-r--r--gtk2_ardour/imageframe_view.cc1
-rw-r--r--gtk2_ardour/imageframe_view.h1
-rw-r--r--gtk2_ardour/io_selector.cc1
-rw-r--r--gtk2_ardour/io_selector.h1
-rw-r--r--gtk2_ardour/keyboard.cc514
-rw-r--r--gtk2_ardour/keyboard.h24
-rw-r--r--gtk2_ardour/keyboard_target.cc258
-rw-r--r--gtk2_ardour/keyboard_target.h83
-rw-r--r--gtk2_ardour/ladspa_pluginui.cc19
-rw-r--r--gtk2_ardour/location_ui.cc1
-rw-r--r--gtk2_ardour/location_ui.h2
-rw-r--r--gtk2_ardour/main.cc198
-rw-r--r--gtk2_ardour/marker.cc1
-rw-r--r--gtk2_ardour/marker.h1
-rw-r--r--gtk2_ardour/marker_time_axis.cc1
-rw-r--r--gtk2_ardour/marker_time_axis.h1
-rw-r--r--gtk2_ardour/marker_time_axis_view.cc1
-rw-r--r--gtk2_ardour/marker_time_axis_view.h1
-rw-r--r--gtk2_ardour/marker_view.cc1
-rw-r--r--gtk2_ardour/marker_view.h1
-rw-r--r--gtk2_ardour/meter_bridge.cc260
-rw-r--r--gtk2_ardour/meter_bridge.h91
-rw-r--r--gtk2_ardour/meter_bridge_strip.cc243
-rw-r--r--gtk2_ardour/meter_bridge_strip.h110
-rw-r--r--gtk2_ardour/mixer_strip.cc76
-rw-r--r--gtk2_ardour/mixer_strip.h3
-rw-r--r--gtk2_ardour/mixer_ui.cc31
-rw-r--r--gtk2_ardour/mixer_ui.h6
-rw-r--r--gtk2_ardour/new_session_dialog.cc1
-rw-r--r--gtk2_ardour/new_session_dialog.h1
-rw-r--r--gtk2_ardour/option_editor.cc43
-rw-r--r--gtk2_ardour/option_editor.h6
-rw-r--r--gtk2_ardour/opts.cc9
-rw-r--r--gtk2_ardour/opts.h1
-rw-r--r--gtk2_ardour/pan_automation_time_axis.cc1
-rw-r--r--gtk2_ardour/panner.cc10
-rw-r--r--gtk2_ardour/panner2d.cc5
-rw-r--r--gtk2_ardour/panner2d.h3
-rw-r--r--gtk2_ardour/panner_ui.cc56
-rw-r--r--gtk2_ardour/panner_ui.h1
-rw-r--r--gtk2_ardour/playlist_selector.cc1
-rw-r--r--gtk2_ardour/plugin_selector.cc10
-rw-r--r--gtk2_ardour/plugin_ui.cc4
-rw-r--r--gtk2_ardour/plugin_ui.h1
-rw-r--r--gtk2_ardour/po/ru_RU.po3528
-rw-r--r--gtk2_ardour/prompter.cc1
-rw-r--r--gtk2_ardour/prompter.h1
-rw-r--r--gtk2_ardour/public_editor.h10
-rw-r--r--gtk2_ardour/redirect_automation_line.cc1
-rw-r--r--gtk2_ardour/redirect_automation_line.h1
-rw-r--r--gtk2_ardour/redirect_automation_time_axis.cc1
-rw-r--r--gtk2_ardour/redirect_box.cc9
-rw-r--r--gtk2_ardour/redirect_box.h3
-rw-r--r--gtk2_ardour/region_editor.h1
-rw-r--r--gtk2_ardour/region_view.cc29
-rw-r--r--gtk2_ardour/region_view.h8
-rw-r--r--gtk2_ardour/rgb_macros.h1
-rw-r--r--gtk2_ardour/route_params_ui.cc6
-rw-r--r--gtk2_ardour/route_params_ui.h6
-rw-r--r--gtk2_ardour/route_redirect_selection.cc1
-rw-r--r--gtk2_ardour/route_redirect_selection.h1
-rw-r--r--gtk2_ardour/route_time_axis.cc35
-rw-r--r--gtk2_ardour/route_time_axis.h1
-rw-r--r--gtk2_ardour/route_ui.cc123
-rw-r--r--gtk2_ardour/route_ui.h6
-rw-r--r--gtk2_ardour/selectable.h1
-rw-r--r--gtk2_ardour/selection.cc1
-rw-r--r--gtk2_ardour/selection.h1
-rw-r--r--gtk2_ardour/selection_templates.h1
-rw-r--r--gtk2_ardour/send_ui.cc1
-rw-r--r--gtk2_ardour/send_ui.h1
-rw-r--r--gtk2_ardour/sfdb_ui.cc13
-rw-r--r--gtk2_ardour/sfdb_ui.h8
-rw-r--r--gtk2_ardour/simpleline.cc1
-rw-r--r--gtk2_ardour/simpleline.h1
-rw-r--r--gtk2_ardour/simplerect.cc1
-rw-r--r--gtk2_ardour/simplerect.h1
-rw-r--r--gtk2_ardour/tape_region_view.cc1
-rw-r--r--gtk2_ardour/tape_region_view.h1
-rw-r--r--gtk2_ardour/tempo_dialog.cc94
-rw-r--r--gtk2_ardour/tempo_dialog.h11
-rw-r--r--gtk2_ardour/time_axis_view.cc7
-rw-r--r--gtk2_ardour/time_axis_view.h1
-rw-r--r--gtk2_ardour/time_axis_view_item.cc35
-rw-r--r--gtk2_ardour/time_axis_view_item.h5
-rw-r--r--gtk2_ardour/time_selection.cc1
-rw-r--r--gtk2_ardour/utils.cc75
-rw-r--r--gtk2_ardour/utils.h2
-rw-r--r--gtk2_ardour/visual_time_axis.cc1
-rw-r--r--gtk2_ardour/visual_time_axis.h1
-rw-r--r--gtk2_ardour/vst_pluginui.cc1
-rw-r--r--gtk2_ardour/waveview.cc1
-rw-r--r--gtk2_ardour/waveview.h1
-rw-r--r--libs/ardour/SConscript18
-rw-r--r--libs/ardour/ardour/ardour.h1
-rw-r--r--libs/ardour/ardour/audio_diskstream.h71
-rw-r--r--libs/ardour/ardour/audio_track.h1
-rw-r--r--libs/ardour/ardour/audioengine.h3
-rw-r--r--libs/ardour/ardour/audiofilesource.h56
-rw-r--r--libs/ardour/ardour/audiofilter.h1
-rw-r--r--libs/ardour/ardour/audioplaylist.h1
-rw-r--r--libs/ardour/ardour/audioregion.h1
-rw-r--r--libs/ardour/ardour/audiosource.h80
-rw-r--r--libs/ardour/ardour/auditioner.h1
-rw-r--r--libs/ardour/ardour/automation_event.h1
-rw-r--r--libs/ardour/ardour/click.h1
-rw-r--r--libs/ardour/ardour/configuration.h1
-rw-r--r--libs/ardour/ardour/configuration_variable.h5
-rw-r--r--libs/ardour/ardour/configuration_vars.h6
-rw-r--r--libs/ardour/ardour/connection.h1
-rw-r--r--libs/ardour/ardour/crossfade.h1
-rw-r--r--libs/ardour/ardour/crossfade_compare.h1
-rw-r--r--libs/ardour/ardour/curve.h1
-rw-r--r--libs/ardour/ardour/cycle_timer.h1
-rw-r--r--libs/ardour/ardour/cycles.h1
-rw-r--r--libs/ardour/ardour/dB.h1
-rw-r--r--libs/ardour/ardour/destructive_filesource.h76
-rw-r--r--libs/ardour/ardour/diskstream.h7
-rw-r--r--libs/ardour/ardour/export.h6
-rw-r--r--libs/ardour/ardour/gain.h1
-rw-r--r--libs/ardour/ardour/gdither.h1
-rw-r--r--libs/ardour/ardour/gdither_types.h1
-rw-r--r--libs/ardour/ardour/gdither_types_internal.h1
-rw-r--r--libs/ardour/ardour/insert.h1
-rw-r--r--libs/ardour/ardour/io.h4
-rw-r--r--libs/ardour/ardour/ladspa_plugin.h1
-rw-r--r--libs/ardour/ardour/location.h9
-rw-r--r--libs/ardour/ardour/logcurve.h1
-rw-r--r--libs/ardour/ardour/mix.h19
-rw-r--r--libs/ardour/ardour/named_selection.h1
-rw-r--r--libs/ardour/ardour/osc.h1
-rw-r--r--libs/ardour/ardour/panner.h1
-rw-r--r--libs/ardour/ardour/pcm_utils.h1
-rw-r--r--libs/ardour/ardour/playlist.h1
-rw-r--r--libs/ardour/ardour/playlist_templates.h1
-rw-r--r--libs/ardour/ardour/plugin.h1
-rw-r--r--libs/ardour/ardour/plugin_manager.h1
-rw-r--r--libs/ardour/ardour/port.h1
-rw-r--r--libs/ardour/ardour/redirect.h1
-rw-r--r--libs/ardour/ardour/region.h1
-rw-r--r--libs/ardour/ardour/reverse.h1
-rw-r--r--libs/ardour/ardour/route.h18
-rw-r--r--libs/ardour/ardour/route_group.h1
-rw-r--r--libs/ardour/ardour/send.h1
-rw-r--r--libs/ardour/ardour/session.h56
-rw-r--r--libs/ardour/ardour/session_connection.h1
-rw-r--r--libs/ardour/ardour/session_playlist.h1
-rw-r--r--libs/ardour/ardour/session_route.h1
-rw-r--r--libs/ardour/ardour/session_selection.h1
-rw-r--r--libs/ardour/ardour/silentfilesource.h66
-rw-r--r--libs/ardour/ardour/slave.h2
-rw-r--r--libs/ardour/ardour/sndfilesource.h7
-rw-r--r--libs/ardour/ardour/soundseq.h1
-rw-r--r--libs/ardour/ardour/source.h1
-rw-r--r--libs/ardour/ardour/source_factory.h2
-rw-r--r--libs/ardour/ardour/tempo.h1
-rw-r--r--libs/ardour/ardour/types.h8
-rw-r--r--libs/ardour/ardour/utils.h1
-rw-r--r--libs/ardour/ardour/vst_plugin.h1
-rw-r--r--libs/ardour/audio_diskstream.cc630
-rw-r--r--libs/ardour/audio_playlist.cc3
-rw-r--r--libs/ardour/audio_track.cc16
-rw-r--r--libs/ardour/audioengine.cc26
-rw-r--r--libs/ardour/audiofilesource.cc131
-rw-r--r--libs/ardour/audiofilter.cc2
-rw-r--r--libs/ardour/audioregion.cc12
-rw-r--r--libs/ardour/audiosource.cc575
-rw-r--r--libs/ardour/auditioner.cc13
-rw-r--r--libs/ardour/automation_event.cc1
-rw-r--r--libs/ardour/buffer.cc12
-rw-r--r--libs/ardour/configuration.cc19
-rw-r--r--libs/ardour/connection.cc1
-rw-r--r--libs/ardour/control_protocol_manager.cc13
-rw-r--r--libs/ardour/crossfade.cc1
-rw-r--r--libs/ardour/curve.cc1
-rw-r--r--libs/ardour/cycle_timer.cc1
-rw-r--r--libs/ardour/default_click.cc1
-rw-r--r--libs/ardour/destructive_filesource.cc424
-rw-r--r--libs/ardour/diskstream.cc5
-rw-r--r--libs/ardour/enums.cc6
-rw-r--r--libs/ardour/gain.cc1
-rw-r--r--libs/ardour/gdither.cc1
-rw-r--r--libs/ardour/globals.cc8
-rw-r--r--libs/ardour/import.cc269
-rw-r--r--libs/ardour/insert.cc1
-rw-r--r--libs/ardour/io.cc7
-rw-r--r--libs/ardour/jack_slave.cc1
-rw-r--r--libs/ardour/ladspa_plugin.cc1
-rw-r--r--libs/ardour/location.cc21
-rw-r--r--libs/ardour/macosx/English.lproj/InfoPlist.stringsbin0 -> 142 bytes
-rw-r--r--libs/ardour/macosx/Info.plist26
-rw-r--r--libs/ardour/macosx/ardour.xcodeproj/project.pbxproj1214
-rw-r--r--libs/ardour/macosx/ardour_Prefix.pch4
-rw-r--r--libs/ardour/macosx/version.cc3
-rw-r--r--libs/ardour/macosx/version.h17
-rw-r--r--libs/ardour/midi_diskstream.cc1
-rw-r--r--libs/ardour/mix.cc28
-rw-r--r--libs/ardour/mtc_slave.cc38
-rw-r--r--libs/ardour/named_selection.cc1
-rw-r--r--libs/ardour/osc.cc18
-rw-r--r--libs/ardour/panner.cc1
-rw-r--r--libs/ardour/pcm_utils.cc1
-rw-r--r--libs/ardour/playlist.cc33
-rw-r--r--libs/ardour/playlist_factory.cc1
-rw-r--r--libs/ardour/plugin.cc1
-rw-r--r--libs/ardour/plugin_manager.cc1
-rw-r--r--libs/ardour/port.cc1
-rw-r--r--libs/ardour/redirect.cc1
-rw-r--r--libs/ardour/region.cc7
-rw-r--r--libs/ardour/region_factory.cc1
-rw-r--r--libs/ardour/reverse.cc33
-rw-r--r--libs/ardour/route.cc48
-rw-r--r--libs/ardour/route_group.cc1
-rw-r--r--libs/ardour/send.cc1
-rw-r--r--libs/ardour/session.cc164
-rw-r--r--libs/ardour/session_butler.cc11
-rw-r--r--libs/ardour/session_click.cc1
-rw-r--r--libs/ardour/session_command.cc5
-rw-r--r--libs/ardour/session_control.cc30
-rw-r--r--libs/ardour/session_events.cc1
-rw-r--r--libs/ardour/session_export.cc58
-rw-r--r--libs/ardour/session_feedback.cc1
-rw-r--r--libs/ardour/session_midi.cc110
-rw-r--r--libs/ardour/session_process.cc29
-rw-r--r--libs/ardour/session_state.cc153
-rw-r--r--libs/ardour/session_time.cc1
-rw-r--r--libs/ardour/session_timefx.cc46
-rw-r--r--libs/ardour/session_transport.cc15
-rw-r--r--libs/ardour/session_vst.cc1
-rw-r--r--libs/ardour/silentfilesource.cc (renamed from gtk2_ardour/ardour_message.h)40
-rw-r--r--libs/ardour/sndfilesource.cc72
-rw-r--r--libs/ardour/source.cc1
-rw-r--r--libs/ardour/source_factory.cc25
-rw-r--r--libs/ardour/sse_functions_xmm.cc116
-rw-r--r--libs/ardour/tempo.cc1
-rw-r--r--libs/ardour/utils.cc1
-rw-r--r--libs/ardour/vst_plugin.cc1
-rw-r--r--libs/clearlooks/clearlooks_theme_main.c2
-rw-r--r--libs/fst/fst.h1
-rw-r--r--libs/fst/vstwin.c23
-rwxr-xr-xlibs/glibmm2/autogen.sh22
-rw-r--r--libs/gtkmm2ext/SConscript1
-rw-r--r--libs/gtkmm2ext/barcontroller.cc8
-rw-r--r--libs/gtkmm2ext/bindable_button.cc13
-rw-r--r--libs/gtkmm2ext/fastmeter.cc59
-rw-r--r--libs/gtkmm2ext/grouped_buttons.cc (renamed from gtk2_ardour/grouped_buttons.cc)2
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/auto_spin.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/barcontroller.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/bindable_button.h38
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/click_box.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/doi.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/fastmeter.h5
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/grouped_buttons.h (renamed from gtk2_ardour/grouped_buttons.h)1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/gtk_ui.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/gtkutils.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/hexentry.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/pixfader.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/popup.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/prompter.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/selector.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/slider_controller.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/stateful_button.h59
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/tearoff.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/textviewer.h1
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/utils.h1
-rw-r--r--libs/gtkmm2ext/stateful_button.cc101
-rw-r--r--libs/midi++2/macosx/English.lproj/InfoPlist.stringsbin0 -> 142 bytes
-rw-r--r--libs/midi++2/macosx/Info.plist26
-rw-r--r--libs/midi++2/macosx/midi++.xcodeproj/project.pbxproj498
-rw-r--r--libs/midi++2/macosx/midi++_Prefix.pch3
-rw-r--r--libs/midi++2/macosx/version.cc3
-rw-r--r--libs/midi++2/macosx/version.h7
-rw-r--r--libs/midi++2/midi++/alsa_rawmidi.h1
-rw-r--r--libs/midi++2/midi++/alsa_sequencer.h1
-rw-r--r--libs/midi++2/midi++/channel.h1
-rw-r--r--libs/midi++2/midi++/factory.h1
-rw-r--r--libs/midi++2/midi++/fd_midiport.h1
-rw-r--r--libs/midi++2/midi++/fifomidi.h1
-rw-r--r--libs/midi++2/midi++/manager.h1
-rw-r--r--libs/midi++2/midi++/mmc.h3
-rw-r--r--libs/midi++2/midi++/nullmidi.h1
-rw-r--r--libs/midi++2/midi++/parser.h5
-rw-r--r--libs/midi++2/midi++/port.h1
-rw-r--r--libs/midi++2/midi++/port_request.h1
-rw-r--r--libs/midi++2/midiparser.cc6
-rw-r--r--libs/midi++2/mmc.cc4
-rw-r--r--libs/midi++2/mtc.cc7
-rw-r--r--libs/pbd/SConscript1
-rw-r--r--libs/pbd/controllable.cc55
-rw-r--r--libs/pbd/macosx/English.lproj/InfoPlist.stringsbin0 -> 136 bytes
-rw-r--r--libs/pbd/macosx/Info.plist26
-rw-r--r--libs/pbd/macosx/pbd.xcodeproj/project.pbxproj634
-rw-r--r--libs/pbd/macosx/pbd_Prefix.pch4
-rw-r--r--libs/pbd/macosx/version.cc3
-rw-r--r--libs/pbd/macosx/version.h7
-rw-r--r--libs/pbd/pbd/abstract_ui.cc12
-rw-r--r--libs/pbd/pbd/abstract_ui.h1
-rw-r--r--libs/pbd/pbd/command.h1
-rw-r--r--libs/pbd/pbd/controllable.h11
-rw-r--r--libs/pbd/pbd/error.h1
-rw-r--r--libs/pbd/pbd/mathfix.h1
-rw-r--r--libs/pbd/pbd/memento_command.h1
-rw-r--r--libs/pbd/pbd/mountpoint.h1
-rw-r--r--libs/pbd/pbd/pool.h1
-rw-r--r--libs/pbd/pbd/rcu.h19
-rw-r--r--libs/pbd/pbd/receiver.h1
-rw-r--r--libs/pbd/pbd/replace_all.h8
-rw-r--r--libs/pbd/pbd/ringbuffer.h146
-rw-r--r--libs/pbd/pbd/ringbufferNPT.h1
-rw-r--r--libs/pbd/pbd/selectable.h1
-rw-r--r--libs/pbd/pbd/stateful.h1
-rw-r--r--libs/pbd/pbd/stl_delete.h1
-rw-r--r--libs/pbd/pbd/stl_functors.h1
-rw-r--r--libs/pbd/pbd/strsplit.h2
-rw-r--r--libs/pbd/pbd/textreceiver.h1
-rw-r--r--libs/pbd/pbd/thrown_error.h1
-rw-r--r--libs/pbd/pbd/touchable.h1
-rw-r--r--libs/pbd/pbd/transmitter.h1
-rw-r--r--libs/pbd/pbd/undo.h1
-rw-r--r--libs/pbd/stacktrace.cc8
-rw-r--r--libs/pbd/strreplace.cc19
-rw-r--r--libs/pbd/strsplit.cc39
-rwxr-xr-xlibs/sigc++2/autogen.sh21
-rw-r--r--libs/soundtouch/RateTransposer.cpp2
-rw-r--r--libs/soundtouch/RateTransposer.h2
-rw-r--r--libs/soundtouch/TDStretch.cpp7
-rw-r--r--libs/soundtouch/cpu_detect_x86_gcc.cpp2
-rw-r--r--libs/surfaces/control_protocol/basic_ui.cc1
-rw-r--r--libs/surfaces/control_protocol/control_protocol.cc1
-rw-r--r--libs/surfaces/control_protocol/control_protocol/basic_ui.h1
-rw-r--r--libs/surfaces/control_protocol/control_protocol/control_protocol.h1
-rw-r--r--libs/surfaces/frontier/kernel_drivers/BUILD10
-rw-r--r--libs/surfaces/frontier/kernel_drivers/Makefile35
-rw-r--r--libs/surfaces/frontier/kernel_drivers/README16
-rw-r--r--libs/surfaces/frontier/kernel_drivers/doc/keycodes.html35
-rw-r--r--libs/surfaces/frontier/kernel_drivers/tests/Makefile23
-rw-r--r--libs/surfaces/frontier/kernel_drivers/tests/README104
-rw-r--r--libs/surfaces/frontier/kernel_drivers/tests/tranzport.c375
-rw-r--r--libs/surfaces/frontier/kernel_drivers/tests/tranzport_lights.c361
-rwxr-xr-xlibs/surfaces/frontier/kernel_drivers/tests/tranzport_tests.sh27
-rw-r--r--libs/surfaces/frontier/kernel_drivers/tranzport.c1065
-rw-r--r--libs/surfaces/frontier/tests/Makefile17
-rw-r--r--libs/surfaces/frontier/tests/README104
-rw-r--r--libs/surfaces/frontier/tests/tranzport.c347
-rw-r--r--libs/surfaces/frontier/tests/tranzport_lights.c361
-rw-r--r--libs/surfaces/frontier/tranzport/SConscript56
-rw-r--r--libs/surfaces/frontier/tranzport/interface.cc51
-rw-r--r--libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc (renamed from libs/surfaces/tranzport/tranzport_control_protocol.cc)3
-rw-r--r--libs/surfaces/frontier/tranzport/tranzport_control_protocol.h320
-rw-r--r--libs/surfaces/generic_midi/SConscript4
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc34
-rw-r--r--libs/surfaces/generic_midi/midicontrollable.cc5
-rw-r--r--libs/surfaces/generic_midi/midicontrollable.h1
-rw-r--r--libs/surfaces/mackie/SConscript74
-rw-r--r--libs/surfaces/mackie/TODO45
-rw-r--r--libs/surfaces/mackie/bcf_surface.cc1473
-rw-r--r--libs/surfaces/mackie/bcf_surface.h27
-rw-r--r--libs/surfaces/mackie/controls.cc109
-rw-r--r--libs/surfaces/mackie/controls.h301
-rw-r--r--libs/surfaces/mackie/interface.cc96
-rw-r--r--libs/surfaces/mackie/mackie_button_handler.cc691
-rw-r--r--libs/surfaces/mackie/mackie_button_handler.h227
-rw-r--r--libs/surfaces/mackie/mackie_control_exception.h47
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc1378
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.h307
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol_poll.cc192
-rw-r--r--libs/surfaces/mackie/mackie_midi_builder.cc173
-rw-r--r--libs/surfaces/mackie/mackie_midi_builder.h81
-rw-r--r--libs/surfaces/mackie/mackie_port.cc399
-rw-r--r--libs/surfaces/mackie/mackie_port.h122
-rw-r--r--libs/surfaces/mackie/mackie_surface.cc1504
-rw-r--r--libs/surfaces/mackie/mackie_surface.h27
-rw-r--r--libs/surfaces/mackie/midi_byte_array.cc98
-rw-r--r--libs/surfaces/mackie/midi_byte_array.h76
-rw-r--r--libs/surfaces/mackie/route_signal.cc95
-rw-r--r--libs/surfaces/mackie/route_signal.h81
-rw-r--r--libs/surfaces/mackie/scripts/bank.rb32
-rw-r--r--libs/surfaces/mackie/scripts/bcf-controls.csv96
-rw-r--r--libs/surfaces/mackie/scripts/controls.rb208
-rwxr-xr-xlibs/surfaces/mackie/scripts/dump.rb11
-rw-r--r--libs/surfaces/mackie/scripts/generate-button-handlers-cc.erb59
-rw-r--r--libs/surfaces/mackie/scripts/generate-button-handlers-h.erb54
-rwxr-xr-xlibs/surfaces/mackie/scripts/generate-surface.rb26
-rwxr-xr-xlibs/surfaces/mackie/scripts/host.rb133
-rw-r--r--libs/surfaces/mackie/scripts/mackie-controls.csv93
-rw-r--r--libs/surfaces/mackie/scripts/mackie.rb119
-rw-r--r--libs/surfaces/mackie/scripts/parse.rb61
-rw-r--r--libs/surfaces/mackie/scripts/signals.rb137
-rw-r--r--libs/surfaces/mackie/scripts/simple_host.rb137
-rw-r--r--libs/surfaces/mackie/scripts/surface-cc-template.erb95
-rw-r--r--libs/surfaces/mackie/scripts/surface-h-template.erb27
-rwxr-xr-xlibs/surfaces/mackie/scripts/test_controls.rb9
-rw-r--r--libs/surfaces/mackie/scripts/transform.rb26
-rw-r--r--libs/surfaces/mackie/scripts/write.rb10
-rw-r--r--libs/surfaces/mackie/surface.cc142
-rw-r--r--libs/surfaces/mackie/surface.h94
-rw-r--r--libs/surfaces/mackie/surface_port.cc178
-rw-r--r--libs/surfaces/mackie/surface_port.h100
-rw-r--r--libs/surfaces/mackie/test.cc25
-rw-r--r--libs/surfaces/mackie/types.cc9
-rw-r--r--libs/surfaces/mackie/types.h93
-rw-r--r--libs/surfaces/tranzport/README90
-rw-r--r--libs/surfaces/tranzport/SConscript46
-rw-r--r--libs/surfaces/tranzport/TODO6
-rw-r--r--libs/surfaces/tranzport/bling.cc115
-rw-r--r--libs/surfaces/tranzport/button_events.cc380
-rw-r--r--libs/surfaces/tranzport/button_yn.cc21
-rw-r--r--libs/surfaces/tranzport/buttons.cc113
-rw-r--r--libs/surfaces/tranzport/general.cc333
-rw-r--r--libs/surfaces/tranzport/init.cc314
-rw-r--r--libs/surfaces/tranzport/interface.cc20
-rw-r--r--libs/surfaces/tranzport/io.cc95
-rw-r--r--libs/surfaces/tranzport/io_kernel.cc144
-rw-r--r--libs/surfaces/tranzport/io_midi.cc26
-rw-r--r--libs/surfaces/tranzport/io_usb.cc232
-rw-r--r--libs/surfaces/tranzport/lcd.cc120
-rw-r--r--libs/surfaces/tranzport/lights.cc95
-rw-r--r--libs/surfaces/tranzport/meter.cc21
-rw-r--r--libs/surfaces/tranzport/mode.cc107
-rw-r--r--libs/surfaces/tranzport/mode_loop.cc21
-rw-r--r--libs/surfaces/tranzport/mode_tuner.cc21
-rw-r--r--libs/surfaces/tranzport/panner.cc34
-rw-r--r--libs/surfaces/tranzport/screen.cc93
-rw-r--r--libs/surfaces/tranzport/show.cc400
-rw-r--r--libs/surfaces/tranzport/slider_gain.h40
-rw-r--r--libs/surfaces/tranzport/state.cc148
-rw-r--r--libs/surfaces/tranzport/tranzport_base.h78
-rw-r--r--libs/surfaces/tranzport/tranzport_common.h44
-rw-r--r--libs/surfaces/tranzport/tranzport_control_protocol.h130
-rw-r--r--libs/surfaces/tranzport/view_automation.cc21
-rw-r--r--libs/surfaces/tranzport/view_bigmeter.cc21
-rw-r--r--libs/surfaces/tranzport/view_bling.cc21
-rw-r--r--libs/surfaces/tranzport/view_bus.cc21
-rw-r--r--libs/surfaces/tranzport/view_config.cc21
-rw-r--r--libs/surfaces/tranzport/view_layer.cc21
-rw-r--r--libs/surfaces/tranzport/view_loop.cc21
-rw-r--r--libs/surfaces/tranzport/view_manymeter.cc21
-rw-r--r--libs/surfaces/tranzport/view_marker.cc21
-rw-r--r--libs/surfaces/tranzport/view_master.cc21
-rw-r--r--libs/surfaces/tranzport/view_plugins.cc21
-rw-r--r--libs/surfaces/tranzport/view_std.cc21
-rw-r--r--libs/surfaces/tranzport/view_tempo.cc21
-rw-r--r--libs/surfaces/tranzport/view_tuner.cc21
-rw-r--r--libs/surfaces/tranzport/wheel.cc206
-rw-r--r--libs/surfaces/tranzport/wheel_modes.cc139
-rw-r--r--manual/Makefile68
-rw-r--r--manual/catalog.xml17
-rw-r--r--manual/config/dbhelper.vim123
-rw-r--r--manual/css/ardour_manual.css208
-rw-r--r--manual/images/add_track_bus.pngbin0 -> 11376 bytes
-rw-r--r--manual/images/admon-bg.pngbin0 -> 186 bytes
-rw-r--r--manual/images/con1.jpgbin0 -> 25851 bytes
-rw-r--r--manual/images/con2.jpgbin0 -> 27603 bytes
-rw-r--r--manual/images/internalhigheroverlap.pngbin0 -> 2849 bytes
-rw-r--r--manual/images/internalloweroverlap.pngbin0 -> 2423 bytes
-rw-r--r--manual/images/ladspa.jpgbin0 -> 80314 bytes
-rw-r--r--manual/images/manual_style.svg167
-rw-r--r--manual/images/matrixmixer.pngbin0 -> 34333 bytes
-rw-r--r--manual/images/midiopts.jpgbin0 -> 21991 bytes
-rw-r--r--manual/images/mixer.pngbin0 -> 19057 bytes
-rw-r--r--manual/images/mixer_strip_name_button_popup.pngbin0 -> 14475 bytes
-rw-r--r--manual/images/mixerstrip.pngbin0 -> 14027 bytes
-rw-r--r--manual/images/new_session_advanced_tab.pngbin0 -> 35381 bytes
-rw-r--r--manual/images/new_session_select_directory.pngbin0 -> 24374 bytes
-rw-r--r--manual/images/overlapearlyhigher.pngbin0 -> 2812 bytes
-rw-r--r--manual/images/overlaplaterhigher.pngbin0 -> 3107 bytes
-rw-r--r--manual/images/pluginmenu.jpgbin0 -> 58905 bytes
-rw-r--r--manual/images/plugins.jpgbin0 -> 341980 bytes
-rw-r--r--manual/images/qjackctl.pngbin0 -> 20818 bytes
-rw-r--r--manual/images/qjopt.jpgbin0 -> 22473 bytes
-rw-r--r--manual/images/qjopts.jpgbin0 -> 43652 bytes
-rw-r--r--manual/images/qjpatch.jpgbin0 -> 36264 bytes
-rw-r--r--manual/images/save_session_dialog.pngbin0 -> 12781 bytes
-rw-r--r--manual/images/save_template_dialog.pngbin0 -> 6618 bytes
-rw-r--r--manual/images/session_control.pngbin0 -> 18820 bytes
-rw-r--r--manual/images/signal_flow.pngbin0 -> 37303 bytes
-rw-r--r--manual/images/tango-icons/COPYING67
-rw-r--r--manual/images/tango-icons/accessories-text-editor.svg552
-rw-r--r--manual/images/tango-icons/dialog-information.svg1145
-rw-r--r--manual/images/tango-icons/dialog-warning.svg359
-rw-r--r--manual/images/tango-icons/emblem-important.svg163
-rw-r--r--manual/images/tango-icons/important.pngbin0 -> 1746 bytes
-rw-r--r--manual/images/tango-icons/note.pngbin0 -> 2242 bytes
-rw-r--r--manual/images/tango-icons/tip.pngbin0 -> 2976 bytes
-rw-r--r--manual/images/tango-icons/warning.pngbin0 -> 1930 bytes
-rw-r--r--manual/images/title-bg.pngbin0 -> 287 bytes
-rw-r--r--manual/images/track_name_field.pngbin0 -> 7492 bytes
-rw-r--r--manual/images/transctls.jpgbin0 -> 8598 bytes
-rw-r--r--manual/images/watermark-draft.pngbin0 -> 9828 bytes
-rw-r--r--manual/templates/chapter_template.xml24
-rw-r--r--manual/templates/section_template.xml23
-rw-r--r--manual/xml/adding_tracks.xml47
-rw-r--r--manual/xml/advanced_editing.xml17
-rw-r--r--manual/xml/ardour_basics.xml29
-rw-r--r--manual/xml/ardour_manual.xml56
-rw-r--r--manual/xml/automation.xml223
-rw-r--r--manual/xml/basic_editing.xml28
-rw-r--r--manual/xml/basic_recording.xml273
-rw-r--r--manual/xml/bcf2000.xml671
-rw-r--r--manual/xml/behringer_ddx3216.xml126
-rw-r--r--manual/xml/book_info.xml43
-rw-r--r--manual/xml/cleaning_up_a_session.xml43
-rw-r--r--manual/xml/clocks.xml105
-rw-r--r--manual/xml/closing_a_session.xml85
-rw-r--r--manual/xml/configuring_usb_device_access.xml69
-rw-r--r--manual/xml/contributing_to_the_manual.xml15
-rw-r--r--manual/xml/control_surfaces.xml25
-rw-r--r--manual/xml/creating_a_new_session.xml138
-rw-r--r--manual/xml/default_track_names.xml22
-rw-r--r--manual/xml/editing_concepts.xml341
-rw-r--r--manual/xml/editor_aligning_key_bindings.xml74
-rw-r--r--manual/xml/editor_canvas_key_bindings.xml112
-rw-r--r--manual/xml/editor_edit_cursor_position_key_bindings.xml133
-rw-r--r--manual/xml/editor_locations_marks_key_bindings.xml62
-rw-r--r--manual/xml/editor_miscellaneous_key_bindings.xml52
-rw-r--r--manual/xml/editor_nudging_key_bindings.xml73
-rw-r--r--manual/xml/editor_play_position_key_bindings.xml122
-rw-r--r--manual/xml/editor_range_operations_key_bindings.xml83
-rw-r--r--manual/xml/editor_region_operations_key_bindings.xml92
-rw-r--r--manual/xml/editor_standard_editing_key_bindings.xml92
-rw-r--r--manual/xml/editor_window.xml88
-rw-r--r--manual/xml/editor_window_controls.xml345
-rw-r--r--manual/xml/editor_window_group_list.xml28
-rw-r--r--manual/xml/editor_window_key_bindings.xml82
-rw-r--r--manual/xml/editor_window_region_list.xml152
-rw-r--r--manual/xml/editor_window_timeline.xml113
-rw-r--r--manual/xml/editor_window_track_list.xml67
-rw-r--r--manual/xml/editor_zoom_key_bindings.xml62
-rw-r--r--manual/xml/entities.ent11
-rw-r--r--manual/xml/exporting.xml15
-rw-r--r--manual/xml/exporting_to_cd.xml190
-rw-r--r--manual/xml/formatting_conventions.xml141
-rw-r--r--manual/xml/frontier_design_tranzport.xml558
-rw-r--r--manual/xml/general_key_bindings.xml122
-rw-r--r--manual/xml/generic_midi_control_surface.xml16
-rw-r--r--manual/xml/generic_mouse_actions.xml74
-rw-r--r--manual/xml/glossary.xml304
-rw-r--r--manual/xml/introduction.xml30
-rw-r--r--manual/xml/jack.xml292
-rw-r--r--manual/xml/key_bindings.xml84
-rw-r--r--manual/xml/known_issues.xml96
-rw-r--r--manual/xml/main_windows.xml92
-rw-r--r--manual/xml/midi_configuration.xml299
-rw-r--r--manual/xml/mixer_strip_list.xml96
-rw-r--r--manual/xml/mixer_strips.xml519
-rw-r--r--manual/xml/mixer_window.xml89
-rw-r--r--manual/xml/mixer_window_key_bindings.xml96
-rw-r--r--manual/xml/mixing.xml22
-rw-r--r--manual/xml/monitoring.xml203
-rw-r--r--manual/xml/mouse_operations.xml42
-rw-r--r--manual/xml/mouse_operations_mixer_controls.xml202
-rw-r--r--manual/xml/mouse_operations_object_mode.xml334
-rw-r--r--manual/xml/mouse_operations_range_mode.xml106
-rw-r--r--manual/xml/mouse_operations_region_gain_mode.xml73
-rw-r--r--manual/xml/mouse_operations_ruler.xml111
-rw-r--r--manual/xml/mouse_operations_zoom_mode.xml73
-rw-r--r--manual/xml/mouse_wheel_actions.xml82
-rw-r--r--manual/xml/opening_a_session.xml53
-rw-r--r--manual/xml/other_windows.xml246
-rw-r--r--manual/xml/plugins.xml60
-rw-r--r--manual/xml/preface.xml16
-rw-r--r--manual/xml/recording.xml19
-rw-r--r--manual/xml/renaming_tracks.xml59
-rw-r--r--manual/xml/saving_a_session.xml32
-rw-r--r--manual/xml/sessions.xml29
-rw-r--r--manual/xml/setting_up_to_record.xml235
-rw-r--r--manual/xml/snapshots.xml44
-rw-r--r--manual/xml/starting_up_your_system.xml14
-rw-r--r--manual/xml/synchronization.xml17
-rw-r--r--manual/xml/synchronization_concepts.xml170
-rw-r--r--manual/xml/templates.xml47
-rw-r--r--manual/xml/tracks_and_busses.xml323
-rw-r--r--manual/xml/transport_key_bindings.xml82
-rw-r--r--manual/xml/user_interface_conventions.xml183
-rw-r--r--manual/xml/using_existing_audio.xml442
-rw-r--r--manual/xml/video_synchronization_via_mtc.xml115
-rw-r--r--manual/xml/vst_plugins.xml51
-rw-r--r--manual/xml/what_is_different_about_ardour.xml133
-rw-r--r--manual/xml/why_is_it_called_ardour.xml222
-rw-r--r--manual/xml/working_with_crossfades.xml224
-rw-r--r--manual/xml/working_with_layers.xml151
-rw-r--r--manual/xml/working_with_playlists.xml233
-rw-r--r--manual/xml/working_with_ranges.xml38
-rw-r--r--manual/xml/working_with_regions.xml645
-rw-r--r--manual/xmlformat/BUGS55
-rw-r--r--manual/xmlformat/ChangeLog28
-rw-r--r--manual/xmlformat/INSTALL29
-rw-r--r--manual/xmlformat/LICENSE93
-rw-r--r--manual/xmlformat/README35
-rw-r--r--manual/xmlformat/xmlformat-ardour.conf137
-rwxr-xr-xmanual/xmlformat/xmlformat.pl1745
-rw-r--r--manual/xsl/html.xsl158
-rw-r--r--svn_revision.h2
-rw-r--r--templates/2 Track.template.in2
-rw-r--r--tools/Spotlight Importer/GetMetadataForFile.c1
-rw-r--r--tools/Spotlight Importer/Info.plist10
-rw-r--r--tools/Spotlight Importer/Spotlight Importer.xcodeproj/project.pbxproj10
-rwxr-xr-xvst/ardevst2
705 files changed, 43607 insertions, 7536 deletions
diff --git a/Makefile b/Makefile
index 1a39c6d179..becce0e48c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-all: scons cscope
+all: scons
scons:
scons
diff --git a/SConstruct b/SConstruct
index 0a58a46596..906b04949e 100644
--- a/SConstruct
+++ b/SConstruct
@@ -16,7 +16,7 @@ import SCons.Node.FS
SConsignFile()
EnsureSConsVersion(0, 96)
-ardour_version = '2.0beta11.1'
+ardour_version = '2.0beta12'
subst_dict = { }
@@ -41,9 +41,11 @@ opts.AddOptions(
PathOption('PREFIX', 'Set the install "prefix"', '/usr/local'),
BoolOption('SURFACES', 'Build support for control surfaces', 1),
BoolOption('SYSLIBS', 'USE AT YOUR OWN RISK: CANCELS ALL SUPPORT FROM ARDOUR AUTHORS: Use existing system versions of various libraries instead of internal ones', 0),
+ BoolOption('UNIVERSAL', 'Compile as universal binary. Requires that external libraries are already universal.', 0),
BoolOption('VERSIONED', 'Add revision information to ardour/gtk executable name inside the build directory', 0),
BoolOption('VST', 'Compile with support for VST', 0),
- BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 0)
+ BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
+ BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1)
)
#----------------------------------------------------------------------
@@ -311,7 +313,7 @@ env.Append (BUILDERS = {'VersionBuild' : version_bld})
#
def versioned_builder(target,source,env):
- w, r = os.popen2( "svn info | awk '/^Revision:/ { print $2}'")
+ w, r = os.popen2( "LANG= svn info | awk '/^Revision:/ { print $2}'")
last_revision = r.readline().strip()
w.close()
@@ -530,7 +532,10 @@ env = conf.Finish()
#
opt_flags = []
-debug_flags = [ '-g' ]
+if env['GPROFILE'] == 1:
+ debug_flags = [ '-g', '-pg' ]
+else:
+ debug_flags = [ '-g' ]
# guess at the platform, used to define compiler flags
@@ -596,7 +601,7 @@ elif ((re.search ("i[0-9]86", config[config_cpu]) != None) or (re.search ("x86_6
if env['DIST_TARGET'] != 'i386':
flag_line = os.popen ("cat /proc/cpuinfo | grep '^flags'").read()[:-1]
- x86_flags = flag_line.split (": ")[1:][0].split (' ')
+ x86_flags = flag_line.split (": ")[1:][0].split ()
if "mmx" in x86_flags:
opt_flags.append ("-mmmx")
@@ -660,13 +665,19 @@ opt_flags[:0] = [
"-fomit-frame-pointer",
"-ffast-math",
"-fstrength-reduce",
- "-fno-strict-aliasing"
+ "-pipe"
]
if env['DEBUG'] == 1:
env.Append(CCFLAGS=" ".join (debug_flags))
+ env.Append(LINKFLAGS=" ".join (debug_flags))
else:
env.Append(CCFLAGS=" ".join (opt_flags))
+ env.Append(LINKFLAGS=" ".join (opt_flags))
+
+if env['UNIVERSAL'] == 1:
+ env.Append(CCFLAGS="-arch i386 -arch ppc")
+ env.Append(LINKFLAGS="-arch i386 -arch ppc")
#
# warnings flags
@@ -676,8 +687,9 @@ env.Append(CCFLAGS="-Wall")
env.Append(CXXFLAGS="-Woverloaded-virtual")
if env['EXTRA_WARN']:
- env.Append(CCFLAGS="-Wextra -pedantic")
+ env.Append(CCFLAGS="-Wextra -pedantic -ansi")
env.Append(CXXFLAGS="-ansi")
+# env.Append(CFLAGS="-iso")
if env['LIBLO']:
env.Append(CCFLAGS="-DHAVE_LIBLO")
@@ -837,7 +849,7 @@ if env['SYSLIBS']:
libraries['sndfile-ardour'] = LibraryInfo(LIBS='libsndfile-ardour',
LIBPATH='#libs/libsndfile',
- CPPPATH=['#libs/libsndfile', '#libs/libsndfile/src'])
+ CPPPATH=['#libs/libsndfile/src'])
# libraries['libglademm'] = LibraryInfo()
# libraries['libglademm'].ParseConfig ('pkg-config --cflags --libs libglademm-2.4')
@@ -957,11 +969,14 @@ else:
# its included in the tarball
#
-surface_subdirs = [ 'libs/surfaces/control_protocol', 'libs/surfaces/generic_midi', 'libs/surfaces/tranzport' ]
+surface_subdirs = [ 'libs/surfaces/control_protocol', 'libs/surfaces/generic_midi', 'libs/surfaces/tranzport', 'libs/surfaces/mackie' ]
if env['SURFACES']:
if have_libusb:
- env['TRANZPORT'] = 'yes'
+ env['TRANZPORT'] = 1
+ else:
+ env['TRANZPORT'] = 0
+ print 'Disabled building Tranzport code because libusb could not be found'
if os.access ('libs/surfaces/sony9pin', os.F_OK):
surface_subdirs += [ 'libs/surfaces/sony9pin' ]
@@ -1076,6 +1091,13 @@ if not conf.CheckFunc('posix_memalign'):
env = conf.Finish()
rcbuild = env.SubstInFile ('ardour.rc','ardour.rc.in', SUBST_DICT = subst_dict)
+subst_dict['%VERSION%'] = ardour_version[0:3]
+subst_dict['%EXTRA_VERSION%'] = ardour_version[3:]
+subst_dict['%REVISION_STRING%'] = ''
+if os.path.exists('.svn'):
+ subst_dict['%REVISION_STRING%'] = '.' + fetch_svn_revision ('.') + 'svn'
+
+# specbuild = env.SubstInFile ('ardour.spec','ardour.spec.in', SUBST_DICT = subst_dict)
the_revision = env.Command ('frobnicatory_decoy', [], create_stored_revision)
diff --git a/ardour.dox b/ardour.dox
index 0ff7c85a41..6b4f419a9e 100644
--- a/ardour.dox
+++ b/ardour.dox
@@ -459,8 +459,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-#INPUT = libs/pbd libs/midi++2 libs/ardour libs/gtkmm2ext gtk2_ardour
-INPUT = libs/ardour gtk2_ardour
+INPUT = libs/pbd libs/midi++2 libs/ardour libs/surfaces libs/gtkmm2ext gtk2_ardour
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
@@ -557,7 +556,7 @@ FILTER_SOURCE_FILES = NO
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.
-SOURCE_BROWSER = NO
+SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.
@@ -604,7 +603,7 @@ VERBATIM_HEADERS = YES
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.
-ALPHABETICAL_INDEX = NO
+ALPHABETICAL_INDEX = YES
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
@@ -767,7 +766,7 @@ COMPACT_LATEX = NO
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
-PAPER_TYPE = a4wide
+PAPER_TYPE = letter
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
@@ -792,7 +791,7 @@ PDF_HYPERLINKS = NO
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
-USE_PDFLATEX = NO
+USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
@@ -1006,7 +1005,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED = HAVE_COREAUDIO VST_SUPPORT HAVE_LIBLO FFT_ANALYSIS
+PREDEFINED = HAVE_LIBLO FFT_ANALYSIS
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
index 4dfe0b7322..60e7bca331 100644
--- a/gtk2_ardour/SConscript
+++ b/gtk2_ardour/SConscript
@@ -147,7 +147,6 @@ export_range_markers_dialog.cc
gain_automation_time_axis.cc
gain_meter.cc
ghostregion.cc
-grouped_buttons.cc
gtk-custom-hruler.c
gtk-custom-ruler.c
imageframe.cc
@@ -276,6 +275,13 @@ rcu = gtkardour.Program(target = 'rcu', source = rcu_files)
tt = gtkmmtests.Program(target = 'tt', source = tt_files)
my_subst_dict = { }
+
+#
+# null substitution just to avoid ardour.bindings being in svn
+#
+
+ardourbindings = env.SubstInFile ('ardour.bindings', 'ardour.bindings.in', SUBST_DICT = my_subst_dict);
+
my_subst_dict['%INSTALL_PREFIX%'] = final_prefix
my_subst_dict['%LIBDIR%'] = env['LIBDIR']
my_subst_dict['%VERSION%'] = ardour_version
@@ -286,6 +292,7 @@ env.AddPostAction (ardoursh, Chmod ('$TARGET', 0755))
ardourdev = env.SubstInFile ('ardev_common.sh','ardev_common.sh.in', SUBST_DICT = my_subst_dict);
env.AddPostAction (ardourdev, Chmod ('$TARGET', 0755))
+Default(ardourbindings)
Default(ardourdev)
Default(ardoursh)
@@ -329,7 +336,7 @@ env.Alias ('tarball', env.Distribute (env['DISTTREE'],
'ardour.sh.in',
'ardev_common.sh.in',
'ardour2_ui.rc', 'splash.png',
- 'ardour.menus', 'ardour.bindings', 'ardour.colors',
+ 'ardour.menus', 'ardour.bindings.in', 'ardour.colors',
'editor_xpms'
] +
gtkardour_files +
diff --git a/gtk2_ardour/about.cc b/gtk2_ardour/about.cc
index 34bb98199c..b0ec4f1436 100644
--- a/gtk2_ardour/about.cc
+++ b/gtk2_ardour/about.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -145,8 +144,13 @@ static const char* authors[] = {
N_("Stefan Kersten"),
N_("Christopher George"),
N_("Robert Jordens"),
+ N_("Dave Robillard"),
+ N_("Hans Fugal"),
N_("Brian Ahr"),
N_("Nimal Ratnayake"),
+ N_("Mike Täht"),
+ N_("John Anderson"),
+ N_("Nedko Arnaudov"),
0
};
diff --git a/gtk2_ardour/about.h b/gtk2_ardour/about.h
index 3468a31a19..2eb02dd223 100644
--- a/gtk2_ardour/about.h
+++ b/gtk2_ardour/about.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_about_h__
diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc
index d382878582..6e4a525ba7 100644
--- a/gtk2_ardour/actions.cc
+++ b/gtk2_ardour/actions.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <vector>
diff --git a/gtk2_ardour/add_route_dialog.cc b/gtk2_ardour/add_route_dialog.cc
index 591fe64244..ea8233ff52 100644
--- a/gtk2_ardour/add_route_dialog.cc
+++ b/gtk2_ardour/add_route_dialog.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdio>
@@ -149,7 +148,7 @@ AddRouteDialog::track_type_chosen ()
if (track_button.get_active()) {
track_mode_combo.set_sensitive (true);
} else {
- track_mode_combo.set_sensitive (true);
+ track_mode_combo.set_sensitive (false);
}
}
diff --git a/gtk2_ardour/analysis_window.cc b/gtk2_ardour/analysis_window.cc
index dd749d2bb1..957dde3d1f 100644
--- a/gtk2_ardour/analysis_window.cc
+++ b/gtk2_ardour/analysis_window.cc
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <gtkmm2ext/gtk_ui.h>
diff --git a/gtk2_ardour/ardbg b/gtk2_ardour/ardbg
index 95466a42b8..ab99296f45 100755
--- a/gtk2_ardour/ardbg
+++ b/gtk2_ardour/ardbg
@@ -1,4 +1,5 @@
#!/bin/sh
dir=`dirname "$0"`
. $dir/ardev_common.sh
+LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
exec gdb $EXECUTABLE $*
diff --git a/gtk2_ardour/ardev b/gtk2_ardour/ardev
index ff68e11fbe..5dd8fc9d13 100755
--- a/gtk2_ardour/ardev
+++ b/gtk2_ardour/ardev
@@ -1,3 +1,4 @@
#!/bin/sh
. `dirname "$0"`/ardev_common.sh
+LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
exec $EXECUTABLE $*
diff --git a/gtk2_ardour/ardour.bindings b/gtk2_ardour/ardour.bindings.in
index 3c7afcde6c..d8316a0147 100644
--- a/gtk2_ardour/ardour.bindings
+++ b/gtk2_ardour/ardour.bindings.in
@@ -9,7 +9,7 @@
; (gtk_accel_path "<Actions>/JACK/JACKReconnect" "")
; (gtk_accel_path "<Actions>/Editor/Autoconnect" "")
; (gtk_accel_path "<Actions>/Editor/Edit" "")
-(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-end" "<Control>grave")
+(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-end" "<Control>comma")
; (gtk_accel_path "<Actions>/redirectmenu/copy" "")
; (gtk_accel_path "<Actions>/options/MeterFalloffFaster" "")
(gtk_accel_path "<Actions>/Transport/ToggleRollForgetCapture" "<Control>space")
@@ -23,7 +23,7 @@
; (gtk_accel_path "<Actions>/options/MeterFalloffSlow" "")
; (gtk_accel_path "<Actions>/RegionList/rlHide" "")
; (gtk_accel_path "<Actions>/Main/Metering" "")
-(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-end" "<Control>Tab")
+(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-end" "<Control>period")
; (gtk_accel_path "<Actions>/Zoom/zoom-focus-playhead" "")
; (gtk_accel_path "<Actions>/Editor/center-edit-cursor" "")
; (gtk_accel_path "<Actions>/Editor/Monitoring" "")
@@ -61,7 +61,7 @@
(gtk_accel_path "<Actions>/Editor/jump-backward-to-mark" "<Control>KP_Left")
; (gtk_accel_path "<Actions>/Main/AudioFileFormatData" "")
; (gtk_accel_path "<Actions>/options/MeterFalloffFastest" "")
-(gtk_accel_path "<Actions>/Editor/audition-at-mouse" "period")
+; (gtk_accel_path "<Actions>/Editor/audition-at-mouse" "")
(gtk_accel_path "<Actions>/Transport/Forward" "<Control>rightarrow")
; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-seconds" "")
; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-frame" "")
@@ -93,7 +93,7 @@
(gtk_accel_path "<Actions>/Editor/set-edit-cursor" "e")
; (gtk_accel_path "<Actions>/Editor/Smpte30drop" "")
; (gtk_accel_path "<Actions>/Zoom/zoom-focus-edit" "")
-(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-start" "grave")
+(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-start" "comma")
; (gtk_accel_path "<Actions>/Editor/EditCursorMovementOptions" "")
; (gtk_accel_path "<Actions>/redirectmenu/activate_all" "")
; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTapeTrack" "")
@@ -112,7 +112,6 @@
(gtk_accel_path "<Actions>/Editor/extend-range-to-end-of-region" "rightanglebracket")
(gtk_accel_path "<Actions>/Editor/scroll-backward" "leftarrow")
(gtk_accel_path "<Actions>/Editor/start-range" "<Control>KP_Down")
-; (gtk_accel_path "<Actions>/Editor/ToggleTranzportSurface" "")
; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsSemitones" "")
; (gtk_accel_path "<Actions>/JACK/JACKLatency128" "")
; (gtk_accel_path "<Actions>/Snap/snap-to-beat" "")
@@ -124,6 +123,7 @@
; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
(gtk_accel_path "<Actions>/Editor/crop" "c")
; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "")
; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
(gtk_accel_path "<Actions>/Transport/GotoStart" "Home")
@@ -151,6 +151,7 @@
(gtk_accel_path "<Actions>/Common/goto-editor" "<Alt>e")
(gtk_accel_path "<Actions>/Editor/select-all" "<Control>a")
(gtk_accel_path "<Actions>/Editor/nudge-next-forward" "<Control>KP_Add")
+; (gtk_accel_path "<Actions>/options/ShowSoloMutes" "")
; (gtk_accel_path "<Actions>/Snap/snap-to-eighths" "")
(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<Shift><Control>p")
(gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11")
@@ -272,7 +273,7 @@
; (gtk_accel_path "<Actions>/options/VerifyRemoveLastCapture" "")
; (gtk_accel_path "<Actions>/options/OutputAutoConnectPhysical" "")
(gtk_accel_path "<Actions>/Editor/step-tracks-up" "uparrow")
-(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-start" "Tab")
+(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-start" "period")
; (gtk_accel_path "<Actions>/options/SendMMC" "")
; (gtk_accel_path "<Actions>/Editor/toggle-auto-xfades" "")
; (gtk_accel_path "<Actions>/Main/AudioFileFormatHeader" "")
@@ -305,6 +306,7 @@
; (gtk_accel_path "<Actions>/Snap/snap-to-region-sync" "")
(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-sync" "apostrophe")
; (gtk_accel_path "<Actions>/redirectmenu/clear" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceFeedback" "")
; (gtk_accel_path "<Actions>/Editor/PullupPlus4Minus1" "")
; (gtk_accel_path "<Actions>/JACK/JACKLatency512" "")
(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-end" "<Control>bracketright")
diff --git a/gtk2_ardour/ardour.colors b/gtk2_ardour/ardour.colors
index 456859162f..9cf1ad359f 100644
--- a/gtk2_ardour/ardour.colors
+++ b/gtk2_ardour/ardour.colors
@@ -101,3 +101,6 @@ cTrimHandleLockedStart 0.92 0.06 0.06 0.16
cTrimHandleLockedEnd 0.92 0.06 0.06 0.16
cTrimHandleStart 0.10 0.00 1.00 0.27
cTrimHandleEnd 0.10 0.00 1.00 0.27
+cEditCursor 0.00 0.00 1.00 1.00
+cPlayHead 1.00 0.00 0.00 1.00
+
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus
index 040c6464c1..f24d5280ea 100644
--- a/gtk2_ardour/ardour.menus
+++ b/gtk2_ardour/ardour.menus
@@ -291,8 +291,12 @@
<menuitem action='OutputAutoConnectMaster'/>
<menuitem action='OutputAutoConnectManual'/>
</menu>
- <menu action='ControlSurfaces'/>
- <menu action='Monitoring'>
+ <menu action='ControlSurfaces'>
+ <menuitem action='RemoteUserDefined'/>
+ <menuitem action='RemoteMixerDefined'/>
+ <menuitem action='RemoteEditorDefined'/>
+ </menu>
+ <menu action='Monitoring'>
<menuitem action='UseHardwareMonitoring'/>
<menuitem action='UseSoftwareMonitoring'/>
<menuitem action='UseExternalMonitoring'/>
@@ -318,6 +322,7 @@
<menuitem action='LatchedSolo'/>
<menuitem action='SoloInPlace'/>
<menuitem action='SoloViaBus'/>
+ <menuitem action='ShowSoloMutes'/>
</menu>
<menu action='Crossfades'>
<menuitem action='toggle-xfades-active'/>
@@ -337,6 +342,7 @@
<menuitem action='SendMMC'/>
<menuitem action='UseMMC'/>
<separator/>
+ <menuitem action='UseOSC'/>
<menuitem action='StopPluginsWithTransport'/>
<menuitem action='DoNotRunPluginsWhileRecording'/>
<menuitem action='LatchedRecordEnable'/>
diff --git a/gtk2_ardour/ardour2_ui.rc b/gtk2_ardour/ardour2_ui.rc
index 7d03368076..b008a4cd17 100644
--- a/gtk2_ardour/ardour2_ui.rc
+++ b/gtk2_ardour/ardour2_ui.rc
@@ -80,7 +80,7 @@ style "marker_text"
style "time_axis_view_item_name"
{
- font_name = "sans 6"
+ font_name = "sans 9"
}
style "default_base" = "medium_text"
@@ -185,24 +185,58 @@ style "small_red_active_and_selected_button" = "small_button"
bg[SELECTED] = { 1.0, 0, 0}
}
+style "gain_fader"
+{
+ bg[NORMAL] = { 0.269, 0.269, 0.300}
+ bg[ACTIVE] = { 0.152, 0.152, 0.168 }
+}
+
+
style "track_rec_enable_button" = "small_button"
{
+}
+
+style "track_rec_enable_button_active" = "small_button"
+{
fg[SELECTED] = { 0.0, 0.0, 0.0 }
fg[ACTIVE] = { 0.0, 0.0, 0.0 }
fg[PRELIGHT] = { 0.0, 0.0, 0.0 }
+ fg[NORMAL] = { 0.0, 0.0, 0.0 }
+ bg[NORMAL] = { 1.0, 0.0, 0.0 }
+ bg[ACTIVE] = { 1.0, 0.0, 0.0 }
bg[SELECTED] = { 1.0, 0.0, 0.0 }
- bg[ACTIVE] = { 0.91, 0.68, 0.68}
bg[PRELIGHT] = { 1.0, 0.0, 0.0 }
}
-style "gain_fader"
+style "track_rec_enable_button_alternate" = "small_button"
{
- bg[NORMAL] = { 0.269, 0.269, 0.300}
- bg[ACTIVE] = { 0.152, 0.152, 0.168 }
+ fg[SELECTED] = { 0.0, 0.0, 0.0 }
+ fg[ACTIVE] = { 0.0, 0.0, 0.0 }
+ fg[PRELIGHT] = { 0.0, 0.0, 0.0 }
+ fg[NORMAL] = { 0.0, 0.0, 0.0 }
+
+ bg[NORMAL] = { 0.91, 0.68, 0.68}
+ bg[ACTIVE] = { 0.91, 0.68, 0.68}
+ bg[SELECTED] = { 0.91, 0.68, 0.68}
+ bg[PRELIGHT] = { 0.91, 0.68, 0.68}
+}
+
+style "mixer_track_rec_enable_button" = "track_rec_enable_button"
+{
+ font_name = "sans 7"
+ xthickness = 0
+ ythickness = 0
}
-style "mixer_rec_enable_button" = "track_rec_enable_button"
+style "mixer_track_rec_enable_button_alternate" = "track_rec_enable_button_alternate"
+{
+ font_name = "sans 7"
+ xthickness = 0
+ ythickness = 0
+}
+
+style "mixer_track_rec_enable_button_active" = "track_rec_enable_button_active"
{
font_name = "sans 7"
xthickness = 0
@@ -211,20 +245,33 @@ style "mixer_rec_enable_button" = "track_rec_enable_button"
style "solo_button" = "small_button"
{
- bg[PRELIGHT] = { 0, 1.0, 0 }
- bg[ACTIVE] = { 0.66, 0.97, 0.19 }
+}
+
+style "solo_button_alternate" = "small_button"
+{
+ bg[NORMAL] = { 0.19, 0.97, 0.69 } # solo-safe
+ bg[ACTIVE] = { 0.19, 0.97, 0.69 } # solo-safe
+ bg[SELECTED] = { 0.19, 0.97, 0.69 } # solo-safe
+ bg[PRELIGHT] = { 0.19, 0.97, 0.69 } # solo-safe
- fg[PRELIGHT] = { 0, 0, 0 }
fg[ACTIVE] = { 0, 0, 0 }
+ fg[SELECTED] = { 0, 0, 0 }
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[PRELIGHT] = { 0, 0, 0 }
}
-style "safe_solo_button" = "small_button"
+
+style "solo_button_active" = "small_button"
{
- bg[PRELIGHT] = { 0, 1.0, 0 }
- bg[ACTIVE] = { 0.19, 0.97, 0.69 }
+ bg[NORMAL] = { 0.66, 0.97, 0.19 } # solo
+ bg[ACTIVE] = { 0.66, 0.97, 0.19 } # solo
+ bg[SELECTED] = { 0.66, 0.97, 0.19 } # solo
+ bg[PRELIGHT] = { 0.66, 0.97, 0.19 } # solo
- fg[PRELIGHT] = { 0, 0, 0 }
fg[ACTIVE] = { 0, 0, 0 }
+ fg[SELECTED] = { 0, 0, 0 }
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[PRELIGHT] = { 0, 0, 0 }
}
style "mixer_solo_button" = "solo_button"
@@ -232,27 +279,72 @@ style "mixer_solo_button" = "solo_button"
font_name = "sans 7"
xthickness = 0
ythickness = 0
-
}
-style "mixer_safe_solo_button" = "safe_solo_button"
+style "mixer_solo_button_alternate" = "solo_button_alternate"
+{
+ font_name = "sans 7"
+ xthickness = 0
+ ythickness = 0
+}
+style "mixer_solo_button_active" = "solo_button_active"
{
font_name = "sans 7"
xthickness = 0
ythickness = 0
-
}
style "mute_button" = "small_button"
{
- bg[PRELIGHT] = { 1.0, 0.65, 0.13 }
+}
+
+style "mute_button_alternate" = "small_button"
+{
bg[ACTIVE] = { 1.0, 0.98, 0.53 }
-
+ bg[NORMAL] = { 1.0, 0.98, 0.53 }
+ bg[SELECTED] = { 1.0, 0.98, 0.53 }
+ bg[PRELIGHT] = { 1.0, 0.98, 0.53 }
+
+ fg[SELECTED] = { 0, 0, 0 }
+ fg[ACTIVE] = { 0, 0, 0 }
+ fg[NORMAL] = { 0, 0, 0 }
fg[PRELIGHT] = { 0, 0, 0 }
+}
+
+style "mute_button_active" = "small_button"
+{
+ bg[NORMAL] = { 0.90, 0.89, 0.73 }
+ bg[ACTIVE] = { 0.90, 0.89, 0.73 }
+ bg[PRELIGHT] = { 0.90, 0.89, 0.73 }
+ bg[SELECTED] = { 0.90, 0.89, 0.73 }
+
+ fg[SELECTED] = { 0, 0, 0 }
fg[ACTIVE] = { 0, 0, 0 }
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[PRELIGHT] = { 0, 0, 0 }
}
+style "mixer_mute_button" = "mute_button"
+{
+ font_name = "sans 7"
+ xthickness = 0
+ ythickness = 0
+}
+
+style "mixer_mute_button_alternate" = "mute_button_alternate"
+{
+ font_name = "sans 7"
+ xthickness = 0
+ ythickness = 0
+}
+
+style "mixer_mute_button_active" = "mute_button_active"
+{
+ font_name = "sans 7"
+ xthickness = 0
+ ythickness = 0
+}
style "multiline_combo" = "small_button"
{
@@ -291,14 +383,39 @@ style "time_button" = "default_buttons_menus"
style "transport_button"
{
+}
+
+style "transport_button_active"
+{
+ bg[NORMAL] = { 0.50, 1.0, 0.50 }
bg[ACTIVE] = { 0.50, 1.0, 0.50 }
+ bg[SELECTED] = { 0.50, 1.0, 0.50 }
+ bg[PRELIGHT] = { 0.50, 1.0, 0.50 }
+
+ fg[NORMAL] = { 0, 0, 0 }
+ fg[PRELIGHT] = { 0, 0, 0 }
+ fg[SELECTED] = { 0, 0, 0 }
fg[ACTIVE] = { 0, 0, 0 }
}
style "transport_rec_button"
{
+}
+
+style "transport_rec_button_active"
+{
bg[ACTIVE] = { 1.0, 0, 0 }
- bg[PRELIGHT] = { 0.91, 0.68, 0.68 } #blinking rec button color
+ bg[NORMAL] = { 1.0, 0, 0 }
+ bg[SELECTED] = { 1.0, 0, 0 }
+ bg[PRELIGHT] = { 1.0, 0, 0 }
+}
+
+style "transport_rec_button_alternate"
+{
+ bg[PRELIGHT] = { 0.91, 0.68, 0.68 }
+ bg[NORMAL] = { 0.91, 0.68, 0.68 }
+ bg[SELECTED] = { 0.91, 0.68, 0.68 }
+ bg[ACTIVE] = { 0.91, 0.68, 0.68 }
}
style "shuttle_control" = "very_small_text"
@@ -1034,361 +1151,366 @@ style "ardour_button" ="default_buttons_menus"
}
#---------------------------------------------------------------
-widget "*FirstActionMessage" style "first_action_message"
-widget "*VerboseCanvasCursor" style "verbose_canvas_cursor"
-widget "*MarkerText" style "marker_text"
-widget "*TimeAxisViewItemName*" style "time_axis_view_item_name"
-#widget "*ExportProgress" style "default_buttons_menus"
-widget "*ExportFileLabel" style "small_bold_text"
-widget "*ExportFormatLabel" style "medium_bold_text"
-widget "*ExportHeader" style "small_bold_text"
-widget "*ExportFileDisplay" style "medium_entry"
-widget "*ExportFormatDisplay" style "medium_entry"
-widget "*ExportCheckbox" style "small_entry"
-widget "*ExportTrackSelector*" style "medium_entry_noselection_bg"
-widget "*ArdourContextMenu*" style "default_buttons_menus"
-widget "*EditGroupTitleButton*" style "default_buttons_menus"
-widget "*MixerGroupTitleButton*" style "default_buttons_menus"
-widget "*ErrorLogCloseButton" style "default_buttons_menus"
-widget "*EditorGTKButton*" style "default_buttons_menus"
-widget "*ToolbarButton" style "default_buttons_menus"
-widget "*ToolbarButton*" style "default_buttons_menus"
-widget "*CrossfadeEditButton" style "default_buttons_menus"
-widget "*CrossfadeEditButton*" style "default_buttons_menus"
-widget "*TrackHistoryButton*" style "default_buttons_menus"
-widget "*TrackSizeButton*" style "default_buttons_menus"
-widget "*TrackPlaylistButton*" style "default_buttons_menus"
-widget "*TrackAutomationButton*" style "default_buttons_menus"
-widget "*TrackGroupButton*" style "default_buttons_menus"
-widget "*TrackMixButton*" style "default_buttons_menus"
-widget "*TrackVisualButton*" style "default_buttons_menus"
-widget "*TrackRemoveButton*" style "default_buttons_menus"
-widget "*BaseButton" style "default_buttons_menus"
-widget "*TakeButtonLabel" style "default_buttons_menus"
-widget "*MixerWidthButton" style "default_buttons_menus"
-widget "*MixerHideButton" style "default_buttons_menus"
-widget "*MixerSendButton" style "default_buttons_menus"
-widget "*MixerSendButtonLabel" style "default_buttons_menus"
-widget "*MixerSendSwitch" style "default_buttons_menus"
-widget "*MixerInsertButton" style "default_buttons_menus"
-widget "*MixerInsertButtonLabel" style "default_buttons_menus"
-widget "*MixerInsertSwitch" style "default_buttons_menus"
-widget "*MixerMonitorInputButton*" style "very_small_button"
-widget "*MixerMonitorInputButton.*" style "very_small_button"
-widget "*MixerIOButton" style "very_small_button"
-widget "*MixerIOButtonLabel" style "very_small_button"
-widget "*AddRouteDialogSpinner" style "ardour_adjusters"
-widget "*AddRouteDialogRadioButton*" style "options_window"
-widget "*OptionsNotebook" style "options_window"
-widget "*OptionEditorToggleButton*" style "options_window"
-widget "*OptionsLabel" style "options_window"
-widget "*OptionEditorAuditionerLabel" style "options_window"
-widget "*OptionsEntry" style "option_entry"
-widget "*InspectorNotebook" style "options_window"
-widget "*NewSessionDialog" style "options_window"
-widget "*NewSessionDialogButton*" style "options_window"
-widget "*MixerSendSwitch*" style "very_small_red_active_and_selected_button"
-widget "*OptionEditorToggleButton" style "small_red_active_and_selected_button"
-widget "*NewSessionDialogButton" style "small_red_active_and_selected_button"
-widget "*MixerRecordEnableButton" style "mixer_rec_enable_button"
-widget "*MixerRecordEnableButton*" style "mixer_rec_enable_button"
-widget "*TrackRecordEnableButton" style "track_rec_enable_button"
-widget "*TrackRecordEnableButton*" style "track_rec_enable_button"
-widget "*TrackMuteButton*" style "mute_button"
-widget "*TrackLoopButton*" style "track_loop_button"
-widget "*PanAutomationLineSelector*" style "multiline_combo"
-widget "*EditorTimeButton*" style "time_button"
-widget "*EditorMixerButton*" style "default_buttons_menus"
-widget "*SoloButton*" style "solo_button"
-widget "*SoloButton.*" style "solo_button"
-widget "*SafeSoloButton*" style "safe_solo_button"
-widget "*SafeSoloButton.*" style "safe_solo_button"
-widget "*MixerPhaseInvertButton*" style "very_small_button"
-widget "*MixerPhaseInvertButton.*" style "very_small_button"
-widget "*MixerAutomationRecordingButton*" style "very_small_button"
-widget "*MixerAutomationRecordingButton.*" style "very_small_button"
-widget "*MixerAutomationModeButton*" style "very_small_button"
-widget "*MixerAutomationModeButton.*" style "very_small_button"
-widget "*MixerAutomationPlaybackButton*" style "very_small_button"
-widget "*MixerAutomationPlaybackButton.*" style "very_small_button"
-widget "*MixerMuteButton*" style "mixer_mute_button"
-widget "*MixerMuteButton.*" style "mixer_mute_button"
-widget "*MixerSoloButton*" style "mixer_solo_button"
-widget "*MixerSoloButton.*" style "mixer_solo_button"
-widget "*MixerNameButton" style "very_small_button"
-widget "*MixerNameButtonLabel" style "very_small_button"
-widget "*MixerGroupButton" style "very_small_button"
-widget "*MixerGroupButtonLabel" style "very_small_button"
-widget "*MixerCommentButton" style "very_small_button"
-widget "*MixerCommentButton*" style "very_small_button"
-widget "*EditGroupButton" style "very_small_button"
-widget "*EditGroupButtonLabel" style "very_small_button"
-widget "*TransportButton" style "transport_button"
-widget "*TransportButton*" style "transport_button"
-widget "*ShuttleButton" style "transport_button"
-widget "*ShuttleButton*" style "transport_button"
-widget "*ShuttleDisplay" style "transport_button"
-widget "*ShuttleDisplay*" style "transport_button"
-widget "*ShuttleControl" style "shuttle_control"
-widget "*TransportRecButton" style "transport_rec_button"
-widget "*TransportRecButton*" style "transport_rec_button"
-widget "*RecordingXrunWarningWindow" style "xrun_warn"
-widget "*RecordingXrunWarningWindow*" style "xrun_warn"
-/*widget "*MainMenuBar" style "menu_bar_base"*/
-widget "*ErrorMessage" style "error_message"
-widget "*FatalMessage" style "fatal_message"
-widget "*InfoMessage" style "info_message"
-widget "*WarningMessage" style "warning_message"
-widget "*BigClockNonRecording" style "non_recording_big_clock_display"
-widget "*BigClockRecording" style "recording_big_clock_display"
-widget "*TransportClockDisplay" style "transport_clock_display"
-widget "*SecondaryClockDisplay" style "transport_clock_display"
-widget "*AudioClockFramesUpperInfo" style "tempo_meter_clock_display"
-widget "*AudioClockFramesLowerInfo" style "tempo_meter_clock_display"
-widget "*AudioClockSMPTEUpperInfo" style "tempo_meter_clock_display"
-widget "*AudioClockSMPTELowerInfo" style "tempo_meter_clock_display"
-widget "*AudioClockBBTUpperInfo" style "tempo_meter_clock_display"
-widget "*AudioClockBBTLowerInfo" style "tempo_meter_clock_display"
-widget "*SelectionStartClock" style "default_clock_display"
-widget "*SelectionEndClock" style "default_clock_display"
-widget "*EditCursorClock" style "default_clock_display"
-widget "*PreRollClock" style "default_clock_display"
-widget "*PostRollClock" style "default_clock_display"
-widget "*NudgeClock" style "default_clock_display"
-widget "*ZoomRangeClock" style "default_clock_display"
-widget "*SMPTEOffsetClock" style "default_clock_display"
-widget "*TransportLabel" style "small_bold_text"
-widget "*TakeLabel" style "small_bold_text"
-widget "*LocationLabel" style "small_bold_text"
-widget "*WipeLabel" style "small_bold_text"
-widget "*TakeTagLabel" style "small_bold_text"
-widget "*ToolBarLabel" style "small_bold_text"
-widget "*EditorDisplayLabel" style "small_bold_text"
-widget "*NewSessionLabel" style "large_text"
-widget "*GlobalButtonLabel" style "default_buttons_menus"
-widget "*ClickButton" style "medium_entry"
-widget "*RegionNameDisplay" style "medium_entry"
-widget "*PluginDisplay" style "medium_entry"
-widget "*SelectionDisplay" style "medium_entry"
-widget "*HistorySelector" style "medium_entry"
-widget "*LocationSelector" style "medium_entry"
-widget "*TakeSelector" style "medium_entry"
-widget "*RegionSelector" style "medium_entry"
-widget "*SMPTERuler" style "editor_time_ruler"
-widget "*BBTRuler" style "editor_time_ruler"
-widget "*FramesRuler" style "editor_time_ruler"
-widget "*MinSecRuler" style "editor_time_ruler"
-widget "*BaseFrame" style "base_frame"
-widget "*AudioBusControlsBaseUnselected" style "audio_bus_base"
-widget "*AudioBusControlsBaseInactiveUnselected" style "track_controls_inactive"
-widget "*AudioBusControlsBaseInactiveSelected" style "track_controls_inactive"
-widget "*AudioBusControlsBaseSelected" style "edit_controls_base_selected"
-widget "*AudioTimeAxisViewControlsBaseUnselected" style "audio_track_base"
-widget "*AudioTrackStripBase" style "audio_track_base"
-widget "*AudioTrackControlsBaseUnselected" style "audio_track_base"
-widget "*AudioTrackFader" style "gain_fader"
-widget "*AudioBusStripBase" style "audio_bus_base"
-widget "*AudioBusFader" style "gain_fader"
-widget "*MidiBusControlsBaseUnselected" style "midi_bus_base"
-widget "*MidiBusControlsBaseInactiveUnselected" style "track_controls_inactive"
-widget "*MidiBusControlsBaseInactiveSelected" style "track_controls_inactive"
-widget "*MidiBusControlsBaseSelected" style "edit_controls_base_selected"
-widget "*MidiTimeAxisViewControlsBaseUnselected" style "midi_track_base"
-widget "*MidiTrackStripBase" style "midi_track_base"
-widget "*MidiTrackControlsBaseUnselected" style "midi_track_base"
-widget "*MidiTrackFader" style "midi_track_base"
-widget "*MidiBusStripBase" style "midi_bus_base"
-widget "*MidiBusFader" style "midi_bus_base"
-widget "*TrackSeparator" style "track_separator"
-widget "*TrackEditIndicator0*" style "edit_group_0"
-widget "*TrackEditIndicator1*" style "edit_group_1"
-widget "*TrackEditIndicator2*" style "edit_group_2"
-widget "*TrackEditIndicator3*" style "edit_group_3"
-widget "*TrackEditIndicator4*" style "edit_group_3"
-widget "*TrackEditIndicator5*" style "edit_group_3"
-widget "*TrackEditIndicator6*" style "edit_group_3"
-widget "*TrackEditIndicator7*" style "edit_group_3"
-widget "*EditorTrackNameDisplay" style "track_name_display"
-widget "*EditorTrackNameDisplay*" style "track_name_display"
-widget "*EditorActiveTrackNameDisplay" style "active_track_name_display"
-widget "*EditorActiveTrackNameDisplay*" style "active_track_name_display"
-widget "*CrossfadeEditAuditionButton" style "red_when_active"
-widget "*CrossfadeEditAuditionButton*" style "red_when_active"
-widget "*CrossfadeEditCurveButton" style "red_when_active"
-widget "*CrossfadeEditCurveButton*" style "red_when_active"
-widget "*CrossfadeEditLabel" style "medium_text"
-widget "*CrossfadeEditFrame" style "base_frame"
-widget "*MouseModeButton" style "default_buttons_menus"
-widget "*MouseModeButton*" style "default_buttons_menus"
-widget "*EditorMainCanvas" style "main_canvas_area"
-widget "*AudioTrackControlsBaseInactiveUnselected" style "track_controls_inactive"
-widget "*AutomationTrackControlsBaseInactiveUnselected" style "track_controls_inactive"
-widget "*AutomationTrackName" style "automation_track_name"
-widget "*AudioTrackControlsBaseInactiveSelected" style "track_controls_inactive"
-widget "*AutomationTrackControlsBaseInactiveSelected" style "track_controls_inactive"
-widget "*AudioTrackStripBaseInactive" style "track_controls_inactive"
-widget "*AudioBusStripBaseInactive" style "track_controls_inactive"
-widget "*AudioTrackControlsBaseSelected" style "edit_controls_base_selected"
-widget "*AutomationTrackControlsBase" style "automation_track_controls_base"
-widget "*AutomationTrackControlsBaseSelected" style "edit_controls_base_selected"
-/*widget "*EditorMenuBar*" style "black_mackie_menu_bar"
-widget "*MainMenuBar*" style "black_mackie_menu_bar"*/
-widget "*ZoomClickBox" style "medium_bold_entry"
-widget "*PluginParameterLabel" style "medium_text"
-widget "*PluginNameInfo" style "plugin_name_text"
-widget "*PluginMakerInfo" style "plugin_maker_text"
-widget "*PluginParameterInfo" style "medium_text"
-widget "*MotionControllerValue" style "medium_entry"
-widget "*ParameterValueDisplay" style "medium_bold_entry"
-widget "*PluginUIClickBox" style "medium_bold_entry"
-widget "*PluginUIClickBox*" style "medium_bold_entry"
-widget "*PluginSlider" style "plugin_slider"
-widget "*RedirectSelector" style "redirect_list_display"
-widget "*RedirectSelector.*" style "redirect_list_display"
-widget "*EditGroupDisplay" style "treeview_display"
-widget "*TrackListDisplay" style "treeview_display"
-widget "*RegionListDisplay" style "treeview_display"
-widget "*NamedSelectionDisplay" style "treeview_display"
-widget "*SnapshotDisplay" style "treeview_display"
-widget "*MixerTrackCommentArea" style "option_entry"
-widget "*MixerPanZone" style "pan_zone"
-widget "*MixerTrackDisplayList" style "treeview_display"
-widget "*MixerSnapshotDisplayList" style "treeview_display"
-widget "*MixerAuxDisplayList" style "treeview_display"
-widget "*MixerGroupList" style "treeview_display"
-widget "*RegionEditorLabel" style "medium_text"
-widget "*RegionEditorSmallLabel" style "small_text"
-widget "*RegionEditorEntry" style "medium_entry"
-widget "*RegionEditorClock" style "default_clock_display"
-widget "*RegionEditorToggleButton" style "paler_red_when_active"
-widget "*RegionEditorToggleButton*" style "paler_red_when_active"
-widget "*MixerStripSpeedBase" style "small_entry"
-widget "*MixerStripSpeedBase*" style "small_entry"
-widget "*MixerStripSpeedBaseNotOne" style "small_red_on_black_entry"
-widget "*MixerStripSpeedBaseNotOne*" style "small_red_on_black_entry"
-widget "*MixerStripGainDisplay" style "small_entry"
-widget "*MixerStripGainDisplay*" style "small_entry"
-widget "*MixerStripGainUnitButton" style "very_small_button"
-widget "*MixerStripGainUnitButton*" style "very_small_button"
-widget "*MixerStripMeterPreButton" style "very_small_button"
-widget "*MixerStripMeterPreButton*" style "very_small_button"
-widget "*MixerStripPeakDisplay*" style "red_active_small_entry"
-widget "*MixerStripPeakDisplayPeak*" style "peak_display_peaked_entry"
-widget "*MixerStripSelectedFrame" style "selected_strip_frame"
-widget "*MixerStripFrame" style "base_frame"
-widget "*HWMonitorButton" style "red_when_active"
-widget "*HWMonitorButton*" style "red_when_active"
-widget "*BypassButton" style "red_when_active"
-widget "*BypassButton*" style "red_when_active"
-widget "*TransportSoloAlert" style "flashing_alert"
-widget "*TransportSoloAlert.*" style "flashing_alert"
-widget "*TransportAuditioningAlert" style "flashing_alert"
-widget "*TransportAuditioningAlert.*" style "flashing_alert"
-widget "*FadeCurve" style "medium_bold_entry"
-widget "*FadeCurve*" style "medium_bold_entry"
-widget "*IOSelectorButton" style "default_buttons_menus"
-widget "*IOSelectorButton*" style "default_buttons_menus"
-widget "*IOSelectorList" style "medium_entry_noselection_fg"
-widget "*IOSelectorPortList" style "io_selector_port_list"
-widget "*IOSelectorPortList.*" style "io_selector_port_list"
-widget "*IOSelectorPortListSelected" style "selected_io_selector_port_list"
-widget "*IOSelectorPortListSelected.*" style "selected_io_selector_port_list"
-widget "*IOSelectorNotebook" style "io_selector_notebook"
-widget "*IOSelectorNotebookTab" style "io_selector_notebook"
-widget "*IOSelectorFrame" style "base_frame"
-widget "*ConnectionEditorButton" style "default_buttons_menus"
-widget "*ConnectionEditorButton*" style "default_buttons_menus"
-widget "*ConnectionEditorList" style "medium_entry_noselection_fg"
-widget "*ConnectionEditorConnectionList" style "medium_entry"
-widget "*ConnectionEditorPortList" style "io_selector_port_list"
-widget "*ConnectionEditorPortListSelected" style "selected_io_selector_port_list"
-widget "*ConnectionEditorNotebook" style "io_selector_notebook"
-widget "*ConnectionEditorNotebookTab" style "io_selector_notebook"
-widget "*ConnectionEditorFrame" style "base_frame"
-widget "*RouteParamsListDisplay" style "inspector_track_list_display"
-widget "*RouteParamsPreListDisplay" style "inspector_redirect_list_display"
-widget "*RouteParamsPostListDisplay" style "inspector_redirect_list_display"
-widget "*TearOffArrow" style "tearoff_arrow"
-widget "*RouteParamsTitleButton" style "medium_text"
-widget "*RouteParamsTitleLabel" style "medium_text"
-widget "*PluginAutomateRecordButton" style "small_red_active_and_selected_button"
-widget "*PluginAutomateRecordButton*" style "small_red_active_and_selected_button"
-widget "*PluginAutomatePlayButton" style "small_red_active_and_selected_button"
-widget "*PluginAutomatePlayButton*" style "small_red_active_and_selected_button"
-widget "*PluginAutomateButton" style "small_button"
-widget "*PluginAutomateButton*" style "small_button"
-widget "*PluginSaveButton" style "small_button"
-widget "*PluginSaveButton*" style "small_button"
-widget "*PluginLoadButton" style "small_button"
-widget "*PluginLoadButton*" style "small_button"
-widget "*FaderMetricsStrip" style "meter_metrics_strip"
-widget "*MeterMetricsStrip" style "meter_metrics_strip"
-widget "*MetricDialogFrame" style "base_frame"
-widget "*MetricEntry" style "medium_bold_entry"
-widget "*MetricButton" style "default_buttons_menus"
-widget "*MetricButton.*" style "default_buttons_menus"
-widget "*MetricLabel" style "medium_text"
-widget "*TimeStretchButton" style "default_buttons_menus"
-widget "*TimeStretchButton.*" style "default_buttons_menus"
-widget "*TimeStretchProgress" style "default_buttons_menus"
-widget "*ChoiceWindow" style "default_buttons_menus"
-widget "*ChoicePrompt" style "default_buttons_menus"
-widget "*ChoiceButton" style "default_buttons_menus"
-widget "*ChoiceButton*" style "default_buttons_menus"
-widget "*SelectionModeButton" style "default_buttons_menus"
-widget "*SelectionModeButton*" style "default_buttons_menus"
-widget "*TrackLabel" style "medium_text"
-widget "*TrackPlugName" style "medium_text"
-widget "*TrackParameterName" style "small_text"
-widget "*AddRouteDialog*" style "medium_text"
-widget "*AddRouteDialog.GtkLabel" style "medium_text"
-widget "*AddRouteDialogChannelChoice" style "medium_bold_entry"
-widget "*AddRouteDialogSpinner" style "medium_bold_entry"
-widget "*AddRouteDialogSpinner*" style "medium_bold_entry"
-widget "*AddRouteDialogRadioButton" style "red_when_active"
-widget "*AddRouteDialogButton" style "default_buttons_menus"
-widget "*AddRouteDialogNameTemplateEntry" style "medium_bold_entry"
-widget "*NewSessionIOLabel" style "larger_bold_text"
-widget "*NewSessionSR1Label" style "red_medium_text"
-widget "*NewSessionSR2Label" style "medium_text"
-widget "*NewSessionChannelChoice" style "medium_bold_entry"
-widget "*NewSessionMainButton" style "larger_bold_text"
-widget "*NewSessionMainButton*" style "larger_bold_text"
-widget "*NewSessionMainLabel" style "larger_bold_text"
-widget "*LocationEditRowClock" style "location_rows_clock"
-widget "*LocationEditNameLabel" style "medium_text"
-widget "*LocationEditSetButton" style "location_row_button"
-widget "*LocationEditSetButton*" style "location_row_button"
-widget "*LocationEditGoButton" style "location_row_button"
-widget "*LocationEditGoButton*" style "location_row_button"
-widget "*LocationEditCdButton" style "small_red_active_and_selected_button"
-widget "*LocationEditCdButton*" style "small_red_active_and_selected_button"
-widget "*LocationEditHideButton" style "small_red_active_and_selected_button"
-widget "*LocationEditHideButton*" style "small_red_active_and_selected_button"
-widget "*LocationEditNumberLabel" style "small_text"
-widget "*LocationLocEditorFrame" style "base_frame"
-widget "*LocationRangeEditorFrame" style "base_frame"
-widget "*LocationEditNameEntry" style "option_entry"
-widget "*LocationAddLocationButton" style "default_buttons_menus"
-widget "*LocationAddLocationButton*" style "default_buttons_menus"
-widget "*LocationAddRangeButton" style "default_buttons_menus"
-widget "*LocationAddRangeButton*" style "default_buttons_menus"
-widget "*LocationEditRemoveButton" style "location_row_button"
-widget "*LocationEditRemoveButton*" style "location_row_button"
-widget "*PanSlider" style "pan_slider"
-widget "*PanningLinkButton" style "mixer_red_active_button"
-widget "*PanningLinkButton.*" style "mixer_red_active_button"
-widget "*PanningLinkDirectionButton" style "very_small_button"
-widget "*PanningLinkDirectionButton.*" style "very_small_button"
-widget "*ChannelCountSelector" style "medium_bold_entry"
-widget "*ChannelCountSelector.GtkArrow" style "default_buttons_menus"
-widget "*RegionListWholeFile" style "treeview_parent_node"
-widget "*EditorHScrollbar" style "editor_hscrollbar"
-
-class "GtkWidget" style "default_base"
-class "GtkScrollbar" style "ardour_adjusters"
-class "GtkLabel" style "default_buttons_menus"
-class "GtkButton" style "ardour_button"
-class "GtkArrow" style "tearoff_arrow"
-class "GtkProgressBar" style "ardour_progressbars"
+
+class "GtkWidget" style:highest "default_base"
+class "GtkScrollbar" style:highest "ardour_adjusters"
+class "GtkLabel" style:highest "default_buttons_menus"
+class "GtkButton" style:highest "ardour_button"
+class "GtkArrow" style:highest "tearoff_arrow"
+class "GtkProgressBar" style:highest "ardour_progressbars"
+
+widget "*FirstActionMessage" style:highest "first_action_message"
+widget "*VerboseCanvasCursor" style:highest "verbose_canvas_cursor"
+widget "*MarkerText" style:highest "marker_text"
+widget "*TimeAxisViewItemName*" style:highest "time_axis_view_item_name"
+#widget "*ExportProgress" style:highest "default_buttons_menus"
+widget "*ExportFileLabel" style:highest "small_bold_text"
+widget "*ExportFormatLabel" style:highest "medium_bold_text"
+widget "*ExportHeader" style:highest "small_bold_text"
+widget "*ExportFileDisplay" style:highest "medium_entry"
+widget "*ExportFormatDisplay" style:highest "medium_entry"
+widget "*ExportCheckbox" style:highest "small_entry"
+widget "*ExportTrackSelector*" style:highest "medium_entry_noselection_bg"
+widget "*EditModeSelector" style:highest "medium_bold_entry"
+widget "*SnapTypeSelector" style:highest "medium_bold_entry"
+widget "*SnapModeSelector" style:highest "medium_bold_entry"
+widget "*ZoomFocusSelector" style:highest "medium_bold_entry"
+widget "*ArdourContextMenu*" style:highest "default_buttons_menus"
+widget "*EditGroupTitleButton*" style:highest "default_buttons_menus"
+widget "*MixerGroupTitleButton*" style:highest "default_buttons_menus"
+widget "*ErrorLogCloseButton" style:highest "default_buttons_menus"
+widget "*EditorGTKButton*" style:highest "default_buttons_menus"
+widget "*ToolbarButton" style:highest "default_buttons_menus"
+widget "*ToolbarButton*" style:highest "default_buttons_menus"
+widget "*CrossfadeEditButton" style:highest "default_buttons_menus"
+widget "*CrossfadeEditButton*" style:highest "default_buttons_menus"
+widget "*TrackHistoryButton*" style:highest "default_buttons_menus"
+widget "*TrackSizeButton*" style:highest "default_buttons_menus"
+widget "*TrackPlaylistButton*" style:highest "default_buttons_menus"
+widget "*TrackAutomationButton*" style:highest "default_buttons_menus"
+widget "*TrackGroupButton*" style:highest "default_buttons_menus"
+widget "*TrackMixButton*" style:highest "default_buttons_menus"
+widget "*TrackVisualButton*" style:highest "default_buttons_menus"
+widget "*TrackRemoveButton*" style:highest "default_buttons_menus"
+widget "*BaseButton" style:highest "default_buttons_menus"
+widget "*TakeButtonLabel" style:highest "default_buttons_menus"
+widget "*MixerWidthButton" style:highest "default_buttons_menus"
+widget "*MixerHideButton" style:highest "default_buttons_menus"
+widget "*MixerSendButton" style:highest "default_buttons_menus"
+widget "*MixerSendButtonLabel" style:highest "default_buttons_menus"
+widget "*MixerSendSwitch" style:highest "default_buttons_menus"
+widget "*MixerInsertButton" style:highest "default_buttons_menus"
+widget "*MixerInsertButtonLabel" style:highest "default_buttons_menus"
+widget "*MixerInsertSwitch" style:highest "default_buttons_menus"
+widget "*MixerMonitorInputButton*" style:highest "very_small_button"
+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 "*OptionsEntry" style:highest "option_entry"
+widget "*InspectorNotebook" style:highest "options_window"
+widget "*NewSessionDialog" style:highest "options_window"
+widget "*NewSessionDialogButton*" style:highest "options_window"
+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"
+widget "*RecordEnableButton" style:highest "track_rec_enable_button"
+widget "*RecordEnableButton-active" style:highest "track_rec_enable_button_active"
+widget "*RecordEnableButton-alternate" style:highest "track_rec_enable_button_alternate"
+widget "*MixerRecordEnableButton" style:highest "mixer_track_rec_enable_button"
+widget "*MixerRecordEnableButton-active" style:highest "mixer_track_rec_enable_button_active"
+widget "*MixerRecordEnableButton-alternate" style:highest "mixer_track_rec_enable_button_alternate"
+widget "*MuteButton" style:highest "mute_button"
+widget "*MuteButton-alternate" style:highest "mute_button_alternate"
+widget "*MuteButton-active" style:highest "mute_button_active"
+widget "*MixerMuteButton" style:highest "mixer_mute_button"
+widget "*MixerMuteButton-alternate" style:highest "mixer_mute_button_alternate"
+widget "*MixerMuteButton-active" style:highest "mixer_mute_button_active"
+widget "*SoloButton" style:highest "solo_button"
+widget "*SoloButton-alternate" style:highest "solo_button_alternate"
+widget "*SoloButton-active" style:highest "solo_button_active"
+widget "*MixerSoloButton" style:highest "mixer_solo_button"
+widget "*MixerSoloButton-alternate" style:highest "mixer_solo_button_alternate"
+widget "*MixerSoloButton-active" style:highest "mixer_solo_button_active"
+widget "*TrackLoopButton*" style:highest "track_loop_button"
+widget "*PanAutomationLineSelector*" style:highest "multiline_combo"
+widget "*EditorTimeButton*" style:highest "time_button"
+widget "*MixerPhaseInvertButton*" style:highest "very_small_button"
+widget "*MixerPhaseInvertButton.*" style:highest "very_small_button"
+widget "*MixerAutomationRecordingButton*" style:highest "very_small_button"
+widget "*MixerAutomationRecordingButton.*" style:highest "very_small_button"
+widget "*MixerAutomationModeButton*" style:highest "very_small_button"
+widget "*MixerAutomationModeButton.*" style:highest "very_small_button"
+widget "*MixerAutomationPlaybackButton*" style:highest "very_small_button"
+widget "*MixerAutomationPlaybackButton.*" style:highest "very_small_button"
+widget "*MixerNameButton" style:highest "very_small_button"
+widget "*MixerNameButtonLabel" style:highest "very_small_button"
+widget "*MixerGroupButton" style:highest "very_small_button"
+widget "*MixerGroupButtonLabel" style:highest "very_small_button"
+widget "*MixerCommentButton" style:highest "very_small_button"
+widget "*MixerCommentButton*" style:highest "very_small_button"
+widget "*EditGroupButton" style:highest "very_small_button"
+widget "*EditGroupButtonLabel" style:highest "very_small_button"
+widget "*TransportButton" style:highest "transport_rec_button"
+widget "*TransportButton-active" style:highest "transport_button_active"
+widget "*ShuttleButton" style:highest "transport_button"
+widget "*ShuttleButton*" style:highest "transport_button"
+widget "*ShuttleDisplay" style:highest "transport_button"
+widget "*ShuttleDisplay*" style:highest "transport_button"
+widget "*ShuttleControl" style:highest "shuttle_control"
+widget "*TransportRecButton" style:highest "transport_rec_button"
+widget "*TransportRecButton*" style:highest "transport_rec_button"
+widget "*TransportRecButton-active" style:highest "transport_rec_button_active"
+widget "*TransportRecButton-active*" style:highest "transport_rec_button_active"
+widget "*TransportRecButton-alternate" style:highest "transport_rec_button_alternate"
+widget "*TransportRecButton-alternate*" style:highest "transport_rec_button_alternate"
+widget "*TransportRecButton*" style:highest "transport_rec_button"
+widget "*RecordingXrunWarningWindow" style:highest "xrun_warn"
+widget "*RecordingXrunWarningWindow*" style:highest "xrun_warn"
+/*widget "*MainMenuBar" style:highest "menu_bar_base"*/
+widget "*ErrorMessage" style:highest "error_message"
+widget "*FatalMessage" style:highest "fatal_message"
+widget "*InfoMessage" style:highest "info_message"
+widget "*WarningMessage" style:highest "warning_message"
+widget "*BigClockNonRecording" style:highest "non_recording_big_clock_display"
+widget "*BigClockRecording" style:highest "recording_big_clock_display"
+widget "*TransportClockDisplay" style:highest "transport_clock_display"
+widget "*SecondaryClockDisplay" style:highest "transport_clock_display"
+widget "*AudioClockFramesUpperInfo" style:highest "tempo_meter_clock_display"
+widget "*AudioClockFramesLowerInfo" style:highest "tempo_meter_clock_display"
+widget "*AudioClockSMPTEUpperInfo" style:highest "tempo_meter_clock_display"
+widget "*AudioClockSMPTELowerInfo" style:highest "tempo_meter_clock_display"
+widget "*AudioClockBBTUpperInfo" style:highest "tempo_meter_clock_display"
+widget "*AudioClockBBTLowerInfo" style:highest "tempo_meter_clock_display"
+widget "*SelectionStartClock" style:highest "default_clock_display"
+widget "*SelectionEndClock" style:highest "default_clock_display"
+widget "*EditCursorClock" style:highest "default_clock_display"
+widget "*PreRollClock" style:highest "default_clock_display"
+widget "*PostRollClock" style:highest "default_clock_display"
+widget "*NudgeClock" style:highest "default_clock_display"
+widget "*ZoomRangeClock" style:highest "default_clock_display"
+widget "*SMPTEOffsetClock" style:highest "default_clock_display"
+widget "*TransportLabel" style:highest "small_bold_text"
+widget "*TakeLabel" style:highest "small_bold_text"
+widget "*LocationLabel" style:highest "small_bold_text"
+widget "*WipeLabel" style:highest "small_bold_text"
+widget "*TakeTagLabel" style:highest "small_bold_text"
+widget "*ToolBarLabel" style:highest "small_bold_text"
+widget "*EditorDisplayLabel" style:highest "small_bold_text"
+widget "*NewSessionLabel" style:highest "large_text"
+widget "*GlobalButtonLabel" style:highest "default_buttons_menus"
+widget "*ClickButton" style:highest "medium_entry"
+widget "*RegionNameDisplay" style:highest "medium_entry"
+widget "*PluginDisplay" style:highest "medium_entry"
+widget "*SelectionDisplay" style:highest "medium_entry"
+widget "*HistorySelector" style:highest "medium_entry"
+widget "*LocationSelector" style:highest "medium_entry"
+widget "*TakeSelector" style:highest "medium_entry"
+widget "*RegionSelector" style:highest "medium_entry"
+widget "*SMPTERuler" style:highest "editor_time_ruler"
+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 "*TimeAxisViewControlsBaseUnselected" style:highest "audio_track_base"
+widget "*AudioTrackControlsBaseUnselected" style:highest "audio_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"
+widget "*TrackEditIndicator0*" style:highest "edit_group_0"
+widget "*TrackEditIndicator1*" style:highest "edit_group_1"
+widget "*TrackEditIndicator2*" style:highest "edit_group_2"
+widget "*TrackEditIndicator3*" style:highest "edit_group_3"
+widget "*TrackEditIndicator4*" style:highest "edit_group_3"
+widget "*TrackEditIndicator5*" style:highest "edit_group_3"
+widget "*TrackEditIndicator6*" style:highest "edit_group_3"
+widget "*TrackEditIndicator7*" style:highest "edit_group_3"
+widget "*EditorTrackNameDisplay" style:highest "track_name_display"
+widget "*EditorTrackNameDisplay*" style:highest "track_name_display"
+widget "*EditorActiveTrackNameDisplay" style:highest "active_track_name_display"
+widget "*EditorActiveTrackNameDisplay*" style:highest "active_track_name_display"
+widget "*CrossfadeEditAuditionButton" style:highest "red_when_active"
+widget "*CrossfadeEditAuditionButton*" style:highest "red_when_active"
+widget "*CrossfadeEditCurveButton" style:highest "red_when_active"
+widget "*CrossfadeEditCurveButton*" style:highest "red_when_active"
+widget "*CrossfadeEditLabel" style:highest "medium_text"
+widget "*CrossfadeEditFrame" style:highest "base_frame"
+widget "*MouseModeButton" style:highest "default_buttons_menus"
+widget "*MouseModeButton*" style:highest "default_buttons_menus"
+widget "*EditorMainCanvas" style:highest "main_canvas_area"
+widget "*AudioTrackControlsBaseInactiveUnselected" style:highest "track_controls_inactive"
+widget "*BusControlsBaseInactiveUnselected" style:highest "track_controls_inactive"
+widget "*AutomationTrackControlsBaseInactiveUnselected" style:highest "track_controls_inactive"
+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 "*BusControlsBaseSelected" style:highest "edit_controls_base_selected"
+widget "*AutomationTrackControlsBase" style:highest "automation_track_controls_base"
+widget "*AutomationTrackControlsBaseSelected" style:highest "edit_controls_base_selected"
+/*widget "*EditorMenuBar*" style:highest "black_mackie_menu_bar"
+widget "*MainMenuBar*" style:highest "black_mackie_menu_bar"
+*/
+widget "*ZoomClickBox" style:highest "medium_bold_entry"
+widget "*PluginParameterLabel" style:highest "medium_text"
+widget "*PluginNameInfo" style:highest "plugin_name_text"
+widget "*PluginMakerInfo" style:highest "plugin_maker_text"
+widget "*PluginParameterInfo" style:highest "medium_text"
+widget "*MotionControllerValue" style:highest "medium_entry"
+widget "*ParameterValueDisplay" style:highest "medium_bold_entry"
+widget "*PluginUIClickBox" style:highest "medium_bold_entry"
+widget "*PluginUIClickBox*" style:highest "medium_bold_entry"
+widget "*PluginSlider" style:highest "plugin_slider"
+widget "*RedirectSelector" style:highest "redirect_list_display"
+widget "*RedirectSelector.*" style:highest "redirect_list_display"
+widget "*EditGroupDisplay" style:highest "treeview_display"
+widget "*TrackListDisplay" style:highest "treeview_display"
+widget "*RegionListDisplay" style:highest "treeview_display"
+widget "*NamedSelectionDisplay" style:highest "treeview_display"
+widget "*SnapshotDisplay" style:highest "treeview_display"
+widget "*MixerTrackCommentArea" style:highest "option_entry"
+widget "*MixerPanZone" style:highest "pan_zone"
+widget "*MixerTrackDisplayList" style:highest "treeview_display"
+widget "*MixerSnapshotDisplayList" style:highest "treeview_display"
+widget "*MixerAuxDisplayList" style:highest "treeview_display"
+widget "*MixerGroupList" style:highest "treeview_display"
+widget "*RegionEditorLabel" style:highest "medium_text"
+widget "*RegionEditorSmallLabel" style:highest "small_text"
+widget "*RegionEditorEntry" style:highest "medium_entry"
+widget "*RegionEditorClock" style:highest "default_clock_display"
+widget "*RegionEditorToggleButton" style:highest "paler_red_when_active"
+widget "*RegionEditorToggleButton*" style:highest "paler_red_when_active"
+widget "*MixerStripSpeedBase" style:highest "small_entry"
+widget "*MixerStripSpeedBase*" style:highest "small_entry"
+widget "*MixerStripSpeedBaseNotOne" style:highest "small_red_on_black_entry"
+widget "*MixerStripSpeedBaseNotOne*" style:highest "small_red_on_black_entry"
+widget "*MixerStripGainDisplay" style:highest "small_entry"
+widget "*MixerStripGainDisplay*" style:highest "small_entry"
+widget "*MixerStripGainUnitButton" style:highest "very_small_button"
+widget "*MixerStripGainUnitButton*" style:highest "very_small_button"
+widget "*MixerStripMeterPreButton" style:highest "very_small_button"
+widget "*MixerStripMeterPreButton*" style:highest "very_small_button"
+widget "*MixerStripPeakDisplay*" style:highest "red_active_small_entry"
+widget "*MixerStripPeakDisplayPeak*" style:highest "peak_display_peaked_entry"
+widget "*MixerStripSelectedFrame" style:highest "selected_strip_frame"
+widget "*MixerStripFrame" style:highest "base_frame"
+widget "*HWMonitorButton" style:highest "red_when_active"
+widget "*HWMonitorButton*" style:highest "red_when_active"
+widget "*BypassButton" style:highest "red_when_active"
+widget "*BypassButton*" style:highest "red_when_active"
+widget "*TransportSoloAlert" style:highest "flashing_alert"
+widget "*TransportSoloAlert.*" style:highest "flashing_alert"
+widget "*TransportAuditioningAlert" style:highest "flashing_alert"
+widget "*TransportAuditioningAlert.*" style:highest "flashing_alert"
+widget "*FadeCurve" style:highest "medium_bold_entry"
+widget "*FadeCurve*" style:highest "medium_bold_entry"
+widget "*IOSelectorButton" style:highest "default_buttons_menus"
+widget "*IOSelectorButton*" style:highest "default_buttons_menus"
+widget "*IOSelectorList" style:highest "medium_entry_noselection_fg"
+widget "*IOSelectorPortList" style:highest "io_selector_port_list"
+widget "*IOSelectorPortList.*" style:highest "io_selector_port_list"
+widget "*IOSelectorPortListSelected" style:highest "selected_io_selector_port_list"
+widget "*IOSelectorPortListSelected.*" style:highest "selected_io_selector_port_list"
+widget "*IOSelectorNotebook" style:highest "io_selector_notebook"
+widget "*IOSelectorNotebookTab" style:highest "io_selector_notebook"
+widget "*IOSelectorFrame" style:highest "base_frame"
+widget "*ConnectionEditorButton" style:highest "default_buttons_menus"
+widget "*ConnectionEditorButton*" style:highest "default_buttons_menus"
+widget "*ConnectionEditorList" style:highest "medium_entry_noselection_fg"
+widget "*ConnectionEditorConnectionList" style:highest "medium_entry"
+widget "*ConnectionEditorPortList" style:highest "io_selector_port_list"
+widget "*ConnectionEditorPortListSelected" style:highest "selected_io_selector_port_list"
+widget "*ConnectionEditorNotebook" style:highest "io_selector_notebook"
+widget "*ConnectionEditorNotebookTab" style:highest "io_selector_notebook"
+widget "*ConnectionEditorFrame" style:highest "base_frame"
+widget "*RouteParamsListDisplay" style:highest "inspector_track_list_display"
+widget "*RouteParamsPreListDisplay" style:highest "inspector_redirect_list_display"
+widget "*RouteParamsPostListDisplay" style:highest "inspector_redirect_list_display"
+widget "*TearOffArrow" style:highest "tearoff_arrow"
+widget "*RouteParamsTitleButton" style:highest "medium_text"
+widget "*RouteParamsTitleLabel" style:highest "medium_text"
+widget "*PluginAutomateRecordButton" style:highest "small_red_active_and_selected_button"
+widget "*PluginAutomateRecordButton*" style:highest "small_red_active_and_selected_button"
+widget "*PluginAutomatePlayButton" style:highest "small_red_active_and_selected_button"
+widget "*PluginAutomatePlayButton*" style:highest "small_red_active_and_selected_button"
+widget "*PluginAutomateButton" style:highest "small_button"
+widget "*PluginAutomateButton*" style:highest "small_button"
+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"
+widget "*MetricButton.*" style:highest "default_buttons_menus"
+widget "*MetricLabel" style:highest "medium_text"
+widget "*TimeStretchButton" style:highest "default_buttons_menus"
+widget "*TimeStretchButton.*" style:highest "default_buttons_menus"
+widget "*TimeStretchProgress" style:highest "default_buttons_menus"
+widget "*ChoiceWindow" style:highest "default_buttons_menus"
+widget "*ChoicePrompt" style:highest "default_buttons_menus"
+widget "*ChoiceButton" style:highest "default_buttons_menus"
+widget "*ChoiceButton*" style:highest "default_buttons_menus"
+widget "*SelectionModeButton" style:highest "default_buttons_menus"
+widget "*SelectionModeButton*" style:highest "default_buttons_menus"
+widget "*TrackLabel" style:highest "medium_text"
+widget "*TrackPlugName" style:highest "medium_text"
+widget "*TrackParameterName" style:highest "small_text"
+widget "*AddRouteDialog*" style:highest "medium_text"
+widget "*AddRouteDialog.GtkLabel" style:highest "medium_text"
+widget "*AddRouteDialogChannelChoice" style:highest "medium_bold_entry"
+widget "*AddRouteDialogSpinner" style:highest "medium_bold_entry"
+widget "*AddRouteDialogSpinner*" style:highest "medium_bold_entry"
+widget "*AddRouteDialogRadioButton" style:highest "red_when_active"
+widget "*AddRouteDialogButton" style:highest "default_buttons_menus"
+widget "*AddRouteDialogNameTemplateEntry" style:highest "medium_bold_entry"
+widget "*NewSessionIOLabel" style:highest "larger_bold_text"
+widget "*NewSessionSR1Label" style:highest "red_medium_text"
+widget "*NewSessionSR2Label" style:highest "medium_text"
+widget "*NewSessionChannelChoice" style:highest "medium_bold_entry"
+widget "*NewSessionMainButton" style:highest "larger_bold_text"
+widget "*NewSessionMainButton*" style:highest "larger_bold_text"
+widget "*NewSessionMainLabel" style:highest "larger_bold_text"
+widget "*LocationEditRowClock" style:highest "location_rows_clock"
+widget "*LocationEditNameLabel" style:highest "medium_text"
+widget "*LocationEditSetButton" style:highest "location_row_button"
+widget "*LocationEditSetButton*" style:highest "location_row_button"
+widget "*LocationEditGoButton" style:highest "location_row_button"
+widget "*LocationEditGoButton*" style:highest "location_row_button"
+widget "*LocationEditCdButton" style:highest "small_red_active_and_selected_button"
+widget "*LocationEditCdButton*" style:highest "small_red_active_and_selected_button"
+widget "*LocationEditHideButton" style:highest "small_red_active_and_selected_button"
+widget "*LocationEditHideButton*" style:highest "small_red_active_and_selected_button"
+widget "*LocationEditNumberLabel" style:highest "small_text"
+widget "*LocationLocEditorFrame" style:highest "base_frame"
+widget "*LocationRangeEditorFrame" style:highest "base_frame"
+widget "*LocationEditNameEntry" style:highest "option_entry"
+widget "*LocationAddLocationButton" style:highest "default_buttons_menus"
+widget "*LocationAddLocationButton*" style:highest "default_buttons_menus"
+widget "*LocationAddRangeButton" style:highest "default_buttons_menus"
+widget "*LocationAddRangeButton*" style:highest "default_buttons_menus"
+widget "*LocationEditRemoveButton" style:highest "location_row_button"
+widget "*LocationEditRemoveButton*" style:highest "location_row_button"
+widget "*PanSlider" style:highest "pan_slider"
+widget "*PanningLinkButton" style:highest "mixer_red_active_button"
+widget "*PanningLinkButton.*" style:highest "mixer_red_active_button"
+widget "*PanningLinkDirectionButton" style:highest "very_small_button"
+widget "*PanningLinkDirectionButton.*" style:highest "very_small_button"
+widget "*ChannelCountSelector" style:highest "medium_bold_entry"
+widget "*ChannelCountSelector.GtkArrow" style:highest "default_buttons_menus"
+widget "*RegionListWholeFile" style:highest "treeview_parent_node"
+widget "*EditorHScrollbar" style:highest "editor_hscrollbar"
diff --git a/gtk2_ardour/ardour_image_compositor_socket.h b/gtk2_ardour/ardour_image_compositor_socket.h
index ad0a7b79c6..6ed92ef8ac 100644
--- a/gtk2_ardour/ardour_image_compositor_socket.h
+++ b/gtk2_ardour/ardour_image_compositor_socket.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
diff --git a/gtk2_ardour/ardour_message.cc b/gtk2_ardour/ardour_message.cc
deleted file mode 100644
index 2948559f14..0000000000
--- a/gtk2_ardour/ardour_message.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- Copyright (C) 2004 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-
-*/
-
-#include <gtkmm/stock.h>
-
-#include "ardour_message.h"
-#include "i18n.h"
-
-using namespace std;
-using namespace Gtk;
-
-ArdourMessage::ArdourMessage (Gtk::Window* parent,
- string name, string msg,
- bool grab_focus, bool auto_run)
- : ArdourDialog (name),
- label (msg)
-{
- label.set_name (X_("PrompterLabel"));
- label.set_justify (JUSTIFY_CENTER);
- label.show ();
-
- get_vbox()->pack_start (label);
-
- Button* ok_button = add_button (Stock::OK, RESPONSE_ACCEPT);
-
- set_name (X_("Prompter"));
- set_position (Gtk::WIN_POS_MOUSE);
- set_modal (true);
- set_type_hint (Gdk::WINDOW_TYPE_HINT_MENU);
-
- if (grab_focus) {
- ok_button->grab_focus ();
- }
-
- if (parent) {
- set_transient_for (*parent);
- }
-
- if (auto_run) {
- run ();
- }
-}
-
-ArdourMessage::~ArdourMessage()
-{
-}
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 3ecc618eba..275c7d7cdc 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 1999-2002 Paul Davis
+ Copyright (C) 1999-2007 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#define __STDC_FORMAT_MACROS 1
@@ -31,6 +30,8 @@
#include <iostream>
+#include <sys/resource.h>
+
#include <gtkmm/messagedialog.h>
#include <gtkmm/accelmap.h>
@@ -71,7 +72,6 @@
#include "mixer_ui.h"
#include "prompter.h"
#include "opts.h"
-#include "keyboard_target.h"
#include "add_route_dialog.h"
#include "new_session_dialog.h"
#include "about.h"
@@ -91,6 +91,7 @@ ARDOUR_UI *ARDOUR_UI::theArdourUI = 0;
sigc::signal<void,bool> ARDOUR_UI::Blink;
sigc::signal<void> ARDOUR_UI::RapidScreenUpdate;
+sigc::signal<void> ARDOUR_UI::MidRapidScreenUpdate;
sigc::signal<void> ARDOUR_UI::SuperRapidScreenUpdate;
sigc::signal<void,nframes_t> ARDOUR_UI::Clock;
@@ -118,16 +119,34 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
/* transport */
- time_master_button (_("time\nmaster")),
-
+ roll_controllable ("transport roll", *this, TransportControllable::Roll),
+ stop_controllable ("transport stop", *this, TransportControllable::Stop),
+ goto_start_controllable ("transport goto start", *this, TransportControllable::GotoStart),
+ goto_end_controllable ("transport goto end", *this, TransportControllable::GotoEnd),
+ auto_loop_controllable ("transport auto loop", *this, TransportControllable::AutoLoop),
+ play_selection_controllable ("transport play selection", *this, TransportControllable::PlaySelection),
+ rec_controllable ("transport rec-enable", *this, TransportControllable::RecordEnable),
+ shuttle_controllable ("shuttle", *this, TransportControllable::ShuttleControl),
+ shuttle_controller_binding_proxy (shuttle_controllable),
+
+ roll_button (roll_controllable),
+ stop_button (stop_controllable),
+ goto_start_button (goto_start_controllable),
+ goto_end_button (goto_end_controllable),
+ auto_loop_button (auto_loop_controllable),
+ play_selection_button (play_selection_controllable),
+ rec_button (rec_controllable),
+
shuttle_units_button (_("% ")),
punch_in_button (_("Punch In")),
punch_out_button (_("Punch Out")),
auto_return_button (_("Auto Return")),
- auto_play_button (_("Autuo Play")),
+ auto_play_button (_("Auto Play")),
auto_input_button (_("Auto Input")),
click_button (_("Click")),
+ time_master_button (_("time\nmaster")),
+
auditioning_alert_button (_("AUDITION")),
solo_alert_button (_("SOLO")),
shown_flag (false)
@@ -164,8 +183,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile)
location_ui = 0;
open_session_selector = 0;
have_configure_timeout = false;
- have_disk_overrun_displayed = false;
- have_disk_underrun_displayed = false;
+ have_disk_speed_dialog_displayed = false;
_will_create_new_session_automatically = false;
session_loaded = false;
last_speed_displayed = -1.0f;
@@ -249,10 +267,6 @@ ARDOUR_UI::set_engine (AudioEngine& e)
AudioFileSource::set_build_peakfiles (true);
AudioFileSource::set_build_missing_peakfiles (true);
- if (AudioSource::start_peak_thread ()) {
- throw failed_constructor();
- }
-
/* set default clock modes */
primary_clock.set_mode (AudioClock::SMPTE);
@@ -290,8 +304,6 @@ ARDOUR_UI::~ARDOUR_UI ()
if (add_route_dialog) {
delete add_route_dialog;
}
-
- AudioSource::stop_peak_thread ();
}
gint
@@ -334,6 +346,63 @@ ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
}
void
+ARDOUR_UI::set_transport_controllable_state (const XMLNode& node)
+{
+ const XMLProperty* prop;
+
+ if ((prop = node.property ("roll")) != 0) {
+ roll_controllable.set_id (prop->value());
+ }
+ if ((prop = node.property ("stop")) != 0) {
+ stop_controllable.set_id (prop->value());
+ }
+ if ((prop = node.property ("goto_start")) != 0) {
+ goto_start_controllable.set_id (prop->value());
+ }
+ if ((prop = node.property ("goto_end")) != 0) {
+ goto_end_controllable.set_id (prop->value());
+ }
+ if ((prop = node.property ("auto_loop")) != 0) {
+ auto_loop_controllable.set_id (prop->value());
+ }
+ if ((prop = node.property ("play_selection")) != 0) {
+ play_selection_controllable.set_id (prop->value());
+ }
+ if ((prop = node.property ("rec")) != 0) {
+ rec_controllable.set_id (prop->value());
+ }
+ if ((prop = node.property ("shuttle")) != 0) {
+ shuttle_controllable.set_id (prop->value());
+ }
+}
+
+XMLNode&
+ARDOUR_UI::get_transport_controllable_state ()
+{
+ XMLNode* node = new XMLNode(X_("TransportControllables"));
+ char buf[64];
+
+ roll_controllable.id().print (buf, sizeof (buf));
+ node->add_property (X_("roll"), buf);
+ stop_controllable.id().print (buf, sizeof (buf));
+ node->add_property (X_("stop"), buf);
+ goto_start_controllable.id().print (buf, sizeof (buf));
+ node->add_property (X_("goto_start"), buf);
+ goto_end_controllable.id().print (buf, sizeof (buf));
+ node->add_property (X_("goto_end"), buf);
+ auto_loop_controllable.id().print (buf, sizeof (buf));
+ node->add_property (X_("auto_loop"), buf);
+ play_selection_controllable.id().print (buf, sizeof (buf));
+ node->add_property (X_("play_selection"), buf);
+ rec_controllable.id().print (buf, sizeof (buf));
+ node->add_property (X_("rec"), buf);
+ shuttle_controllable.id().print (buf, sizeof (buf));
+ node->add_property (X_("shuttle"), buf);
+
+ return *node;
+}
+
+void
ARDOUR_UI::save_ardour_state ()
{
if (!keyboard || !mixer || !editor) {
@@ -346,6 +415,7 @@ ARDOUR_UI::save_ardour_state ()
XMLNode* node = new XMLNode (keyboard->get_state());
Config->add_extra_xml (*node);
+ Config->add_extra_xml (get_transport_controllable_state());
Config->save_state();
XMLNode enode(static_cast<Stateful*>(editor)->get_state());
@@ -365,9 +435,72 @@ ARDOUR_UI::save_ardour_state ()
void
ARDOUR_UI::startup ()
{
- // relax
+ check_memory_locking();
+}
+
+void
+ARDOUR_UI::no_memory_warning ()
+{
+ XMLNode node (X_("no-memory-warning"));
+ Config->add_instant_xml (node, get_user_ardour_path());
+}
+
+void
+ARDOUR_UI::check_memory_locking ()
+{
+#ifdef __APPLE__
+ /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
+ return;
+#else // !__APPLE__
+
+ XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"), get_user_ardour_path());
+
+ if (engine->is_realtime() && memory_warning_node == 0) {
+
+ struct rlimit limits;
+ int64_t ram;
+ long pages, page_size;
+
+ if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0) {
+ ram = 0;
+ } else {
+ ram = (int64_t) pages * (int64_t) page_size;
+ }
+
+ if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
+ return;
+ }
+
+ if (limits.rlim_cur != RLIM_INFINITY) {
+
+ if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
+
+
+ MessageDialog msg (_("WARNING: Your system has a limit for maximum amount of locked memory. "
+ "This might cause Ardour to run out of memory before your system "
+ "runs out of memory. \n\n"
+ "You can view the memory limit with 'ulimit -l', "
+ "and it is normally controlled by /etc/security/limits.conf"));
+
+ VBox* vbox = msg.get_vbox();
+ HBox hbox;
+ CheckButton cb (_("Do not show this window again"));
+
+ cb.signal_toggled().connect (mem_fun (*this, &ARDOUR_UI::no_memory_warning));
+
+ hbox.pack_start (cb, true, false);
+ vbox->pack_start (hbox);
+ hbox.show_all ();
+
+ editor->ensure_float (msg);
+ msg.run ();
+ }
+ }
+ }
+#endif // !__APPLE__
}
+
void
ARDOUR_UI::finish()
{
@@ -491,6 +624,13 @@ ARDOUR_UI::every_point_one_seconds ()
}
gint
+ARDOUR_UI::every_point_oh_five_seconds ()
+{
+ MidRapidScreenUpdate(); /* EMIT_SIGNAL */
+ return true;
+}
+
+gint
ARDOUR_UI::every_point_zero_one_seconds ()
{
SuperRapidScreenUpdate(); /* EMIT_SIGNAL */
@@ -609,40 +749,6 @@ ARDOUR_UI::update_wall_clock ()
return TRUE;
}
-void
-ARDOUR_UI::control_methods_adjusted ()
-
-{
- int which_method;
-
- which_method = (int) online_control_button->adjustment.get_value();
- switch (which_method) {
- case 0:
- allow_mmc_and_local ();
- break;
- case 1:
- allow_mmc_only ();
- break;
- case 2:
- allow_local_only ();
- break;
- default:
- fatal << _("programming error: impossible control method") << endmsg;
- }
-}
-
-
-void
-ARDOUR_UI::mmc_device_id_adjusted ()
-
-{
-#if 0
- if (mmc) {
- int dev_id = (int) mmc_id_button->adjustment.get_value();
- mmc->set_device_id (dev_id);
- }
-#endif
-}
gint
ARDOUR_UI::session_menu (GdkEventButton *ev)
@@ -923,7 +1029,8 @@ ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t
if (how_many == 1) {
error << _("could not create a new audio track") << endmsg;
} else {
- error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
+ error << string_compose (_("could only create %1 of %2 new audio %3"),
+ tracks.size(), how_many, (track ? _("tracks") : _("busses"))) << endmsg;
}
}
@@ -954,6 +1061,7 @@ ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t
}
catch (...) {
+ cerr << "About to complain about JACK\n";
MessageDialog msg (*editor,
_("There are insufficient JACK ports available\n\
to create a new track or bus.\n\
@@ -1101,11 +1209,11 @@ ARDOUR_UI::transport_roll ()
if (session->get_play_loop()) {
session->request_play_loop (false);
- auto_loop_button.set_active (false);
- roll_button.set_active (true);
+ auto_loop_button.set_visual_state (1);
+ roll_button.set_visual_state (1);
} else if (session->get_play_range ()) {
session->request_play_range (false);
- play_selection_button.set_active (false);
+ play_selection_button.set_visual_state (0);
} else if (rolling) {
session->request_locate (session->last_transport_start(), true);
}
@@ -1244,24 +1352,6 @@ ARDOUR_UI::map_transport_state ()
}
void
-ARDOUR_UI::allow_local_only ()
-{
-
-}
-
-void
-ARDOUR_UI::allow_mmc_only ()
-{
-
-}
-
-void
-ARDOUR_UI::allow_mmc_and_local ()
-{
-
-}
-
-void
ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
{
snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
@@ -1282,6 +1372,49 @@ ARDOUR_UI::engine_running ()
ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::engine_running));
ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true);
ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false);
+
+ Glib::RefPtr<Action> action;
+ char* action_name = 0;
+
+ switch (engine->frames_per_cycle()) {
+ case 32:
+ action_name = X_("JACKLatency32");
+ break;
+ case 64:
+ action_name = X_("JACKLatency64");
+ break;
+ case 128:
+ action_name = X_("JACKLatency128");
+ break;
+ case 512:
+ action_name = X_("JACKLatency512");
+ break;
+ case 1024:
+ action_name = X_("JACKLatency1024");
+ break;
+ case 2048:
+ action_name = X_("JACKLatency2048");
+ break;
+ case 4096:
+ action_name = X_("JACKLatency4096");
+ break;
+ case 8192:
+ action_name = X_("JACKLatency8192");
+ break;
+ default:
+ /* XXX can we do anything useful ? */
+ break;
+ }
+
+ if (action_name) {
+
+ action = ActionManager::get_action (X_("JACK"), action_name);
+
+ if (action) {
+ Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
+ ract->set_active ();
+ }
+ }
}
void
@@ -1379,7 +1512,7 @@ ARDOUR_UI::_blink (void *arg)
void
ARDOUR_UI::blink ()
{
- Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
+ Blink (blink_on = !blink_on); /* EMIT_SIGNAL */
}
void
@@ -1454,17 +1587,18 @@ ARDOUR_UI::snapshot_session ()
{
ArdourPrompter prompter (true);
string snapname;
- string now;
+ char timebuf[128];
time_t n;
+ struct tm local_time;
time (&n);
- now = ctime (&n);
- now = now.substr (20, 4) + now.substr (3, 16) + " (" + now.substr (0, 3) + ")";
+ localtime_r (&n, &local_time);
+ strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.set_prompt (_("Name of New Snapshot"));
- prompter.set_initial_text (now);
+ prompter.set_initial_text (timebuf);
switch (prompter.run()) {
case RESPONSE_ACCEPT:
@@ -1571,18 +1705,18 @@ ARDOUR_UI::transport_rec_enable_blink (bool onoff)
switch (session->record_status()) {
case Session::Enabled:
if (onoff) {
- rec_button.set_state (1);
+ rec_button.set_visual_state (2);
} else {
- rec_button.set_state (0);
+ rec_button.set_visual_state (0);
}
break;
case Session::Recording:
- rec_button.set_state (2);
+ rec_button.set_visual_state (1);
break;
default:
- rec_button.set_state (0);
+ rec_button.set_visual_state (0);
break;
}
}
@@ -1596,12 +1730,6 @@ ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
}
void
-ARDOUR_UI::start_keyboard_prefix ()
-{
- keyboard->start_prefix();
-}
-
-void
ARDOUR_UI::save_template ()
{
@@ -1627,12 +1755,18 @@ ARDOUR_UI::save_template ()
}
}
-void
+bool
ARDOUR_UI::new_session (std::string predetermined_path)
{
string session_name;
string session_path;
+ if (!engine->connected()) {
+ MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
+ msg.run ();
+ return false;
+ }
+
int response = Gtk::RESPONSE_NONE;
new_session_dialog->set_modal(true);
@@ -1642,6 +1776,13 @@ ARDOUR_UI::new_session (std::string predetermined_path)
do {
response = new_session_dialog->run ();
+
+ if (!engine->connected()) {
+ new_session_dialog->hide ();
+ MessageDialog msg (_("Ardour is not connected to JACK at this time. Creating new sessions is not possible."));
+ msg.run ();
+ return false;
+ }
_session_is_new = false;
@@ -1651,7 +1792,7 @@ ARDOUR_UI::new_session (std::string predetermined_path)
quit();
}
new_session_dialog->hide ();
- return;
+ return false;
} else if (response == Gtk::RESPONSE_NONE) {
@@ -1802,15 +1943,20 @@ ARDOUR_UI::new_session (std::string predetermined_path)
uint32_t nphysin = (uint32_t) new_session_dialog->input_limit_count();
uint32_t nphysout = (uint32_t) new_session_dialog->output_limit_count();
- build_session (session_path,
- session_name,
- cchns,
- mchns,
- iconnect,
- oconnect,
- nphysin,
- nphysout,
- engine->frame_rate() * 60 * 5);
+ 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;
+ }
}
}
}
@@ -1821,6 +1967,7 @@ ARDOUR_UI::new_session (std::string predetermined_path)
show();
new_session_dialog->get_window()->set_cursor();
new_session_dialog->hide();
+ return true;
}
void
@@ -1876,6 +2023,7 @@ ARDOUR_UI::load_session (const string & path, const string & snap_name, string*
session->set_clean ();
}
+ editor->edit_cursor_position (true);
return 0;
}
@@ -1909,7 +2057,8 @@ ARDOUR_UI::build_session (const string & path, const string & snap_name,
catch (...) {
- error << string_compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg;
+ MessageDialog msg (string_compose(_("Could not create session in \"%1\""), path));
+ msg.run ();
return -1;
}
@@ -2095,9 +2244,17 @@ After cleanup, unused audio files will be moved to a \
editor->prepare_for_cleanup ();
+ /* do not allow flush until a session is reloaded */
+
+ Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
+ if (act) {
+ act->set_sensitive (false);
+ }
+
if (session->cleanup_sources (rep)) {
return;
}
+
checker.hide();
display_cleanup_results (rep,
_("cleaned files"),
@@ -2109,6 +2266,9 @@ Flushing the wastebasket will \n\
release an additional\n\
%4 %5bytes of disk space.\n"
));
+
+
+
}
void
@@ -2133,7 +2293,7 @@ releasing %4 %5bytes of disk space"));
}
void
-ARDOUR_UI::add_route ()
+ARDOUR_UI::add_route (Gtk::Window* float_window)
{
int count;
@@ -2143,7 +2303,9 @@ ARDOUR_UI::add_route ()
if (add_route_dialog == 0) {
add_route_dialog = new AddRouteDialog;
- editor->ensure_float (*add_route_dialog);
+ if (float_window) {
+ add_route_dialog->set_transient_for (*float_window);
+ }
}
if (add_route_dialog->is_visible()) {
@@ -2261,18 +2423,18 @@ ARDOUR_UI::halt_on_xrun_message ()
void
ARDOUR_UI::disk_overrun_handler ()
{
- ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
+ ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
- if (!have_disk_overrun_displayed) {
- have_disk_overrun_displayed = true;
- MessageDialog msg (*editor, X_("diskrate dialog"), _("\
+ if (!have_disk_speed_dialog_displayed) {
+ have_disk_speed_dialog_displayed = true;
+ MessageDialog* msg = new MessageDialog (*editor, X_("diskrate dialog"), _("\
The disk system on your computer\n\
was not able to keep up with Ardour.\n\
\n\
Specifically, it failed to write data to disk\n\
quickly enough to keep up with recording.\n"));
- msg.run ();
- have_disk_overrun_displayed = false;
+ msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
+ msg->show_all ();
}
}
@@ -2281,29 +2443,24 @@ ARDOUR_UI::disk_underrun_handler ()
{
ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
- if (!have_disk_underrun_displayed) {
- have_disk_underrun_displayed = true;
- MessageDialog msg (*editor,
- (_("The disk system on your computer\n\
+ if (!have_disk_speed_dialog_displayed) {
+ have_disk_speed_dialog_displayed = true;
+ MessageDialog* msg = new MessageDialog (*editor,
+ _("The disk system on your computer\n\
was not able to keep up with Ardour.\n\
\n\
Specifically, it failed to read data from disk\n\
-quickly enough to keep up with playback.\n")));
- msg.run ();
- have_disk_underrun_displayed = false;
+quickly enough to keep up with playback.\n"));
+ msg->signal_response().connect (bind (mem_fun (*this, &ARDOUR_UI::disk_speed_dialog_gone), msg));
+ msg->show_all ();
}
}
void
-ARDOUR_UI::disk_underrun_message_gone ()
+ARDOUR_UI::disk_speed_dialog_gone (int ignored_response, MessageDialog* msg)
{
- have_disk_underrun_displayed = false;
-}
-
-void
-ARDOUR_UI::disk_overrun_message_gone ()
-{
- have_disk_underrun_displayed = false;
+ have_disk_speed_dialog_displayed = false;
+ delete msg;
}
int
@@ -2360,13 +2517,6 @@ ARDOUR_UI::reconnect_to_jack ()
}
}
-void
-ARDOUR_UI::set_jack_buffer_size (nframes_t nframes)
-{
- engine->request_buffer_size (nframes);
- update_sample_rate (0);
-}
-
int
ARDOUR_UI::cmdline_new_session (string path)
{
@@ -2434,6 +2584,11 @@ ARDOUR_UI::use_config ()
Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
ract->set_active ();
}
+
+ XMLNode* node = Config->extra_xml (X_("TransportControllables"));
+ if (node) {
+ set_transport_controllable_state (*node);
+ }
}
void
@@ -2503,3 +2658,107 @@ ARDOUR_UI::store_clock_modes ()
+ARDOUR_UI::TransportControllable::TransportControllable (std::string name, ARDOUR_UI& u, ToggleType tp)
+ : Controllable (name), ui (u), type(tp)
+{
+
+}
+
+void
+ARDOUR_UI::TransportControllable::set_value (float val)
+{
+ if (type == ShuttleControl) {
+ double fract;
+
+ if (val == 0.5f) {
+ fract = 0.0;
+ } else {
+ if (val < 0.5f) {
+ fract = -((0.5f - val)/0.5f);
+ } else {
+ fract = ((val - 0.5f)/0.5f);
+ }
+ }
+
+ ui.set_shuttle_fract (fract);
+ return;
+ }
+
+ if (val < 0.5f) {
+ /* do nothing: these are radio-style actions */
+ return;
+ }
+
+ char *action = 0;
+
+ switch (type) {
+ case Roll:
+ action = X_("Roll");
+ break;
+ case Stop:
+ action = X_("Stop");
+ break;
+ case GotoStart:
+ action = X_("Goto Start");
+ break;
+ case GotoEnd:
+ action = X_("Goto End");
+ break;
+ case AutoLoop:
+ action = X_("Loop");
+ break;
+ case PlaySelection:
+ action = X_("Play Selection");
+ break;
+ case RecordEnable:
+ action = X_("Record");
+ break;
+ default:
+ break;
+ }
+
+ if (action == 0) {
+ return;
+ }
+
+ Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", action);
+
+ if (act) {
+ act->activate ();
+ }
+}
+
+float
+ARDOUR_UI::TransportControllable::get_value (void) const
+{
+ float val = 0.0f;
+
+ switch (type) {
+ case Roll:
+ break;
+ case Stop:
+ break;
+ case GotoStart:
+ break;
+ case GotoEnd:
+ break;
+ case AutoLoop:
+ break;
+ case PlaySelection:
+ break;
+ case RecordEnable:
+ break;
+ case ShuttleControl:
+ break;
+ default:
+ break;
+ }
+
+ return val;
+}
+
+void
+ARDOUR_UI::TransportControllable::set_id (const string& str)
+{
+ _id = str;
+}
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 45a795dec3..171974deaa 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gui_h__
@@ -55,6 +54,7 @@
#include <gtkmm2ext/gtk_ui.h>
#include <gtkmm2ext/click_box.h>
#include <gtkmm2ext/stateful_button.h>
+#include <gtkmm2ext/bindable_button.h>
#include <ardour/ardour.h>
#include <ardour/session.h>
@@ -65,7 +65,6 @@
class AudioClock;
class PublicEditor;
class Keyboard;
-class MeterBridge;
class OptionEditor;
class Mixer_UI;
class ConnectionEditor;
@@ -128,7 +127,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
_will_create_new_session_automatically = yn;
}
- void new_session(std::string path = string());
+ bool new_session(std::string path = string());
gint cmdline_new_session (string path);
int unload_session ();
void close_session();
@@ -156,6 +155,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
static sigc::signal<void,bool> Blink;
static sigc::signal<void> RapidScreenUpdate;
+ static sigc::signal<void> MidRapidScreenUpdate;
static sigc::signal<void> SuperRapidScreenUpdate;
static sigc::signal<void,nframes_t> Clock;
@@ -187,7 +187,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void store_clock_modes ();
void restore_clock_modes ();
- void add_route ();
+ void add_route (Gtk::Window* float_window);
void session_add_audio_track (int input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many) {
session_add_audio_route (true, input_channels, output_channels, mode, how_many);
@@ -277,9 +277,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
GlobalClickBox *crossfade_time_button;
vector<string> crossfade_time_strings;
- GlobalClickBox *mmc_id_button;
- vector<string> mmc_id_strings;
-
Gtk::ToggleButton preroll_button;
Gtk::ToggleButton postroll_button;
@@ -289,7 +286,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
int setup_windows ();
void setup_transport ();
void setup_clock ();
- void setup_adjustables ();
static ARDOUR_UI *theArdourUI;
@@ -317,9 +313,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void start_blinking ();
void stop_blinking ();
- void control_methods_adjusted ();
- void mmc_device_id_adjusted ();
-
void about_signal_response(int response);
private:
@@ -360,18 +353,51 @@ class ARDOUR_UI : public Gtkmm2ext::UI
Gtk::HBox primary_clock_hbox;
Gtk::HBox secondary_clock_hbox;
- Gtkmm2ext::StatefulButton roll_button;
- Gtkmm2ext::StatefulButton stop_button;
- Gtkmm2ext::StatefulButton rewind_button;
- Gtkmm2ext::StatefulButton forward_button;
- Gtkmm2ext::StatefulButton goto_start_button;
- Gtkmm2ext::StatefulButton goto_end_button;
- Gtkmm2ext::StatefulButton auto_loop_button;
- Gtkmm2ext::StatefulButton play_selection_button;
- Gtkmm2ext::StatefulButton rec_button;
+ struct TransportControllable : public PBD::Controllable {
+ enum ToggleType {
+ Roll = 0,
+ Stop,
+ RecordEnable,
+ GotoStart,
+ GotoEnd,
+ AutoLoop,
+ PlaySelection,
+ ShuttleControl
+
+ };
+
+ TransportControllable (std::string name, ARDOUR_UI&, ToggleType);
+ void set_value (float);
+ float get_value (void) const;
+
+ void set_id (const std::string&);
+
+ ARDOUR_UI& ui;
+ ToggleType type;
+ };
+
+ TransportControllable roll_controllable;
+ TransportControllable stop_controllable;
+ TransportControllable goto_start_controllable;
+ TransportControllable goto_end_controllable;
+ TransportControllable auto_loop_controllable;
+ TransportControllable play_selection_controllable;
+ TransportControllable rec_controllable;
+ TransportControllable shuttle_controllable;
+ BindingProxy shuttle_controller_binding_proxy;
+
+ void set_transport_controllable_state (const XMLNode&);
+ XMLNode& get_transport_controllable_state ();
+
+ BindableButton roll_button;
+ BindableButton stop_button;
+ BindableButton goto_start_button;
+ BindableButton goto_end_button;
+ BindableButton auto_loop_button;
+ BindableButton play_selection_button;
+ BindableButton rec_button;
- Gtk::ToggleButton time_master_button;
Gtk::ComboBoxText sync_option_combo;
void sync_option_changed ();
@@ -403,16 +429,19 @@ 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;
- Gtk::ToggleButton punch_in_button;
- Gtk::ToggleButton punch_out_button;
- Gtk::ToggleButton auto_return_button;
- Gtk::ToggleButton auto_play_button;
- Gtk::ToggleButton auto_input_button;
- Gtk::ToggleButton click_button;
+ Gtkmm2ext::StatefulToggleButton punch_in_button;
+ Gtkmm2ext::StatefulToggleButton punch_out_button;
+ Gtkmm2ext::StatefulToggleButton auto_return_button;
+ Gtkmm2ext::StatefulToggleButton auto_play_button;
+ Gtkmm2ext::StatefulToggleButton auto_input_button;
+ Gtkmm2ext::StatefulToggleButton click_button;
+ Gtkmm2ext::StatefulToggleButton time_master_button;
+
Gtk::ToggleButton auditioning_alert_button;
Gtk::ToggleButton solo_alert_button;
@@ -435,14 +464,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void transport_rec_enable_blink (bool onoff);
- /* These change where we accept control from:
- MMC, X (local) or both.
- */
-
- void allow_mmc_only ();
- void allow_mmc_and_local ();
- void allow_local_only ();
-
Gtk::Menu* session_popup_menu;
struct RecentSessionModelColumns : public Gtk::TreeModel::ColumnRecord {
@@ -502,10 +523,12 @@ class ARDOUR_UI : public Gtkmm2ext::UI
gint every_second ();
gint every_point_one_seconds ();
+ gint every_point_oh_five_seconds ();
gint every_point_zero_one_seconds ();
sigc::connection second_connection;
sigc::connection point_one_second_connection;
+ sigc::connection point_oh_five_second_connection;
sigc::connection point_zero_one_second_connection;
gint session_menu (GdkEventButton *);
@@ -589,7 +612,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
/* Keymap handling */
void install_actions ();
- void start_keyboard_prefix();
void toggle_record_enable (uint32_t);
@@ -613,11 +635,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
struct timeval last_peak_grab;
struct timeval last_shuttle_request;
- bool have_disk_overrun_displayed;
- bool have_disk_underrun_displayed;
-
- void disk_overrun_message_gone ();
- void disk_underrun_message_gone ();
+ bool have_disk_speed_dialog_displayed;
+ void disk_speed_dialog_gone (int ignored_response, Gtk::MessageDialog*);
void disk_overrun_handler ();
void disk_underrun_handler ();
@@ -646,10 +665,13 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_use_midi_control();
void toggle_send_mtc ();
+ void toggle_use_osc ();
+
void set_input_auto_connect (ARDOUR::AutoConnectOption);
void set_output_auto_connect (ARDOUR::AutoConnectOption);
void set_solo_model (ARDOUR::SoloModel);
void set_monitor_model (ARDOUR::MonitorModel);
+ void set_remote_model (ARDOUR::RemoteModel);
void toggle_StopPluginsWithTransport();
void toggle_DoNotRunPluginsWhileRecording();
@@ -658,12 +680,14 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void toggle_StopTransportAtEndOfSession();
void toggle_GainReduceFastTransport();
void toggle_LatchedSolo();
+ void toggle_ShowSoloMutes();
void toggle_LatchedRecordEnable ();
void toggle_RegionEquivalentsOverlap ();
void mtc_port_changed ();
void map_solo_model ();
void map_monitor_model ();
+ void map_remote_model ();
void map_file_header_format ();
void map_file_data_format ();
void map_input_auto_connect ();
@@ -680,6 +704,9 @@ class ARDOUR_UI : public Gtkmm2ext::UI
bool can_save_keybindings;
bool first_idle ();
+
+ void no_memory_warning ();
+ void check_memory_locking ();
};
#endif /* __ardour_gui_h__ */
diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc
index a39bcb124d..eec94b525f 100644
--- a/gtk2_ardour/ardour_ui2.cc
+++ b/gtk2_ardour/ardour_ui2.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <fcntl.h>
@@ -38,10 +37,12 @@
#include <ardour/route.h>
#include "ardour_ui.h"
+#include "keyboard.h"
#include "public_editor.h"
#include "audio_clock.h"
#include "actions.h"
#include "utils.h"
+#include "color_manager.h"
#include "i18n.h"
@@ -72,9 +73,10 @@ ARDOUR_UI::setup_windows ()
setup_clock ();
setup_transport();
- setup_adjustables ();
build_menu_bar ();
+ color_manager->signal_unmap().connect (bind (sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleColorManager")));
+
top_packer.pack_start (menu_bar_base, false, false);
top_packer.pack_start (transport_frame, false, false);
@@ -84,45 +86,13 @@ ARDOUR_UI::setup_windows ()
}
void
-ARDOUR_UI::setup_adjustables ()
-{
- adjuster_table.set_homogeneous (true);
-
- online_control_strings.push_back (_("MMC + Local"));
- online_control_strings.push_back (_("MMC"));
- online_control_strings.push_back (_("Local"));
-
- online_control_button = new GlobalClickBox ("CONTROL",
- online_control_strings);
-
- online_control_button->adjustment.signal_value_changed().connect(mem_fun(*this,&ARDOUR_UI::control_methods_adjusted));
-
- mmc_id_strings.push_back ("1");
- mmc_id_strings.push_back ("2");
- mmc_id_strings.push_back ("3");
- mmc_id_strings.push_back ("4");
- mmc_id_strings.push_back ("5");
- mmc_id_strings.push_back ("6");
- mmc_id_strings.push_back ("7");
- mmc_id_strings.push_back ("8");
- mmc_id_strings.push_back ("9");
-
- mmc_id_button = new GlobalClickBox (_("MMC ID"), mmc_id_strings);
-
- mmc_id_button->adjustment.signal_value_changed().connect (mem_fun(*this,&ARDOUR_UI::mmc_device_id_adjusted));
-
- adjuster_table.attach (*online_control_button, 0, 2, 1, 2, FILL|EXPAND, FILL, 5, 5);
- adjuster_table.attach (*mmc_id_button, 2, 3, 1, 2, FILL, FILL, 5, 5);
-}
-
-void
ARDOUR_UI::transport_stopped ()
{
- stop_button.set_active (true);
+ stop_button.set_visual_state (1);
- roll_button.set_active (false);
- play_selection_button.set_active (false);
- auto_loop_button.set_active (false);
+ roll_button.set_visual_state (0);
+ play_selection_button.set_visual_state (0);
+ auto_loop_button.set_visual_state (0);
shuttle_fract = 0;
shuttle_box.queue_draw ();
@@ -133,22 +103,22 @@ ARDOUR_UI::transport_stopped ()
void
ARDOUR_UI::transport_rolling ()
{
- stop_button.set_active (false);
+ stop_button.set_visual_state (0);
if (session->get_play_range()) {
- play_selection_button.set_active (true);
- roll_button.set_active (false);
- auto_loop_button.set_active (false);
+ play_selection_button.set_visual_state (1);
+ roll_button.set_visual_state (0);
+ auto_loop_button.set_visual_state (0);
} else if (session->get_play_loop ()) {
- auto_loop_button.set_active (true);
- play_selection_button.set_active (false);
- roll_button.set_active (false);
+ auto_loop_button.set_visual_state (1);
+ play_selection_button.set_visual_state (0);
+ roll_button.set_visual_state (0);
} else {
- roll_button.set_active (true);
- play_selection_button.set_active (false);
- auto_loop_button.set_active (false);
+ roll_button.set_visual_state (1);
+ play_selection_button.set_visual_state (0);
+ auto_loop_button.set_visual_state (0);
}
/* reset shuttle controller */
@@ -160,19 +130,19 @@ ARDOUR_UI::transport_rolling ()
void
ARDOUR_UI::transport_rewinding ()
{
- stop_button.set_active(false);
- roll_button.set_active (true);
- play_selection_button.set_active (false);
- auto_loop_button.set_active (false);
+ stop_button.set_visual_state (0);
+ roll_button.set_visual_state (1);
+ play_selection_button.set_visual_state (0);
+ auto_loop_button.set_visual_state (0);
}
void
ARDOUR_UI::transport_forwarding ()
{
- stop_button.set_active (false);
- roll_button.set_active (true);
- play_selection_button.set_active (false);
- auto_loop_button.set_active (false);
+ stop_button.set_visual_state (0);
+ roll_button.set_visual_state (1);
+ play_selection_button.set_visual_state (0);
+ auto_loop_button.set_visual_state (0);
}
void
@@ -207,6 +177,7 @@ ARDOUR_UI::setup_transport ()
play_selection_button.set_name ("TransportButton");
rec_button.set_name ("TransportRecButton");
auto_loop_button.set_name ("TransportButton");
+
auto_return_button.set_name ("TransportButton");
auto_play_button.set_name ("TransportButton");
auto_input_button.set_name ("TransportButton");
@@ -215,30 +186,6 @@ ARDOUR_UI::setup_transport ()
click_button.set_name ("TransportButton");
time_master_button.set_name ("TransportButton");
- vector<Gdk::Color> colors;
- Gdk::Color c;
-
- /* record button has 3 color states, so we set 2 extra here */
- set_color(c, rgba_from_style ("TransportRecButton", 0xff, 0, 0, 0, "bg", Gtk::STATE_PRELIGHT, false ));
- colors.push_back (c);
-
- set_color(c, rgba_from_style ("TransportRecButton", 0xff, 0, 0, 0, "bg", Gtk::STATE_ACTIVE, false ));
- colors.push_back (c);
-
- rec_button.set_colors (colors);
- colors.clear ();
-
- /* other buttons get 2 color states, so add one here */
- set_color(c, rgba_from_style ("TransportButton", 0x7f, 0xff, 0x7f, 0, "bg", Gtk::STATE_ACTIVE, false ));
- colors.push_back (c);
-
- stop_button.set_colors (colors);
- roll_button.set_colors (colors);
- auto_loop_button.set_colors (colors);
- play_selection_button.set_colors (colors);
- goto_start_button.set_colors (colors);
- goto_end_button.set_colors (colors);
-
stop_button.set_size_request(29, -1);
roll_button.set_size_request(29, -1);
auto_loop_button.set_size_request(29, -1);
@@ -249,7 +196,7 @@ ARDOUR_UI::setup_transport ()
Widget* w;
- stop_button.set_active (true);
+ stop_button.set_visual_state (1);
w = manage (new Image (get_icon (X_("transport_start"))));
w->show();
@@ -298,6 +245,7 @@ ARDOUR_UI::setup_transport ()
ARDOUR_UI::instance()->tooltips().set_tip (goto_start_button, _("Go to start of session"));
ARDOUR_UI::instance()->tooltips().set_tip (goto_end_button, _("Go to end of session"));
ARDOUR_UI::instance()->tooltips().set_tip (auto_loop_button, _("Play loop range"));
+
ARDOUR_UI::instance()->tooltips().set_tip (auto_return_button, _("Return to last playback start when stopped"));
ARDOUR_UI::instance()->tooltips().set_tip (auto_play_button, _("Start playback after any locate"));
ARDOUR_UI::instance()->tooltips().set_tip (auto_input_button, _("Be sensible about input monitoring"));
@@ -338,12 +286,7 @@ ARDOUR_UI::setup_transport ()
ActionManager::get_action ("Transport", "TogglePunchIn")->connect_proxy (punch_in_button);
ActionManager::get_action ("Transport", "TogglePunchOut")->connect_proxy (punch_out_button);
- preroll_button.unset_flags (CAN_FOCUS);
- preroll_button.set_events (preroll_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
preroll_button.set_name ("TransportButton");
-
- postroll_button.unset_flags (CAN_FOCUS);
- postroll_button.set_events (postroll_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
postroll_button.set_name ("TransportButton");
preroll_clock.set_mode (AudioClock::MinSec);
@@ -622,6 +565,10 @@ ARDOUR_UI::shuttle_box_button_press (GdkEventButton* ev)
return true;
}
+ if (shuttle_controller_binding_proxy.button_press_handler (ev)) {
+ return true;
+ }
+
if (Keyboard::is_context_menu_event (ev)) {
show_shuttle_context_menu ();
return true;
@@ -659,8 +606,8 @@ ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev)
if (Config->get_auto_play() || roll_button.get_state()) {
shuttle_fract = SHUTTLE_FRACT_SPEED1;
session->request_transport_speed (1.0);
- stop_button.set_active (false);
- roll_button.set_active (true);
+ stop_button.set_visual_state (0);
+ roll_button.set_visual_state (1);
} else {
shuttle_fract = 0;
session->request_transport_speed (0.0);
@@ -673,8 +620,8 @@ ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev)
if (session->transport_rolling()) {
shuttle_fract = SHUTTLE_FRACT_SPEED1;
session->request_transport_speed (1.0);
- stop_button.set_active (false);
- roll_button.set_active (true);
+ stop_button.set_visual_state (0);
+ roll_button.set_visual_state (1);
} else {
shuttle_fract = 0;
}
@@ -750,6 +697,13 @@ ARDOUR_UI::mouse_shuttle (double x, bool force)
}
void
+ARDOUR_UI::set_shuttle_fract (double f)
+{
+ shuttle_fract = f;
+ use_shuttle_fract (false);
+}
+
+void
ARDOUR_UI::use_shuttle_fract (bool force)
{
struct timeval now;
diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc
index 9c6daa8952..5617cdbc4f 100644
--- a/gtk2_ardour/ardour_ui_dependents.cc
+++ b/gtk2_ardour/ardour_ui_dependents.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
/* this file exists solely to break compilation dependencies that
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
index 140ee649ea..765eb53282 100644
--- a/gtk2_ardour/ardour_ui_dialogs.cc
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -62,6 +62,20 @@ ARDOUR_UI::connect_to_session (Session *s)
ActionManager::set_sensitive (ActionManager::range_sensitive_actions, false);
}
+ if (!session->control_out()) {
+ Glib::RefPtr<Action> act = ActionManager::get_action (X_("options"), X_("SoloViaBus"));
+ if (act) {
+ act->set_sensitive (false);
+ }
+ }
+
+ /* allow wastebasket flush again */
+
+ Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), X_("FlushWastebasket"));
+ if (act) {
+ act->set_sensitive (true);
+ }
+
/* there are never any selections on startup */
ActionManager::set_sensitive (ActionManager::region_selection_sensitive_actions, false);
@@ -139,6 +153,7 @@ ARDOUR_UI::connect_to_session (Session *s)
second_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::every_second), 1000);
point_one_second_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::every_point_one_seconds), 100);
+ // point_oh_five_second_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::every_point_oh_five_seconds), 50);
point_zero_one_second_connection = Glib::signal_timeout().connect (mem_fun(*this, &ARDOUR_UI::every_point_zero_one_seconds), 40);
}
@@ -158,6 +173,7 @@ ARDOUR_UI::unload_session ()
editor->hide ();
second_connection.disconnect ();
point_one_second_connection.disconnect ();
+ point_oh_five_second_connection.disconnect ();
point_zero_one_second_connection.disconnect();
ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
@@ -322,7 +338,7 @@ int
ARDOUR_UI::create_route_params ()
{
if (route_params == 0) {
- route_params = new RouteParams_UI (*engine);
+ route_params = new RouteParams_UI ();
route_params->set_session (session);
route_params->signal_unmap().connect (sigc::bind(sigc::ptr_fun(&ActionManager::uncheck_toggleaction), X_("<Actions>/Common/ToggleInspector")));
}
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index b6e31d12d8..7f0ddeef78 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
/* This file contains any ARDOUR_UI methods that require knowledge of
@@ -35,6 +34,7 @@
#include "actions.h"
#include <ardour/session.h>
+#include <ardour/audioengine.h>
#include <ardour/control_protocol_manager.h>
#include <control_protocol/control_protocol.h>
@@ -54,7 +54,7 @@ ARDOUR_UI::create_editor ()
{
try {
- editor = new Editor (*engine);
+ editor = new Editor ();
}
catch (failed_constructor& err) {
@@ -92,14 +92,15 @@ ARDOUR_UI::install_actions ()
/* the real actions */
- act = ActionManager::register_action (main_actions, X_("New"), _("New"), 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::new_session), string ())));
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));
act = ActionManager::register_action (main_actions, X_("Close"), _("Close"), mem_fun(*this, &ARDOUR_UI::close_session));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (main_actions, X_("AddTrackBus"), _("Add Track/Bus"), mem_fun(*this, &ARDOUR_UI::add_route));
+ act = ActionManager::register_action (main_actions, X_("AddTrackBus"), _("Add Track/Bus"),
+ bind (mem_fun(*this, &ARDOUR_UI::add_route), (Gtk::Window*) 0));
ActionManager::session_sensitive_actions.push_back (act);
@@ -180,7 +181,6 @@ ARDOUR_UI::install_actions ()
common_actions = ActionGroup::create (X_("Common"));
ActionManager::register_action (main_actions, X_("Windows"), _("Windows"));
- ActionManager::register_action (common_actions, X_("Start-Prefix"), _("start prefix"), mem_fun(*this, &ARDOUR_UI::start_keyboard_prefix));
ActionManager::register_action (common_actions, X_("Quit"), _("Quit"), (mem_fun(*this, &ARDOUR_UI::finish)));
/* windows visibility actions */
@@ -397,6 +397,11 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_toggle_action (option_actions, X_("UseMIDIcontrol"), _("Use MIDI control"), mem_fun (*this, &ARDOUR_UI::toggle_use_midi_control));
ActionManager::session_sensitive_actions.push_back (act);
+ act = ActionManager::register_toggle_action (option_actions, X_("UseOSC"), _("Use OSC"), mem_fun (*this, &ARDOUR_UI::toggle_use_osc));
+#ifndef HAVE_LIBLO
+ act->set_sensitive (false);
+#endif
+
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_("StopRecordingOnXrun"), _("Stop recording on xrun"), mem_fun (*this, &ARDOUR_UI::toggle_StopRecordingOnXrun));
@@ -410,6 +415,8 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_toggle_action (option_actions, X_("LatchedSolo"), _("Latched solo"), mem_fun (*this, &ARDOUR_UI::toggle_LatchedSolo));
ActionManager::session_sensitive_actions.push_back (act);
+ act = ActionManager::register_toggle_action (option_actions, X_("ShowSoloMutes"), _("Show solo muting"), mem_fun (*this, &ARDOUR_UI::toggle_ShowSoloMutes));
+ ActionManager::session_sensitive_actions.push_back (act);
/* !!! REMEMBER THAT RADIO ACTIONS HAVE TO BE HANDLED WITH MORE FINESSE THAN SIMPLE TOGGLES !!! */
@@ -472,6 +479,15 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_radio_action (option_actions, output_auto_connect_group, X_("OutputAutoConnectManual"), _("Manually connect outputs"), hide_return (bind (mem_fun (*this, &ARDOUR_UI::set_output_auto_connect), (AutoConnectOption) 0)));
ActionManager::session_sensitive_actions.push_back (act);
+ RadioAction::Group remote_group;
+
+ act = ActionManager::register_radio_action (option_actions, remote_group, X_("RemoteUserDefined"), _("Remote ID assigned by User"), hide_return (bind (mem_fun (*this, &ARDOUR_UI::set_remote_model), UserOrdered)));
+ ActionManager::session_sensitive_actions.push_back (act);
+ act = ActionManager::register_radio_action (option_actions, remote_group, X_("RemoteMixerDefined"), _("Remote ID follows order of Mixer"), hide_return (bind (mem_fun (*this, &ARDOUR_UI::set_remote_model), MixerOrdered)));
+ ActionManager::session_sensitive_actions.push_back (act);
+ act = ActionManager::register_radio_action (option_actions, remote_group, X_("RemoteEditorDefined"), _("Remote ID follows order of Editor"), hide_return (bind (mem_fun (*this, &ARDOUR_UI::set_remote_model), EditorOrdered)));
+ ActionManager::session_sensitive_actions.push_back (act);
+
ActionManager::add_action_group (shuttle_actions);
ActionManager::add_action_group (option_actions);
ActionManager::add_action_group (jack_actions);
@@ -527,6 +543,57 @@ ARDOUR_UI::toggle_control_protocol_feedback (ControlProtocolInfo* cpi, const cha
}
void
+ARDOUR_UI::set_jack_buffer_size (nframes_t nframes)
+{
+ Glib::RefPtr<Action> action;
+ char* action_name = 0;
+
+ switch (nframes) {
+ case 32:
+ action_name = X_("JACKLatency32");
+ break;
+ case 64:
+ action_name = X_("JACKLatency64");
+ break;
+ case 128:
+ action_name = X_("JACKLatency128");
+ break;
+ case 512:
+ action_name = X_("JACKLatency512");
+ break;
+ case 1024:
+ action_name = X_("JACKLatency1024");
+ break;
+ case 2048:
+ action_name = X_("JACKLatency2048");
+ break;
+ case 4096:
+ action_name = X_("JACKLatency4096");
+ break;
+ case 8192:
+ action_name = X_("JACKLatency8192");
+ break;
+ default:
+ /* XXX can we do anything useful ? */
+ break;
+ }
+
+ if (action_name) {
+
+ action = ActionManager::get_action (X_("JACK"), action_name);
+
+ if (action) {
+ Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic (action);
+
+ if (ract && ract->get_active()) {
+ engine->request_buffer_size (nframes);
+ update_sample_rate (0);
+ }
+ }
+ }
+}
+
+void
ARDOUR_UI::build_control_surface_menu ()
{
list<ControlProtocolInfo*>::iterator i;
diff --git a/gtk2_ardour/ardour_ui_mixer.cc b/gtk2_ardour/ardour_ui_mixer.cc
index 991f37c3a7..dfc5d644b0 100644
--- a/gtk2_ardour/ardour_ui_mixer.cc
+++ b/gtk2_ardour/ardour_ui_mixer.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
/* This file contains any ARDOUR_UI methods that require knowledge of
@@ -35,7 +34,7 @@ ARDOUR_UI::create_mixer ()
{
try {
- mixer = new Mixer_UI (*engine);
+ mixer = new Mixer_UI ();
}
catch (failed_constructor& err) {
@@ -44,3 +43,4 @@ ARDOUR_UI::create_mixer ()
return 0;
}
+
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index 5674d6dee1..c7db8f4ec6 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <pbd/convert.h>
@@ -25,6 +24,7 @@
#include <ardour/configuration.h>
#include <ardour/session.h>
+#include <ardour/osc.h>
#include <ardour/audioengine.h>
#include "ardour_ui.h"
@@ -64,6 +64,12 @@ ARDOUR_UI::toggle_use_mmc ()
}
void
+ARDOUR_UI::toggle_use_osc ()
+{
+ ActionManager::toggle_config_state ("options", "UseOSC", &Configuration::set_use_osc, &Configuration::get_use_osc);
+}
+
+void
ARDOUR_UI::toggle_use_midi_control ()
{
ActionManager::toggle_config_state ("options", "UseMIDIcontrol", &Configuration::set_midi_control, &Configuration::get_midi_control);
@@ -78,7 +84,7 @@ ARDOUR_UI::toggle_send_midi_feedback ()
void
ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
{
- const char *action;
+ const char *action = 0;
switch (hf) {
case BWF:
@@ -120,7 +126,7 @@ ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
void
ARDOUR_UI::set_native_file_data_format (SampleFormat sf)
{
- const char* action;
+ const char* action = 0;
switch (sf) {
case FormatFloat:
@@ -226,6 +232,39 @@ ARDOUR_UI::set_solo_model (SoloModel model)
}
void
+ARDOUR_UI::set_remote_model (RemoteModel model)
+{
+ const char* action = 0;
+
+ switch (model) {
+ case UserOrdered:
+ action = X_("RemoteUserDefined");
+ break;
+ case MixerOrdered:
+ action = X_("RemoteMixerDefined");
+ break;
+ case EditorOrdered:
+ action = X_("RemoteEditorDefined");
+ break;
+
+ default:
+ fatal << string_compose (_("programming error: unknown remote model in ARDOUR_UI::set_remote_model: %1"), model) << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Glib::RefPtr<Action> act = ActionManager::get_action ("options", action);
+
+ if (act) {
+ Glib::RefPtr<RadioAction> ract = Glib::RefPtr<RadioAction>::cast_dynamic(act);
+
+ if (ract && ract->get_active() && Config->get_remote_model() != model) {
+ Config->set_remote_model (model);
+ }
+ }
+
+}
+
+void
ARDOUR_UI::set_monitor_model (MonitorModel model)
{
const char* action = 0;
@@ -390,6 +429,12 @@ ARDOUR_UI::toggle_LatchedSolo()
}
void
+ARDOUR_UI::toggle_ShowSoloMutes()
+{
+ ActionManager::toggle_config_state ("options", "ShowSoloMutes", &Configuration::set_show_solo_mutes, &Configuration::get_show_solo_mutes);
+}
+
+void
ARDOUR_UI::mtc_port_changed ()
{
bool have_mtc;
@@ -472,6 +517,33 @@ ARDOUR_UI::map_monitor_model ()
}
void
+ARDOUR_UI::map_remote_model ()
+{
+ const char* on = 0;
+
+ switch (Config->get_remote_model()) {
+ case UserOrdered:
+ on = X_("RemoteUserDefined");
+ break;
+ case MixerOrdered:
+ on = X_("RemoteMixerDefined");
+ break;
+ case EditorOrdered:
+ on = X_("RemoteEditorDefined");
+ break;
+ }
+
+ Glib::RefPtr<Action> act = ActionManager::get_action ("options", on);
+ if (act) {
+ Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+
+ if (tact && !tact->get_active()) {
+ tact->set_active (true);
+ }
+ }
+}
+
+void
ARDOUR_UI::map_file_header_format ()
{
const char* action = 0;
@@ -757,6 +829,19 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
if (PARAM_IS ("slave-source")) {
sync_option_combo.set_active_text (slave_source_to_string (Config->get_slave_source()));
+
+ switch (Config->get_slave_source()) {
+ case None:
+ ActionManager::get_action ("Transport", "ToggleAutoPlay")->set_sensitive (true);
+ ActionManager::get_action ("Transport", "ToggleAutoReturn")->set_sensitive (true);
+ break;
+
+ default:
+ /* XXX need to make auto-play is off as well as insensitive */
+ ActionManager::get_action ("Transport", "ToggleAutoPlay")->set_sensitive (false);
+ ActionManager::get_action ("Transport", "ToggleAutoReturn")->set_sensitive (false);
+ break;
+ }
} else if (PARAM_IS ("send-mtc")) {
@@ -766,6 +851,18 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
ActionManager::map_some_state ("options", "SendMMC", &Configuration::get_send_mmc);
+ } else if (PARAM_IS ("use-osc")) {
+
+#ifdef HAVE_LIBLO
+ if (Config->get_use_osc()) {
+ osc->start ();
+ } else {
+ osc->stop ();
+ }
+#endif
+
+ ActionManager::map_some_state ("options", "UseOSC", &Configuration::get_use_osc);
+
} else if (PARAM_IS ("mmc-control")) {
ActionManager::map_some_state ("options", "UseMMC", &Configuration::get_mmc_control);
} else if (PARAM_IS ("midi-feedback")) {
@@ -778,6 +875,8 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
ActionManager::map_some_state ("options", "LatchedRecordEnable", &Configuration::get_latched_record_enable);
} else if (PARAM_IS ("solo-latched")) {
ActionManager::map_some_state ("options", "LatchedSolo", &Configuration::get_solo_latched);
+ } else if (PARAM_IS ("show-solo-mutes")) {
+ ActionManager::map_some_state ("options", "ShowSoloMutes", &Configuration::get_show_solo_mutes);
} else if (PARAM_IS ("solo-model")) {
map_solo_model ();
} else if (PARAM_IS ("auto-play")) {
@@ -806,6 +905,8 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
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 ("remote-model")) {
+ map_remote_model ();
} else if (PARAM_IS ("use-video-sync")) {
ActionManager::map_some_state ("Transport", "ToggleVideoSync", &Configuration::get_use_video_sync);
} else if (PARAM_IS ("quieten-at-speed")) {
diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc
index 481e91b09a..1334bfdc4b 100644
--- a/gtk2_ardour/audio_clock.cc
+++ b/gtk2_ardour/audio_clock.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdio> // for sprintf
diff --git a/gtk2_ardour/audio_clock.h b/gtk2_ardour/audio_clock.h
index 662cb949e6..f0790dcbc8 100644
--- a/gtk2_ardour/audio_clock.h
+++ b/gtk2_ardour/audio_clock.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __audio_clock_h__
diff --git a/gtk2_ardour/audio_region_editor.cc b/gtk2_ardour/audio_region_editor.cc
index b7106a0796..4f1d0852bd 100644
--- a/gtk2_ardour/audio_region_editor.cc
+++ b/gtk2_ardour/audio_region_editor.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <pbd/memento_command.h>
diff --git a/gtk2_ardour/audio_region_editor.h b/gtk2_ardour/audio_region_editor.h
index a84aec27c0..024f390d40 100644
--- a/gtk2_ardour/audio_region_editor.h
+++ b/gtk2_ardour/audio_region_editor.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_audio_region_edit_h__
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index 4bded299b4..ee2dd63b6c 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -88,14 +88,37 @@ AudioRegionView::AudioRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView
{
}
+
+AudioRegionView::AudioRegionView (const AudioRegionView& other)
+ : RegionView (other)
+ , zero_line(0)
+ , fade_in_shape(0)
+ , fade_out_shape(0)
+ , fade_in_handle(0)
+ , fade_out_handle(0)
+ , gain_line(0)
+ , _amplitude_above_axis(1.0)
+ , _flags(0)
+ , fade_color(0)
+
+{
+ Gdk::Color c;
+ int r,g,b,a;
+
+ UINT_TO_RGBA (other.fill_color, &r, &g, &b, &a);
+ c.set_rgb_p (r/255.0, g/255.0, b/255.0);
+
+ init (c, false);
+}
+
void
AudioRegionView::init (Gdk::Color& basic_color, bool wfd)
{
// FIXME: Some redundancy here with RegionView::init. Need to figure out
// where order is important and where it isn't...
- RegionView::init(basic_color, wfd);
-
+ RegionView::init(basic_color, false);
+
XMLNode *node;
_amplitude_above_axis = 1.0;
@@ -629,13 +652,16 @@ AudioRegionView::set_samples_per_unit (gdouble spu)
{
RegionView::set_samples_per_unit (spu);
- for (uint32_t n=0; n < waves.size(); ++n) {
- waves[n]->property_samples_per_unit() = spu;
+ if (_flags & WaveformVisible) {
+ for (uint32_t n=0; n < waves.size(); ++n) {
+ waves[n]->property_samples_per_unit() = spu;
+ }
}
if (gain_line) {
gain_line->reset ();
}
+
reset_fade_shapes ();
}
@@ -698,6 +724,10 @@ AudioRegionView::set_waveform_visible (bool yn)
if (((_flags & WaveformVisible) != yn)) {
if (yn) {
for (uint32_t n=0; n < waves.size(); ++n) {
+ /* make sure the zoom level is correct, since we don't update
+ this when waveforms are hidden.
+ */
+ waves[n]->property_samples_per_unit() = samples_per_unit;
waves[n]->show();
}
_flags |= WaveformVisible;
diff --git a/gtk2_ardour/audio_region_view.h b/gtk2_ardour/audio_region_view.h
index a59972b807..233e1a7c9b 100644
--- a/gtk2_ardour/audio_region_view.h
+++ b/gtk2_ardour/audio_region_view.h
@@ -55,6 +55,8 @@ class AudioRegionView : public RegionView
double initial_samples_per_unit,
Gdk::Color& basic_color);
+ AudioRegionView (const AudioRegionView& other);
+
~AudioRegionView ();
virtual void init (Gdk::Color& base_color, bool wait_for_data = false);
@@ -159,10 +161,10 @@ class AudioRegionView : public RegionView
void compute_colors (Gdk::Color&);
void reset_width_dependent_items (double pixel_width);
void set_waveview_data_src();
-
- vector<GnomeCanvasWaveViewCache*> wave_caches;
void color_handler (ColorID, uint32_t);
+
+ vector<GnomeCanvasWaveViewCache*> wave_caches;
};
#endif /* __gtk_ardour_audio_region_view_h__ */
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc
index 11d151fb91..5e0728b05a 100644
--- a/gtk2_ardour/audio_time_axis.cc
+++ b/gtk2_ardour/audio_time_axis.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
@@ -116,21 +115,13 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
_route->panner().Changed.connect (mem_fun(*this, &AudioTimeAxisView::update_pans));
- if (is_track()) {
+ update_control_names ();
- controls_ebox.set_name ("AudioTrackControlsBaseUnselected");
- controls_base_selected_name = "AudioTrackControlsBaseSelected";
- controls_base_unselected_name = "AudioTrackControlsBaseUnselected";
+ if (is_audio_track()) {
/* ask for notifications of any new RegionViews */
_view->RegionViewAdded.connect (mem_fun(*this, &AudioTimeAxisView::region_view_added));
_view->attach ();
-
- } else { /* bus */
-
- controls_ebox.set_name ("AudioBusControlsBaseUnselected");
- controls_base_selected_name = "AudioBusControlsBaseSelected";
- controls_base_unselected_name = "AudioBusControlsBaseUnselected";
}
post_construct ();
@@ -630,7 +621,19 @@ void
AudioTimeAxisView::route_active_changed ()
{
RouteTimeAxisView::route_active_changed ();
+ update_control_names ();
+}
+
+/**
+ * Set up the names of the controls so that they are coloured
+ * correctly depending on whether this route is inactive or
+ * selected.
+ */
+
+void
+AudioTimeAxisView::update_control_names ()
+{
if (is_audio_track()) {
if (_route->active()) {
controls_ebox.set_name ("AudioTrackControlsBaseUnselected");
diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h
index 95bd8c0955..d8c3f07cc1 100644
--- a/gtk2_ardour/audio_time_axis.h
+++ b/gtk2_ardour/audio_time_axis.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_audio_time_axis_h__
@@ -115,6 +114,7 @@ class AudioTimeAxisView : public RouteTimeAxisView
void pan_hidden ();
void update_pans ();
+ void update_control_names ();
AutomationTimeAxisView* gain_track;
AutomationTimeAxisView* pan_track;
diff --git a/gtk2_ardour/automation_gain_line.cc b/gtk2_ardour/automation_gain_line.cc
index 74e4f64e3c..006543df18 100644
--- a/gtk2_ardour/automation_gain_line.cc
+++ b/gtk2_ardour/automation_gain_line.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <sigc++/signal.h>
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
index 5598689855..4978a1ef68 100644
--- a/gtk2_ardour/automation_line.cc
+++ b/gtk2_ardour/automation_line.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -25,6 +24,7 @@
#include <pbd/stl_delete.h>
#include <pbd/memento_command.h>
+#include <pbd/stacktrace.h>
#include <ardour/automation_event.h>
#include <ardour/curve.h>
diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h
index 1349efac4b..4942643b65 100644
--- a/gtk2_ardour/automation_line.h
+++ b/gtk2_ardour/automation_line.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_automation_line_h__
diff --git a/gtk2_ardour/automation_pan_line.cc b/gtk2_ardour/automation_pan_line.cc
index aacfbdde75..04cfb0a311 100644
--- a/gtk2_ardour/automation_pan_line.cc
+++ b/gtk2_ardour/automation_pan_line.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <sigc++/signal.h>
diff --git a/gtk2_ardour/axis_view.cc b/gtk2_ardour/axis_view.cc
index e69fdf0540..0c57eebfca 100644
--- a/gtk2_ardour/axis_view.cc
+++ b/gtk2_ardour/axis_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
diff --git a/gtk2_ardour/axis_view.h b/gtk2_ardour/axis_view.h
index 4ae8f8d46e..51f744c4e5 100644
--- a/gtk2_ardour/axis_view.h
+++ b/gtk2_ardour/axis_view.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_axis_view_h__
diff --git a/gtk2_ardour/canvas-imageframe.h b/gtk2_ardour/canvas-imageframe.h
index 6c2e5ab8b6..7c66c5e1db 100644
--- a/gtk2_ardour/canvas-imageframe.h
+++ b/gtk2_ardour/canvas-imageframe.h
@@ -16,7 +16,15 @@
#include <libgnomecanvas/libgnomecanvas.h>
#include <gtk/gtkenums.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#include <libart_lgpl/art_misc.h>
+#ifdef __cplusplus
+}
+#endif
+
#include <libart_lgpl/art_pixbuf.h>
diff --git a/gtk2_ardour/canvas-simplerect.c b/gtk2_ardour/canvas-simplerect.c
index d59096e68b..54339b9e3a 100644
--- a/gtk2_ardour/canvas-simplerect.c
+++ b/gtk2_ardour/canvas-simplerect.c
@@ -257,19 +257,20 @@ gnome_canvas_simplerect_bounds (GnomeCanvasItem *item, double *x1, double *y1, d
}
+
static void
gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
{
GnomeCanvasSimpleRect* simplerect;
double x1, x2, y1, y2;
double old_x1, old_x2, old_y1, old_y2;
- double a, b, c, d;
-
+ ArtDRect unionrect, old, new;
+
old_x1 = item->x1;
old_y1 = item->y1;
old_x2 = item->x2;
old_y2 = item->y2;
-
+
gnome_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2);
gnome_canvas_item_i2w (item, &x1, &y1);
gnome_canvas_item_i2w (item, &x2, &y2);
@@ -287,24 +288,74 @@ gnome_canvas_simplerect_reset_bounds (GnomeCanvasItem *item)
gnome_canvas_w2c (GNOME_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry);
/* now queue redraws for changed areas */
-
- a = MIN(item->x1, old_x1);
- b = MAX(item->x1, old_x1);
- a = MIN(a, item->x2);
- a = MIN(a, old_x2);
- b = MAX(b, item->x2);
- b = MAX(b, old_x2);
+ if (item->x1 == old_x1 && item->x2 == old_x2) {
+
+ /* no change in x-axis position */
- c = MIN(item->y1, old_y1);
- d = MAX(item->y1, old_y1);
+ if (item->y1 == old_y1) {
+ /* top didn't change, so just draw bottom */
- c = MIN(c,item->y2);
- c = MIN(c, old_y2);
- d = MAX(d,item->y2);
- d = MAX(d, old_y2);
+ double start_y = MIN (item->y2, old_y2);
+ double end_y = MAX (item->y2, old_y2);
- gnome_canvas_request_redraw (item->canvas, a, c, b + 0.5, d + 0.5);
+ gnome_canvas_request_redraw (item->canvas, item->x1, start_y - 0.5, item->x2 + 0.5, end_y + 0.5);
+ return;
+
+ } else if (item->y2 == old_y2) {
+
+ /* bottom didn't change, just draw top */
+
+ double start_y = MIN (item->y1, old_y1);
+ double end_y = MAX (item->y1, old_y1);
+
+ gnome_canvas_request_redraw (item->canvas, item->x1, start_y - 0.5, item->x2 + 0.5, end_y + 0.5);
+ return;
+
+ }
+
+ } else if (item->y1 == old_y1 && item->y2 == old_y2) {
+
+ /* no change in y-axis position */
+
+ if (item->x1 == old_x1) {
+ /* start didn't change, so just draw at the end */
+
+ double start_x = MIN (item->x2, old_x2);
+ double end_x = MAX (item->x2, old_x2);
+
+ gnome_canvas_request_redraw (item->canvas, start_x - 0.5, item->y1, end_x + 0.5, item->y2 + 0.5);
+ return;
+
+ } else if (item->x2 == old_x2) {
+
+ /* end didn't change, so just draw at the start */
+
+ double start_x = MIN (item->x1, old_x1);
+ double end_x = MAX (item->x1, old_x1);
+
+ gnome_canvas_request_redraw (item->canvas, start_x - 0.5, item->y1, end_x + 0.5, item->y2 + 0.5);
+ return;
+
+ }
+ }
+
+ new.x0 = x1;
+ new.y0 = y1;
+ new.x1 = x2;
+ new.y1 = y2;
+
+ old.x0 = old_x1;
+ old.y0 = old_y1;
+ old.x1 = old_x2;
+ old.y1 = old_y2;
+
+ art_drect_union (&unionrect, &old, &new);
+ gnome_canvas_request_redraw (item->canvas,
+ unionrect.x0,
+ unionrect.y0,
+ unionrect.x1 + 0.5,
+ unionrect.y1 + 0.5);
}
/*
@@ -509,7 +560,7 @@ gnome_canvas_simplerect_render (GnomeCanvasItem *item,
if (parent_class->render) {
(*parent_class->render) (item, buf);
}
-
+
if (buf->is_bg) {
#ifdef HARLEQUIN_DEBUGGING
diff --git a/gtk2_ardour/canvas-waveview.c b/gtk2_ardour/canvas-waveview.c
index 747761ea9a..c8e9f61332 100644
--- a/gtk2_ardour/canvas-waveview.c
+++ b/gtk2_ardour/canvas-waveview.c
@@ -369,7 +369,8 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
end_sample = end_sample + waveview->region_start;
#if DEBUG_CACHE
// printf("waveview->region_start == %lu\n",waveview->region_start);
- printf ("=> 0x%x cache @ 0x%x range: %lu - %lu request: %lu - %lu (%lu frames)\n",
+ // c_stacktrace ();
+ printf ("\n\n=> 0x%x cache @ 0x%x range: %lu - %lu request: %lu - %lu (%lu frames)\n",
waveview, cache,
cache->start, cache->end,
start_sample, end_sample, end_sample - start_sample);
@@ -413,7 +414,7 @@ gnome_canvas_waveview_ensure_cache (GnomeCanvasWaveView *waveview, gulong start_
}
#if DEBUG_CACHE
- fprintf (stderr, "\n\nAVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n",
+ fprintf (stderr, "AVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n",
rf3, waveview->sourcefile_length_function (waveview->data_src, waveview->samples_per_unit),
waveview->region_start, start_sample, new_cache_start);
#endif
diff --git a/gtk2_ardour/colors.h b/gtk2_ardour/colors.h
index e6bdf1de4d..6997a61c70 100644
--- a/gtk2_ardour/colors.h
+++ b/gtk2_ardour/colors.h
@@ -104,3 +104,6 @@ COLORID(cTrimHandleLockedStart)
COLORID(cTrimHandleLockedEnd)
COLORID(cTrimHandleStart)
COLORID(cTrimHandleEnd)
+COLORID(cEditCursor)
+COLORID(cPlayHead)
+
diff --git a/gtk2_ardour/connection_editor.cc b/gtk2_ardour/connection_editor.cc
index a7c6e265ed..79d7605497 100644
--- a/gtk2_ardour/connection_editor.cc
+++ b/gtk2_ardour/connection_editor.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <map>
diff --git a/gtk2_ardour/connection_editor.h b/gtk2_ardour/connection_editor.h
index 71d201cd8d..aca85c7a83 100644
--- a/gtk2_ardour/connection_editor.h
+++ b/gtk2_ardour/connection_editor.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_connection_editor_h__
diff --git a/gtk2_ardour/crossfade_edit.cc b/gtk2_ardour/crossfade_edit.cc
index 208ef13aab..26d61035ba 100644
--- a/gtk2_ardour/crossfade_edit.cc
+++ b/gtk2_ardour/crossfade_edit.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -194,7 +193,7 @@ CrossfadeEditor::CrossfadeEditor (Session& s, boost::shared_ptr<Crossfade> xf, d
for (list<Preset*>::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) {
- pxmap = manage (new Image (get_xpm((*i)->xpm)));
+ pxmap = manage (new Image (::get_icon ((*i)->image_name)));
pbutton = manage (new Button);
pbutton->add (*pxmap);
pbutton->set_name ("CrossfadeEditButton");
@@ -215,7 +214,7 @@ CrossfadeEditor::CrossfadeEditor (Session& s, boost::shared_ptr<Crossfade> xf, d
for (list<Preset*>::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) {
- pxmap = manage (new Image (get_xpm((*i)->xpm)));
+ pxmap = manage (new Image (::get_icon ((*i)->image_name)));
pbutton = manage (new Button);
pbutton->add (*pxmap);
pbutton->set_name ("CrossfadeEditButton");
@@ -832,7 +831,8 @@ CrossfadeEditor::build_presets ()
fade_out_presets = new Presets;
/* FADE OUT */
- p = new Preset ("hiin.xpm");
+ // p = new Preset ("hiin.xpm");
+ p = new Preset ("crossfade_in_fast-cut");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.0207373, 0.197222));
p->push_back (PresetPoint (0.0645161, 0.525));
@@ -843,7 +843,8 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
- p = new Preset ("loin.xpm");
+ // p = new Preset ("loin.xpm");
+ p = new Preset ("crossfade_in_transition");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.389401, 0.0333333));
p->push_back (PresetPoint (0.629032, 0.0861111));
@@ -853,7 +854,8 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
- p = new Preset ("regin.xpm");
+ // p = new Preset ("regin.xpm");
+ p = new Preset ("crossfade_in_constant");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.0737327, 0.308333));
p->push_back (PresetPoint (0.246544, 0.658333));
@@ -863,7 +865,8 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
- p = new Preset ("regin2.xpm");
+ // p = new Preset ("regin2.xpm");
+ p = new Preset ("crossfade_in_slow-cut");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (0.304147, 0.0694444));
p->push_back (PresetPoint (0.529954, 0.152778));
@@ -873,14 +876,16 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
- p = new Preset ("linin.xpm");
+ // p = new Preset ("linin.xpm");
+ p = new Preset ("crossfade_in_dipped");
p->push_back (PresetPoint (0, 0));
p->push_back (PresetPoint (1, 1));
fade_in_presets->push_back (p);
/* FADE OUT */
- p = new Preset ("hiout.xpm");
+ // p = new Preset ("hiout.xpm");
+ p = new Preset ("crossfade_out_fast-cut");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.305556, 1));
p->push_back (PresetPoint (0.548611, 0.991736));
@@ -890,7 +895,8 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 0));
fade_out_presets->push_back (p);
- p = new Preset ("regout.xpm");
+ // p = new Preset ("regout.xpm");
+ p = new Preset ("crossfade_out_constant");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.228111, 0.988889));
p->push_back (PresetPoint (0.347926, 0.972222));
@@ -900,7 +906,8 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 0));
fade_out_presets->push_back (p);
- p = new Preset ("loout.xpm");
+ // p = new Preset ("loout.xpm");
+ p = new Preset ("crossfade_out_transition");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.023041, 0.697222));
p->push_back (PresetPoint (0.0553, 0.483333));
@@ -910,7 +917,8 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 0));
fade_out_presets->push_back (p);
- p = new Preset ("regout2.xpm");
+ // p = new Preset ("regout2.xpm");
+ p = new Preset ("crossfade_out_slow-fade");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (0.080645, 0.730556));
p->push_back (PresetPoint (0.277778, 0.289256));
@@ -919,7 +927,8 @@ CrossfadeEditor::build_presets ()
p->push_back (PresetPoint (1, 0));
fade_out_presets->push_back (p);
- p = new Preset ("linout.xpm");
+ // p = new Preset ("linout.xpm");
+ p = new Preset ("crossfade_out_dipped");
p->push_back (PresetPoint (0, 1));
p->push_back (PresetPoint (1, 0));
fade_out_presets->push_back (p);
diff --git a/gtk2_ardour/crossfade_edit.h b/gtk2_ardour/crossfade_edit.h
index 3c9a6a13c1..4f2a617d92 100644
--- a/gtk2_ardour/crossfade_edit.h
+++ b/gtk2_ardour/crossfade_edit.h
@@ -43,10 +43,9 @@ class CrossfadeEditor : public ArdourDialog
};
struct Preset : public list<PresetPoint> {
- string xpm;
+ const char* image_name;
- Preset (string x)
- : xpm (x) {}
+ Preset (const char* x) : image_name (x) {}
};
typedef list<Preset*> Presets;
diff --git a/gtk2_ardour/crossfade_view.cc b/gtk2_ardour/crossfade_view.cc
index 281a3251bc..ef43ee9873 100644
--- a/gtk2_ardour/crossfade_view.cc
+++ b/gtk2_ardour/crossfade_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/gtk2_ardour/crossfade_view.h b/gtk2_ardour/crossfade_view.h
index 730813f78c..556d8c80c5 100644
--- a/gtk2_ardour/crossfade_view.h
+++ b/gtk2_ardour/crossfade_view.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_crossfade_view_h__
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 0f77f157f6..4df3b4ea11 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <unistd.h>
@@ -35,6 +34,7 @@
#include <gdkmm/color.h>
#include <gdkmm/bitmap.h>
+#include <gtkmm2ext/grouped_buttons.h>
#include <gtkmm2ext/gtk_ui.h>
#include <gtkmm2ext/tearoff.h>
#include <gtkmm2ext/utils.h>
@@ -54,7 +54,6 @@
#include "ardour_ui.h"
#include "editor.h"
-#include "grouped_buttons.h"
#include "keyboard.h"
#include "marker.h"
#include "playlist_selector.h"
@@ -69,7 +68,6 @@
#include "editing.h"
#include "public_editor.h"
#include "crossfade_edit.h"
-#include "audio_time_axis.h"
#include "canvas_impl.h"
#include "actions.h"
#include "gui_thread.h"
@@ -172,9 +170,8 @@ check_adjustment (Gtk::Adjustment* adj)
}
-Editor::Editor (AudioEngine& eng)
- : engine (eng),
-
+Editor::Editor ()
+ :
/* time display buttons */
minsec_label (_("Mins:Secs")),
@@ -311,6 +308,7 @@ Editor::Editor (AudioEngine& eng)
button_release_can_deselect = true;
canvas_idle_queued = false;
_dragging_playhead = false;
+ _dragging_hscrollbar = false;
location_marker_color = color_map[cLocationMarker];
location_range_color = color_map[cLocationRange];
@@ -356,8 +354,8 @@ Editor::Editor (AudioEngine& eng)
edit_vscrollbar.set_adjustment (vertical_adjustment);
edit_hscrollbar.set_adjustment (horizontal_adjustment);
- edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscrollbar_button_press));
- edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscrollbar_button_release));
+ edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscrollbar_button_press), false);
+ edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscrollbar_button_release), false);
edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscrollbar_allocate));
edit_hscrollbar.set_name ("EditorHScrollbar");
@@ -511,7 +509,7 @@ Editor::Editor (AudioEngine& eng)
edit_group_display.set_name ("EditGroupList");
edit_group_display.get_selection()->set_mode (SELECTION_SINGLE);
- edit_group_display.set_headers_visible (false);
+ edit_group_display.set_headers_visible (true);
edit_group_display.set_reorderable (false);
edit_group_display.set_rules_hint (true);
edit_group_display.set_size_request (75, -1);
@@ -986,6 +984,7 @@ Editor::handle_new_duration ()
if (new_end > last_canvas_frame) {
last_canvas_frame = new_end;
+ horizontal_adjustment.set_upper (last_canvas_frame / frames_per_unit);
reset_scrolling_region ();
}
@@ -1072,7 +1071,7 @@ Editor::connect_to_session (Session *t)
session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
- session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
+ session_connections.push_back (session->tempo_map().StateChanged.connect (bind (mem_fun(*this, &Editor::tempo_map_changed), false)));
edit_groups_changed ();
@@ -1094,8 +1093,7 @@ Editor::connect_to_session (Session *t)
}
session->locations()->add (loc, false);
session->set_auto_loop_location (loc);
- }
- else {
+ } else {
// force name
loc->set_name (_("Loop"));
}
@@ -1108,8 +1106,7 @@ Editor::connect_to_session (Session *t)
}
session->locations()->add (loc, false);
session->set_auto_punch_location (loc);
- }
- else {
+ } else {
// force name
loc->set_name (_("Punch"));
}
@@ -1241,8 +1238,8 @@ 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::LogB)));
- items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Fast)));
+ 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;
@@ -1258,10 +1255,10 @@ 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::Fast)));
- items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogB)));
- items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogA)));
- items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
+ 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;
@@ -3032,7 +3029,7 @@ gint
Editor::edit_controls_button_release (GdkEventButton* ev)
{
if (Keyboard::is_context_menu_event (ev)) {
- ARDOUR_UI::instance()->add_route ();
+ ARDOUR_UI::instance()->add_route (this);
}
return TRUE;
}
@@ -3181,7 +3178,6 @@ Editor::set_show_measures (bool yn)
if ((_show_measures = yn) == true) {
draw_measures ();
}
- DisplayControlChanged (ShowMeasures);
instant_save ();
}
}
@@ -3204,7 +3200,6 @@ Editor::set_follow_playhead (bool yn)
/* catch up */
update_current_screen ();
}
- DisplayControlChanged (FollowPlayhead);
instant_save ();
}
}
@@ -3290,7 +3285,7 @@ Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
label.show ();
dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
- dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
+ dialog.add_button (_("Keep playlist"), RESPONSE_REJECT);
dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
switch (dialog.run ()) {
@@ -3621,26 +3616,6 @@ Editor::set_frames_per_unit (double fpu)
instant_save ();
}
-void
-Editor::canvas_horizontally_scrolled ()
-{
- /* this is the core function that controls horizontal scrolling of the canvas. it is called
- whenever the horizontal_adjustment emits its "value_changed" signal. it executes in an
- idle handler.
- */
-
- leftmost_frame = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
- nframes_t rightmost_frame = leftmost_frame + current_page_frames ();
-
- if (rightmost_frame > last_canvas_frame) {
- last_canvas_frame = rightmost_frame;
- reset_scrolling_region ();
- }
-
- update_fixed_rulers ();
- tempo_map_changed (Change (0));
-}
-
void
Editor::queue_visual_change (nframes_t where)
{
@@ -3687,7 +3662,7 @@ Editor::idle_visual_changer ()
/* the signal handler will do the rest */
} else {
update_fixed_rulers();
- tempo_map_changed (Change (0));
+ tempo_map_changed (Change (0), true);
}
}
@@ -3707,3 +3682,12 @@ Editor::sort_track_selection ()
selection->tracks.sort (cmp);
}
+nframes_t
+Editor::edit_cursor_position(bool sync)
+{
+ if (sync && edit_cursor->current_frame != edit_cursor_clock.current_time()) {
+ edit_cursor_clock.set(edit_cursor->current_frame, true);
+ }
+
+ return edit_cursor->current_frame;
+}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index b0eaa83fd9..2e4b81208b 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_editor_h__
@@ -61,10 +60,6 @@ namespace Gtkmm2ext {
class TearOff;
}
-namespace LinuxAudioSystems {
- class AudioEngine;
-}
-
namespace ARDOUR {
class AudioDiskstream;
class RouteGroup;
@@ -122,7 +117,7 @@ class TimeAxisViewItem ;
class Editor : public PublicEditor
{
public:
- Editor (ARDOUR::AudioEngine&);
+ Editor ();
~Editor ();
void connect_to_session (ARDOUR::Session *);
@@ -147,11 +142,11 @@ class Editor : public PublicEditor
void step_mouse_mode (bool next);
Editing::MouseMode current_mouse_mode () { return mouse_mode; }
- void add_imageframe_time_axis(const string & track_name, void*) ;
- void add_imageframe_marker_time_axis(const string & track_name, TimeAxisView* marked_track, void*) ;
+ void add_imageframe_time_axis(const std::string & track_name, void*) ;
+ void add_imageframe_marker_time_axis(const std::string & track_name, TimeAxisView* marked_track, void*) ;
void connect_to_image_compositor() ;
void scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) ;
- TimeAxisView* get_named_time_axis(const string & name) ;
+ TimeAxisView* get_named_time_axis(const std::string & name) ;
void consider_auditioning (boost::shared_ptr<ARDOUR::Region>);
void hide_a_region (boost::shared_ptr<ARDOUR::Region>);
@@ -340,6 +335,8 @@ class Editor : public PublicEditor
void reset_zoom (double);
void reposition_and_zoom (nframes_t, double);
+ nframes_t edit_cursor_position(bool);
+
protected:
void map_transport_state ();
void map_position_change (nframes_t);
@@ -349,7 +346,6 @@ class Editor : public PublicEditor
private:
ARDOUR::Session *session;
- ARDOUR::AudioEngine& engine;
bool constructed;
PlaylistSelector* _playlist_selector;
@@ -441,6 +437,7 @@ class Editor : public PublicEditor
void catch_vanishing_regionview (RegionView *);
bool set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove=false);
+ void select_all_tracks ();
bool set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool no_remove=false);
bool set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool no_remove=false);
@@ -608,7 +605,7 @@ class Editor : public PublicEditor
nframes_t current_frame;
double length;
- Cursor (Editor&, const string& color, bool (Editor::*)(GdkEvent*,ArdourCanvas::Item*));
+ Cursor (Editor&, bool (Editor::*)(GdkEvent*,ArdourCanvas::Item*));
~Cursor ();
void set_position (nframes_t);
@@ -653,6 +650,7 @@ class Editor : public PublicEditor
void controls_layout_size_request (Gtk::Requisition*);
Gtk::HScrollbar edit_hscrollbar;
+ bool _dragging_hscrollbar;
void reset_hscrollbar_stepping ();
@@ -1174,7 +1172,7 @@ class Editor : public PublicEditor
Gtk::Allocation canvas_allocation;
bool canvas_idle_queued;
void track_canvas_allocate (Gtk::Allocation alloc);
- bool track_canvas_idle ();
+ bool track_canvas_size_allocated ();
void set_edit_cursor (GdkEvent* event);
void set_playhead_cursor (GdkEvent* event);
@@ -1241,6 +1239,7 @@ class Editor : public PublicEditor
void marker_menu_hide ();
void marker_menu_loop_range ();
void marker_menu_select_all_selectables_using_range ();
+ void marker_menu_select_using_range ();
void marker_menu_separate_regions_using_location ();
void marker_menu_play_from ();
void marker_menu_play_range ();
@@ -1275,7 +1274,7 @@ class Editor : public PublicEditor
void remove_metric_marks ();
void draw_metric_marks (const ARDOUR::Metrics& metrics);
- void tempo_map_changed (ARDOUR::Change);
+ void tempo_map_changed (ARDOUR::Change, bool immediate_redraw);
void redisplay_tempo ();
void snap_to (nframes_t& first, int32_t direction = 0, bool for_mark = false);
diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
index 138fa8510e..e04941b32b 100644
--- a/gtk2_ardour/editor_actions.cc
+++ b/gtk2_ardour/editor_actions.cc
@@ -126,7 +126,7 @@ Editor::register_actions ()
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "jump-backward-to-mark", _("Jump Backward to Mark"), mem_fun(*this, &Editor::jump_backward_to_mark));
ActionManager::session_sensitive_actions.push_back (act);
- act = ActionManager::register_action (editor_actions, "add-location-from-playhead", _("Add Location from Playhead"), mem_fun(*this, &Editor::add_location_from_playhead_cursor));
+ act = ActionManager::register_action (editor_actions, "add-location-from-playhead", _("Add Mark from Playhead"), mem_fun(*this, &Editor::add_location_from_playhead_cursor));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, "nudge-forward", _("Nudge Forward"), bind (mem_fun(*this, &Editor::nudge_forward), false));
@@ -430,7 +430,7 @@ Editor::toggle_waveform_visibility ()
void
Editor::toggle_waveforms_while_recording ()
{
- Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleWaveformVisibility"));
+ Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleWaveformsWhileRecording"));
if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
set_show_waveforms_recording (tact->get_active());
diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc
index a7d7d0de96..2d7a7e2435 100644
--- a/gtk2_ardour/editor_audio_import.cc
+++ b/gtk2_ardour/editor_audio_import.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <pbd/pthread_utils.h>
@@ -40,6 +39,7 @@
#include "sfdb_ui.h"
#include "editing.h"
#include "audio_time_axis.h"
+#include "utils.h"
#include "i18n.h"
@@ -244,6 +244,8 @@ Editor::import_sndfile (vector<ustring> paths, ImportMode mode, AudioTrack* trac
while (!(import_status.done || import_status.cancel)) {
gtk_main_iteration ();
}
+
+ interthread_progress_window->hide ();
import_status.done = true;
interthread_progress_connection.disconnect ();
@@ -315,7 +317,8 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
choices.push_back (_("Embed all without questions"));
Gtkmm2ext::Choice rate_choice (
- string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
+ string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"),
+ short_path (path, 40)),
choices, false);
int resx = rate_choice.run ();
@@ -367,11 +370,21 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
for (int n = 0; n < finfo.channels; ++n)
{
try {
- source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable
- (DataType::AUDIO, *session, path, n,
- (mode == ImportAsTapeTrack ?
- AudioFileSource::Destructive :
- AudioFileSource::Flag (0))));
+
+ /* check if we have this thing embedded already */
+
+ boost::shared_ptr<Source> s;
+
+ if ((s = session->source_by_path_and_channel (path, n)) == 0) {
+ cerr << "source doesn't exist yet\n";
+ source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable
+ (DataType::AUDIO, *session, path, n,
+ (mode == ImportAsTapeTrack ?
+ AudioFileSource::Destructive :
+ AudioFileSource::Flag (0))));
+ } else {
+ source = boost::dynamic_pointer_cast<AudioFileSource> (s);
+ }
sources.push_back(source);
}
diff --git a/gtk2_ardour/editor_audiotrack.cc b/gtk2_ardour/editor_audiotrack.cc
index f524dcdd40..31f382dbff 100644
--- a/gtk2_ardour/editor_audiotrack.cc
+++ b/gtk2_ardour/editor_audiotrack.cc
@@ -45,7 +45,6 @@ Editor::set_show_waveforms (bool yn)
atv->set_show_waveforms (yn);
}
}
- DisplayControlChanged (Editing::ShowWaveforms);
}
}
@@ -61,6 +60,5 @@ Editor::set_show_waveforms_recording (bool yn)
atv->set_show_waveforms_recording (yn);
}
}
- DisplayControlChanged (Editing::ShowWaveformsRecording);
}
}
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index 417d4ab0c4..617e3f4c8e 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <libgnomecanvasmm/init.h>
@@ -264,8 +263,20 @@ Editor::initialize_canvas ()
double time_width = FLT_MAX/frames_per_unit;
time_canvas.set_scroll_region(0.0, 0.0, time_width, time_height);
- edit_cursor = new Cursor (*this, "blue", &Editor::canvas_edit_cursor_event);
- playhead_cursor = new Cursor (*this, "red", &Editor::canvas_playhead_cursor_event);
+ if (!color_map[cEditCursor]) {
+ warning << _("edit cursor color not defined, check your ardour.colors file!") << endmsg;
+ color_map[cEditCursor] = RGBA_TO_UINT (30,30,30,255);
+ }
+
+ if (!color_map[cPlayHead]) {
+ warning << _("playhead color not defined, check your ardour.colors file!") << endmsg;
+ color_map[cPlayHead] = RGBA_TO_UINT (0,0,0,255);
+ }
+
+ edit_cursor = new Cursor (*this, &Editor::canvas_edit_cursor_event);
+ edit_cursor->canvas_item.property_fill_color_rgba() = color_map[cEditCursor];
+ playhead_cursor = new Cursor (*this, &Editor::canvas_playhead_cursor_event);
+ playhead_cursor->canvas_item.property_fill_color_rgba() = color_map[cPlayHead];
initial_ruler_update_required = true;
track_canvas.signal_size_allocate().connect (mem_fun(*this, &Editor::track_canvas_allocate));
@@ -280,7 +291,7 @@ Editor::track_canvas_allocate (Gtk::Allocation alloc)
if (!initial_ruler_update_required) {
if (!canvas_idle_queued) {
/* call this first so that we do stuff before any pending redraw */
- Glib::signal_idle().connect (mem_fun (*this, &Editor::track_canvas_idle), false);
+ Glib::signal_idle().connect (mem_fun (*this, &Editor::track_canvas_size_allocated), false);
canvas_idle_queued = true;
}
return;
@@ -288,11 +299,11 @@ Editor::track_canvas_allocate (Gtk::Allocation alloc)
initial_ruler_update_required = false;
- track_canvas_idle ();
+ track_canvas_size_allocated ();
}
bool
-Editor::track_canvas_idle ()
+Editor::track_canvas_size_allocated ()
{
if (canvas_idle_queued) {
canvas_idle_queued = false;
@@ -321,7 +332,6 @@ Editor::track_canvas_idle ()
full_canvas_height = height;
}
-
zoom_range_clock.set ((nframes_t) floor ((canvas_width * frames_per_unit)));
edit_cursor->set_position (edit_cursor->current_frame);
playhead_cursor->set_position (playhead_cursor->current_frame);
@@ -363,7 +373,7 @@ Editor::track_canvas_idle ()
}
update_fixed_rulers();
- tempo_map_changed (Change (0));
+ tempo_map_changed (Change (0), true);
Resized (); /* EMIT_SIGNAL */
@@ -698,3 +708,25 @@ Editor::left_track_canvas (GdkEventCrossing *ev)
}
+void
+Editor::canvas_horizontally_scrolled ()
+{
+ /* this is the core function that controls horizontal scrolling of the canvas. it is called
+ whenever the horizontal_adjustment emits its "value_changed" signal. it typically executes in an
+ idle handler, which is important because tempo_map_changed() should issue redraws immediately
+ and not defer them to an idle handler.
+ */
+
+ leftmost_frame = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
+ nframes_t rightmost_frame = leftmost_frame + current_page_frames ();
+
+ if (rightmost_frame > last_canvas_frame) {
+ last_canvas_frame = rightmost_frame;
+ reset_scrolling_region ();
+ }
+
+ update_fixed_rulers ();
+
+ tempo_map_changed (Change (0), !_dragging_hscrollbar);
+}
+
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index 4e0d6d5fe3..4a23e8b316 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
@@ -25,6 +24,7 @@
#include <ardour/audioplaylist.h>
#include "editor.h"
+#include "keyboard.h"
#include "public_editor.h"
#include "audio_region_view.h"
#include "audio_streamview.h"
@@ -71,7 +71,7 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
event.button.y = wy;
nframes_t where = event_frame (&event, 0, 0);
- temporal_zoom_to_frame (true, where);
+ temporal_zoom_to_frame (false, where);
return true;
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
if (!current_stepping_trackview) {
@@ -102,7 +102,7 @@ Editor::track_canvas_scroll (GdkEventScroll* ev)
event.button.y = wy;
nframes_t where = event_frame (&event, 0, 0);
- temporal_zoom_to_frame (false, where);
+ temporal_zoom_to_frame (true, where);
return true;
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
if (!current_stepping_trackview) {
diff --git a/gtk2_ardour/editor_cursors.cc b/gtk2_ardour/editor_cursors.cc
index 7cd13cf686..239d27d4f9 100644
--- a/gtk2_ardour/editor_cursors.cc
+++ b/gtk2_ardour/editor_cursors.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
@@ -31,7 +30,7 @@ using namespace ARDOUR;
using namespace PBD;
using namespace Gtk;
-Editor::Cursor::Cursor (Editor& ed, const string& color, bool (Editor::*callbck)(GdkEvent*,ArdourCanvas::Item*))
+Editor::Cursor::Cursor (Editor& ed, bool (Editor::*callbck)(GdkEvent*,ArdourCanvas::Item*))
: editor (ed),
canvas_item (*editor.cursor_group),
length(1.0)
@@ -43,7 +42,6 @@ Editor::Cursor::Cursor (Editor& ed, const string& color, bool (Editor::*callbck)
points.push_back(Gnome::Art::Point(1.0, 0.0));
canvas_item.property_points() = points;
- canvas_item.property_fill_color() = color; //.c_str());
canvas_item.property_width_pixels() = 1;
canvas_item.property_first_arrowhead() = TRUE;
canvas_item.property_last_arrowhead() = TRUE;
diff --git a/gtk2_ardour/editor_edit_groups.cc b/gtk2_ardour/editor_edit_groups.cc
index 2ee1773646..20179f84c6 100644
--- a/gtk2_ardour/editor_edit_groups.cc
+++ b/gtk2_ardour/editor_edit_groups.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc
index ce7de29aa1..10438bfb02 100644
--- a/gtk2_ardour/editor_export_audio.cc
+++ b/gtk2_ardour/editor_export_audio.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <unistd.h>
diff --git a/gtk2_ardour/editor_hscroller.cc b/gtk2_ardour/editor_hscroller.cc
index c95d923092..f5f94c4163 100644
--- a/gtk2_ardour/editor_hscroller.cc
+++ b/gtk2_ardour/editor_hscroller.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include "editor.h"
@@ -34,17 +33,20 @@ Editor::hscrollbar_allocate (Gtk::Allocation &alloc)
bool
Editor::hscrollbar_button_press (GdkEventButton *ev)
{
- return true;
+ _dragging_hscrollbar = true;
+ return false;
}
bool
Editor::hscrollbar_button_release (GdkEventButton *ev)
{
+ _dragging_hscrollbar = false;
+
if (session) {
}
- return true;
+ return false;
}
void
diff --git a/gtk2_ardour/editor_imageframe.cc b/gtk2_ardour/editor_imageframe.cc
index 84419dbe7f..eb78fb5c7f 100644
--- a/gtk2_ardour/editor_imageframe.cc
+++ b/gtk2_ardour/editor_imageframe.cc
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include "imageframe_view.h"
diff --git a/gtk2_ardour/editor_keyboard.cc b/gtk2_ardour/editor_keyboard.cc
index bfe61eae5c..e9082445c4 100644
--- a/gtk2_ardour/editor_keyboard.cc
+++ b/gtk2_ardour/editor_keyboard.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/audioregion.h>
diff --git a/gtk2_ardour/editor_keys.cc b/gtk2_ardour/editor_keys.cc
index 1bcaafd279..b3081e8c8a 100644
--- a/gtk2_ardour/editor_keys.cc
+++ b/gtk2_ardour/editor_keys.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
@@ -70,7 +69,7 @@ Editor::keyboard_duplicate_region ()
return;
}
- float prefix;
+ float prefix = 0;
bool was_floating;
if (get_prefix (prefix, was_floating) == 0) {
@@ -83,7 +82,7 @@ Editor::keyboard_duplicate_region ()
void
Editor::keyboard_duplicate_selection ()
{
- float prefix;
+ float prefix = 0;
bool was_floating;
if (get_prefix (prefix, was_floating) == 0) {
@@ -96,7 +95,7 @@ Editor::keyboard_duplicate_selection ()
void
Editor::keyboard_paste ()
{
- float prefix;
+ float prefix = 0;
bool was_floating;
if (get_prefix (prefix, was_floating) == 0) {
@@ -109,7 +108,7 @@ Editor::keyboard_paste ()
void
Editor::keyboard_insert_region_list_selection ()
{
- float prefix;
+ float prefix = 0;
bool was_floating;
if (get_prefix (prefix, was_floating) == 0) {
@@ -122,6 +121,7 @@ Editor::keyboard_insert_region_list_selection ()
int
Editor::get_prefix (float& val, bool& was_floating)
{
- return Keyboard::the_keyboard().get_prefix (val, was_floating);
+ was_floating = false;
+ return 1;
}
diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc
index 238a45c4d1..06e99d0fbb 100644
--- a/gtk2_ardour/editor_markers.cc
+++ b/gtk2_ardour/editor_markers.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <sigc++/retype.h>
@@ -511,6 +510,7 @@ Editor::build_range_marker_menu (bool loop_or_punch)
items.push_back (MenuElem (_("Separate Regions in Range"), mem_fun(*this, &Editor::marker_menu_separate_regions_using_location)));
items.push_back (MenuElem (_("Select All in Range"), mem_fun(*this, &Editor::marker_menu_select_all_selectables_using_range)));
+ items.push_back (MenuElem (_("Select Range"), mem_fun(*this, &Editor::marker_menu_select_using_range)));
}
@@ -561,6 +561,24 @@ Editor::marker_menu_hide ()
}
void
+Editor::marker_menu_select_using_range ()
+{
+ Marker* marker;
+
+ if ((marker = reinterpret_cast<Marker *> (marker_menu_item->get_data ("marker"))) == 0) {
+ fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg;
+ /*NOTREACHED*/
+ }
+
+ Location* l;
+ bool is_start;
+
+ if (((l = find_location_from_marker (marker, is_start)) != 0) && (l->end() > l->start())) {
+ set_selection_from_range (*l);
+ }
+}
+
+void
Editor::marker_menu_select_all_selectables_using_range ()
{
Marker* marker;
diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc
index 0e8901b881..cf0f831fa8 100644
--- a/gtk2_ardour/editor_mixer.cc
+++ b/gtk2_ardour/editor_mixer.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <gtkmm2ext/utils.h>
@@ -158,10 +157,13 @@ Editor::set_selected_mixer_strip (TimeAxisView& view)
}
}
+double current = 0.0;
+bool currentInitialized = 0;
+
void
Editor::update_current_screen ()
{
- if (session && engine.running()) {
+ if (session && session->engine().running()) {
nframes_t frame;
@@ -178,35 +180,52 @@ Editor::update_current_screen ()
playhead_cursor->canvas_item.show();
if (frame != last_update_frame) {
- const jack_nframes_t page_width = current_page_frames();
-
- // Percentage width of the visible range to use as a scroll interval
- // Idea: snap this to the nearest bar/beat/tick/etc, would make scrolling much
- // less jarring when zoomed in.. and it would be fun to watch :)
- static const double scroll_pct = 3.0/4.0;
-
- const jack_nframes_t rightmost_frame = leftmost_frame + page_width;
- const jack_nframes_t scroll_interval = (jack_nframes_t)(page_width * scroll_pct);
- const jack_nframes_t padding = (jack_nframes_t)floor((page_width-scroll_interval) / 2.0);
- if (frame < leftmost_frame + padding || frame > rightmost_frame - padding) {
+#undef CONTINUOUS_SCROLL
+#ifndef CONTINUOUS_SCROLL
+ if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) {
+
if (session->transport_speed() < 0) {
- if (frame > scroll_interval) {
- center_screen (frame - scroll_interval/2);
+ if (frame > (current_page_frames()/2)) {
+ center_screen (frame-(current_page_frames()/2));
} else {
- center_screen (scroll_interval);
+ center_screen (current_page_frames()/2);
}
} else {
- center_screen(frame + scroll_interval/2);
+ center_screen (frame+(current_page_frames()/2));
}
}
playhead_cursor->set_position (frame);
+
+#else // CONTINUOUS_SCROLL
+
+ /* don't do continuous scroll till the new position is in the rightmost quarter of the
+ editor canvas
+ */
+
+ if (session->transport_speed()) {
+ double target = ((double)frame - (double)current_page_frames()/2.0) / frames_per_unit;
+ if (target <= 0.0) target = 0.0;
+ if ( fabs(target - current) < current_page_frames()/frames_per_unit ) {
+ target = (target * 0.15) + (current * 0.85);
+ } else {
+ /* relax */
+ }
+ //printf("frame: %d, cpf: %d, fpu: %6.6f, current: %6.6f, target : %6.6f\n", frame, current_page_frames(), frames_per_unit, current, target );
+ current = target;
+ horizontal_adjustment.set_value ( current );
+ }
+
+ playhead_cursor->set_position (frame);
+
+#endif // CONTINUOUS_SCROLL
+
}
} else {
-
+
if (frame != last_update_frame) {
if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) {
playhead_cursor->canvas_item.hide();
@@ -222,7 +241,7 @@ Editor::update_current_screen ()
if (current_mixer_strip) {
current_mixer_strip->fast_update ();
}
-
+
}
}
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index a7095d9e09..e007a225d8 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cassert>
@@ -35,6 +34,7 @@
#include "time_axis_view.h"
#include "audio_time_axis.h"
#include "audio_region_view.h"
+#include "midi_region_view.h"
#include "marker.h"
#include "streamview.h"
#include "region_gain_line.h"
@@ -302,7 +302,9 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
if (((mouse_mode != MouseObject) &&
(mouse_mode != MouseAudition || item_type != RegionItem) &&
- (mouse_mode != MouseTimeFX || item_type != RegionItem)) ||
+ (mouse_mode != MouseTimeFX || item_type != RegionItem) &&
+ (mouse_mode != MouseRange)) ||
+
(event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE || event->button.button > 3)) {
return;
@@ -312,9 +314,11 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
if ((event->button.state & Keyboard::RelevantModifierKeyMask) && event->button.button != 1) {
- /* no selection action on modified button-2 or button-3 events */
-
- return;
+ /* almost no selection action on modified button-2 or button-3 events */
+
+ if (item_type != RegionItem && event->button.button != 2) {
+ return;
+ }
}
}
@@ -325,29 +329,48 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
switch (item_type) {
case RegionItem:
- commit = set_selected_regionview_from_click (press, op, true);
+ 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:
- commit = set_selected_regionview_from_click (press, op, true);
+ 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:
case FadeOutItem:
- commit = set_selected_regionview_from_click (press, op, true);
+ 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 GainAutomationControlPointItem:
case PanAutomationControlPointItem:
case RedirectAutomationControlPointItem:
- commit = set_selected_control_point_from_click (op, false);
+ if (mouse_mode != MouseRange) {
+ commit = set_selected_control_point_from_click (op, false);
+ }
break;
case StreamItem:
- // commit = set_selected_track_from_click (press, op, true);
+ /* for context click or range selection, select track */
+ if (event->button.button == 3) {
+ commit = set_selected_track_from_click (press, op, true);
+ } else if (event->type == GDK_BUTTON_PRESS && mouse_mode == MouseRange) {
+ commit = set_selected_track_from_click (press, op, false);
+ }
break;
case AutomationTrackItem:
@@ -358,26 +381,6 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
break;
}
-#define SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE
-#ifdef SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE
- /* in range mode, button 1/2/3 press potentially selects a track */
-
- if (mouse_mode == MouseRange &&
- event->type == GDK_BUTTON_PRESS &&
- event->button.button <= 3) {
-
- switch (item_type) {
- case StreamItem:
- case RegionItem:
- case AutomationTrackItem:
- commit = set_selected_track_from_click (true, op, true);
- break;
-
- default:
- break;
- }
- }
-#endif
if (commit) {
commit_reversible_command ();
}
@@ -1174,23 +1177,25 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
case GainAutomationControlPointItem:
case PanAutomationControlPointItem:
case RedirectAutomationControlPointItem:
- cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
- cp->set_visible (true);
-
- double at_x, at_y;
- at_x = cp->get_x();
- at_y = cp->get_y ();
- cp->item->i2w (at_x, at_y);
- at_x += 20.0;
- at_y += 20.0;
-
- fraction = 1.0 - (cp->get_y() / cp->line.height());
-
- set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y);
- show_verbose_canvas_cursor ();
-
- if (is_drawable()) {
- track_canvas.get_window()->set_cursor (*fader_cursor);
+ if (mouse_mode == MouseGain || mouse_mode == MouseObject) {
+ cp = static_cast<ControlPoint*>(item->get_data ("control_point"));
+ cp->set_visible (true);
+
+ double at_x, at_y;
+ at_x = cp->get_x();
+ at_y = cp->get_y ();
+ cp->item->i2w (at_x, at_y);
+ at_x += 20.0;
+ at_y += 20.0;
+
+ fraction = 1.0 - (cp->get_y() / cp->line.height());
+
+ set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y);
+ show_verbose_canvas_cursor ();
+
+ if (is_drawable()) {
+ track_canvas.get_window()->set_cursor (*fader_cursor);
+ }
}
break;
@@ -1208,13 +1213,15 @@ Editor::enter_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_
case GainAutomationLineItem:
case RedirectAutomationLineItem:
case PanAutomationLineItem:
- {
- ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
- if (line)
- line->property_fill_color_rgba() = color_map[cEnteredAutomationLine];
- }
- if (is_drawable()) {
- track_canvas.get_window()->set_cursor (*fader_cursor);
+ if (mouse_mode == MouseGain || mouse_mode == MouseObject) {
+ {
+ ArdourCanvas::Line *line = dynamic_cast<ArdourCanvas::Line *> (item);
+ if (line)
+ line->property_fill_color_rgba() = color_map[cEnteredAutomationLine];
+ }
+ if (is_drawable()) {
+ track_canvas.get_window()->set_cursor (*fader_cursor);
+ }
}
break;
@@ -1515,7 +1522,10 @@ Editor::motion_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item
*/
if (!drag_info.move_threshold_passed) {
- drag_info.move_threshold_passed = (abs ((int) (drag_info.current_pointer_x - drag_info.grab_x)) > 4);
+ bool x_threshold_passed = (abs ((int) (drag_info.current_pointer_x - drag_info.grab_x)) > 4);
+ bool y_threshold_passed = (abs ((int) (drag_info.current_pointer_y - drag_info.grab_y)) > 4);
+
+ drag_info.move_threshold_passed = (x_threshold_passed || y_threshold_passed);
// and change the initial grab loc/frame if this drag info wants us to
@@ -2825,60 +2835,34 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
drag_info.want_move_threshold = false; // don't copy again
- /* this is committed in the grab finished callback. */
-
- begin_reversible_command (_("Drag region copy"));
-
/* duplicate the region(s) */
vector<RegionView*> new_regionviews;
- set<boost::shared_ptr<Playlist> > affected_playlists;
- pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
-
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
RegionView* rv;
-
+ RegionView* nrv;
+ AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
+ MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(rv);
+
rv = (*i);
-
- boost::shared_ptr<Playlist> to_playlist = rv->region()->playlist();
- RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&rv->get_time_axis_view());
- insert_result = affected_playlists.insert (to_playlist);
- if (insert_result.second) {
- session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
- }
-
- latest_regionview = 0;
-
- sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
-
- /* create a new region with the same name. */
-
- boost::shared_ptr<Region> newregion;
+ if (arv)
+ nrv = new AudioRegionView (*arv);
+ else if (mrv)
+ nrv = new MidiRegionView (*mrv);
+ else
+ continue;
- newregion = RegionFactory::create (rv->region());
- assert(newregion != 0);
+ nrv->get_canvas_group()->show ();
- /* if the original region was locked, we don't care */
-
- newregion->set_locked (false);
-
- to_playlist->add_region (newregion, (nframes_t) (rv->region()->position() * rtv->get_diskstream()->speed()));
-
- c.disconnect ();
-
- if (latest_regionview) {
- new_regionviews.push_back (latest_regionview);
- }
+ new_regionviews.push_back (nrv);
}
-
-
if (new_regionviews.empty()) {
return;
}
-
+
/* reset selection to new regionviews */
selection->set (new_regionviews);
@@ -2886,6 +2870,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
/* reset drag_info data to reflect the fact that we are dragging the copies */
drag_info.data = new_regionviews.front();
+
swap_grab (new_regionviews.front()->get_canvas_group (), 0, event->motion.time);
}
@@ -3164,149 +3149,147 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
MOTION
************************************************************/
- pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
- const list<RegionView*>& layered_regions = selection->regions.by_layer();
+ bool do_move;
- for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
+ if (drag_info.first_move) {
+ if (drag_info.move_threshold_passed) {
+ do_move = true;
+ } else {
+ do_move = false;
+ }
+ } else {
+ do_move = true;
+ }
+
+ if (do_move) {
+
+ pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
+ const list<RegionView*>& layered_regions = selection->regions.by_layer();
+
+ for (list<RegionView*>::const_iterator i = layered_regions.begin(); i != layered_regions.end(); ++i) {
- RegionView* rv = (*i);
- double ix1, ix2, iy1, iy2;
- int32_t temp_pointer_y_span = pointer_y_span;
+ RegionView* rv = (*i);
+ double ix1, ix2, iy1, iy2;
+ int32_t temp_pointer_y_span = pointer_y_span;
- /* get item BBox, which will be relative to parent. so we have
- to query on a child, then convert to world coordinates using
- the parent.
- */
+ /* get item BBox, which will be relative to parent. so we have
+ to query on a child, then convert to world coordinates using
+ the parent.
+ */
- rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
- rv->get_canvas_group()->i2w (ix1, iy1);
- TimeAxisView* tvp2 = trackview_by_y_position (iy1);
- RouteTimeAxisView* canvas_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
- RouteTimeAxisView* temp_rtv;
-
- if ((pointer_y_span != 0) && !clamp_y_axis) {
- y_delta = 0;
- int32_t x = 0;
- for (j = height_list.begin(); j!= height_list.end(); j++) {
- if (x == canvas_rtv->order) {
- /* we found the track the region is on */
- if (x != original_pointer_order) {
- /*this isn't from the same track we're dragging from */
- temp_pointer_y_span = canvas_pointer_y_span;
- }
- while (temp_pointer_y_span > 0) {
- /* we're moving up canvas-wise,
- so we need to find the next track height
- */
- if (j != height_list.begin()) {
- j--;
- }
- if (x != original_pointer_order) {
- /* we're not from the dragged track, so ignore hidden tracks. */
- if ((*j) == 0) {
- temp_pointer_y_span++;
- }
- }
- y_delta -= (*j);
- temp_pointer_y_span--;
- }
- while (temp_pointer_y_span < 0) {
- y_delta += (*j);
- if (x != original_pointer_order) {
- if ((*j) == 0) {
- temp_pointer_y_span--;
+ rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
+ rv->get_canvas_group()->i2w (ix1, iy1);
+ TimeAxisView* tvp2 = trackview_by_y_position (iy1);
+ RouteTimeAxisView* canvas_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
+ RouteTimeAxisView* temp_rtv;
+
+ if ((pointer_y_span != 0) && !clamp_y_axis) {
+ y_delta = 0;
+ int32_t x = 0;
+ for (j = height_list.begin(); j!= height_list.end(); j++) {
+ if (x == canvas_rtv->order) {
+ /* we found the track the region is on */
+ if (x != original_pointer_order) {
+ /*this isn't from the same track we're dragging from */
+ temp_pointer_y_span = canvas_pointer_y_span;
+ }
+ while (temp_pointer_y_span > 0) {
+ /* we're moving up canvas-wise,
+ so we need to find the next track height
+ */
+ if (j != height_list.begin()) {
+ j--;
}
- }
+ if (x != original_pointer_order) {
+ /* we're not from the dragged track, so ignore hidden tracks. */
+ if ((*j) == 0) {
+ temp_pointer_y_span++;
+ }
+ }
+ y_delta -= (*j);
+ temp_pointer_y_span--;
+ }
+ while (temp_pointer_y_span < 0) {
+ y_delta += (*j);
+ if (x != original_pointer_order) {
+ if ((*j) == 0) {
+ temp_pointer_y_span--;
+ }
+ }
- if (j != height_list.end()) {
- j++;
+ if (j != height_list.end()) {
+ j++;
+ }
+ temp_pointer_y_span++;
}
- temp_pointer_y_span++;
- }
- /* find out where we'll be when we move and set height accordingly */
+ /* find out where we'll be when we move and set height accordingly */
- tvp2 = trackview_by_y_position (iy1 + y_delta);
- temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
- rv->set_height (temp_rtv->height);
+ tvp2 = trackview_by_y_position (iy1 + y_delta);
+ temp_rtv = dynamic_cast<RouteTimeAxisView*>(tvp2);
+ rv->set_height (temp_rtv->height);
- /* if you un-comment the following, the region colours will follow the track colours whilst dragging,
- personally, i think this can confuse things, but never mind.
- */
+ /* if you un-comment the following, the region colours will follow the track colours whilst dragging,
+ personally, i think this can confuse things, but never mind.
+ */
- //const GdkColor& col (temp_rtv->view->get_region_color());
- //rv->set_color (const_cast<GdkColor&>(col));
- break;
+ //const GdkColor& col (temp_rtv->view->get_region_color());
+ //rv->set_color (const_cast<GdkColor&>(col));
+ break;
+ }
+ x++;
}
- x++;
}
- }
- /* prevent the regionview from being moved to before
- the zero position on the canvas.
- */
- /* clamp */
+ /* prevent the regionview from being moved to before
+ the zero position on the canvas.
+ */
+ /* clamp */
- if (x_delta < 0) {
- if (-x_delta > ix1) {
- x_delta = -ix1;
+ if (x_delta < 0) {
+ if (-x_delta > ix1) {
+ x_delta = -ix1;
+ }
+ } else if ((x_delta > 0) &&(rv->region()->last_frame() > max_frames - x_delta)) {
+ x_delta = max_frames - rv->region()->last_frame();
}
- } else if ((x_delta > 0) &&(rv->region()->last_frame() > max_frames - x_delta)) {
- x_delta = max_frames - rv->region()->last_frame();
- }
-
- if (drag_info.first_move) {
-
- /* hide any dependent views */
- rv->get_time_axis_view().hide_dependent_views (*rv);
-
- /* this is subtle. raising the regionview itself won't help,
- because raise_to_top() just puts the item on the top of
- its parent's stack. so, we need to put the trackview canvas_display group
- on the top, since its parent is the whole canvas.
- */
+ if (drag_info.first_move) {
- rv->get_canvas_group()->raise_to_top();
- rv->get_time_axis_view().canvas_display->raise_to_top();
- cursor_group->raise_to_top();
+ /* hide any dependent views */
+
+ rv->get_time_axis_view().hide_dependent_views (*rv);
+
+ /* this is subtle. raising the regionview itself won't help,
+ because raise_to_top() just puts the item on the top of
+ its parent's stack. so, we need to put the trackview canvas_display group
+ on the top, since its parent is the whole canvas.
+ */
+
+ rv->get_canvas_group()->raise_to_top();
+ rv->get_time_axis_view().canvas_display->raise_to_top();
+ cursor_group->raise_to_top();
- /* freeze the playlists from notifying till
- the motion is done.
- */
+ rv->fake_set_opaque (true);
+ }
+
+ if (drag_info.brushing) {
+ mouse_brush_insert_region (rv, pending_region_position);
+ } else {
+ rv->move (x_delta, y_delta);
+ }
- RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&rv->get_time_axis_view());
- if (rtv && rtv->is_audio_track()) {
- boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>(rtv->get_diskstream()->playlist());
- if (pl) {
- /* only freeze and capture state once */
+ } /* foreach region */
- insert_result = motion_frozen_playlists.insert (pl);
- if (insert_result.second) {
- pl->freeze();
- session->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
- }
- }
- }
- rv->region()->set_opaque(false);
- }
+ } /* if do_move */
- if (drag_info.brushing) {
- mouse_brush_insert_region (rv, pending_region_position);
- } else {
- rv->move (x_delta, y_delta);
- }
- }
-
- if (drag_info.first_move) {
+ if (drag_info.first_move && drag_info.move_threshold_passed) {
cursor_group->raise_to_top();
+ drag_info.first_move = false;
}
-
- drag_info.first_move = false;
-
+
if (x_delta != 0 && !drag_info.brushing) {
show_verbose_time_cursor (drag_info.last_frame_position, 10);
}
-
}
void
@@ -3317,7 +3300,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
pair<set<boost::shared_ptr<Playlist> >::iterator,bool> insert_result;
bool nocommit = true;
double speed;
- RouteTimeAxisView* atv;
+ RouteTimeAxisView* rtv;
bool regionview_y_movement;
bool regionview_x_movement;
@@ -3346,9 +3329,9 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
/* adjust for track speed */
speed = 1.0;
- atv = dynamic_cast<RouteTimeAxisView*> (drag_info.last_trackview);
- if (atv && atv->get_diskstream()) {
- speed = atv->get_diskstream()->speed();
+ rtv = dynamic_cast<RouteTimeAxisView*> (drag_info.last_trackview);
+ if (rtv && rtv->get_diskstream()) {
+ speed = rtv->get_diskstream()->speed();
}
regionview_x_movement = (drag_info.last_frame_position != (nframes_t) (rv->region()->position()/speed));
@@ -3357,106 +3340,94 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
//printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed);
//printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str());
+ char* op_string;
+
+ if (drag_info.copy) {
+ if (drag_info.x_constrained) {
+ op_string = _("fixed time region copy");
+ } else {
+ op_string = _("region copy");
+ }
+ } else {
+ if (drag_info.x_constrained) {
+ op_string = _("fixed time region drag");
+ } else {
+ op_string = _("region drag");
+ }
+ }
+
+ begin_reversible_command (op_string);
+
if (regionview_y_movement) {
- /* motion between tracks */
+ /* moved to a different audio track. */
list<RegionView*> new_selection;
-
- /* moved to a different audio track. */
+ new_selection = selection->regions.by_layer();
+ selection->clear_regions ();
- for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ) {
-
- RegionView* rv2 = (*i);
-
- /* the region that used to be in the old playlist is not
- moved to the new one - we make a copy of it. as a result,
- any existing editor for the region should no longer be
- visible.
- */
+ for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end(); ++i) {
- if (!drag_info.copy) {
- rv2->hide_region_editor();
- }
- new_selection.push_back (rv2);
- i++;
- }
-
- /* first, freeze the target tracks */
-
- for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
+ RegionView* rv = (*i);
- boost::shared_ptr<Playlist> from_playlist;
- boost::shared_ptr<Playlist> to_playlist;
-
double ix1, ix2, iy1, iy2;
-
- (*i)->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
- (*i)->get_canvas_group()->i2w (ix1, iy1);
+
+ rv->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
+ rv->get_canvas_group()->i2w (ix1, iy1);
TimeAxisView* tvp2 = trackview_by_y_position (iy1);
- RouteTimeAxisView* atv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
+ RouteTimeAxisView* rtv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
- (*i)->region()->set_opaque (true);
+ boost::shared_ptr<Playlist> from_playlist = rv->region()->playlist();
+ boost::shared_ptr<Playlist> to_playlist = rtv2->playlist();
- from_playlist = (*i)->region()->playlist();
- to_playlist = atv2->playlist();
-
- /* the from_playlist was frozen in the "first_move" case
- of the motion handler. the insert can fail,
- but that doesn't matter. it just means
- we already have the playlist in the list.
- */
-
- motion_frozen_playlists.insert (from_playlist);
-
- /* only freeze the to_playlist once */
-
- insert_result = motion_frozen_playlists.insert(to_playlist);
- if (insert_result.second) {
- to_playlist->freeze();
- session->add_command(new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
- }
-
- }
-
- /* now do it again with the actual operations */
-
- for (list<RegionView*>::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) {
+ where = (nframes_t) (unit_to_frame (ix1) * speed);
+ boost::shared_ptr<Region> new_region (RegionFactory::create (rv->region()));
- boost::shared_ptr<Playlist> from_playlist;
- boost::shared_ptr<Playlist> to_playlist;
+ if (!drag_info.copy) {
- double ix1, ix2, iy1, iy2;
-
- (*i)->get_canvas_frame()->get_bounds (ix1, iy1, ix2, iy2);
- (*i)->get_canvas_group()->i2w (ix1, iy1);
- TimeAxisView* tvp2 = trackview_by_y_position (iy1);
- RouteTimeAxisView* atv2 = dynamic_cast<RouteTimeAxisView*>(tvp2);
+ /* the region that used to be in the old playlist is not
+ moved to the new one - we make a copy of it. as a result,
+ any existing editor for the region should no longer be
+ visible.
+ */
- from_playlist = (*i)->region()->playlist();
- to_playlist = atv2->playlist();
+ rv->hide_region_editor();
+ rv->fake_set_opaque (false);
- latest_regionview = 0;
-
- where = (nframes_t) (unit_to_frame (ix1) * speed);
- boost::shared_ptr<Region> new_region (RegionFactory::create ((*i)->region()));
+ session->add_command (new MementoCommand<Playlist>(*from_playlist, &from_playlist->get_state(), 0));
+ from_playlist->remove_region ((rv->region()));
+ session->add_command (new MementoCommand<Playlist>(*from_playlist, 0, &from_playlist->get_state()));
+ }
- from_playlist->remove_region (((*i)->region()));
+ latest_regionview = 0;
- sigc::connection c = atv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+ sigc::connection c = rtv2->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+ session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
to_playlist->add_region (new_region, where);
+ session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
c.disconnect ();
if (latest_regionview) {
selection->add (latest_regionview);
}
+
+ if (drag_info.copy) {
+ // get rid of the copy
+ delete rv;
+ }
}
} else {
/* motion within a single track */
+
+ list<RegionView*> regions = selection->regions.by_layer();
+
+ if (drag_info.copy) {
+ selection->clear_regions();
+ }
- for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
+ for (list<RegionView*>::iterator i = regions.begin(); i != regions.end(); ++i) {
rv = (*i);
@@ -3464,12 +3435,13 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
continue;
}
+
if (regionview_x_movement) {
double ownspeed = 1.0;
- RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*> (&(rv->get_time_axis_view()));
+ rtv = dynamic_cast<RouteTimeAxisView*> (&(rv->get_time_axis_view()));
- if (atv && atv->get_diskstream()) {
- ownspeed = atv->get_diskstream()->speed();
+ if (rtv && rtv->get_diskstream()) {
+ ownspeed = rtv->get_diskstream()->speed();
}
/* base the new region position on the current position of the regionview.*/
@@ -3485,23 +3457,62 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
where = rv->region()->position();
}
- rv->get_time_axis_view().reveal_dependent_views (*rv);
+ boost::shared_ptr<Playlist> to_playlist = rv->region()->playlist();
- /* no need to add an undo here, we did that when we added this playlist to motion_frozen playlists */
-
- rv->region()->set_position (where, (void *) this);
- rv->region()->set_opaque (true);
+ /* add the undo */
+
+ session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
+
+ if (drag_info.copy) {
+
+ boost::shared_ptr<Region> newregion;
+ boost::shared_ptr<Region> ar;
+
+ if ((ar = boost::dynamic_pointer_cast<AudioRegion>(rv->region())) != 0) {
+ newregion = RegionFactory::create (ar);
+ } else {
+ /* XXX MIDI HERE drobilla */
+ continue;
+ }
+
+ /* add it */
+
+ latest_regionview = 0;
+ sigc::connection c = rtv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
+ to_playlist->add_region (newregion, (nframes_t) (where * rtv->get_diskstream()->speed()));
+ c.disconnect ();
+
+ if (latest_regionview) {
+ 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 {
+
+ /* just change the model */
+
+ rv->region()->set_position (where, (void*) this);
+
+ }
+
+ /* add the redo */
+
+ session->add_command (new MementoCommand<Playlist>(*to_playlist, 0, &to_playlist->get_state()));
+
+ /* get rid of the copy */
+
+ if (drag_info.copy) {
+ delete rv;
+ }
}
}
out:
- for (set<boost::shared_ptr<Playlist> >::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
- (*p)->thaw ();
- session->add_command (new MementoCommand<Playlist>(*((*p).get()), 0, & (*p)->get_state()));
- }
-
- motion_frozen_playlists.clear ();
-
+
if (!nocommit) {
commit_reversible_command ();
}
@@ -3516,10 +3527,10 @@ Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event)
if (Keyboard::modifier_state_contains (event->state, Keyboard::Control)) {
TimeAxisView* tv = &rv.get_time_axis_view();
- RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(tv);
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(tv);
double speed = 1.0;
- if (atv && atv->is_track()) {
- speed = atv->get_diskstream()->speed();
+ if (rtv && rtv->is_track()) {
+ speed = rtv->get_diskstream()->speed();
}
if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
@@ -3976,8 +3987,6 @@ Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event)
nframes_t region_end = (nframes_t) (clicked_regionview->region()->last_frame() / speed);
nframes_t region_length = (nframes_t) (clicked_regionview->region()->length() / speed);
- motion_frozen_playlists.clear();
-
//drag_info.item = clicked_regionview->get_name_highlight();
drag_info.item = item;
drag_info.motion_callback = &Editor::trim_motion_callback;
@@ -4066,7 +4075,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
begin_reversible_command (trim_type);
for (list<RegionView*>::const_iterator i = selection->regions.by_layer().begin(); i != selection->regions.by_layer().end(); ++i) {
- (*i)->region()->set_opaque(false);
+ (*i)->fake_set_opaque(false);
(*i)->region()->freeze ();
AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
@@ -4261,7 +4270,7 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
i != selection->regions.by_layer().end(); ++i)
{
thaw_region_after_trim (**i);
- (*i)->region()->set_opaque(true);
+ (*i)->fake_set_opaque (true);
}
}
@@ -4887,14 +4896,14 @@ Editor::mouse_brush_insert_region (RegionView* rv, nframes_t pos)
return;
}
- RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(&arv->get_time_axis_view());
+ RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(&arv->get_time_axis_view());
- if (atv == 0 || !atv->is_track()) {
+ if (rtv == 0 || !rtv->is_track()) {
return;
}
- boost::shared_ptr<Playlist> playlist = atv->playlist();
- double speed = atv->get_diskstream()->speed();
+ boost::shared_ptr<Playlist> playlist = rtv->playlist();
+ double speed = rtv->get_diskstream()->speed();
XMLNode &before = playlist->get_state();
playlist->add_region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (arv->audio_region())), (nframes_t) (pos * speed));
diff --git a/gtk2_ardour/editor_nudge.cc b/gtk2_ardour/editor_nudge.cc
index c6f5eeeb48..1420fd6fc2 100644
--- a/gtk2_ardour/editor_nudge.cc
+++ b/gtk2_ardour/editor_nudge.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 3a2658c204..fbf384ace9 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <unistd.h>
@@ -2570,7 +2569,7 @@ Editor::bounce_range_selection ()
return;
}
- TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
+ TrackSelection views = selection->tracks;
nframes_t start = selection->time[clicked_selection].start;
nframes_t end = selection->time[clicked_selection].end;
@@ -2578,7 +2577,7 @@ Editor::bounce_range_selection ()
begin_reversible_command (_("bounce range"));
- for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
+ for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) {
AudioTimeAxisView* atv;
@@ -2605,8 +2604,6 @@ Editor::bounce_range_selection ()
}
commit_reversible_command ();
-
- delete views;
}
void
diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc
index 5bf704f649..5b1b9c63de 100644
--- a/gtk2_ardour/editor_region_list.cc
+++ b/gtk2_ardour/editor_region_list.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
@@ -27,12 +26,14 @@
#include <ardour/audioregion.h>
#include <ardour/audiofilesource.h>
+#include <ardour/silentfilesource.h>
#include <ardour/session_region.h>
#include <gtkmm2ext/stop_signal.h>
#include "editor.h"
#include "editing.h"
+#include "keyboard.h"
#include "ardour_ui.h"
#include "gui_thread.h"
#include "actions.h"
@@ -85,6 +86,9 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
string str;
TreeModel::Row row;
Gdk::Color c;
+ bool missing_source;
+
+ missing_source = boost::dynamic_pointer_cast<SilentFileSource>(region->source());
if (!show_automatic_regions_in_region_list && region->automatic()) {
return;
@@ -124,7 +128,11 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
} else if (region->whole_file()) {
row = *(region_list_model->append());
- set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false ));
+ if (missing_source) {
+ c.set_rgb(65535,0,0); // FIXME: error color from style
+ } else {
+ set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false ));
+ }
row[region_list_columns.color_] = c;
if (region->source()->name()[0] == '/') { // external file
@@ -150,6 +158,10 @@ Editor::add_region_to_region_display (boost::shared_ptr<Region> region)
}
+ if (missing_source) {
+ str += _(" (MISSING)");
+ }
+
row[region_list_columns.name] = str;
row[region_list_columns.region] = region;
diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc
index 216e3a8e1b..5c97685ee8 100644
--- a/gtk2_ardour/editor_route_list.cc
+++ b/gtk2_ardour/editor_route_list.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -24,11 +23,13 @@
#include <cassert>
#include "editor.h"
+#include "keyboard.h"
#include "ardour_ui.h"
#include "audio_time_axis.h"
#include "midi_time_axis.h"
#include "mixer_strip.h"
#include "gui_thread.h"
+#include "actions.h"
#include <pbd/unknown_type.h>
@@ -56,7 +57,7 @@ Editor::handle_new_route (Session::RouteList& routes)
boost::shared_ptr<Route> route = (*x);
if (route->hidden()) {
- return;
+ continue;
}
if (route->default_type() == ARDOUR::DataType::AUDIO)
@@ -157,9 +158,10 @@ Editor::remove_route (TimeAxisView *tv)
}
}
/* since the editor mixer goes away when you remove a route, set the
- * button to inacttive
+ * button to inactive and untick the menu option
*/
editor_mixer_button.set_active(false);
+ ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
/* and disable if all tracks and/or routes are gone */
@@ -275,6 +277,8 @@ Editor::redisplay_route_list ()
}
+ full_canvas_height = position;
+
/* make sure the cursors stay on top of every newly added track */
cursor_group->raise_to_top ();
@@ -518,11 +522,13 @@ Editor::initial_route_list_display ()
void
Editor::route_list_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter)
{
+ session->set_remote_control_ids();
redisplay_route_list ();
}
void
Editor::route_list_delete (const Gtk::TreeModel::Path& path)
{
+ session->set_remote_control_ids();
redisplay_route_list ();
}
diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc
index bc2328b524..9cf09d0ace 100644
--- a/gtk2_ardour/editor_rulers.cc
+++ b/gtk2_ardour/editor_rulers.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdio> // for sprintf, grrr
@@ -706,7 +705,7 @@ Editor::update_ruler_visibility ()
update_fixed_rulers();
//update_tempo_based_rulers();
- tempo_map_changed(Change (0));
+ tempo_map_changed(Change (0), false);
time_canvas_event_box.show_all();
time_button_event_box.show_all();
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index c1f563658b..3052fb72fa 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: editor.cc 1353 2007-01-18 03:06:15Z paul $
*/
#include <pbd/stacktrace.h>
@@ -154,6 +153,11 @@ Editor::extend_selection_to_track (TimeAxisView& view)
return false;
}
+void
+Editor::select_all_tracks ()
+{
+ selection->set (track_views);
+}
bool
Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
diff --git a/gtk2_ardour/editor_selection_list.cc b/gtk2_ardour/editor_selection_list.cc
index 864e527b59..1d75bf5d13 100644
--- a/gtk2_ardour/editor_selection_list.cc
+++ b/gtk2_ardour/editor_selection_list.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
@@ -31,6 +30,7 @@
#include <gtkmm2ext/stop_signal.h>
#include "editor.h"
+#include "keyboard.h"
#include "selection.h"
#include "time_axis_view.h"
#include "ardour_ui.h"
diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc
index 8aa978a79c..ae2bda903e 100644
--- a/gtk2_ardour/editor_tempodisplay.cc
+++ b/gtk2_ardour/editor_tempodisplay.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdio> // for sprintf, grrr
@@ -94,13 +93,13 @@ Editor::draw_metric_marks (const Metrics& metrics)
}
void
-Editor::tempo_map_changed (Change ignored)
+Editor::tempo_map_changed (Change ignored, bool immediate_redraw)
{
if (!session) {
return;
}
- ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::tempo_map_changed), ignored));
+ ENSURE_GUI_THREAD(bind (mem_fun (*this, &Editor::tempo_map_changed), ignored, immediate_redraw));
BBT_Time previous_beat, next_beat; // the beats previous to the leftmost frame and after the rightmost frame
@@ -135,18 +134,27 @@ Editor::tempo_map_changed (Change ignored)
current_bbt_points = 0;
}
- redisplay_tempo ();
+ if (immediate_redraw) {
+
+ hide_measures ();
+
+ if (session && current_bbt_points) {
+ draw_measures ();
+ }
+
+ } else {
+
+ if (session && current_bbt_points) {
+ Glib::signal_idle().connect (mem_fun (*this, &Editor::lazy_hide_and_draw_measures));
+ } else {
+ hide_measures ();
+ }
+ }
}
void
Editor::redisplay_tempo ()
{
-
- if (session && current_bbt_points) {
- Glib::signal_idle().connect (mem_fun (*this, &Editor::lazy_hide_and_draw_measures));
- } else {
- hide_measures ();
- }
}
void
diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc
index bfc5ee85cd..45cc42b11c 100644
--- a/gtk2_ardour/editor_timefx.cc
+++ b/gtk2_ardour/editor_timefx.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc
index 921e6776aa..bd5292032b 100644
--- a/gtk2_ardour/export_dialog.cc
+++ b/gtk2_ardour/export_dialog.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
@@ -109,7 +108,6 @@ ExportDialog::ExportDialog(PublicEditor& e)
src_quality_label (_("Conversion Quality"), 1.0, 0.5),
dither_type_label (_("Dither Type"), 1.0, 0.5),
cuefile_only_checkbox (_("Export CD Marker File Only")),
- file_frame (_("Export to File")),
file_browse_button (_("Browse")),
track_selector_button (_("Specific tracks ..."))
{
@@ -571,7 +569,7 @@ ExportDialog::save_state()
row = *ri;
track->add_property(X_("channel1"), row[exp_cols.left] ? X_("on") : X_("off"));
- track->add_property(X_("channel1"), row[exp_cols.right] ? X_("on") : X_("off"));
+ track->add_property(X_("channel2"), row[exp_cols.right] ? X_("on") : X_("off"));
tracks->add_child_nocopy(*track);
}
@@ -917,11 +915,9 @@ ExportDialog::do_export ()
end_dialog ();
}
-
void
ExportDialog::end_dialog ()
{
-
if (spec.running) {
spec.stop = true;
@@ -934,7 +930,7 @@ ExportDialog::end_dialog ()
}
}
- session->engine().freewheel (false);
+ session->finalize_audio_export ();
hide_all ();
@@ -950,19 +946,21 @@ ExportDialog::start_export ()
}
/* If the filename hasn't been set before, use the
- directory above the current session as a default
+ current session's export directory as a default
location for the export.
*/
if (file_entry.get_text().length() == 0) {
- string dir = session->path();
+ string dir = session->export_dir();
string::size_type last_slash;
- if ((last_slash = dir.find_last_of ('/')) != string::npos) {
+ if ((last_slash = dir.find_last_of ('/')) != string::npos && last_slash != 0) {
dir = dir.substr (0, last_slash+1);
}
- dir = dir + "export.wav";
+ if (!wants_dir()) {
+ dir = dir + "export.wav";
+ }
file_entry.set_text (dir);
}
@@ -1307,7 +1305,7 @@ ExportDialog::window_closed (GdkEventAny *ignored)
void
ExportDialog::browse ()
{
- FileChooserDialog dialog("Export to file", FILE_CHOOSER_ACTION_SAVE);
+ FileChooserDialog dialog("Export to file", browse_action());
dialog.set_transient_for(*this);
dialog.set_filename (file_entry.get_text());
diff --git a/gtk2_ardour/export_dialog.h b/gtk2_ardour/export_dialog.h
index 13b327fe50..2831384cd3 100644
--- a/gtk2_ardour/export_dialog.h
+++ b/gtk2_ardour/export_dialog.h
@@ -29,6 +29,7 @@
#include <gtkmm/progressbar.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/fileselection.h>
+#include <gtkmm/filechooser.h>
#include <gtkmm/comboboxtext.h>
#include <gtkmm/treeview.h>
#include <gtkmm/liststore.h>
@@ -56,8 +57,11 @@ class ExportDialog : public ArdourDialog
virtual void set_range (nframes_t start, nframes_t end);
void start_export ();
+ virtual Gtk::FileChooserAction browse_action() const { return Gtk::FILE_CHOOSER_ACTION_SAVE; }
+
protected:
ARDOUR::AudioExportSpecification spec;
+ Gtk::Frame file_frame;
struct ExportModelColumns : public Gtk::TreeModel::ColumnRecord
{
@@ -86,6 +90,8 @@ class ExportDialog : public ArdourDialog
// audio data. spec has already been filled with user input before calling
// this method. The dialog will be closed after this function exited.
virtual void export_audio_data() = 0;
+
+ virtual bool wants_dir() { return false; }
// reads the user input and fills spec with the according values
// filepath: complete path to the target file, including filename
@@ -138,7 +144,6 @@ class ExportDialog : public ArdourDialog
Gtk::CheckButton cuefile_only_checkbox;
- Gtk::Frame file_frame;
Gtk::Entry file_entry;
Gtk::HBox file_hbox;
Gtk::Button file_browse_button;
diff --git a/gtk2_ardour/export_range_markers_dialog.cc b/gtk2_ardour/export_range_markers_dialog.cc
index c91e1c101a..1184294a67 100644
--- a/gtk2_ardour/export_range_markers_dialog.cc
+++ b/gtk2_ardour/export_range_markers_dialog.cc
@@ -38,12 +38,20 @@ using namespace std;
ExportRangeMarkersDialog::ExportRangeMarkersDialog (PublicEditor& editor)
: ExportDialog(editor)
{
+ set_title (_("ardour: export ranges"));
+ file_frame.set_label (_("Export to Directory"));
+
do_not_allow_export_cd_markers();
total_duration = 0;
current_range_marker_index = 0;
}
-
+
+Gtk::FileChooserAction
+ExportRangeMarkersDialog::browse_action () const
+{
+ return Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER;
+}
void
ExportRangeMarkersDialog::export_audio_data ()
@@ -57,7 +65,7 @@ ExportRangeMarkersDialog::process_range_markers_export(Locations::LocationList&
Locations::LocationList::iterator locationIter;
current_range_marker_index = 0;
init_progress_computing(locations);
-
+
for (locationIter = locations.begin(); locationIter != locations.end(); ++locationIter) {
Location *currentLocation = (*locationIter);
@@ -82,7 +90,8 @@ ExportRangeMarkersDialog::process_range_markers_export(Locations::LocationList&
// wait until export of this range finished
gtk_main_iteration();
- while(spec.running){
+
+ while (spec.running){
if(gtk_events_pending()){
gtk_main_iteration();
}else {
@@ -90,7 +99,6 @@ ExportRangeMarkersDialog::process_range_markers_export(Locations::LocationList&
}
}
- getSession().engine().freewheel (false);
current_range_marker_index++;
}
}
@@ -140,8 +148,7 @@ ExportRangeMarkersDialog::is_filepath_valid(string &filepath)
if ( (stat (filepath.c_str(), &statbuf) != 0) ||
(!S_ISDIR (statbuf.st_mode)) ) {
- string txt = _("Please select an existing target directory. Files\n"
- "are not allowed!");
+ string txt = _("Please select an existing target directory. Files are not allowed!");
MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
msg.run();
return false;
@@ -173,13 +180,11 @@ ExportRangeMarkersDialog::init_progress_computing(Locations::LocationList& locat
Location *currentLocation = (*locationIter);
if(currentLocation->is_range_marker()){
- range_markers_durations_aggregated.push_back(
- duration_before_current_location);
+ range_markers_durations_aggregated.push_back (duration_before_current_location);
- nframes_t duration =
- currentLocation->end() - currentLocation->start();
+ nframes_t duration = currentLocation->end() - currentLocation->start();
- range_markers_durations.push_back(duration);
+ range_markers_durations.push_back (duration);
duration_before_current_location += duration;
}
}
@@ -192,14 +197,12 @@ gint
ExportRangeMarkersDialog::progress_timeout ()
{
double progress = 0.0;
-
- if(current_range_marker_index >= range_markers_durations.size()){
+
+ if (current_range_marker_index >= range_markers_durations.size()){
progress = 1.0;
- }
- else{
- progress =
- ((double) range_markers_durations_aggregated[current_range_marker_index] +
- (spec.progress * (double) range_markers_durations[current_range_marker_index])) /
+ } else{
+ progress = ((double) range_markers_durations_aggregated[current_range_marker_index] +
+ (spec.progress * (double) range_markers_durations[current_range_marker_index])) /
(double) total_duration;
}
diff --git a/gtk2_ardour/export_range_markers_dialog.h b/gtk2_ardour/export_range_markers_dialog.h
index 7aae9640bf..7d231c62d5 100644
--- a/gtk2_ardour/export_range_markers_dialog.h
+++ b/gtk2_ardour/export_range_markers_dialog.h
@@ -30,10 +30,14 @@ class ExportRangeMarkersDialog : public ExportDialog
public:
ExportRangeMarkersDialog (PublicEditor&);
+ Gtk::FileChooserAction browse_action() const;
+
protected:
virtual bool is_filepath_valid(string &filepath);
void export_audio_data();
+
+ bool wants_dir() { return true; }
private:
// keeps the duration of all range_markers before the current
diff --git a/gtk2_ardour/export_region_dialog.cc b/gtk2_ardour/export_region_dialog.cc
index 30ff05dc5c..cb3804c11b 100644
--- a/gtk2_ardour/export_region_dialog.cc
+++ b/gtk2_ardour/export_region_dialog.cc
@@ -31,6 +31,9 @@
ExportRegionDialog::ExportRegionDialog (PublicEditor& editor, boost::shared_ptr<ARDOUR::Region> region)
: ExportDialog(editor)
{
+ set_title (_("ardour: export region"));
+ file_frame.set_label (_("Export to File")),
+
audio_region = boost::dynamic_pointer_cast<ARDOUR::AudioRegion>(region);
assert(audio_region);
diff --git a/gtk2_ardour/export_session_dialog.cc b/gtk2_ardour/export_session_dialog.cc
index 7cd7fdc06f..006f9675b3 100644
--- a/gtk2_ardour/export_session_dialog.cc
+++ b/gtk2_ardour/export_session_dialog.cc
@@ -21,13 +21,14 @@
#include "ardour_ui.h"
#include "export_session_dialog.h"
+#include "i18n.h"
ExportSessionDialog::ExportSessionDialog (PublicEditor& editor)
: ExportDialog(editor)
{
+ file_frame.set_label (_("Export to File"));
}
-
void
ExportSessionDialog::export_audio_data ()
{
diff --git a/gtk2_ardour/gain_automation_time_axis.cc b/gtk2_ardour/gain_automation_time_axis.cc
index c1261fdf23..9890854d4b 100644
--- a/gtk2_ardour/gain_automation_time_axis.cc
+++ b/gtk2_ardour/gain_automation_time_axis.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/curve.h>
diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc
index 2d7cd5883e..fa719bcca2 100644
--- a/gtk2_ardour/gain_meter.cc
+++ b/gtk2_ardour/gain_meter.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <limits.h>
@@ -107,11 +106,11 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s)
gain_display_box.pack_start (gain_display, true, true);
peak_display.set_name ("MixerStripPeakDisplay");
- peak_display.set_has_frame (false);
- peak_display.set_editable (false);
+// peak_display.set_has_frame (false);
+// peak_display.set_editable (false);
set_size_request_to_display_given_text (peak_display, "-80.g", 2, 6); /* note the descender */
max_peak = minus_infinity();
- peak_display.set_text (_("-inf"));
+ peak_display.set_label (_("-inf"));
peak_display.unset_flags (Gtk::CAN_FOCUS);
meter_metric_area.set_name ("MeterMetricsStrip");
@@ -161,7 +160,7 @@ GainMeter::GainMeter (boost::shared_ptr<IO> io, Session& s)
using namespace Menu_Helpers;
- gain_astate_menu.items().push_back (MenuElem (_("Off"),
+ gain_astate_menu.items().push_back (MenuElem (_("Manual"),
bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Off)));
gain_astate_menu.items().push_back (MenuElem (_("Play"),
bind (mem_fun (*_io, &IO::set_gain_automation_state), (AutoState) Play)));
@@ -231,11 +230,11 @@ GainMeter::render_metrics (Gtk::Widget& w)
Glib::RefPtr<Gdk::Window> win (w.get_window());
Glib::RefPtr<Gdk::GC> fg_gc (w.get_style()->get_fg_gc (Gtk::STATE_NORMAL));
Glib::RefPtr<Gdk::GC> bg_gc (w.get_style()->get_bg_gc (Gtk::STATE_NORMAL));
- gint x, y, width, height, depth;
+ gint width, height;
int db_points[] = { -50, -40, -20, -30, -10, -3, 0, 4 };
char buf[32];
- win->get_geometry (x, y, width, height, depth);
+ win->get_size (width, height);
Glib::RefPtr<Gdk::Pixmap> pixmap = Gdk::Pixmap::create (win, width, height);
@@ -274,9 +273,9 @@ GainMeter::meter_metrics_expose (GdkEventExpose *ev)
Glib::RefPtr<Gdk::GC> bg_gc (meter_metric_area.get_style()->get_bg_gc (Gtk::STATE_NORMAL));
GdkRectangle base_rect;
GdkRectangle draw_rect;
- gint x, y, width, height, depth;
+ gint width, height;
- win->get_geometry (x, y, width, height, depth);
+ win->get_size (width, height);
base_rect.width = width;
base_rect.height = height;
@@ -332,10 +331,10 @@ GainMeter::update_meters ()
max_peak = mpeak;
/* set peak display */
if (max_peak <= -200.0f) {
- peak_display.set_text (_("-inf"));
+ peak_display.set_label (_("-inf"));
} else {
snprintf (buf, sizeof(buf), "%.1f", max_peak);
- peak_display.set_text (buf);
+ peak_display.set_label (buf);
}
if (max_peak >= 0.0f) {
@@ -452,6 +451,14 @@ GainMeter::setup_meters ()
}
}
+int
+GainMeter::get_gm_width ()
+{
+ Gtk::Requisition sz;
+ hbox.size_request (sz);
+ return sz.width;
+}
+
bool
GainMeter::gain_key_press (GdkEventKey* ev)
{
@@ -491,7 +498,7 @@ GainMeter::reset_peak_display ()
}
max_peak = -INFINITY;
- peak_display.set_text (_("-Inf"));
+ peak_display.set_label (_("-Inf"));
peak_display.set_name ("MixerStripPeakDisplay");
}
@@ -513,7 +520,7 @@ GainMeter::meter_button_release (GdkEventButton* ev, uint32_t which)
case 1:
meters[which].meter->clear();
max_peak = minus_infinity();
- peak_display.set_text (_("-inf"));
+ peak_display.set_label (_("-inf"));
peak_display.set_name ("MixerStripPeakDisplay");
break;
@@ -842,7 +849,7 @@ GainMeter::_astate_string (AutoState state, bool shrt)
switch (state) {
case Off:
- sstr = (shrt ? "O" : _("O"));
+ sstr = (shrt ? "M" : _("M"));
break;
case Play:
sstr = (shrt ? "P" : _("P"));
diff --git a/gtk2_ardour/gain_meter.h b/gtk2_ardour/gain_meter.h
index 88105ce846..a24b93c034 100644
--- a/gtk2_ardour/gain_meter.h
+++ b/gtk2_ardour/gain_meter.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_gain_meter_h__
@@ -70,6 +69,8 @@ class GainMeter : public Gtk::VBox
void set_width (Width);
void setup_meters ();
+ int get_gm_width ();
+
void set_meter_strip_name (const char * name);
void set_fader_name (const char * name);
@@ -85,7 +86,7 @@ class GainMeter : public Gtk::VBox
Gtkmm2ext::VSliderController *gain_slider;
Gtk::Adjustment gain_adjustment;
Gtkmm2ext::FocusEntry gain_display;
- Gtk::Entry peak_display;
+ Gtk::Button peak_display;
Gtk::HBox gain_display_box;
Gtk::HBox fader_box;
Gtk::DrawingArea meter_metric_area;
diff --git a/gtk2_ardour/ghostregion.h b/gtk2_ardour/ghostregion.h
index 0255035ea1..77b22f942c 100644
--- a/gtk2_ardour/ghostregion.h
+++ b/gtk2_ardour/ghostregion.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_ghost_region_h__
diff --git a/gtk2_ardour/icons/crossfade_in_constant.png b/gtk2_ardour/icons/crossfade_in_constant.png
new file mode 100644
index 0000000000..ce7d48032e
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_in_constant.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_in_dipped.png b/gtk2_ardour/icons/crossfade_in_dipped.png
new file mode 100644
index 0000000000..667e9d9c06
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_in_dipped.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_in_fast-cut.png b/gtk2_ardour/icons/crossfade_in_fast-cut.png
new file mode 100644
index 0000000000..a55dab560a
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_in_fast-cut.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_in_slow-cut.png b/gtk2_ardour/icons/crossfade_in_slow-cut.png
new file mode 100644
index 0000000000..fe76c3bc89
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_in_slow-cut.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_in_slow-fade.png b/gtk2_ardour/icons/crossfade_in_slow-fade.png
new file mode 100644
index 0000000000..a105967da1
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_in_slow-fade.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_in_transition.png b/gtk2_ardour/icons/crossfade_in_transition.png
new file mode 100644
index 0000000000..482e8a63bd
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_in_transition.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_out_constant.png b/gtk2_ardour/icons/crossfade_out_constant.png
new file mode 100644
index 0000000000..602ba806c5
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_out_constant.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_out_dipped.png b/gtk2_ardour/icons/crossfade_out_dipped.png
new file mode 100644
index 0000000000..3f1e84c485
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_out_dipped.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_out_fast-cut.png b/gtk2_ardour/icons/crossfade_out_fast-cut.png
new file mode 100644
index 0000000000..33eaafe7b3
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_out_fast-cut.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_out_slow-cut.png b/gtk2_ardour/icons/crossfade_out_slow-cut.png
new file mode 100644
index 0000000000..fd6260228e
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_out_slow-cut.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_out_slow-fade.png b/gtk2_ardour/icons/crossfade_out_slow-fade.png
new file mode 100644
index 0000000000..d752879bec
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_out_slow-fade.png
Binary files differ
diff --git a/gtk2_ardour/icons/crossfade_out_transition.png b/gtk2_ardour/icons/crossfade_out_transition.png
new file mode 100644
index 0000000000..a48e645fbd
--- /dev/null
+++ b/gtk2_ardour/icons/crossfade_out_transition.png
Binary files differ
diff --git a/gtk2_ardour/imageframe.cc b/gtk2_ardour/imageframe.cc
index bc59fec2c0..7ff05ee9e9 100644
--- a/gtk2_ardour/imageframe.cc
+++ b/gtk2_ardour/imageframe.cc
@@ -4,7 +4,6 @@
#include "imageframe_p.h"
#include <libgnomecanvasmm/private/shape_p.h>
-/* $Id$ */
/* rect.c
*
diff --git a/gtk2_ardour/imageframe.h b/gtk2_ardour/imageframe.h
index b2ff25b408..76787f8b88 100644
--- a/gtk2_ardour/imageframe.h
+++ b/gtk2_ardour/imageframe.h
@@ -4,7 +4,6 @@
#include <glibmm.h>
-/* $Id$ */
/* rect.h
*
diff --git a/gtk2_ardour/imageframe_socket_handler.cc b/gtk2_ardour/imageframe_socket_handler.cc
index a7f4d603a7..96b61cafdd 100644
--- a/gtk2_ardour/imageframe_socket_handler.cc
+++ b/gtk2_ardour/imageframe_socket_handler.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <iostream>
diff --git a/gtk2_ardour/imageframe_socket_handler.h b/gtk2_ardour/imageframe_socket_handler.h
index 4dd8d69650..3a87f5bf71 100644
--- a/gtk2_ardour/imageframe_socket_handler.h
+++ b/gtk2_ardour/imageframe_socket_handler.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_imageframe_socket_handler_h__
diff --git a/gtk2_ardour/imageframe_time_axis.cc b/gtk2_ardour/imageframe_time_axis.cc
index ae288ec9ab..018fae6895 100644
--- a/gtk2_ardour/imageframe_time_axis.cc
+++ b/gtk2_ardour/imageframe_time_axis.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <string>
diff --git a/gtk2_ardour/imageframe_time_axis.h b/gtk2_ardour/imageframe_time_axis.h
index cefd0c5d09..4b3bf0c857 100644
--- a/gtk2_ardour/imageframe_time_axis.h
+++ b/gtk2_ardour/imageframe_time_axis.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_imageframe_time_axis_h__
diff --git a/gtk2_ardour/imageframe_time_axis_group.cc b/gtk2_ardour/imageframe_time_axis_group.cc
index 647d45b963..5dc76978b0 100644
--- a/gtk2_ardour/imageframe_time_axis_group.cc
+++ b/gtk2_ardour/imageframe_time_axis_group.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/gtk2_ardour/imageframe_time_axis_group.h b/gtk2_ardour/imageframe_time_axis_group.h
index 4619ae448a..ba7790c04a 100644
--- a/gtk2_ardour/imageframe_time_axis_group.h
+++ b/gtk2_ardour/imageframe_time_axis_group.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_imageframe_time_axis_group_h__
diff --git a/gtk2_ardour/imageframe_time_axis_view.cc b/gtk2_ardour/imageframe_time_axis_view.cc
index 6e896ea5ec..91575f3cc5 100644
--- a/gtk2_ardour/imageframe_time_axis_view.cc
+++ b/gtk2_ardour/imageframe_time_axis_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/gtk2_ardour/imageframe_time_axis_view.h b/gtk2_ardour/imageframe_time_axis_view.h
index d51901d4e0..45725038d1 100644
--- a/gtk2_ardour/imageframe_time_axis_view.h
+++ b/gtk2_ardour/imageframe_time_axis_view.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_imageframe_time_axis_view_h__
diff --git a/gtk2_ardour/imageframe_view.cc b/gtk2_ardour/imageframe_view.cc
index 2c943dcae4..f8bba3aa84 100644
--- a/gtk2_ardour/imageframe_view.cc
+++ b/gtk2_ardour/imageframe_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/gtk2_ardour/imageframe_view.h b/gtk2_ardour/imageframe_view.h
index 71d9268fef..db83264e46 100644
--- a/gtk2_ardour/imageframe_view.h
+++ b/gtk2_ardour/imageframe_view.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_imageframe_view_h__
diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc
index 00d24287ed..5ad04b929d 100644
--- a/gtk2_ardour/io_selector.cc
+++ b/gtk2_ardour/io_selector.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <map>
diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h
index 288edd0be5..430926f761 100644
--- a/gtk2_ardour/io_selector.h
+++ b/gtk2_ardour/io_selector.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_ui_io_selector_h__
diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc
index a6a14ad55b..83918da918 100644
--- a/gtk2_ardour/keyboard.cc
+++ b/gtk2_ardour/keyboard.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include "ardour_ui.h"
@@ -25,8 +24,6 @@
#include <ctype.h>
-#include <X11/keysymdef.h>
-#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <pbd/error.h>
@@ -49,14 +46,13 @@ guint Keyboard::snap_mod = GDK_MOD3_MASK;
uint32_t Keyboard::Control = GDK_CONTROL_MASK;
uint32_t Keyboard::Shift = GDK_SHIFT_MASK;
uint32_t Keyboard::Alt = GDK_MOD1_MASK;
-uint32_t Keyboard::Meta = GDK_MOD2_MASK;
+uint32_t Keyboard::Meta;
Keyboard* Keyboard::_the_keyboard = 0;
/* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */
-GdkModifierType Keyboard::RelevantModifierKeyMask =
- GdkModifierType (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD1_MASK|GDK_MOD3_MASK);
+GdkModifierType Keyboard::RelevantModifierKeyMask;
Keyboard::Keyboard ()
@@ -65,9 +61,19 @@ Keyboard::Keyboard ()
_the_keyboard = this;
}
- collecting_prefix = false;
+ RelevantModifierKeyMask = (GdkModifierType) gtk_accelerator_get_default_mod_mask ();
- get_modifier_masks ();
+ /* figure out Meta */
+
+ uint32_t possible_meta[] = { GDK_MOD2_MASK, GDK_MOD3_MASK, GDK_MOD4_MASK, GDK_MOD5_MASK, 0};
+ int i;
+
+ for (i = 0; possible_meta[i]; ++i) {
+ if (!(RelevantModifierKeyMask & possible_meta[i])) {
+ break;
+ }
+ }
+ Meta = possible_meta[i];
snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
@@ -78,7 +84,6 @@ Keyboard::Keyboard ()
Keyboard::~Keyboard ()
{
gtk_key_snooper_remove (snooper_id);
- delete [] modifier_masks;
}
XMLNode&
@@ -158,60 +163,6 @@ Keyboard::snooper (GtkWidget *widget, GdkEventKey *event)
}
if (event->type == GDK_KEY_PRESS) {
- bool was_prefix = false;
-
- if (collecting_prefix) {
- switch (keyval) {
- case GDK_0:
- current_prefix += '0';
- was_prefix = true;
- break;
- case GDK_1:
- current_prefix += '1';
- was_prefix = true;
- break;
- case GDK_2:
- current_prefix += '2';
- was_prefix = true;
- break;
- case GDK_3:
- current_prefix += '3';
- was_prefix = true;
- break;
- case GDK_4:
- current_prefix += '4';
- was_prefix = true;
- break;
- case GDK_5:
- current_prefix += '5';
- was_prefix = true;
- break;
- case GDK_6:
- current_prefix += '6';
- was_prefix = true;
- break;
- case GDK_7:
- current_prefix += '7';
- was_prefix = true;
- break;
- case GDK_8:
- current_prefix += '8';
- was_prefix = true;
- break;
- case GDK_9:
- current_prefix += '9';
- was_prefix = true;
- break;
- case GDK_period:
- current_prefix += '.';
- was_prefix = true;
- break;
- default:
- was_prefix = false;
- collecting_prefix = false;
- break;
- }
- }
if (find (state.begin(), state.end(), keyval) == state.end()) {
state.push_back (keyval);
@@ -238,441 +189,10 @@ Keyboard::key_is_down (uint32_t keyval)
return find (state.begin(), state.end(), keyval) != state.end();
}
-Keyboard::State
-Keyboard::translate_key_name (const string& name)
-
-{
- string::size_type i;
- string::size_type len;
- bool at_end;
- string::size_type hyphen;
- string keyname;
- string whatevers_left;
- State result;
- guint keycode;
-
- i = 0;
- len = name.length();
- at_end = (len == 0);
-
- while (!at_end) {
-
- whatevers_left = name.substr (i);
-
- if ((hyphen = whatevers_left.find_first_of ('-')) == string::npos) {
-
- /* no hyphen, so use the whole thing */
-
- keyname = whatevers_left;
- at_end = true;
-
- } else {
-
- /* There is a hyphen. */
-
- if (hyphen == 0 && whatevers_left.length() == 1) {
- /* its the first and only character */
-
- keyname = "-";
- at_end = true;
-
- } else {
-
- /* use the text before the hypen */
-
- keyname = whatevers_left.substr (0, hyphen);
-
- if (hyphen == len - 1) {
- at_end = true;
- } else {
- i += hyphen + 1;
- at_end = (i >= len);
- }
- }
- }
-
- if (keyname.length() == 1 && isupper (keyname[0])) {
- result.push_back (GDK_Shift_L);
- }
-
- if ((keycode = gdk_keyval_from_name(get_real_keyname (keyname).c_str())) == GDK_VoidSymbol) {
- error << string_compose(_("KeyboardTarget: keyname \"%1\" is unknown."), keyname) << endmsg;
- result.clear();
- return result;
- }
-
- result.push_back (keycode);
- }
-
- sort (result.begin(), result.end());
-
- return result;
-}
-
-string
-Keyboard::get_real_keyname (const string& name)
-{
-
- if (name == "Control" || name == "Ctrl") {
- return "Control_L";
- }
- if (name == "Meta" || name == "MetaL") {
- return "Meta_L";
- }
- if (name == "MetaR") {
- return "Meta_R";
- }
- if (name == "Alt" || name == "AltL") {
- return "Alt_L";
- }
- if (name == "AltR") {
- return "Alt_R";
- }
- if (name == "Shift") {
- return "Shift_L";
- }
- if (name == "Shift_R") {
- return "Shift_L";
- }
- if (name == " ") {
- return "space";
- }
- if (name == "!") {
- return "exclam";
- }
- if (name == "\"") {
- return "quotedbl";
- }
- if (name == "#") {
- return "numbersign";
- }
- if (name == "$") {
- return "dollar";
- }
- if (name == "%") {
- return "percent";
- }
- if (name == "&") {
- return "ampersand";
- }
- if (name == "'") {
- return "apostrophe";
- }
- if (name == "'") {
- return "quoteright";
- }
- if (name == "(") {
- return "parenleft";
- }
- if (name == ")") {
- return "parenright";
- }
- if (name == "*") {
- return "asterisk";
- }
- if (name == "+") {
- return "plus";
- }
- if (name == ",") {
- return "comma";
- }
- if (name == "-") {
- return "minus";
- }
- if (name == ".") {
- return "period";
- }
- if (name == "/") {
- return "slash";
- }
- if (name == ":") {
- return "colon";
- }
- if (name == ";") {
- return "semicolon";
- }
- if (name == "<") {
- return "less";
- }
- if (name == "=") {
- return "equal";
- }
- if (name == ">") {
- return "greater";
- }
- if (name == "?") {
- return "question";
- }
- if (name == "@") {
- return "at";
- }
- if (name == "[") {
- return "bracketleft";
- }
- if (name == "\\") {
- return "backslash";
- }
- if (name == "]") {
- return "bracketright";
- }
- if (name == "^") {
- return "asciicircum";
- }
- if (name == "_") {
- return "underscore";
- }
- if (name == "`") {
- return "grave";
- }
- if (name == "`") {
- return "quoteleft";
- }
- if (name == "{") {
- return "braceleft";
- }
- if (name == "|") {
- return "bar";
- }
- if (name == "}") {
- return "braceright";
- }
- if (name == "~") {
- return "asciitilde";
- }
-
- return name;
-}
-
-int
-Keyboard::get_prefix (float& val, bool& was_floating)
-{
- if (current_prefix.length()) {
- if (current_prefix.find ('.') != string::npos) {
- was_floating = true;
- } else {
- was_floating = false;
- }
- if (sscanf (current_prefix.c_str(), "%f", &val) == 1) {
- return 0;
- }
- current_prefix = "";
- }
- return -1;
-}
-
-void
-Keyboard::start_prefix ()
-{
- collecting_prefix = true;
- current_prefix = "";
-}
-
-void
-Keyboard::clear_modifier_state ()
-{
- modifier_mask = 0;
-}
-
-void
-Keyboard::check_modifier_state ()
-{
- char keys[32];
- int i, j;
-
- clear_modifier_state ();
- XQueryKeymap (GDK_DISPLAY(), keys);
-
- for (i = 0; i < 32; ++i) {
- for (j = 0; j < 8; ++j) {
-
- if (keys[i] & (1<<j)) {
- modifier_mask |= modifier_masks[(i*8)+j];
- }
- }
- }
-}
-
-void
-Keyboard::check_meta_numlock (char keycode, guint mod, string modname)
-{
- guint alternate_meta_mod;
- string alternate_meta_modname;
-
- if (mod == Meta) {
-
- guint keysym = XKeycodeToKeysym (GDK_DISPLAY(), keycode, 0);
-
- if (keysym == GDK_Num_Lock) {
-
- switch (mod) {
- case GDK_MOD2_MASK:
- alternate_meta_mod = GDK_MOD3_MASK;
- alternate_meta_modname = "Mod3";
- break;
- case GDK_MOD3_MASK:
- alternate_meta_mod = GDK_MOD2_MASK;
- alternate_meta_modname = "Mod2";
- break;
- case GDK_MOD4_MASK:
- alternate_meta_mod = GDK_MOD2_MASK;
- alternate_meta_modname = "Mod2";
- break;
- case GDK_MOD5_MASK:
- alternate_meta_mod = GDK_MOD2_MASK;
- alternate_meta_modname = "Mod2";
- break;
- default:
- error << string_compose (_("Your system is completely broken - NumLock uses \"%1\""
- "as its modifier. This is madness - see the man page "
- "for xmodmap to find out how to fix this."),
- modname)
- << endmsg;
- return;
- }
-
- warning << string_compose (_("Your system generates \"%1\" when the NumLock key "
- "is pressed. This can cause problems when editing "
- "so Ardour will use %2 to mean Meta rather than %1"),
- modname, alternate_meta_modname)
- << endmsg;
-
- set_meta_modifier (alternate_meta_mod);
- }
- }
-}
-
-void
-Keyboard::get_modifier_masks ()
-{
- XModifierKeymap *modifiers;
- KeyCode *keycode;
- int i;
- int bound;
-
- XDisplayKeycodes (GDK_DISPLAY(), &min_keycode, &max_keycode);
-
- /* This function builds a lookup table to provide rapid answers to
- the question: what, if any, modmask, is associated with a given
- keycode ?
- */
-
- modifiers = XGetModifierMapping (GDK_DISPLAY());
-
- modifier_masks = new int32_t [max_keycode+1];
-
- keycode = modifiers->modifiermap;
-
- for (i = 0; i < modifiers->max_keypermod; ++i) { /* shift */
- if (*keycode) {
- modifier_masks[*keycode] = GDK_SHIFT_MASK;
- // cerr << "Shift = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
- }
- keycode++;
- }
-
- for (i = 0; i < modifiers->max_keypermod; ++i) keycode++; /* skip lock */
-
- for (i = 0; i < modifiers->max_keypermod; ++i) { /* control */
- if (*keycode) {
- modifier_masks[*keycode] = GDK_CONTROL_MASK;
- // cerr << "Control = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
- }
- keycode++;
- }
-
- bound = 0;
- for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 1 */
- if (*keycode) {
- modifier_masks[*keycode] = GDK_MOD1_MASK;
- // cerr << "Mod1 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
- bound++;
- }
- keycode++;
- }
-#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
- if (bound > 1) {
- warning << string_compose (_("You have %1 keys bound to \"mod1\""), bound) << endmsg;
- }
-#endif
- bound = 0;
- for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod2 */
- if (*keycode) {
- modifier_masks[*keycode] = GDK_MOD2_MASK;
- check_meta_numlock (*keycode, GDK_MOD2_MASK, "Mod2");
- //cerr << "Mod2 = " << std::hex << (int) *keycode << std::dec << " = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
- bound++;
- }
- keycode++;
- }
-#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
- if (bound > 1) {
- warning << string_compose (_("You have %1 keys bound to \"mod2\""), bound) << endmsg;
- }
-#endif
- bound = 0;
- for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod3 */
- if (*keycode) {
- modifier_masks[*keycode] = GDK_MOD3_MASK;
- check_meta_numlock (*keycode, GDK_MOD3_MASK, "Mod3");
- // cerr << "Mod3 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
- bound++;
- }
- keycode++;
- }
-#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
- if (bound > 1) {
- warning << string_compose (_("You have %1 keys bound to \"mod3\""), bound) << endmsg;
- }
-#endif
- bound = 0;
- for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 4 */
- if (*keycode) {
- modifier_masks[*keycode] = GDK_MOD4_MASK;
- check_meta_numlock (*keycode, GDK_MOD4_MASK, "Mod4");
- // cerr << "Mod4 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
- bound++;
- }
- keycode++;
- }
-#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
- if (bound > 1) {
- warning << string_compose (_("You have %1 keys bound to \"mod4\""), bound) << endmsg;
- }
-#endif
- bound = 0;
- for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 5 */
- if (*keycode) {
- modifier_masks[*keycode] = GDK_MOD5_MASK;
- check_meta_numlock (*keycode, GDK_MOD5_MASK, "Mod5");
- // cerr << "Mod5 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl;
- bound++;
- }
- keycode++;
- }
-#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS
- if (bound > 1) {
- warning << string_compose (_("You have %1 keys bound to \"mod5\""), bound) << endmsg;
- }
-#endif
-
- XFreeModifiermap (modifiers);
-}
-
bool
Keyboard::enter_window (GdkEventCrossing *ev, Gtk::Window* win)
{
- switch (ev->detail) {
- case GDK_NOTIFY_INFERIOR:
- break;
-
- case GDK_NOTIFY_VIRTUAL:
- /* fallthru */
-
- default:
- check_modifier_state ();
- }
-
- return FALSE;
+ return false;
}
bool
@@ -697,10 +217,9 @@ Keyboard::leave_window (GdkEventCrossing *ev, Gtk::Window* win)
cerr << "clearing current target\n";
}
state.clear ();
- clear_modifier_state ();
}
- return FALSE;
+ return false;
}
void
@@ -754,6 +273,7 @@ Keyboard::set_snap_modifier (guint mod)
bool
Keyboard::is_edit_event (GdkEventButton *ev)
{
+
return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) &&
(ev->button == Keyboard::edit_button()) &&
((ev->state & RelevantModifierKeyMask) == Keyboard::edit_modifier());
diff --git a/gtk2_ardour/keyboard.h b/gtk2_ardour/keyboard.h
index c13b06afe5..ec55dc54db 100644
--- a/gtk2_ardour/keyboard.h
+++ b/gtk2_ardour/keyboard.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_keyboard_h__
@@ -45,13 +44,6 @@ class Keyboard : public sigc::trackable, Stateful
int set_state (const XMLNode&);
typedef vector<uint32_t> State;
-
- int get_prefix(float&, bool& was_floating);
- void start_prefix ();
-
- static State translate_key_name (const string&);
- static string get_real_keyname (const string& name);
-
typedef uint32_t ModifierMask;
static uint32_t Control;
@@ -101,17 +93,8 @@ class Keyboard : public sigc::trackable, Stateful
private:
static Keyboard* _the_keyboard;
- bool _queue_events;
- bool _flush_queue;
-
guint snooper_id;
State state;
- bool collecting_prefix;
- string current_prefix;
- int* modifier_masks;
- int modifier_mask;
- int min_keycode;
- int max_keycode;
static guint edit_but;
static guint edit_mod;
@@ -121,13 +104,6 @@ class Keyboard : public sigc::trackable, Stateful
static gint _snooper (GtkWidget*, GdkEventKey*, gpointer);
gint snooper (GtkWidget*, GdkEventKey*);
-
- void queue_event (GdkEventKey*);
- void get_modifier_masks ();
- void check_modifier_state ();
- void clear_modifier_state ();
-
- void check_meta_numlock (char keycode, guint mod, string modname);
};
#endif /* __ardour_keyboard_h__ */
diff --git a/gtk2_ardour/keyboard_target.cc b/gtk2_ardour/keyboard_target.cc
deleted file mode 100644
index 71e4e9652e..0000000000
--- a/gtk2_ardour/keyboard_target.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- Copyright (C) 2001-2002 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
-
-#include <gdk/gdkkeysyms.h>
-#include <pbd/error.h>
-
-#include "keyboard.h"
-#include "keyboard_target.h"
-
-#include "i18n.h"
-
-using std::pair;
-
-KeyboardTarget::ActionMap KeyboardTarget::actions;
-
-KeyboardTarget::KeyboardTarget (Gtk::Window& win, string name)
- : _window (win)
-{
- _name = name;
- Keyboard::the_keyboard().register_target (this);
-}
-
-KeyboardTarget::~KeyboardTarget ()
-{
- GoingAway ();
-}
-
-void
-KeyboardTarget::key_release_event (GdkEventKey *event, Keyboard::State& state)
-{
- // relax
-}
-
-void
-KeyboardTarget::key_press_event (GdkEventKey *event, Keyboard::State& state, bool& handled)
-{
- KeyMap::iterator result;
-
- if ((result = keymap.find (state)) != keymap.end()) {
- (*result).second ();
- handled = true;
- }
-}
-
-int
-KeyboardTarget::add_binding (string keystring, string action)
-{
- KeyMap::iterator existing;
- Keyboard::State state;
- KeyAction key_action;
-
- state = Keyboard::translate_key_name (keystring);
-
- if (keystring.length() == 0) {
- error << _("KeyboardTarget: empty string passed to add_binding.")
- << endmsg;
- return -1;
- }
-
- if (state.size() == 0) {
- error << string_compose(_("KeyboardTarget: no translation found for \"%1\""), keystring) << endmsg;
- return -1;
- }
-
- if (find_action (action, key_action)) {
- error << string_compose(_("KeyboardTarget: unknown action \"%1\""), action) << endmsg;
- return -1;
- }
-
- /* remove any existing binding */
-
- if ((existing = keymap.find (state)) != keymap.end()) {
- keymap.erase (existing);
- }
-
- keymap.insert (pair<Keyboard::State,KeyAction> (state, key_action));
- bindings.insert (pair<string,string> (keystring, action));
- return 0;
-}
-
-string
-KeyboardTarget::get_binding (string name)
-{
- BindingMap::iterator i;
-
- for (i = bindings.begin(); i != bindings.end(); ++i) {
-
- if (i->second == name) {
-
- /* convert keystring to GTK format */
-
- string str = i->first;
- string gtkstr;
- string::size_type p;
-
- while (1) {
-
- if ((p = str.find ('-')) == string::npos || (p == str.length() - 1)) {
- break;
- }
-
- gtkstr += '<';
- gtkstr += str.substr (0, p);
- gtkstr += '>';
-
- str = str.substr (p+1);
-
- }
-
- gtkstr += str;
-
- if (gtkstr.length() == 0) {
- return i->first;
- }
-
- return gtkstr;
- }
- }
- return string ();
-}
-
-void
-KeyboardTarget::show_all_actions ()
-{
- ActionMap::iterator i;
-
- for (i = actions.begin(); i != actions.end(); ++i) {
- cout << i->first << endl;
- }
-}
-
-int
-KeyboardTarget::add_action (string name, KeyAction action)
-{
- pair<string,KeyAction> newpair;
- pair<ActionMap::iterator,bool> result;
- newpair.first = name;
- newpair.second = action;
-
- result = actions.insert (newpair);
- return result.second ? 0 : -1;
-}
-
-int
-KeyboardTarget::find_action (string name, KeyAction& action)
-{
- map<string,KeyAction>::iterator i;
-
- if ((i = actions.find (name)) != actions.end()) {
- action = i->second;
- return 0;
- } else {
- return -1;
- }
-}
-
-int
-KeyboardTarget::remove_action (string name)
-{
- map<string,KeyAction>::iterator i;
-
- if ((i = actions.find (name)) != actions.end()) {
- actions.erase (i);
- return 0;
- } else {
- return -1;
- }
-}
-
-XMLNode&
-KeyboardTarget::get_binding_state () const
-{
- XMLNode *node = new XMLNode ("context");
- BindingMap::const_iterator i;
-
- node->add_property ("name", _name);
-
- for (i = bindings.begin(); i != bindings.end(); ++i) {
- XMLNode *child;
-
- child = new XMLNode ("binding");
- child->add_property ("keys", i->first);
- child->add_property ("action", i->second);
- node->add_child_nocopy (*child);
- }
-
- return *node;
-}
-
-int
-KeyboardTarget::set_binding_state (const XMLNode& node)
-{
- XMLNodeList nlist = node.children();
- XMLNodeConstIterator niter;
- XMLNode *child_node;
-
- bindings.clear ();
- keymap.clear ();
-
- for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- child_node = *niter;
-
- if (child_node->name() == "context") {
- XMLProperty *prop;
-
- if ((prop = child_node->property ("name")) != 0) {
- if (prop->value() == _name) {
- return load_bindings (*child_node);
- }
- }
- }
- }
-
- return 0;
-}
-
-int
-KeyboardTarget::load_bindings (const XMLNode& node)
-{
- XMLNodeList nlist = node.children();
- XMLNodeConstIterator niter;
-
- for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- XMLProperty *keys;
- XMLProperty *action;
-
- keys = (*niter)->property ("keys");
- action = (*niter)->property ("action");
-
- if (!keys || !action) {
- error << _("misformed binding node - ignored") << endmsg;
- continue;
- }
-
- add_binding (keys->value(), action->value());
-
- }
-
- return 0;
-}
-
diff --git a/gtk2_ardour/keyboard_target.h b/gtk2_ardour/keyboard_target.h
deleted file mode 100644
index f542261b54..0000000000
--- a/gtk2_ardour/keyboard_target.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- Copyright (C) 2001 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
-
-#ifndef __ardour_keyboard_target_h__
-#define __ardour_keyboard_target_h__
-
-#include <map>
-#include <string>
-#include <sigc++/signal.h>
-#include <sigc++/slot.h>
-#include <gdk/gdk.h>
-#include <pbd/xml++.h>
-
-#include "keyboard.h"
-
-namespace Gtk {
- class Window;
-}
-
-class KeyboardTarget
-{
- public:
- KeyboardTarget(Gtk::Window& w, std::string name);
- virtual ~KeyboardTarget();
-
- sigc::signal<void> Hiding;
- sigc::signal<void> GoingAway;
-
- typedef sigc::slot<void> KeyAction;
-
- std::string name() const { return _name; }
-
- void key_press_event (GdkEventKey *, Keyboard::State&, bool& handled);
- void key_release_event (GdkEventKey *, Keyboard::State&);
-
- int add_binding (std::string keys, std::string name);
- std::string get_binding (std::string name); /* returns keys bound to name */
-
- XMLNode& get_binding_state () const;
- int set_binding_state (const XMLNode&);
-
- static int32_t add_action (std::string, KeyAction);
- static int32_t find_action (std::string, KeyAction&);
- static int32_t remove_action (std::string);
- static void show_all_actions();
-
- Gtk::Window& window() const { return _window; }
-
- protected:
- typedef std::map<Keyboard::State,KeyAction> KeyMap;
- typedef std::map<std::string,std::string> BindingMap;
-
- KeyMap keymap;
- BindingMap bindings;
-
- private:
- typedef map<std::string,KeyAction> ActionMap;
- static ActionMap actions;
- std::string _name;
- Gtk::Window& _window;
-
- int load_bindings (const XMLNode&);
-};
-
-#endif /* __ardour_keyboard_target_h__ */
-
diff --git a/gtk2_ardour/ladspa_pluginui.cc b/gtk2_ardour/ladspa_pluginui.cc
index 6aaea06a7e..1f7ba8d4c0 100644
--- a/gtk2_ardour/ladspa_pluginui.cc
+++ b/gtk2_ardour/ladspa_pluginui.cc
@@ -288,12 +288,14 @@ LadspaPluginUI::ControlUI::ControlUI ()
: automate_button (X_("")) // force creation of a label
{
automate_button.set_name ("PluginAutomateButton");
- ARDOUR_UI::instance()->tooltips().set_tip (automate_button,
- _("Automation control"));
+ ARDOUR_UI::instance()->tooltips().set_tip (automate_button, _("Automation control"));
- /* don't fix the height, it messes up the bar controllers */
+ /* XXX translators: use a string here that will be at least as long
+ as the longest automation label (see ::automation_state_changed()
+ below). be sure to include a descender.
+ */
- set_size_request_to_display_given_text (automate_button, X_("lngnuf"), 2, 2);
+ set_size_request_to_display_given_text (*automate_button.get_child(), _("Mgnual"), 5, 5);
ignore_change = 0;
display = 0;
@@ -323,7 +325,7 @@ LadspaPluginUI::automation_state_changed (ControlUI* cui)
switch (insert->get_port_automation_state (cui->port_index) & (Off|Play|Touch|Write)) {
case Off:
- cui->automate_button.set_label (_("Off"));
+ cui->automate_button.set_label (_("Manual"));
break;
case Play:
cui->automate_button.set_label (_("Play"));
@@ -373,6 +375,8 @@ LadspaPluginUI::build_control_ui (guint32 port_index, PBD::Controllable* mcontro
control_ui->set_spacing (5);
+ Gtk::Requisition req (control_ui->automate_button.size_request());
+
if (plugin->parameter_is_input (port_index)) {
boost::shared_ptr<LadspaPlugin> lp;
@@ -451,8 +455,7 @@ LadspaPluginUI::build_control_ui (guint32 port_index, PBD::Controllable* mcontro
sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &LadspaPluginUI::print_parameter), (uint32_t) port_index);
control_ui->control = new BarController (*control_ui->adjustment, *mcontrol, pslot);
- // should really match the height of the text in the automation button+label
- control_ui->control->set_size_request (200, 22);
+ control_ui->control->set_size_request (200, req.height);
control_ui->control->set_name (X_("PluginSlider"));
control_ui->control->set_style (BarController::LeftToRight);
control_ui->control->set_use_parent (true);
@@ -566,7 +569,7 @@ LadspaPluginUI::astate_clicked (ControlUI* cui, uint32_t port)
MenuList& items (automation_menu->items());
items.clear ();
- items.push_back (MenuElem (_("Off"),
+ items.push_back (MenuElem (_("Manual"),
bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Off, cui)));
items.push_back (MenuElem (_("Play"),
bind (mem_fun(*this, &LadspaPluginUI::set_automation_state), (AutoState) Play, cui)));
diff --git a/gtk2_ardour/location_ui.cc b/gtk2_ardour/location_ui.cc
index b77c3a5561..e13366fd12 100644
--- a/gtk2_ardour/location_ui.cc
+++ b/gtk2_ardour/location_ui.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
diff --git a/gtk2_ardour/location_ui.h b/gtk2_ardour/location_ui.h
index 580d47ff5d..51daa6814d 100644
--- a/gtk2_ardour/location_ui.h
+++ b/gtk2_ardour/location_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_location_ui_h__
@@ -32,7 +31,6 @@
#include <ardour/session.h>
#include "ardour_dialog.h"
-#include "keyboard_target.h"
namespace ARDOUR {
class LocationStack;
diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
index e7ede36b39..41a279f604 100644
--- a/gtk2_ardour/main.cc
+++ b/gtk2_ardour/main.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2001-2006 Paul Davis
+ Copyright (C) 2001-2007 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,16 +15,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-#include <cerrno>
#include <cstdlib>
-#include <signal.h>
-#include <unistd.h>
#include <sigc++/bind.h>
#include <gtkmm/settings.h>
@@ -64,172 +57,6 @@ extern int curvetest (string);
static ARDOUR_UI *ui = 0;
-static void
-shutdown (int status)
-{
- char* msg;
-
- if (status) {
-
- msg = _("ardour is killing itself for a clean exit\n");
- write (1, msg, strlen (msg));
- /* drastic, but perhaps necessary */
- kill (-getpgrp(), SIGKILL);
- /*NOTREACHED*/
-
- } else {
-
- if (ui) {
- ui->kill();
- }
-
- pthread_cancel_all ();
- }
-
- exit (status);
-}
-
-
-static void
-handler (int sig)
-{
- char buf[64];
- int n;
-
- /* XXX its doubtful that snprintf() is async-safe */
- n = snprintf (buf, sizeof(buf), _("%d(%d): received signal %d\n"), getpid(), (int) pthread_self(), sig);
- write (1, buf, n);
-
- shutdown (1);
-}
-
-static void *
-signal_thread (void *arg)
-{
- int sig;
- sigset_t blocked;
-
- PBD::ThreadCreated (pthread_self(), X_("Signal"));
-
- pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
-
- /* find out what's blocked right now */
-
- //sigprocmask (SIG_SETMASK, 0, &blocked);
- if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
- cerr << "getting blocked signals failed\n";
- }
-
- /* wait for any of the currently blocked signals.
-
- According to the man page found in linux 2.6 and 2.4, sigwait()
- never returns an error. This is incorrect. Checking the man
- pages for some other *nix systems makes it clear that
- sigwait() can return several error codes, one of which
- is EINTR. This happens if the thread receives a signal
- which is not in the blocked set.
-
- We do not expect that to happen, and if it did we should generally
- exit as planned. However, under 2.6, the ptrace facility used
- by gdb seems to also cause sigwait() to return with EINTR
- but with a signal that sigwait cannot understand. As a result,
- "sig" is set to zero, an impossible signal number.
-
- Handling the EINTR code makes it possible to debug
- ardour on a 2.6 kernel.
-
- */
-
- int swerr;
-
- again:
- if ((swerr = sigwait (&blocked, &sig))) {
- if (swerr == EINTR) {
- goto again;
- } else {
- cerr << "sigwait failed with " << swerr << endl;
- }
- }
-
- cerr << "Signal " << sig << " received\n";
-
- if (sig != SIGSEGV) {
-
- /* unblock signals so we can see them during shutdown.
- this will help prod developers not to lose sight
- of bugs that cause segfaults etc. during shutdown.
- */
-
- sigprocmask (SIG_UNBLOCK, &blocked, 0);
- }
-
- shutdown (1);
- /*NOTREACHED*/
- return 0;
-}
-
-int
-catch_signals (void)
-{
- struct sigaction action;
- pthread_t signal_thread_id;
- sigset_t signals;
-
-// if (setpgid (0,0)) {
- if (setsid ()) {
- warning << string_compose (_("cannot become new process group leader (%1)"),
- strerror (errno))
- << endmsg;
- }
-
- sigemptyset (&signals);
- sigaddset(&signals, SIGHUP);
- sigaddset(&signals, SIGINT);
- sigaddset(&signals, SIGQUIT);
- sigaddset(&signals, SIGPIPE);
- sigaddset(&signals, SIGTERM);
- sigaddset(&signals, SIGUSR1);
- sigaddset(&signals, SIGUSR2);
-
-
- /* install a handler because otherwise
- pthreads behaviour is undefined when we enter
- sigwait.
- */
-
- action.sa_handler = handler;
- action.sa_mask = signals;
- action.sa_flags = SA_RESTART|SA_RESETHAND;
-
- for (int i = 1; i < 32; i++) {
- if (sigismember (&signals, i)) {
- if (sigaction (i, &action, 0)) {
- cerr << string_compose (_("cannot setup signal handling for %1"), i) << endl;
- return -1;
- }
- }
- }
-
- /* this sets the signal mask for this and all
- subsequent threads that do not reset it.
- */
-
- if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
- cerr << string_compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
- return -1;
- }
-
- /* start a thread to wait for signals */
-
- if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
- cerr << "cannot create signal catching thread" << endl;
- return -1;
- }
-
- pthread_detach (signal_thread_id);
- return 0;
-}
-
string
which_ui_rcfile ()
{
@@ -300,7 +127,9 @@ maybe_load_session ()
if (!session_name.length()) {
ui->hide_splash ();
if (!Config->get_no_new_session_dialog()) {
- ui->new_session ();
+ if (!ui->new_session ()) {
+ return false;
+ }
}
return true;
@@ -341,7 +170,9 @@ maybe_load_session ()
/* Show the NSD */
ui->hide_splash ();
if (!Config->get_no_new_session_dialog()) {
- ui->new_session ();
+ if (!ui->new_session ()) {
+ return false;
+ }
}
}
@@ -406,7 +237,7 @@ int main (int argc, char *argv[])
}
if (no_splash) {
- cerr << _("Copyright (C) 1999-2006 Paul Davis") << endl
+ cerr << _("Copyright (C) 1999-2007 Paul Davis") << endl
<< _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
<< endl
<< _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
@@ -416,6 +247,10 @@ int main (int argc, char *argv[])
<< endl;
}
+ /* some GUI objects need this */
+
+ PBD::ID::init ();
+
try {
ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
} catch (failed_constructor& err) {
@@ -463,7 +298,14 @@ int main (int argc, char *argv[])
delete engine;
ARDOUR::cleanup ();
- shutdown (0);
+
+ if (ui) {
+ ui->kill();
+ }
+
+ pthread_cancel_all ();
+
+ exit (0);
return 0;
}
diff --git a/gtk2_ardour/marker.cc b/gtk2_ardour/marker.cc
index d5517b4bce..918a2786c9 100644
--- a/gtk2_ardour/marker.cc
+++ b/gtk2_ardour/marker.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <sigc++/bind.h>
diff --git a/gtk2_ardour/marker.h b/gtk2_ardour/marker.h
index e2e4307782..7865004d54 100644
--- a/gtk2_ardour/marker.h
+++ b/gtk2_ardour/marker.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_marker_h__
diff --git a/gtk2_ardour/marker_time_axis.cc b/gtk2_ardour/marker_time_axis.cc
index 1c6e7af2c7..e10967d01a 100644
--- a/gtk2_ardour/marker_time_axis.cc
+++ b/gtk2_ardour/marker_time_axis.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <string>
diff --git a/gtk2_ardour/marker_time_axis.h b/gtk2_ardour/marker_time_axis.h
index e321fe4003..13288ce66f 100644
--- a/gtk2_ardour/marker_time_axis.h
+++ b/gtk2_ardour/marker_time_axis.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_marker_time_axis_h__
diff --git a/gtk2_ardour/marker_time_axis_view.cc b/gtk2_ardour/marker_time_axis_view.cc
index b6e87f8715..f33e0bbefc 100644
--- a/gtk2_ardour/marker_time_axis_view.cc
+++ b/gtk2_ardour/marker_time_axis_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/gtk2_ardour/marker_time_axis_view.h b/gtk2_ardour/marker_time_axis_view.h
index 4853f29855..fd23c1de87 100644
--- a/gtk2_ardour/marker_time_axis_view.h
+++ b/gtk2_ardour/marker_time_axis_view.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_marker_time_axis_view_h__
diff --git a/gtk2_ardour/marker_view.cc b/gtk2_ardour/marker_view.cc
index f45a3ce971..d82554f891 100644
--- a/gtk2_ardour/marker_view.cc
+++ b/gtk2_ardour/marker_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <gtkmm.h>
diff --git a/gtk2_ardour/marker_view.h b/gtk2_ardour/marker_view.h
index 04b8587649..6c49a4dc0f 100644
--- a/gtk2_ardour/marker_view.h
+++ b/gtk2_ardour/marker_view.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_marker_view_h__
diff --git a/gtk2_ardour/meter_bridge.cc b/gtk2_ardour/meter_bridge.cc
deleted file mode 100644
index 0e88eff5e0..0000000000
--- a/gtk2_ardour/meter_bridge.cc
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- Copyright (C) 2002 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
-
-#include <ardour/session.h>
-#include <ardour/session_route.h>
-#include <ardour/audio_diskstream.h>
-#include <ardour/audio_track.h>
-
-#include "ardour_ui.h"
-#include "meter_bridge.h"
-#include "meter_bridge_strip.h"
-#include "utils.h"
-#include "gui_thread.h"
-
-#include "i18n.h"
-
-using namespace ARDOUR;
-using namespace PBD;
-using namespace Gtk;
-using namespace sigc;
-
-#define FRAME_SHADOW_STYLE Gtk::SHADOW_IN
-#define FRAME_NAME "BaseFrame"
-
-MeterBridge::MeterBridge ()
- : ArdourDialog ("meter bridge"),
- hadjustment (0.0, 0.0, 0.0),
- vadjustment (0.0, 0.0, 0.0),
- meter_viewport (hadjustment, vadjustment)
-{
- meter_base.set_name ("MeterBase");
- meter_frame.set_shadow_type (FRAME_SHADOW_STYLE);
- meter_frame.set_name (FRAME_NAME);
- meter_frame.add (meter_base);
-
- upper_metering_box.set_name ("AboveMeterZone");
- lower_metering_box.set_name ("BelowMeterZone");
-
- metering_vbox.set_spacing (5);
- metering_vbox.set_border_width (10);
- metering_vbox.pack_start (upper_metering_box, false, false);
- metering_vbox.pack_start (meter_frame, false, false);
- metering_vbox.pack_start (lower_metering_box, false, false);
-
- metering_hbox.pack_start (metering_vbox, false, false);
-
- meter_scroll_base.set_name ("MeterScrollBase");
- meter_scroll_base.add (metering_hbox);
-
- meter_viewport.add (meter_scroll_base);
- meter_viewport.set_shadow_type (Gtk::SHADOW_NONE);
-
- meter_scroller.add (meter_viewport);
- meter_scroller.set_name ("MeterBridgeWindow");
- meter_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
- meter_scroller.set_border_width (5);
-
- add (meter_scroller);
- add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
- set_name ("MeterBridgeWindow");
- set_title (_("ardour: meter bridge"));
- set_wmclass (X_("ardour_meter_bridge"), "Ardour");
- // set_policy (false, false, false); // no user resizing of any kind
-
- signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Gtk::Window*>(this)));
-
- metering = false;
-
- /* don't show: this window doesn't come up by default */
-}
-
-MeterBridge::~MeterBridge ()
-{
- stop_metering ();
-}
-
-void
-MeterBridge::set_session (Session *s)
-{
- ArdourDialog::set_session (s);
-
- if (session) {
- // XXX this stuff has to be fixed if we ever use this code again
- // (refs vs. ptrs)
- // session->foreach_route (this, &MeterBridge::add_route);
- session->RouteAdded.connect (mem_fun(*this, &MeterBridge::add_route));
- session->GoingAway.connect (mem_fun(*this, &MeterBridge::session_gone));
- start_metering ();
- }
-}
-
-void
-MeterBridge::session_gone ()
-{
- ENSURE_GUI_THREAD(mem_fun(*this, &MeterBridge::session_gone));
-
- stop_metering ();
- hide_all ();
-
- list<MeterBridgeStrip *>::iterator i;
-
- for (i = meters.begin(); i != meters.end(); ++i) {
-
- upper_metering_box.remove ((*i)->above_box());
- meter_base.remove ((*i)->meter_widget());
- lower_metering_box.remove ((*i)->below_box());
-
-// delete (*i);
- }
-
- meters.clear ();
-
- ArdourDialog::session_gone();
-}
-
-void
-MeterBridge::add_route (ARDOUR::Route* route)
-{
- ENSURE_GUI_THREAD(bind (mem_fun(*this, &MeterBridge::add_route), route));
-
- uint32_t n;
- char buf[32];
-
- if (!session || route->hidden() || dynamic_cast<AudioTrack*>(route) == 0) {
- return;
- }
-
- n = meters.size();
- snprintf (buf, sizeof (buf), "%u", n+1);
-
- MeterBridgeStrip *meter = new MeterBridgeStrip (session->engine(),
- *session,
- *route,
- buf,
- session->over_length_long,
- session->over_length_short,
- 200);
-
-#define packing_factor 30
-
- upper_metering_box.put (meter->above_box(), n * packing_factor, 0);
-
- meter_base.put (meter->meter_widget(), (n * packing_factor) + (meter->meter_width()/2), 0);
- lower_metering_box.put (meter->below_box(), n * packing_factor, 0);
-
- meter->above_box().show_all ();
- meter->meter_widget().show ();
- meter->below_box().show_all ();
-
- route->GoingAway.connect (bind (mem_fun(*this, &MeterBridge::remove_route), route));
- meters.insert (meters.begin(), meter);
-
- set_default_size (30 + ((n+1) * packing_factor), 315);
-
- meter->set_meter_on(true);
-
- session->GoingAway.connect (mem_fun(*this, &MeterBridge::session_gone));
-}
-
-void
-MeterBridge::remove_route (Route* route)
-{
- ENSURE_GUI_THREAD(bind (mem_fun(*this, &MeterBridge::remove_route), route));
- list<MeterBridgeStrip *>::iterator i;
-
- for (i = meters.begin(); i != meters.end(); ++i) {
- if (&((*i)->route()) == route) {
- delete *i;
- meters.erase (i);
- return;
- }
- }
-}
-
-void
-MeterBridge::clear_all_meters ()
-{
- list<MeterBridgeStrip *>::iterator i;
-
- for (i = meters.begin(); i != meters.end(); ++i) {
- (*i)->clear_meter ();
- }
-}
-
-void
-MeterBridge::update ()
-{
- list<MeterBridgeStrip *>::iterator i;
-
- for (i = meters.begin(); i != meters.end(); ++i) {
- (*i)->update ();
- }
-}
-
-void
-MeterBridge::start_metering ()
-{
- list<MeterBridgeStrip *>::iterator i;
-
- for (i = meters.begin(); i != meters.end(); ++i) {
- (*i)->set_meter_on (true);
- }
- metering_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
- (mem_fun(*this, &MeterBridge::update));
- metering = true;
-}
-
-void
-MeterBridge::stop_metering ()
-{
- list<MeterBridgeStrip *>::iterator i;
-
- for (i = meters.begin(); i != meters.end(); ++i) {
- (*i)->set_meter_on (false);
- }
- metering_connection.disconnect();
- metering = false;
-}
-
-void
-MeterBridge::toggle_metering ()
-{
- if (!metering) {
- start_metering ();
- } else {
- stop_metering ();
- }
-}
-
-void
-MeterBridge::on_map ()
-{
- start_metering ();
- return Window::on_map ();
-}
-
-void
-MeterBridge::on_unmap ()
-{
- stop_metering ();
- return Window::on_unmap ();
-}
-
diff --git a/gtk2_ardour/meter_bridge.h b/gtk2_ardour/meter_bridge.h
deleted file mode 100644
index 6ceb7402fc..0000000000
--- a/gtk2_ardour/meter_bridge.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- Copyright (C) 1999-2002 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
-
-#ifndef __ardour_meter_bridge_h__
-#define __ardour_meter_bridge_h__
-
-#include <list>
-
-#include <gtkmm/eventbox.h>
-#include <gtkmm/viewport.h>
-#include <gtkmm/scrolledwindow.h>
-#include <gtkmm/box.h>
-#include <gtkmm/fixed.h>
-#include <gtkmm/frame.h>
-
-#include "keyboard_target.h"
-#include "ardour_dialog.h"
-
-class MeterBridgeStrip;
-
-namespace ARDOUR {
- class Session;
- class Route;
-}
-
-class MeterBridge : public ArdourDialog
-{
-
- public:
- MeterBridge ();
- ~MeterBridge ();
-
- void set_session (ARDOUR::Session*);
- void clear_all_meters ();
- void start_metering ();
- void stop_metering ();
- void toggle_metering ();
-
- protected:
- void on_map ();
- void on_unmap ();
-
- private:
- /* diskstream/recorder display */
- Gtk::Adjustment hadjustment;
- Gtk::Adjustment vadjustment;
- Gtk::Viewport meter_viewport;
- Gtk::ScrolledWindow meter_scroller;
- Gtk::EventBox meter_scroll_base;
- Gtk::HBox meter_scroller_hpacker;
- Gtk::VBox meter_scroller_vpacker;
- Gtk::VBox metering_vpacker;
- Gtk::VBox metering_hpacker;
-
- Gtk::VBox metering_vbox;
- Gtk::HBox metering_hbox;
- Gtk::Fixed upper_metering_box;
- Gtk::Fixed lower_metering_box;
- Gtk::Fixed meter_base;
- Gtk::Frame meter_frame;
-
- list<MeterBridgeStrip*> meters;
-
- bool metering;
- sigc::connection metering_connection;
-
- void update ();
-
- void add_route (ARDOUR::Route*);
- void remove_route (ARDOUR::Route*);
- void session_gone(); /* overrides ArdourDialog::session_gone() */
-};
-
-#endif /* __ardour_meter_bridge_h__ (*/
diff --git a/gtk2_ardour/meter_bridge_strip.cc b/gtk2_ardour/meter_bridge_strip.cc
deleted file mode 100644
index 8a91603748..0000000000
--- a/gtk2_ardour/meter_bridge_strip.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- Copyright (C) 1999 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
-
-#include <cmath>
-#include <ctime>
-#include <sys/stat.h>
-
-#include <pbd/pathscanner.h>
-#include <pbd/fastlog.h>
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/selector.h>
-
-#include <ardour/audioengine.h>
-#include <ardour/route.h>
-#include <ardour/port.h>
-#include <ardour/utils.h>
-
-#include "meter_bridge_strip.h"
-#include "ardour_ui.h"
-#include "prompter.h"
-#include "logmeter.h"
-
-#include "i18n.h"
-
-using namespace ARDOUR;
-using namespace PBD;
-using namespace Gtk;
-using namespace Gtkmm2ext;
-
-MeterBridgeStrip::MeterBridgeStrip (AudioEngine &eng,
- Session& s,
- Route& r,
- string name,
- nframes_t long_over,
- nframes_t short_over,
- nframes_t meter_hold)
- : engine (eng),
- session (s),
- _route (r),
- meter (meter_hold, 5, FastMeter::Vertical)
-{
- char buf[64];
-
- label.set_text (name);
- label.set_name ("ChannelMeterLabel");
-
- label_ebox.set_name ("MeterBridgeWindow");
- label_ebox.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
- label_ebox.add (label);
-
- label_ebox.signal_button_release_event().connect (mem_fun(*this, &MeterBridgeStrip::label_button_press_release));
- ARDOUR_UI::instance()->tooltips().set_tip (label_ebox, _route.name());
-
- over_long_label.set_text ("0");
- over_long_label.set_name ("OverMeterLabel");
- over_long_button.add (over_long_label);
- over_long_button.set_name ("OverMeter");
- over_long_frame.add (over_long_button);
- over_long_frame.set_shadow_type (Gtk::SHADOW_IN);
- over_long_frame.set_name ("BaseFrame");
- over_long_hbox.pack_start (over_long_frame, false, false);
-
- snprintf(buf, sizeof(buf)-1, _("# of %u-sample overs"), long_over);
- ARDOUR_UI::instance()->tooltips().set_tip (over_long_button, buf);
-
- set_size_request_to_display_given_text (over_long_button, "88g", 2, 2);
-
- over_short_label.set_text ("0");
- over_short_label.set_name ("OverMeterLabel");
- over_short_button.add (over_short_label);
- over_short_button.set_name ("OverMeter");
- over_short_frame.add (over_short_button);
- over_short_frame.set_shadow_type (Gtk::SHADOW_IN);
- over_short_frame.set_name ("BaseFrame");
- over_short_hbox.pack_start (over_short_frame, false, false);
-
- snprintf(buf, sizeof(buf)-1, _("# of %u-sample overs"), short_over);
- ARDOUR_UI::instance()->tooltips().set_tip (over_short_button, buf);
-
- set_size_request_to_display_given_text (over_short_button, "88g", 2, 2);
- above_meter_vbox.set_spacing (5);
- below_meter_vbox.set_spacing (5);
-
- above_meter_vbox.pack_start (over_long_hbox, false, false);
- above_meter_vbox.pack_start (over_short_hbox, false, false);
-
- below_meter_vbox.pack_start (label_ebox);
-
- over_short_button.signal_button_release_event().connect (mem_fun(*this,&MeterBridgeStrip::gui_clear_overs));
- over_long_button.signal_button_release_event().connect (mem_fun(*this,&MeterBridgeStrip::gui_clear_overs));
-
- last_over_short = 0;
- last_over_long = 0;
-
- meter_clear_pending = false;
- over_clear_pending = false;
-
- meter_on = true;
-}
-
-void
-MeterBridgeStrip::update ()
-{
- string buf;
- Port *port;
- guint32 over_short = 0;
- guint32 over_long = 0;
-
- if ((port = _route.input (0)) == 0) {
- meter.set (0.0);
- return;
- } else {
- over_short = port->short_overs ();
- over_long = port->long_overs ();
- }
-
- if (meter_on) {
- float power = minus_infinity();
-
- if ((power = _route.peak_input_power (0)) != minus_infinity()) {
- meter.set (log_meter (power));
-
- if (over_short != last_over_short) {
- buf = string_compose("%1", over_short);
- over_short_label.set_text (buf);
- last_over_short = over_short;
- }
-
- if (over_long != last_over_long) {
- buf = string_compose("%1", over_long);
- over_long_label.set_text (buf);
- last_over_long = over_long;
- }
-
- } else {
- meter.set (0.0);
- }
-
- }
-
- if (meter_clear_pending) {
- meter_clear_pending = false;
- meter.clear ();
- }
-
- if (over_clear_pending) {
- over_clear_pending = false;
- port->reset_overs ();
- over_long_label.set_text ("0");
- over_short_label.set_text ("0");
- last_over_short = 0;
- last_over_long = 0;
- }
-}
-
-gint
-MeterBridgeStrip::gui_clear_overs (GdkEventButton *ev)
-{
- clear_overs ();
- return FALSE;
-}
-
-void
-MeterBridgeStrip::clear_meter ()
-
-{
- meter_clear_pending = true;
-}
-
-void
-MeterBridgeStrip::clear_overs ()
-
-{
- over_clear_pending = true;
-}
-
-void
-MeterBridgeStrip::set_meter_on (bool yn)
-{
- Port* port;
- meter_on = yn;
-
- if (!meter_on) {
- meter_clear_pending = true;
- over_clear_pending = true;
- }
-
- if (meter.is_visible()) {
- if ((port = _route.input (0)) != 0) {
- if (meter_on) {
- port->enable_metering ();
- } else {
- port->disable_metering ();
- }
- }
- }
-}
-
-gint
-MeterBridgeStrip::label_button_press_release (GdkEventButton *ev)
-{
- string name;
- ArdourPrompter prompter (true);
-
- prompter.set_prompt (_("New Name for Meter:"));
- prompter.set_initial_text (label.get_text());
- prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
- prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
- prompter.show_all();
-
- switch (prompter.run ()) {
- case Gtk::RESPONSE_ACCEPT:
-
- prompter.get_result (name);
-
- if (name.length()) {
- label.set_text(name);
- }
-
- default:
- break;
- }
-
- return FALSE;
-}
-
diff --git a/gtk2_ardour/meter_bridge_strip.h b/gtk2_ardour/meter_bridge_strip.h
deleted file mode 100644
index bdce16f17c..0000000000
--- a/gtk2_ardour/meter_bridge_strip.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- Copyright (C) 1999 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
-
-#ifndef __ardour_meterbridgestrip_h__
-#define __ardour_meterbridgestrip_h__
-
-#include <sigc++/signal.h>
-
-#include <gtkmm/box.h>
-#include <gtkmm/widget.h>
-#include <gtkmm/eventbox.h>
-#include <gtkmm/label.h>
-#include <gtkmm/frame.h>
-
-#include <gtkmm2ext/fastmeter.h>
-
-namespace ARDOUR {
- class AudioEngine;
- class Session;
- class Route;
-}
-
-namespace Gtkmm2ext {
- class Selector;
- struct SelectionResult;
-}
-
-class MeterBridgeStrip : public sigc::trackable
-
-{
- public:
- MeterBridgeStrip (ARDOUR::AudioEngine &,
- ARDOUR::Session&,
- ARDOUR::Route&,
- string label,
- nframes_t long_over,
- nframes_t short_over,
- nframes_t meter_hold);
-
- void update (); /* called by meter timeout handler from ARDOUR_UI */
-
- Gtk::Box &above_box() { return above_meter_vbox; }
- Gtk::Box &below_box() { return below_meter_vbox; }
- Gtk::Widget &meter_widget() { return meter; }
-
- guint32 meter_width() const { return 8; }
-
- void clear_meter ();
- void clear_overs ();
-
- void set_meter_on (bool yn);
- bool get_meter_on () const { return meter_on; }
-
- ARDOUR::Route& route() const { return _route; }
-
- private:
- ARDOUR::AudioEngine& engine;
- ARDOUR::Session& session;
- ARDOUR::Route& _route;
-
- Gtk::EventBox label_ebox;
- Gtk::Label label;
- bool meter_clear_pending;
- bool over_clear_pending;
-
- Gtkmm2ext::FastMeter meter;
- bool meter_on;
-
- Gtk::VBox above_meter_vbox;
- Gtk::VBox below_meter_vbox;
-
- Gtk::HBox over_long_hbox;
- Gtk::HBox over_long_vbox;
- Gtk::EventBox over_long_button;
- Gtk::Frame over_long_frame;
- Gtk::Label over_long_label;
-
- Gtk::HBox over_short_hbox;
- Gtk::HBox over_short_vbox;
- Gtk::EventBox over_short_button;
- Gtk::Frame over_short_frame;
- Gtk::Label over_short_label;
-
- guint32 last_over_short;
- guint32 last_over_long;
-
- gint gui_clear_overs (GdkEventButton *);
- gint label_button_press_release (GdkEventButton *);
-};
-
-#endif /* __ardour_meterbridgestrip_h__ */
-
-
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index edc66c92bb..bef8ee787f 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -17,6 +17,7 @@
*/
#include <cmath>
+#include <algorithm>
#include <sigc++/bind.h>
@@ -61,6 +62,7 @@ using namespace ARDOUR;
using namespace PBD;
using namespace Gtk;
using namespace Gtkmm2ext;
+using namespace std;
int MixerStrip::scrollbar_height = 0;
@@ -153,17 +155,10 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
/* XXX what is this meant to do? */
//meter_point_button.signal_button_release_event().connect (mem_fun (gpm, &GainMeter::meter_release), false);
- solo_button->set_name ("MixerSoloButton");
- mute_button->set_name ("MixerMuteButton");
-
hide_button.set_events (hide_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
- width_button.unset_flags (Gtk::CAN_FOCUS);
- hide_button.unset_flags (Gtk::CAN_FOCUS);
- input_button.unset_flags (Gtk::CAN_FOCUS);
- output_button.unset_flags (Gtk::CAN_FOCUS);
- solo_button->unset_flags (Gtk::CAN_FOCUS);
- mute_button->unset_flags (Gtk::CAN_FOCUS);
+ mute_button->set_name ("MixerMuteButton");
+ solo_button->set_name ("MixerSoloButton");
button_table.set_homogeneous (true);
button_table.set_spacings (0);
@@ -182,9 +177,10 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
if (is_audio_track()) {
+ rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press), false);
+ rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release));
+
rec_enable_button->set_name ("MixerRecordEnableButton");
- rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
- rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
AudioTrack* at = audio_track();
@@ -266,8 +262,7 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
if (scrollbar_height == 0) {
HScrollbar scrollbar;
- Gtk::Requisition requisition;
- scrollbar.size_request (requisition);
+ Gtk::Requisition requisition(scrollbar.size_request ());
scrollbar_height = requisition.height;
}
@@ -395,8 +390,7 @@ MixerStrip::set_stuff_from_route ()
} else {
_marked_for_display = true;
}
- }
- else {
+ } else {
/* backwards compatibility */
_marked_for_display = true;
}
@@ -418,56 +412,56 @@ MixerStrip::set_width (Width w)
ensure_xml_node ();
_width = w;
-
+
switch (w) {
case Wide:
set_size_request (-1, -1);
xml_node->add_property ("strip_width", "wide");
-
- if (rec_enable_button) {
- rec_enable_button->set_label (_("record"));
+
+ if (rec_enable_button) {
+ ((Gtk::Label*)rec_enable_button->get_child())->set_text (_("record"));
}
- mute_button->set_label (_("Mute"));
- solo_button->set_label (_("Solo"));
+ ((Gtk::Label*)mute_button->get_child())->set_text (_("Mute"));
+ ((Gtk::Label*)solo_button->get_child())->set_text (_("Solo"));
if (_route->comment() == "") {
comment_button.unset_bg (STATE_NORMAL);
- comment_button.set_label (_("comments"));
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("comments"));
} else {
comment_button.modify_bg (STATE_NORMAL, color());
- comment_button.set_label (_("*comments*"));
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("*comments*"));
}
- gpm.gain_automation_style_button.set_label (gpm.astyle_string(_route->gain_automation_curve().automation_style()));
- gpm.gain_automation_state_button.set_label (gpm.astate_string(_route->gain_automation_curve().automation_state()));
- panners.pan_automation_style_button.set_label (panners.astyle_string(_route->panner().automation_style()));
- panners.pan_automation_state_button.set_label (panners.astate_string(_route->panner().automation_state()));
+ ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.astyle_string(_route->gain_automation_curve().automation_style()));
+ ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.astate_string(_route->gain_automation_curve().automation_state()));
+ ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (panners.astyle_string(_route->panner().automation_style()));
+ ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (panners.astate_string(_route->panner().automation_state()));
Gtkmm2ext::set_size_request_to_display_given_text (name_button, "long", 2, 2);
break;
case Narrow:
- set_size_request (50, -1);
xml_node->add_property ("strip_width", "narrow");
if (rec_enable_button) {
- rec_enable_button->set_label (_("Rec"));
+ ((Gtk::Label*)rec_enable_button->get_child())->set_text (_("Rec"));
}
- mute_button->set_label (_("M"));
- solo_button->set_label (_("S"));
+ ((Gtk::Label*)mute_button->get_child())->set_text (_("M"));
+ ((Gtk::Label*)solo_button->get_child())->set_text (_("S"));
if (_route->comment() == "") {
comment_button.unset_bg (STATE_NORMAL);
- comment_button.set_label (_("Cmt"));
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("Cmt"));
} else {
comment_button.modify_bg (STATE_NORMAL, color());
- comment_button.set_label (_("*Cmt*"));
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("*Cmt*"));
}
- gpm.gain_automation_style_button.set_label (gpm.short_astyle_string(_route->gain_automation_curve().automation_style()));
- gpm.gain_automation_state_button.set_label (gpm.short_astate_string(_route->gain_automation_curve().automation_state()));
- panners.pan_automation_style_button.set_label (panners.short_astyle_string(_route->panner().automation_style()));
- panners.pan_automation_state_button.set_label (panners.short_astate_string(_route->panner().automation_state()));
+ ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.short_astyle_string(_route->gain_automation_curve().automation_style()));
+ ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.short_astate_string(_route->gain_automation_curve().automation_state()));
+ ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (panners.short_astyle_string(_route->panner().automation_style()));
+ ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (panners.short_astate_string(_route->panner().automation_state()));
Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2);
+ set_size_request (max (50, gpm.get_gm_width()), -1);
break;
}
@@ -788,20 +782,20 @@ MixerStrip::comment_editor_done_editing() {
case Wide:
if (! str.empty()) {
comment_button.modify_bg (STATE_NORMAL, color());
- comment_button.set_label (_("*Comments*"));
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("*Comments*"));
} else {
comment_button.unset_bg (STATE_NORMAL);
- comment_button.set_label (_("Comments"));
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("Comments"));
}
break;
case Narrow:
if (! str.empty()) {
comment_button.modify_bg (STATE_NORMAL, color());
- comment_button.set_label (_("*Cmt*"));
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("*Cmt*"));
} else {
comment_button.unset_bg (STATE_NORMAL);
- comment_button.set_label (_("Cmt"));
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("Cmt"));
}
break;
}
diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h
index 430f774eb6..ea2569b644 100644
--- a/gtk2_ardour/mixer_strip.h
+++ b/gtk2_ardour/mixer_strip.h
@@ -241,9 +241,6 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
bool ignore_speed_adjustment;
- string solo_button_name () const { return "MixerSoloButton"; }
- string safe_solo_button_name () const { return "MixerSafeSoloButton"; }
-
void engine_running();
void engine_stopped();
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
index f20171f9fb..d1089e48e6 100644
--- a/gtk2_ardour/mixer_ui.cc
+++ b/gtk2_ardour/mixer_ui.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -30,13 +29,13 @@
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/stop_signal.h>
-#include <ardour/audioengine.h>
#include <ardour/session.h>
#include <ardour/audio_track.h>
#include <ardour/session_route.h>
#include <ardour/audio_diskstream.h>
#include <ardour/plugin_manager.h>
+#include "keyboard.h"
#include "mixer_ui.h"
#include "mixer_strip.h"
#include "plugin_selector.h"
@@ -58,9 +57,8 @@ using namespace std;
using PBD::atoi;
-Mixer_UI::Mixer_UI (AudioEngine& eng)
- : Window (Gtk::WINDOW_TOPLEVEL),
- engine (eng)
+Mixer_UI::Mixer_UI ()
+ : Window (Gtk::WINDOW_TOPLEVEL)
{
_strip_width = Wide;
track_menu = 0;
@@ -279,7 +277,7 @@ Mixer_UI::add_strip (Session::RouteList& routes)
TreeModel::Row row = *(track_model->append());
row[track_columns.text] = route->name();
- row[track_columns.visible] = true;
+ row[track_columns.visible] = strip->marked_for_display();
row[track_columns.route] = route;
row[track_columns.strip] = strip;
@@ -383,6 +381,7 @@ Mixer_UI::disconnect_from_session ()
ENSURE_GUI_THREAD(mem_fun(*this, &Mixer_UI::disconnect_from_session));
group_model->clear ();
+ _selection.clear ();
set_title (_("ardour: mixer"));
stop_updating ();
}
@@ -554,12 +553,14 @@ Mixer_UI::hide_all_audiotracks ()
void
Mixer_UI::track_list_change (const Gtk::TreeModel::Path& path,const Gtk::TreeModel::iterator& iter)
{
+ session->set_remote_control_ids();
redisplay_track_list ();
}
void
Mixer_UI::track_list_delete (const Gtk::TreeModel::Path& path)
{
+ session->set_remote_control_ids();
redisplay_track_list ();
}
@@ -612,8 +613,10 @@ Mixer_UI::redisplay_track_list ()
if (strip->route()->master() || strip->route()->control()) {
/* do nothing, these cannot be hidden */
} else {
- strip_packer.remove (*strip);
- strip->set_packed (false);
+ if (strip->packed()) {
+ strip_packer.remove (*strip);
+ strip->set_packed (false);
+ }
}
}
}
@@ -892,6 +895,16 @@ Mixer_UI::group_flags_changed (void* src, RouteGroup* group)
}
ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::group_flags_changed), src, group));
+
+ /* force an update of any mixer strips that are using this group,
+ otherwise mix group names don't change in mixer strips
+ */
+
+ for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
+ if ((*i)->mix_group() == group) {
+ (*i)->mix_group_changed(0);
+ }
+ }
TreeModel::iterator i;
TreeModel::Children rows = group_model->children();
@@ -1003,7 +1016,7 @@ Mixer_UI::strip_scroller_button_release (GdkEventButton* ev)
using namespace Menu_Helpers;
if (Keyboard::is_context_menu_event (ev)) {
- ARDOUR_UI::instance()->add_route();
+ ARDOUR_UI::instance()->add_route (this);
return true;
}
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
index 2a5b416ae0..bf9c9cbd18 100644
--- a/gtk2_ardour/mixer_ui.h
+++ b/gtk2_ardour/mixer_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_mixer_ui_h__
@@ -38,7 +37,6 @@
#include <ardour/ardour.h>
#include <ardour/io.h>
-#include "keyboard_target.h"
#include "route_redirect_selection.h"
#include "enums.h"
@@ -47,7 +45,6 @@ namespace ARDOUR {
class RouteGroup;
class Session;
class AudioDiskstream;
- class AudioEngine;
};
class MixerStrip;
@@ -56,7 +53,7 @@ class PluginSelector;
class Mixer_UI : public Gtk::Window
{
public:
- Mixer_UI (ARDOUR::AudioEngine&);
+ Mixer_UI ();
~Mixer_UI();
void connect_to_session (ARDOUR::Session *);
@@ -82,7 +79,6 @@ class Mixer_UI : public Gtk::Window
RouteRedirectSelection& selection() { return _selection; }
private:
- ARDOUR::AudioEngine& engine;
ARDOUR::Session *session;
bool _visible;
diff --git a/gtk2_ardour/new_session_dialog.cc b/gtk2_ardour/new_session_dialog.cc
index 9e094c9ad0..4875ff835a 100644
--- a/gtk2_ardour/new_session_dialog.cc
+++ b/gtk2_ardour/new_session_dialog.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include "i18n.h"
diff --git a/gtk2_ardour/new_session_dialog.h b/gtk2_ardour/new_session_dialog.h
index e0f488dc80..0d4124f8cc 100644
--- a/gtk2_ardour/new_session_dialog.h
+++ b/gtk2_ardour/new_session_dialog.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
// -*- c++ -*-
diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc
index 1c76f8079b..5dd9727193 100644
--- a/gtk2_ardour/option_editor.cc
+++ b/gtk2_ardour/option_editor.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <pbd/whitespace.h>
@@ -24,13 +23,14 @@
#include <ardour/audioengine.h>
#include <ardour/configuration.h>
#include <ardour/auditioner.h>
-#include <ardour/destructive_filesource.h>
+#include <ardour/sndfilesource.h>
#include <ardour/crossfade.h>
#include <midi++/manager.h>
#include <gtkmm2ext/stop_signal.h>
#include <gtkmm2ext/utils.h>
#include "public_editor.h"
+#include "keyboard.h"
#include "mixer_ui.h"
#include "ardour_ui.h"
#include "io_selector.h"
@@ -74,6 +74,9 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
/* MIDI */
+ mmc_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
+ mmc_device_id_spinner (mmc_device_id_adjustment),
+
/* Click */
click_table (2, 3),
@@ -367,23 +370,28 @@ OptionEditor::setup_midi_options ()
ToggleButton* tb;
RadioButton* rb;
- Gtk::Table* table = manage (new Table (ports.size() + 4, 9));
+ Gtk::Table* table = manage (new Table (ports.size() + 4, 10));
table->set_row_spacings (6);
table->set_col_spacings (10);
- table->attach (*(manage (new Label (X_("Port")))), 0, 1, 0, 1);
- table->attach (*(manage (new Label (X_("Offline")))), 1, 2, 0, 1);
- table->attach (*(manage (new Label (X_("Trace\nInput")))), 2, 3, 0, 1);
- table->attach (*(manage (new Label (X_("Trace\nOutput")))), 3, 4, 0, 1);
- table->attach (*(manage (new Label (X_("MTC")))), 4, 5, 0, 1);
- table->attach (*(manage (new Label (X_("MMC")))), 6, 7, 0, 1);
- table->attach (*(manage (new Label (X_("MIDI Parameter\nControl")))), 8, 9, 0, 1);
+ table->attach (*(manage (new Label (_("Port")))), 0, 1, 0, 1);
+ table->attach (*(manage (new Label (_("Offline")))), 1, 2, 0, 1);
+ table->attach (*(manage (new Label (_("Trace\nInput")))), 2, 3, 0, 1);
+ table->attach (*(manage (new Label (_("Trace\nOutput")))), 3, 4, 0, 1);
+ table->attach (*(manage (new Label (_("MTC")))), 4, 5, 0, 1);
+ table->attach (*(manage (new Label (_("MMC")))), 6, 7, 0, 1);
+ table->attach (*(manage (new Label (_("MIDI Parameter\nControl")))), 8, 9, 0, 1);
table->attach (*(manage (new HSeparator())), 0, 9, 1, 2);
table->attach (*(manage (new VSeparator())), 5, 6, 0, 8);
table->attach (*(manage (new VSeparator())), 7, 8, 0, 8);
+ table->attach (*(manage (new Label (_("MMC Device ID")))), 9, 10, 0, 1);
+ table->attach (mmc_device_id_spinner, 9, 10, 1, 2);
+
+ mmc_device_id_adjustment.signal_value_changed().connect (mem_fun (*this, &OptionEditor::mmc_device_id_adjusted));
+
for (n = 0, i = ports.begin(); i != ports.end(); ++n, ++i) {
pair<MIDI::Port*,vector<RadioButton*> > newpair;
@@ -483,7 +491,6 @@ OptionEditor::mtc_port_chosen (MIDI::Port *port, Gtk::RadioButton* rb)
{
if (session) {
if (rb->get_active()) {
- cerr << "Activating MTC port " << port->name() << endl;
if (port) {
session->set_mtc_port (port->name());
Config->set_mtc_port_name (port->name());
@@ -500,7 +507,6 @@ OptionEditor::mmc_port_chosen (MIDI::Port* port, Gtk::RadioButton* rb)
{
if (session) {
if (rb->get_active()) {
- cerr << "Activating MMC port " << port->name() << endl;
if (port) {
session->set_mmc_port (port->name());
Config->set_mtc_port_name (port->name());
@@ -517,7 +523,6 @@ OptionEditor::midi_port_chosen (MIDI::Port* port, Gtk::RadioButton* rb)
{
if (session) {
if (rb->get_active()) {
- cerr << "Activating MIDI port " << port->name() << endl;
if (port) {
session->set_midi_port (port->name());
Config->set_midi_port_name (port->name());
@@ -556,12 +561,22 @@ OptionEditor::map_port_online (MIDI::Port* port, ToggleButton* tb)
}
void
+OptionEditor::mmc_device_id_adjusted ()
+{
+ uint8_t id = (uint8_t) mmc_device_id_spinner.get_value();
+
+ if (id != Config->get_mmc_device_id()) {
+ Config->set_mmc_device_id (id);
+ }
+}
+
+void
OptionEditor::port_trace_in_toggled (MIDI::Port* port, ToggleButton* tb)
{
bool trace = tb->get_active();
if (port->input()->tracing() != trace) {
- port->output()->trace (trace, &cerr, string (port->name()) + string (" input: "));
+ port->input()->trace (trace, &cerr, string (port->name()) + string (" input: "));
}
}
diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h
index cc28a74e60..7754b0555d 100644
--- a/gtk2_ardour/option_editor.h
+++ b/gtk2_ardour/option_editor.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_option_editor_h__
@@ -111,6 +110,9 @@ class OptionEditor : public Gtk::Dialog
Gtk::RadioButton::Group mmc_button_group;
Gtk::RadioButton::Group midi_button_group;
+ Gtk::Adjustment mmc_device_id_adjustment;
+ Gtk::SpinButton mmc_device_id_spinner;
+
void port_online_toggled (MIDI::Port*,Gtk::ToggleButton*);
void port_trace_in_toggled (MIDI::Port*,Gtk::ToggleButton*);
void port_trace_out_toggled (MIDI::Port*,Gtk::ToggleButton*);
@@ -119,6 +121,8 @@ class OptionEditor : public Gtk::Dialog
void mtc_port_chosen (MIDI::Port*,Gtk::RadioButton*);
void midi_port_chosen (MIDI::Port*,Gtk::RadioButton*);
+ void mmc_device_id_adjusted ();
+
void map_port_online (MIDI::Port*, Gtk::ToggleButton*);
void setup_midi_options();
diff --git a/gtk2_ardour/opts.cc b/gtk2_ardour/opts.cc
index 792fde3a10..608f684fc9 100644
--- a/gtk2_ardour/opts.cc
+++ b/gtk2_ardour/opts.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <getopt.h>
@@ -52,6 +51,7 @@ print_help (const char *execname)
<< _(" -c, --name name Use a specific jack client name, default is ardour\n")
<< _(" -N, --new session-name Create a new session from the command line\n")
<< _(" -O, --no-hw-optimizations Disable h/w specific optimizations\n")
+ << _(" -S, --sync Draw the gui synchronously \n")
#ifdef VST_SUPPORT
<< _(" -V, --novst Do not use VST support\n")
#endif
@@ -67,7 +67,7 @@ int
GTK_ARDOUR::parse_opts (int argc, char *argv[])
{
- const char *optstring = "U:hbvVnOc:C:N:k:";
+ const char *optstring = "U:hSbvVnOc:C:N:k:";
const char *execname = strrchr (argv[0], '/');
if (execname == 0) {
@@ -85,6 +85,7 @@ GTK_ARDOUR::parse_opts (int argc, char *argv[])
{ "novst", 0, 0, 'V' },
{ "new", 1, 0, 'N' },
{ "no-hw-optimizations", 0, 0, 'O' },
+ { "sync", 0, 0, 'O' },
{ "curvetest", 1, 0, 'C' },
{ 0, 0, 0, 0 }
};
@@ -118,6 +119,10 @@ GTK_ARDOUR::parse_opts (int argc, char *argv[])
case 'n':
no_splash = false;
break;
+
+ case 'S':
+ // ; just pass this through to gtk it will figure it out
+ break;
case 'N':
new_session = true;
diff --git a/gtk2_ardour/opts.h b/gtk2_ardour/opts.h
index 710621ac65..fb780fc8aa 100644
--- a/gtk2_ardour/opts.h
+++ b/gtk2_ardour/opts.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_opts_h__
diff --git a/gtk2_ardour/pan_automation_time_axis.cc b/gtk2_ardour/pan_automation_time_axis.cc
index c484673c99..c008a10ff0 100644
--- a/gtk2_ardour/pan_automation_time_axis.cc
+++ b/gtk2_ardour/pan_automation_time_axis.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/curve.h>
diff --git a/gtk2_ardour/panner.cc b/gtk2_ardour/panner.cc
index bb9b432184..d54d6b89ac 100644
--- a/gtk2_ardour/panner.cc
+++ b/gtk2_ardour/panner.cc
@@ -55,23 +55,23 @@ PannerBar::expose (GdkEventExpose* ev)
points[0].x = (darea.get_width()/2 - triangle_size);
points[0].y = 0;
- points[1].x = (darea.get_width()/2 + triangle_size) - 1;
+ points[1].x = (darea.get_width()/2 + triangle_size);
points[1].y = 0;
- points[2].x = darea.get_width()/2 - 1;
+ points[2].x = darea.get_width()/2;
points[2].y = triangle_size - 1;
gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3);
// right
- points[0].x = (darea.get_width() - triangle_size) - 1;
+ points[0].x = (darea.get_width() - triangle_size);
points[0].y = 0;
- points[1].x = darea.get_width() - 1;
+ points[1].x = darea.get_width();
points[1].y = 0;
- points[2].x = darea.get_width() - 1;
+ points[2].x = darea.get_width();
points[2].y = triangle_size;
gdk_draw_polygon (win->gobj(), gc->gobj(), true, points, 3);
diff --git a/gtk2_ardour/panner2d.cc b/gtk2_ardour/panner2d.cc
index 1e6e4c16c9..34f367b25b 100644
--- a/gtk2_ardour/panner2d.cc
+++ b/gtk2_ardour/panner2d.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -58,8 +57,8 @@ Panner2d::Target::~Target ()
}
}
-Panner2d::Panner2d (Panner& p, int32_t w, int32_t h)
- : panner (p), width (w), height (h)
+Panner2d::Panner2d (Panner& p, int32_t h)
+ : panner (p), width (0), height (h)
{
context_menu = 0;
bypass_menu_item = 0;
diff --git a/gtk2_ardour/panner2d.h b/gtk2_ardour/panner2d.h
index 1bf8879ba5..fb4929ad2d 100644
--- a/gtk2_ardour/panner2d.h
+++ b/gtk2_ardour/panner2d.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_panner_2d_h__
@@ -47,7 +46,7 @@ namespace Pango {
class Panner2d : public Gtk::DrawingArea
{
public:
- Panner2d (ARDOUR::Panner&, int32_t width, int32_t height);
+ Panner2d (ARDOUR::Panner&, int32_t height);
~Panner2d ();
int puck_position (int which_puck, float& x, float& y);
diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc
index af5379b40f..8f9a1b1394 100644
--- a/gtk2_ardour/panner_ui.cc
+++ b/gtk2_ardour/panner_ui.cc
@@ -73,8 +73,7 @@ PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
//set_size_request_to_display_given_text (pan_automation_style_button, X_("0"), 2, 2);
pan_bar_packer.set_size_request (-1, 61);
- panning_viewport.set_size_request (64, 61);
-
+ panning_viewport.set_size_request (-1, 61);
panning_viewport.set_name (X_("BaseFrame"));
ARDOUR_UI::instance()->tooltips().set_tip (panning_link_button,
@@ -86,7 +85,7 @@ PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
pan_automation_state_button.unset_flags (Gtk::CAN_FOCUS);
using namespace Menu_Helpers;
- pan_astate_menu.items().push_back (MenuElem (_("Off"),
+ pan_astate_menu.items().push_back (MenuElem (_("Manual"),
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Off)));
pan_astate_menu.items().push_back (MenuElem (_("Play"),
bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Play)));
@@ -137,7 +136,7 @@ PannerUI::PannerUI (boost::shared_ptr<IO> io, Session& s)
pan_vbox.pack_start (panning_viewport, Gtk::PACK_SHRINK);
pan_vbox.pack_start (panning_link_box, Gtk::PACK_SHRINK);
- pack_start (pan_vbox, true, false);
+ pack_start (pan_vbox, true, true);
panner = 0;
@@ -215,23 +214,9 @@ PannerUI::set_width (Width w)
{
switch (w) {
case Wide:
- panning_viewport.set_size_request (64, 61);
- if (panner) {
- panner->set_size_request (63, 61);
- }
- for (vector<PannerBar*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
- (*i)->set_size_request (63, pan_bar_height);
- }
panning_link_button.set_label (_("link"));
break;
case Narrow:
- panning_viewport.set_size_request (34, 61);
- if (panner) {
- panner->set_size_request (33, 61);
- }
- for (vector<PannerBar*>::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) {
- (*i)->set_size_request (33, pan_bar_height);
- }
panning_link_button.set_label (_("L"));
break;
}
@@ -289,6 +274,13 @@ PannerUI::setup_pan ()
pan_adjustments.pop_back ();
}
+ /* stick something into the panning viewport so that it redraws */
+
+ EventBox* eb = manage (new EventBox());
+ panning_viewport.remove ();
+ panning_viewport.add (*eb);
+ panning_viewport.show_all ();
+
} else if (nouts == 2) {
vector<Adjustment*>::size_type asz;
@@ -344,16 +336,9 @@ PannerUI::setup_pan ()
bc->event_widget().signal_button_release_event().connect
(bind (mem_fun(*this, &PannerUI::pan_button_event), (uint32_t) asz));
- pan_bars.push_back (bc);
- switch (_width) {
- case Wide:
- bc->set_size_request (63, pan_bar_height);
- break;
- case Narrow:
- bc->set_size_request (33, pan_bar_height);
- break;
- }
+ bc->set_size_request (-1, pan_bar_height);
+ pan_bars.push_back (bc);
pan_bar_packer.pack_start (*bc, false, false);
}
@@ -370,26 +355,15 @@ PannerUI::setup_pan ()
} else {
- int w = 0;
-
- switch (_width) {
- case Wide:
- w = 63;
- break;
- case Narrow:
- w = 33;
- break;
- }
-
if (panner == 0) {
- panner = new Panner2d (_io->panner(), w, 61);
+ panner = new Panner2d (_io->panner(), 61);
panner->set_name ("MixerPanZone");
panner->show ();
}
update_pan_sensitive ();
panner->reset (_io->n_inputs().get(ARDOUR::DataType::AUDIO));
- panner->set_size_request (w, 61);
+ panner->set_size_request (-1, 61);
/* and finally, add it to the panner frame */
@@ -771,7 +745,7 @@ PannerUI::_astate_string (AutoState state, bool shrt)
switch (state) {
case Off:
- sstr = (shrt ? "O" : _("O"));
+ sstr = (shrt ? "M" : _("M"));
break;
case Play:
sstr = (shrt ? "P" : _("P"));
diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h
index 79a8085488..d587359ecd 100644
--- a/gtk2_ardour/panner_ui.h
+++ b/gtk2_ardour/panner_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_panner_ui_h__
diff --git a/gtk2_ardour/playlist_selector.cc b/gtk2_ardour/playlist_selector.cc
index ddb771bb18..0ee99d1413 100644
--- a/gtk2_ardour/playlist_selector.cc
+++ b/gtk2_ardour/playlist_selector.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc
index 8a52e8587f..1283837e0c 100644
--- a/gtk2_ardour/plugin_selector.cc
+++ b/gtk2_ardour/plugin_selector.cc
@@ -471,11 +471,11 @@ PluginSelector::ladspa_display_selection_changed()
void
PluginSelector::added_list_selection_changed()
{
- if (added_list.get_selection()->count_selected_rows() != 0) {
- btn_remove->set_sensitive (true);
- } else {
- btn_remove->set_sensitive (false);
- }
+ if (added_list.get_selection()->count_selected_rows() != 0) {
+ btn_remove->set_sensitive (true);
+ } else {
+ btn_remove->set_sensitive (false);
+ }
}
int
diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc
index 26f38250a5..90d19d81b6 100644
--- a/gtk2_ardour/plugin_ui.cc
+++ b/gtk2_ardour/plugin_ui.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <climits>
@@ -96,13 +95,14 @@ PluginUIWindow::PluginUIWindow (boost::shared_ptr<PluginInsert> insert, bool scr
_pluginui = pu;
get_vbox()->add (*pu);
+ set_wmclass (X_("ardour_plugin_editor"), "Ardour");
+
signal_map_event().connect (mem_fun (*pu, &LadspaPluginUI::start_updating));
signal_unmap_event().connect (mem_fun (*pu, &LadspaPluginUI::stop_updating));
}
set_position (Gtk::WIN_POS_MOUSE);
set_name ("PluginEditor");
- set_wmclass (X_("ardour_plugin_editor"), "Ardour");
add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), reinterpret_cast<Window*> (this)));
diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h
index c1d538b3d1..2f15356c61 100644
--- a/gtk2_ardour/plugin_ui.h
+++ b/gtk2_ardour/plugin_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_plugin_ui_h__
diff --git a/gtk2_ardour/po/ru_RU.po b/gtk2_ardour/po/ru_RU.po
index 7a11f8bb1d..e5db030c2d 100644
--- a/gtk2_ardour/po/ru_RU.po
+++ b/gtk2_ardour/po/ru_RU.po
@@ -3,118 +3,148 @@
# This file is distributed under the same license as the gtk-ardour package.
#
# Igor Blinov pitstop@nm.ru, 2004.
-# Alexandre Prokoudine <alexandre.prokoudine@gmail.com>, 2006.
+# Alexandre Prokoudine <alexandre.prokoudine@gmail.com>, 2006, 2007.
msgid ""
msgstr ""
"Project-Id-Version: ru_RU\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-09-21 04:11+0400\n"
-"PO-Revision-Date: 2006-09-21 07:53+0400\n"
+"POT-Creation-Date: 2007-01-05 08:01+0300\n"
+"PO-Revision-Date: 2007-01-11 06:31+0300\n"
"Last-Translator: Alexandre Prokoudine <alexandre.prokoudine@gmail.com>\n"
-"Language-Team: Russian <ru@li.org>\n"
+"Language-Team: Russian <gnome-cyr@lists.gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
-#: gtk2_ardour/about.cc:120
+#: gtk2_ardour/about.cc:121
msgid "Paul Davis"
msgstr "Paul Davis"
-#: gtk2_ardour/about.cc:121
+#: gtk2_ardour/about.cc:122
msgid "Jesse Chappell"
msgstr "Jesse Chappell"
-#: gtk2_ardour/about.cc:122
+#: gtk2_ardour/about.cc:123
msgid "Taybin Rutkin"
msgstr "Taybin Rutkin"
-#: gtk2_ardour/about.cc:123
+#: gtk2_ardour/about.cc:124
msgid "Marcus Andersson"
msgstr "Marcus Andersson"
-#: gtk2_ardour/about.cc:124
+#: gtk2_ardour/about.cc:125
msgid "Jeremy Hall"
msgstr "Jeremy Hall"
-#: gtk2_ardour/about.cc:125
+#: gtk2_ardour/about.cc:126
msgid "Steve Harris"
msgstr "Steve Harris"
-#: gtk2_ardour/about.cc:126
+#: gtk2_ardour/about.cc:127
msgid "Tim Mayberry"
msgstr "Tim Mayberry"
-#: gtk2_ardour/about.cc:127
+#: gtk2_ardour/about.cc:128
msgid "Mark Stewart"
msgstr "Mark Stewart"
-#: gtk2_ardour/about.cc:128
+#: gtk2_ardour/about.cc:129
msgid "Sam Chessman"
msgstr "Sam Chessman"
-#: gtk2_ardour/about.cc:129
+#: gtk2_ardour/about.cc:130
msgid "Jack O'Quin"
msgstr "Jack O'Quin"
-#: gtk2_ardour/about.cc:130
+#: gtk2_ardour/about.cc:131
msgid "Matt Krai"
msgstr "Matt Krai"
-#: gtk2_ardour/about.cc:131
+#: gtk2_ardour/about.cc:132
msgid "Ben Bell"
msgstr "Ben Bell"
-#: gtk2_ardour/about.cc:132
+#: gtk2_ardour/about.cc:133
msgid "Gerard van Dongen"
msgstr "Gerard van Dongen"
-#: gtk2_ardour/about.cc:133
+#: gtk2_ardour/about.cc:134
msgid "Thomas Charbonnel"
msgstr "Thomas Charbonnel"
-#: gtk2_ardour/about.cc:134
+#: gtk2_ardour/about.cc:135
msgid "Nick Mainsbridge"
msgstr "Nick Mainsbridge"
-#: gtk2_ardour/about.cc:135
+#: gtk2_ardour/about.cc:136
msgid "Colin Law"
msgstr "Colin Law"
-#: gtk2_ardour/about.cc:136
+#: gtk2_ardour/about.cc:137
msgid "Sampo Savolainen"
msgstr "Sampo Savolainen"
-#: gtk2_ardour/about.cc:137
+#: gtk2_ardour/about.cc:138
msgid "Joshua Leach"
msgstr "Joshua Leach"
-#: gtk2_ardour/about.cc:138
+#: gtk2_ardour/about.cc:139
msgid "Rob Holland"
msgstr "Rob Holland"
-#: gtk2_ardour/about.cc:139
+#: gtk2_ardour/about.cc:140
msgid "Per Sigmond"
msgstr "Per Sigmond"
-#: gtk2_ardour/about.cc:140
+#: gtk2_ardour/about.cc:141
msgid "Doug Mclain"
msgstr "Doug Mclain"
-#: gtk2_ardour/about.cc:141
+#: gtk2_ardour/about.cc:142
msgid "Petter Sundlöf"
msgstr "Petter Sundlöf"
+#: gtk2_ardour/about.cc:143
+msgid "Thorsten Wilms"
+msgstr "Thorsten Wilms"
+
+#: gtk2_ardour/about.cc:144
+msgid "Ben Loftis"
+msgstr "Ben Loftis"
+
+#: gtk2_ardour/about.cc:145
+msgid "Stefan Kersten"
+msgstr "Stefan Kersten"
+
#: gtk2_ardour/about.cc:146
+msgid "Christopher George"
+msgstr "Christopher George"
+
+#: gtk2_ardour/about.cc:147
+msgid "Robert Jordens"
+msgstr "Robert Jordens"
+
+#: gtk2_ardour/about.cc:148
+msgid "Brian Ahr"
+msgstr "Brian Ahr"
+
+#: gtk2_ardour/about.cc:149
+msgid "Nimal Ratnayake"
+msgstr "Nimal Ratnayake"
+
+#: gtk2_ardour/about.cc:154
msgid ""
"French:\n"
"\tAlain Fréhel <alain.frehel@free.fr>\n"
+"\tChristophe Combelles <ccomb@free.fr>\n"
msgstr ""
"ФранцузÑкий:\n"
"\tAlain Fréhel <alain.frehel@free.fr>\n"
+"\tChristophe Combelles <ccomb@free.fr>\n"
-#: gtk2_ardour/about.cc:147
+#: gtk2_ardour/about.cc:155
msgid ""
"German:\n"
"\tKarsten Petersen <kapet@kapet.de>\n"
@@ -122,7 +152,7 @@ msgstr ""
"Ðемецкий:\n"
"\tKarsten Petersen <kapet@kapet.de>\n"
-#: gtk2_ardour/about.cc:148
+#: gtk2_ardour/about.cc:156
msgid ""
"Italian:\n"
"\tFilippo Pappalardo <filippo@email.it>\n"
@@ -130,7 +160,7 @@ msgstr ""
"ИтальÑнÑкий:\n"
"\tFilippo Pappalardo <filippo@email.it>\n"
-#: gtk2_ardour/about.cc:149
+#: gtk2_ardour/about.cc:157
msgid ""
"Portuguese:\n"
"\tRui Nuno Capela <rncbc@rncbc.org>\n"
@@ -138,7 +168,7 @@ msgstr ""
"ПортугальÑкий:\n"
"\tRui Nuno Capela <rncbc@rncbc.org>\n"
-#: gtk2_ardour/about.cc:150
+#: gtk2_ardour/about.cc:158
msgid ""
"Brazilian Portuguese:\n"
"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
@@ -148,7 +178,7 @@ msgstr ""
"\tAlexander da Franca Fernandes <alexander@nautae.eti.br>\n"
"\tChris Ross <chris@tebibyte.org>\n"
-#: gtk2_ardour/about.cc:152
+#: gtk2_ardour/about.cc:160
msgid ""
"Spanish:\n"
"\t Alex Krohn <alexkrohn@fastmail.fm>\n"
@@ -156,7 +186,7 @@ msgstr ""
"ИÑпанÑкий:\n"
"\t Alex Krohn <alexkrohn@fastmail.fm>\n"
-#: gtk2_ardour/about.cc:153
+#: gtk2_ardour/about.cc:161
msgid ""
"Russian:\n"
"\t Igor Blinov <pitstop@nm.ru>\n"
@@ -165,47 +195,93 @@ msgstr ""
"\t Igor Blinov <pitstop@nm.ru>\n"
"\t Alexandre Prokoudine <alexandre.prokoudine@gmail.com>\n"
-#: gtk2_ardour/about.cc:181
-msgid "Copyright (C) 1999-2005 Paul Davis\n"
-msgstr "ÐвторÑкие права 1999-2005 Paul Davis\n"
+#: gtk2_ardour/about.cc:189
+#, fuzzy
+msgid "Copyright (C) 1999-2006 Paul Davis\n"
+msgstr "ÐвторÑкие права © 1999-2006 Paul Davis"
-#: gtk2_ardour/about.cc:182
+#: gtk2_ardour/about.cc:190
msgid ""
"Ardour comes with ABSOLUTELY NO WARRANTY\n"
"This is free software, and you are welcome to redistribute it\n"
"under certain conditions; see the file COPYING for details.\n"
msgstr ""
-#: gtk2_ardour/about.cc:188
+#: gtk2_ardour/about.cc:195
+msgid "visit http://www.ardour.org/"
+msgstr "Зайдите на http://www.ardour.org/"
+
+#: gtk2_ardour/about.cc:196
+#, fuzzy
msgid ""
"%1\n"
-"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"
+"(built from revision %2)"
msgstr ""
+"%1\n"
+"(Ñобрано из ревизии %2)"
-#: gtk2_ardour/actions.cc:76
+#: gtk2_ardour/actions.cc:77
msgid "badly formatted UI definition file"
-msgstr ""
+msgstr "некорректно отформатированный файл Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñа"
-#: gtk2_ardour/actions.cc:78
+#: gtk2_ardour/actions.cc:79
msgid "Ardour menu definition file not found"
-msgstr ""
+msgstr "Файл Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð¼ÐµÐ½ÑŽ Ardour не найден"
-#: gtk2_ardour/actions.cc:82
+#: gtk2_ardour/actions.cc:83
msgid "ardour will not work without a valid ardour.menus file"
-msgstr ""
+msgstr "Ardour не будет работать без корректного файла ardour.menus"
-#: gtk2_ardour/actions.cc:261
+#: gtk2_ardour/actions.cc:235
#, fuzzy
msgid "programmer error: %1 %2"
msgstr "ошибка в программе: "
-#: gtk2_ardour/actions.cc:280
+#: gtk2_ardour/actions.cc:254
msgid "Unknown action name: %1"
+msgstr "ÐеизвеÑтное Ð¸Ð¼Ñ Ð´ÐµÐ¹ÑтвиÑ: %1"
+
+#: gtk2_ardour/add_route_dialog.cc:41 gtk2_ardour/add_route_dialog.cc:196
+msgid "Mono"
+msgstr "Моно"
+
+#: gtk2_ardour/add_route_dialog.cc:42 gtk2_ardour/add_route_dialog.cc:198
+msgid "Stereo"
+msgstr "Стерео"
+
+#: gtk2_ardour/add_route_dialog.cc:43
+msgid "3 Channels"
+msgstr "3 канала"
+
+#: gtk2_ardour/add_route_dialog.cc:44
+msgid "4 Channels"
+msgstr "4 канала"
+
+#: gtk2_ardour/add_route_dialog.cc:45
+msgid "6 Channels"
+msgstr "6 каналов"
+
+#: gtk2_ardour/add_route_dialog.cc:46
+msgid "8 Channels"
+msgstr "8 каналов"
+
+#: gtk2_ardour/add_route_dialog.cc:47
+msgid "Manual Setup"
+msgstr "Ð ÑƒÑ‡Ð½Ð°Ñ Ð½Ð°Ñтройка"
+
+#: gtk2_ardour/add_route_dialog.cc:52 gtk2_ardour/add_route_dialog.cc:177
+#: gtk2_ardour/editor.cc:126 gtk2_ardour/editor.cc:3616
+#: gtk2_ardour/editor_actions.cc:286 gtk2_ardour/time_axis_view.cc:586
+msgid "Normal"
+msgstr "Ðорм."
+
+#: gtk2_ardour/add_route_dialog.cc:53 gtk2_ardour/add_route_dialog.cc:179
+msgid "Tape"
msgstr ""
#: gtk2_ardour/add_route_dialog.cc:62
msgid "ardour: add track/bus"
-msgstr "ardour: добавить трек/шину"
+msgstr "ardour: добавить дорожку/шину"
#: gtk2_ardour/add_route_dialog.cc:63 gtk2_ardour/editor_route_list.cc:71
msgid "Tracks"
@@ -215,7 +291,7 @@ msgstr "Дорожки"
msgid "Busses"
msgstr "Шины"
-#: gtk2_ardour/add_route_dialog.cc:96 gtk2_ardour/plugin_ui.cc:145
+#: gtk2_ardour/add_route_dialog.cc:96 gtk2_ardour/plugin_ui.cc:151
msgid "Add"
msgstr "Добавить"
@@ -224,25 +300,8 @@ msgid "Name (template)"
msgstr "Ð˜Ð¼Ñ (шаблона)"
#: gtk2_ardour/add_route_dialog.cc:120
-#, fuzzy
msgid "Channel Configuration"
-msgstr "Отменить импорт"
-
-#: gtk2_ardour/add_route_dialog.cc:177 gtk2_ardour/time_axis_view.cc:553
-msgid "Normal"
-msgstr "Ðорм."
-
-#: gtk2_ardour/add_route_dialog.cc:179
-msgid "Tape"
-msgstr ""
-
-#: gtk2_ardour/add_route_dialog.cc:196
-msgid "Mono"
-msgstr "Моно"
-
-#: gtk2_ardour/add_route_dialog.cc:198
-msgid "Stereo"
-msgstr "Стерео"
+msgstr "Парометры каналов"
#: gtk2_ardour/ardour_ui.cc:106
msgid ""
@@ -266,15 +325,15 @@ msgstr ""
msgid "% "
msgstr "% "
-#: gtk2_ardour/ardour_ui.cc:119 gtk2_ardour/ardour_ui_ed.cc:267
+#: gtk2_ardour/ardour_ui.cc:119 gtk2_ardour/ardour_ui_ed.cc:274
msgid "Punch In"
msgstr "Ðачало врезки"
-#: gtk2_ardour/ardour_ui.cc:120 gtk2_ardour/ardour_ui_ed.cc:270
+#: gtk2_ardour/ardour_ui.cc:120 gtk2_ardour/ardour_ui_ed.cc:277
msgid "Punch Out"
msgstr "Конец врезки"
-#: gtk2_ardour/ardour_ui.cc:121 gtk2_ardour/ardour_ui_ed.cc:282
+#: gtk2_ardour/ardour_ui.cc:121 gtk2_ardour/ardour_ui_ed.cc:289
msgid "Auto Return"
msgstr "Ðвтовозврат"
@@ -282,12 +341,12 @@ msgstr "Ðвтовозврат"
msgid "Autuo Play"
msgstr "ÐвтовоÑпр."
-#: gtk2_ardour/ardour_ui.cc:123 gtk2_ardour/ardour_ui_ed.cc:276
+#: gtk2_ardour/ardour_ui.cc:123 gtk2_ardour/ardour_ui_ed.cc:283
msgid "Auto Input"
msgstr "Ðвтовход"
-#: gtk2_ardour/ardour_ui.cc:124 gtk2_ardour/ardour_ui_ed.cc:273
-#: gtk2_ardour/option_editor.cc:128
+#: gtk2_ardour/ardour_ui.cc:124 gtk2_ardour/ardour_ui_ed.cc:280
+#: gtk2_ardour/option_editor.cc:126
msgid "Click"
msgstr "Метроном"
@@ -299,11 +358,11 @@ msgstr "КОÐТРОЛЬ"
msgid "SOLO"
msgstr "СОЛО"
-#: gtk2_ardour/ardour_ui.cc:374
+#: gtk2_ardour/ardour_ui.cc:364
msgid "quit"
msgstr "выйти"
-#: gtk2_ardour/ardour_ui.cc:383
+#: gtk2_ardour/ardour_ui.cc:373
msgid ""
"Ardour was unable to save your session.\n"
"\n"
@@ -312,34 +371,33 @@ msgid ""
"\"Just quit\" option."
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:402
+#: gtk2_ardour/ardour_ui.cc:397
msgid "ardour: save session?"
msgstr "ardour: Ñохранить ÑеÑÑию?"
-#: gtk2_ardour/ardour_ui.cc:409
+#: gtk2_ardour/ardour_ui.cc:404
msgid "Don't %1"
msgstr "Отмена"
-#: gtk2_ardour/ardour_ui.cc:411
+#: gtk2_ardour/ardour_ui.cc:406
msgid "Just %1"
msgstr "Да, %1"
-#: gtk2_ardour/ardour_ui.cc:413
+#: gtk2_ardour/ardour_ui.cc:408
msgid "Save and %1"
msgstr "Сохранить и %1"
-#: gtk2_ardour/ardour_ui.cc:425
+#: gtk2_ardour/ardour_ui.cc:420
#, fuzzy
msgid "session"
msgstr "СеÑÑиÑ"
-#: gtk2_ardour/ardour_ui.cc:427
+#: gtk2_ardour/ardour_ui.cc:422
#, fuzzy
msgid "snapshot"
msgstr "Снимок"
-#: gtk2_ardour/ardour_ui.cc:429
-#, fuzzy
+#: gtk2_ardour/ardour_ui.cc:424
msgid ""
"The %1\"%2\"\n"
"has not been saved.\n"
@@ -355,84 +413,84 @@ msgstr ""
"Ð’Ñе Ñделанные изменениÑ\n"
"будут потерÑны, еÑли не Ñохранить их.\n"
"\n"
-"Что Ð’Ñ‹ хотите Ñделать?"
+"Что вы хотите Ñделать?"
-#: gtk2_ardour/ardour_ui.cc:443
+#: gtk2_ardour/ardour_ui.cc:438
msgid "Prompter"
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:502
-#, fuzzy, c-format
+#: gtk2_ardour/ardour_ui.cc:498
+#, c-format
msgid "disconnected"
-msgstr "ОтÑоединить"
+msgstr "отÑоединено"
-#: gtk2_ardour/ardour_ui.cc:509
+#: gtk2_ardour/ardour_ui.cc:505
#, fuzzy, c-format
msgid "%.1f kHz / %4.1f msecs"
msgstr "SR: %.1f кГц"
-#: gtk2_ardour/ardour_ui.cc:513
+#: gtk2_ardour/ardour_ui.cc:509
#, fuzzy, c-format
msgid "%u kHz / %4.1f msecs"
msgstr "SR: %.1f кГц"
-#: gtk2_ardour/ardour_ui.cc:526
+#: gtk2_ardour/ardour_ui.cc:522
#, fuzzy, c-format
msgid "DSP: %.1f%%"
msgstr "Загрузка DSP: %.1f%%"
-#: gtk2_ardour/ardour_ui.cc:536
+#: gtk2_ardour/ardour_ui.cc:532
#, fuzzy, c-format
msgid "Buffers p:%<PRIu32>%% c:%<PRIu32>%%"
msgstr "Буферы p:%5.0f%% c:%5.0f%%"
-#: gtk2_ardour/ardour_ui.cc:564
+#: gtk2_ardour/ardour_ui.cc:560
#, fuzzy
msgid "Disk: 24hrs+"
msgstr "меÑто на диÑке: 24 чаÑа +"
-#: gtk2_ardour/ardour_ui.cc:594
+#: gtk2_ardour/ardour_ui.cc:580
#, fuzzy, c-format
msgid "Disk: %02dh:%02dm:%02ds"
msgstr "Ñвободное меÑто: %02dч:%02dмин:%02dÑек"
-#: gtk2_ardour/ardour_ui.cc:633
+#: gtk2_ardour/ardour_ui.cc:619
msgid "programming error: impossible control method"
msgstr "ошибка в программе: impossible control method"
-#: gtk2_ardour/ardour_ui.cc:741 gtk2_ardour/new_session_dialog.cc:301
+#: gtk2_ardour/ardour_ui.cc:727 gtk2_ardour/new_session_dialog.cc:355
#, fuzzy
msgid "Recent Sessions"
msgstr "открыть ÑеÑÑию"
-#: gtk2_ardour/ardour_ui.cc:834
+#: gtk2_ardour/ardour_ui.cc:820
msgid "open session"
msgstr "открыть ÑеÑÑию"
-#: gtk2_ardour/ardour_ui.cc:840
+#: gtk2_ardour/ardour_ui.cc:826
msgid "Ardour sessions"
msgstr "СеÑÑии Ardour"
-#: gtk2_ardour/ardour_ui.cc:873
+#: gtk2_ardour/ardour_ui.cc:859
msgid "Patience is a virtue.\n"
msgstr "По нитке дойдёшь и до клубка.\n"
-#: gtk2_ardour/ardour_ui.cc:883
+#: gtk2_ardour/ardour_ui.cc:869
#, fuzzy
msgid "You cannot add a track or bus without a session already loaded."
msgstr "Ð’Ñ‹ не можете добавить трек пока ÑеÑÑÐ¸Ñ Ð½Ðµ загружена."
-#: gtk2_ardour/ardour_ui.cc:893 gtk2_ardour/ardour_ui.cc:905
+#: gtk2_ardour/ardour_ui.cc:879 gtk2_ardour/ardour_ui.cc:891
#, fuzzy
msgid "could not create a new audio track"
msgstr "не удалоÑÑŒ Ñоздать новый аудиотрек"
-#: gtk2_ardour/ardour_ui.cc:895 gtk2_ardour/ardour_ui.cc:907
+#: gtk2_ardour/ardour_ui.cc:881 gtk2_ardour/ardour_ui.cc:893
#, fuzzy
msgid "could not create %1 new audio tracks"
msgstr "не удалоÑÑŒ Ñоздать новый аудиотрек"
-#: gtk2_ardour/ardour_ui.cc:927
+#: gtk2_ardour/ardour_ui.cc:913
msgid ""
"There are insufficient JACK ports available\n"
"to create a new track or bus.\n"
@@ -440,14 +498,14 @@ msgid ""
"restart JACK with more ports."
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:1046
+#: gtk2_ardour/ardour_ui.cc:1033
msgid ""
"Please create 1 or more track\n"
"before trying to record.\n"
"Check the Session menu."
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:1268
+#: gtk2_ardour/ardour_ui.cc:1253
#, fuzzy
msgid ""
"JACK has either been shutdown or it\n"
@@ -460,42 +518,47 @@ msgstr ""
"Ðеобходимо Ñохранить ÑеÑÑию и\n"
"перезапуÑтить JACK и Ardour."
-#: gtk2_ardour/ardour_ui.cc:1285
-msgid "Unable to create all required ports"
-msgstr ""
-
-#: gtk2_ardour/ardour_ui.cc:1293
+#: gtk2_ardour/ardour_ui.cc:1270
#, fuzzy
msgid "Unable to start the session running"
msgstr "Ð’ начало ÑеÑÑии"
-#: gtk2_ardour/ardour_ui.cc:1399 gtk2_ardour/ardour_ui.cc:1418
+#: gtk2_ardour/ardour_ui.cc:1370 gtk2_ardour/ardour_ui.cc:1389
+#: gtk2_ardour/audio_clock.cc:451
msgid "none"
msgstr "нет"
-#: gtk2_ardour/ardour_ui.cc:1408 gtk2_ardour/ardour_ui.cc:1427
+#: gtk2_ardour/ardour_ui.cc:1379 gtk2_ardour/ardour_ui.cc:1398
msgid "off"
-msgstr "выкл"
+msgstr "выкл."
-#: gtk2_ardour/ardour_ui.cc:1451
+#: gtk2_ardour/ardour_ui.cc:1421
msgid "Name of New Snapshot"
msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ Ñнимка:"
-#: gtk2_ardour/ardour_ui.cc:1597
+#: gtk2_ardour/ardour_ui.cc:1567
msgid "Name for mix template:"
msgstr "Ð˜Ð¼Ñ mix-шаблона:"
-#: gtk2_ardour/ardour_ui.cc:1598
+#: gtk2_ardour/ardour_ui.cc:1568
msgid "-template"
msgstr "-шаблон"
-#: gtk2_ardour/ardour_ui.cc:1806
+#: gtk2_ardour/ardour_ui.cc:1689
+#, fuzzy
+msgid ""
+"This session\n"
+"%1\n"
+"already exists. Do you want to open it?"
+msgstr "Файл Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже еÑÑ‚ÑŒ. ПерезапиÑать его?"
+
+#: gtk2_ardour/ardour_ui.cc:1805
msgid ""
"You do not have write access to this session.\n"
"This prevents the session from being loaded."
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:1819 gtk2_ardour/ardour_ui.cc:1871
+#: gtk2_ardour/ardour_ui.cc:1818 gtk2_ardour/ardour_ui.cc:1867
msgid "Session \"%1 (snapshot %2)\" did not load successfully"
msgstr "Ðе удалоÑÑŒ загрузить ÑеÑÑию \"%1 (Ñнимок %2)\""
@@ -545,14 +608,9 @@ msgstr "ОчиÑтка"
msgid "CleanupDialog"
msgstr "ОчиÑтка"
-#: gtk2_ardour/ardour_ui.cc:2039
-#, fuzzy
-msgid "ardour_cleanup"
-msgstr "ardour: очиÑтка"
-
#: gtk2_ardour/ardour_ui.cc:2058
msgid "cleaned files"
-msgstr ""
+msgstr "очищенные файлы"
#: gtk2_ardour/ardour_ui.cc:2059
#, fuzzy
@@ -586,7 +644,7 @@ msgstr "Следующие %1 файлов были удалены, оÑвобо
msgid "Recording was stopped because your system could not keep up."
msgstr "ЗапиÑÑŒ оÑтановлена из-за недоÑтаточного быÑтродейÑÑ‚Ð²Ð¸Ñ ÑиÑтемы"
-#: gtk2_ardour/ardour_ui.cc:2224
+#: gtk2_ardour/ardour_ui.cc:2212
msgid ""
"The disk system on your computer\n"
"was not able to keep up with Ardour.\n"
@@ -595,7 +653,7 @@ msgid ""
"quickly enough to keep up with recording.\n"
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:2243
+#: gtk2_ardour/ardour_ui.cc:2231
msgid ""
"The disk system on your computer\n"
"was not able to keep up with Ardour.\n"
@@ -604,7 +662,7 @@ msgid ""
"quickly enough to keep up with playback.\n"
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:2269
+#: gtk2_ardour/ardour_ui.cc:2257
msgid ""
"This session appears to have been in\n"
"middle of recording when ardour or\n"
@@ -615,20 +673,20 @@ msgid ""
"what you would like to do.\n"
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:2279
+#: gtk2_ardour/ardour_ui.cc:2267
msgid "Recover from crash"
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:2280
+#: gtk2_ardour/ardour_ui.cc:2268
msgid "Ignore crash data"
msgstr ""
-#: gtk2_ardour/ardour_ui.cc:2298
+#: gtk2_ardour/ardour_ui.cc:2286
#, fuzzy
msgid "Could not disconnect from JACK"
msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\""
-#: gtk2_ardour/ardour_ui.cc:2311
+#: gtk2_ardour/ardour_ui.cc:2299
#, fuzzy
msgid "Could not reconnect to JACK"
msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\""
@@ -657,977 +715,1056 @@ msgstr ""
msgid "MMC ID"
msgstr "MMC идентификатор"
-#: gtk2_ardour/ardour_ui2.cc:291
+#: gtk2_ardour/ardour_ui2.cc:295
msgid "Play from playhead"
msgstr "ВоÑпроизвеÑти от указателÑ"
-#: gtk2_ardour/ardour_ui2.cc:292
+#: gtk2_ardour/ardour_ui2.cc:296
msgid "Stop playback"
msgstr "Стоп"
-#: gtk2_ardour/ardour_ui2.cc:293
-#, fuzzy
+#: gtk2_ardour/ardour_ui2.cc:297
msgid "Play range/selection"
-msgstr "ВоÑпроизвеÑти выделенное"
+msgstr "ВоÑпроизвеÑти выделение"
-#: gtk2_ardour/ardour_ui2.cc:294
+#: gtk2_ardour/ardour_ui2.cc:298
msgid "Go to start of session"
msgstr "Ð’ начало ÑеÑÑии"
-#: gtk2_ardour/ardour_ui2.cc:295
+#: gtk2_ardour/ardour_ui2.cc:299
msgid "Go to end of session"
msgstr "Ð’ конец ÑеÑÑии"
-#: gtk2_ardour/ardour_ui2.cc:296
+#: gtk2_ardour/ardour_ui2.cc:300
msgid "Play loop range"
-msgstr "ВоÑпроизвеÑти \"кольцо\""
+msgstr "Закольцевать выделение"
-#: gtk2_ardour/ardour_ui2.cc:297
+#: gtk2_ardour/ardour_ui2.cc:301
msgid "Return to last playback start when stopped"
msgstr "ВернутьÑÑ Ðº точке начала воÑпроизведениÑ"
-#: gtk2_ardour/ardour_ui2.cc:298
+#: gtk2_ardour/ardour_ui2.cc:302
msgid "Start playback after any locate"
msgstr ""
-#: gtk2_ardour/ardour_ui2.cc:299
+#: gtk2_ardour/ardour_ui2.cc:303
msgid "Be sensible about input monitoring"
msgstr ""
-#: gtk2_ardour/ardour_ui2.cc:300
+#: gtk2_ardour/ardour_ui2.cc:304
msgid "Start recording at auto-punch start"
msgstr "Ðачать запиÑÑŒ Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° \"авто-врезки\""
-#: gtk2_ardour/ardour_ui2.cc:301
+#: gtk2_ardour/ardour_ui2.cc:305
msgid "Stop recording at auto-punch end"
msgstr "ОÑтановить запиÑÑŒ в конце \"авто-врезки\""
-#: gtk2_ardour/ardour_ui2.cc:302
+#: gtk2_ardour/ardour_ui2.cc:306
msgid "Enable/Disable audio click"
msgstr "Вкл./Выкл. метроном"
-#: gtk2_ardour/ardour_ui2.cc:303
+#: gtk2_ardour/ardour_ui2.cc:307
msgid "Positional sync source"
msgstr ""
-#: gtk2_ardour/ardour_ui2.cc:304
+#: gtk2_ardour/ardour_ui2.cc:308
msgid "Does Ardour control the time?"
msgstr ""
-#: gtk2_ardour/ardour_ui2.cc:305
+#: gtk2_ardour/ardour_ui2.cc:309
msgid "Shuttle speed control"
msgstr ""
-#: gtk2_ardour/ardour_ui2.cc:306
+#: gtk2_ardour/ardour_ui2.cc:310
#, c-format
msgid "Select semitones or %%-age for speed display"
msgstr ""
-#: gtk2_ardour/ardour_ui2.cc:307
+#: gtk2_ardour/ardour_ui2.cc:311
msgid "Current transport speed"
msgstr "ТекщаÑÑ ÑкорÑÑ‚ÑŒ транÑпорта"
-#: gtk2_ardour/ardour_ui2.cc:330
+#: gtk2_ardour/ardour_ui2.cc:334
msgid "Primary clock"
msgstr "ОÑновной Ñчётчик"
-#: gtk2_ardour/ardour_ui2.cc:331
+#: gtk2_ardour/ardour_ui2.cc:335
msgid "secondary clock"
msgstr "дополнительный Ñчётчик"
-#: gtk2_ardour/ardour_ui2.cc:388 gtk2_ardour/ardour_ui2.cc:849
-#: gtk2_ardour/ardour_ui2.cc:862 gtk2_ardour/ardour_ui2.cc:925
-#: gtk2_ardour/ardour_ui2.cc:927
+#: gtk2_ardour/ardour_ui2.cc:366
+msgid ""
+"When active, something is soloed.\n"
+"Click to de-solo everything"
+msgstr ""
+
+#: gtk2_ardour/ardour_ui2.cc:367
+msgid ""
+"When active, auditioning is taking place\n"
+"Click to stop the audition"
+msgstr ""
+
+#: gtk2_ardour/ardour_ui2.cc:395 gtk2_ardour/ardour_ui2.cc:826
+#: gtk2_ardour/ardour_ui2.cc:882 gtk2_ardour/ardour_ui_options.cc:802
msgid "sprung"
msgstr ""
-#: gtk2_ardour/ardour_ui2.cc:389 gtk2_ardour/ardour_ui2.cc:851
-#: gtk2_ardour/ardour_ui2.cc:873
+#: gtk2_ardour/ardour_ui2.cc:396 gtk2_ardour/ardour_ui2.cc:828
+#: gtk2_ardour/ardour_ui_options.cc:813
msgid "wheel"
msgstr ""
-#: gtk2_ardour/ardour_ui2.cc:467
-msgid "ardour: clock"
-msgstr "ardour: Ñчётчик"
-
-#: gtk2_ardour/ardour_ui2.cc:612
+#: gtk2_ardour/ardour_ui2.cc:602
msgid "Maximum speed"
msgstr "МакÑ. ÑкороÑÑ‚ÑŒ"
-#: gtk2_ardour/ardour_ui2.cc:839
-#, fuzzy
-msgid "ST"
-msgstr "УСТÐÐОВИТЬ"
-
-#: gtk2_ardour/ardour_ui2.cc:883 gtk2_ardour/ardour_ui2.cc:906
+#: gtk2_ardour/ardour_ui2.cc:838 gtk2_ardour/ardour_ui2.cc:861
#, fuzzy
msgid "stop"
msgstr "Стоп"
-#: gtk2_ardour/ardour_ui2.cc:923
+#: gtk2_ardour/ardour_ui2.cc:880
msgid "-0.55"
msgstr "-0.55"
-#: gtk2_ardour/ardour_ui_dialogs.cc:145 gtk2_ardour/playlist_selector.cc:70
-#, fuzzy
+#: gtk2_ardour/ardour_ui_dependents.cc:85
+msgid "Ardour key bindings file not found at \"%1\" or contains errors."
+msgstr "Файл комбинаций клавиш Ð´Ð»Ñ Ardour не найден в каталоге \"%1\" или Ñодержит ошибки."
+
+#: gtk2_ardour/ardour_ui_dialogs.cc:142 gtk2_ardour/playlist_selector.cc:69
msgid "close"
msgstr "Закрыть"
-#: gtk2_ardour/ardour_ui_dialogs.cc:352 gtk2_ardour/ardour_ui_ed.cc:184
-msgid "Sound File Browser"
-msgstr "Ðудиобиблиотека"
-
-#: gtk2_ardour/ardour_ui_ed.cc:72
+#: gtk2_ardour/ardour_ui_ed.cc:77
msgid "Session"
msgstr "СеÑÑиÑ"
-#: gtk2_ardour/ardour_ui_ed.cc:73 gtk2_ardour/ardour_ui_ed.cc:130
-#: gtk2_ardour/editor.cc:1786 gtk2_ardour/export_dialog.cc:350
-#: gtk2_ardour/export_dialog.cc:1059 gtk2_ardour/export_dialog.cc:1063
+#: gtk2_ardour/ardour_ui_ed.cc:78 gtk2_ardour/ardour_ui_ed.cc:138
+#: gtk2_ardour/editor.cc:1736 gtk2_ardour/export_dialog.cc:348
+#: gtk2_ardour/export_dialog.cc:1057 gtk2_ardour/export_dialog.cc:1061
msgid "Export"
msgstr "ЭкÑпортировать"
-#: gtk2_ardour/ardour_ui_ed.cc:74
+#: gtk2_ardour/ardour_ui_ed.cc:79
msgid "Cleanup"
msgstr "ОчиÑтить"
-#: gtk2_ardour/ardour_ui_ed.cc:75 gtk2_ardour/option_editor.cc:125
+#: gtk2_ardour/ardour_ui_ed.cc:80 gtk2_ardour/option_editor.cc:123
msgid "Sync"
-msgstr "Синхр."
+msgstr "СинхронизациÑ"
-#: gtk2_ardour/ardour_ui_ed.cc:76 gtk2_ardour/ardour_ui_ed.cc:77
+#: gtk2_ardour/ardour_ui_ed.cc:81 gtk2_ardour/ardour_ui_ed.cc:82
msgid "Options"
msgstr "Параметры"
-#: gtk2_ardour/ardour_ui_ed.cc:78
+#: gtk2_ardour/ardour_ui_ed.cc:83
msgid "Help"
msgstr "Справка"
-#: gtk2_ardour/ardour_ui_ed.cc:79
+#: gtk2_ardour/ardour_ui_ed.cc:84
msgid "KeyMouse Actions"
-msgstr "ГорÑчие клавиши"
+msgstr "Клавиатурные комбинации"
-#: gtk2_ardour/ardour_ui_ed.cc:80
+#: gtk2_ardour/ardour_ui_ed.cc:85
msgid "Audio File Format"
msgstr "Формат звуковых файлов"
-#: gtk2_ardour/ardour_ui_ed.cc:81
+#: gtk2_ardour/ardour_ui_ed.cc:86
msgid "Header"
msgstr "Заголовок"
-#: gtk2_ardour/ardour_ui_ed.cc:82
+#: gtk2_ardour/ardour_ui_ed.cc:87
msgid "Data"
msgstr "Данные"
-#: gtk2_ardour/ardour_ui_ed.cc:83
+#: gtk2_ardour/ardour_ui_ed.cc:88
msgid "Control Surfaces"
-msgstr ""
+msgstr "УÑтройÑтва управлениÑ"
+
+#: gtk2_ardour/ardour_ui_ed.cc:89
+msgid "Metering"
+msgstr "Индикаторы"
+
+#: gtk2_ardour/ardour_ui_ed.cc:90
+msgid "Fall off rate"
+msgstr "ЧаÑтота Ñпада"
+
+#: gtk2_ardour/ardour_ui_ed.cc:91
+msgid "Hold Time"
+msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð´ÐµÑ€Ð¶ÐºÐ¸"
-#: gtk2_ardour/ardour_ui_ed.cc:87 gtk2_ardour/route_time_axis.cc:1139
-#: gtk2_ardour/new_session_dialog.cc:546
+#: gtk2_ardour/ardour_ui_ed.cc:95 gtk2_ardour/route_time_axis.cc:1309
+#: gtk2_ardour/new_session_dialog.cc:612
msgid "New"
msgstr "ÐоваÑ"
-#: gtk2_ardour/ardour_ui_ed.cc:89 gtk2_ardour/new_session_dialog.cc:533
+#: gtk2_ardour/ardour_ui_ed.cc:97 gtk2_ardour/new_session_dialog.cc:599
msgid "Open"
msgstr "Открыть"
-#: gtk2_ardour/ardour_ui_ed.cc:90
+#: gtk2_ardour/ardour_ui_ed.cc:98
msgid "Recent"
msgstr "ПоÑледние"
-#: gtk2_ardour/ardour_ui_ed.cc:91 gtk2_ardour/io_selector.cc:60
-#: gtk2_ardour/io_selector.cc:794 gtk2_ardour/connection_editor.cc:59
+#: gtk2_ardour/ardour_ui_ed.cc:99 gtk2_ardour/io_selector.cc:60
+#: gtk2_ardour/io_selector.cc:748 gtk2_ardour/connection_editor.cc:59
msgid "Close"
msgstr "Закрыть"
-#: gtk2_ardour/ardour_ui_ed.cc:94 gtk2_ardour/route_params_ui.cc:510
+#: gtk2_ardour/ardour_ui_ed.cc:102 gtk2_ardour/route_params_ui.cc:510
msgid "Add Track/Bus"
-msgstr "Добавить Дорожку/Шину"
+msgstr "Добавить дорожку/шину"
-#: gtk2_ardour/ardour_ui_ed.cc:105
+#: gtk2_ardour/ardour_ui_ed.cc:113
msgid "Connect"
msgstr "Соединить"
-#: gtk2_ardour/ardour_ui_ed.cc:113
+#: gtk2_ardour/ardour_ui_ed.cc:121
msgid "Snapshot"
msgstr "Снимок"
-#: gtk2_ardour/ardour_ui_ed.cc:116
+#: gtk2_ardour/ardour_ui_ed.cc:124
msgid "Save Template..."
msgstr "Сохранить шаблон..."
-#: gtk2_ardour/ardour_ui_ed.cc:119
+#: gtk2_ardour/ardour_ui_ed.cc:127
msgid "Export session to audiofile..."
-msgstr "ЭкÑпорт ÑеÑÑии в аудиофайл..."
+msgstr "СеÑÑию в аудиофайл..."
-#: gtk2_ardour/ardour_ui_ed.cc:122
+#: gtk2_ardour/ardour_ui_ed.cc:130
msgid "Export selection to audiofile..."
-msgstr "ЭкÑпорт выделение в аудиофайл..."
+msgstr "Выделение в аудиофайл..."
-#: gtk2_ardour/ardour_ui_ed.cc:126
+#: gtk2_ardour/ardour_ui_ed.cc:134
msgid "Export range markers to audiofile..."
-msgstr "ЭкÑпортировать маркеры облаÑти в аудиофайл..."
+msgstr "Маркеры облаÑти в аудиофайл..."
-#: gtk2_ardour/ardour_ui_ed.cc:133
+#: gtk2_ardour/ardour_ui_ed.cc:141
msgid "Cleanup unused sources"
msgstr "ОчиÑтить неиÑпользуемые иÑточники"
-#: gtk2_ardour/ardour_ui_ed.cc:135
+#: gtk2_ardour/ardour_ui_ed.cc:143
msgid "Flush wastebasket"
msgstr "ОчиÑтить корзину"
-#: gtk2_ardour/ardour_ui_ed.cc:141 gtk2_ardour/ardour_ui_options.cc:425
-#: gtk2_ardour/ardour_ui_options.cc:434 gtk2_ardour/ardour_ui_options.cc:507
+#: gtk2_ardour/ardour_ui_ed.cc:149
msgid "JACK"
msgstr "JACK"
-#: gtk2_ardour/ardour_ui_ed.cc:142
+#: gtk2_ardour/ardour_ui_ed.cc:150
msgid "Latency"
msgstr "Задержка отклика"
-#: gtk2_ardour/ardour_ui_ed.cc:144
+#: gtk2_ardour/ardour_ui_ed.cc:152
msgid "Reconnect"
msgstr "ПереÑоединитьÑÑ"
-#: gtk2_ardour/ardour_ui_ed.cc:147 gtk2_ardour/mixer_strip.cc:498
-#: gtk2_ardour/mixer_strip.cc:561
+#: gtk2_ardour/ardour_ui_ed.cc:155 gtk2_ardour/mixer_strip.cc:517
+#: gtk2_ardour/mixer_strip.cc:579
msgid "Disconnect"
msgstr "ОтÑоединитьÑÑ"
-#: gtk2_ardour/ardour_ui_ed.cc:174
+#: gtk2_ardour/ardour_ui_ed.cc:182
msgid "Windows"
msgstr "Окна"
-#: gtk2_ardour/ardour_ui_ed.cc:175
+#: gtk2_ardour/ardour_ui_ed.cc:183
msgid "start prefix"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:176
+#: gtk2_ardour/ardour_ui_ed.cc:184
msgid "Quit"
msgstr "Выйти"
-#: gtk2_ardour/ardour_ui_ed.cc:180
+#: gtk2_ardour/ardour_ui_ed.cc:188
msgid "Maximise Editor Space"
msgstr "Редактор на полный Ñкран"
-#: gtk2_ardour/ardour_ui_ed.cc:182
+#: gtk2_ardour/ardour_ui_ed.cc:190
msgid "Show Editor"
msgstr "Показать редактор"
-#: gtk2_ardour/ardour_ui_ed.cc:183
+#: gtk2_ardour/ardour_ui_ed.cc:191
msgid "Show Mixer"
msgstr "Показать микшер"
-#: gtk2_ardour/ardour_ui_ed.cc:185
+#: gtk2_ardour/ardour_ui_ed.cc:192
msgid "Options Editor"
-msgstr "Редактор параметров"
+msgstr "Параметры программы"
-#: gtk2_ardour/ardour_ui_ed.cc:186
+#: gtk2_ardour/ardour_ui_ed.cc:193
msgid "Track/Bus Inspector"
msgstr "ИнÑпектор дорожек/шин"
-#: gtk2_ardour/ardour_ui_ed.cc:188 gtk2_ardour/connection_editor.cc:147
+#: gtk2_ardour/ardour_ui_ed.cc:195 gtk2_ardour/connection_editor.cc:147
#: gtk2_ardour/connection_editor.cc:148
msgid "Connections"
msgstr "СоединениÑ"
-#: gtk2_ardour/ardour_ui_ed.cc:190
+#: gtk2_ardour/ardour_ui_ed.cc:197
msgid "Locations"
msgstr "Интервалы"
-#: gtk2_ardour/ardour_ui_ed.cc:192
+#: gtk2_ardour/ardour_ui_ed.cc:199
msgid "Big Clock"
msgstr "Большой Ñчётчик"
-#: gtk2_ardour/ardour_ui_ed.cc:194
+#: gtk2_ardour/ardour_ui_ed.cc:201
msgid "About"
msgstr "О программе"
-#: gtk2_ardour/ardour_ui_ed.cc:195
+#: gtk2_ardour/ardour_ui_ed.cc:202
msgid "Colors"
msgstr "Цвета"
-#: gtk2_ardour/ardour_ui_ed.cc:197
+#: gtk2_ardour/ardour_ui_ed.cc:204
msgid "Add Audio Track"
msgstr "Добавить звуковую дорожку"
-#: gtk2_ardour/ardour_ui_ed.cc:199
+#: gtk2_ardour/ardour_ui_ed.cc:206
msgid "Add Audio Bus"
msgstr "Добавить звуковую шину"
-#: gtk2_ardour/ardour_ui_ed.cc:201
+#: gtk2_ardour/ardour_ui_ed.cc:208
msgid "Save"
msgstr "Сохранить"
-#: gtk2_ardour/ardour_ui_ed.cc:203 gtk2_ardour/editor_actions.cc:257
-#, fuzzy
+#: gtk2_ardour/ardour_ui_ed.cc:210 gtk2_ardour/editor_actions.cc:256
msgid "Remove Last Capture"
msgstr "Удалить поÑледнюю запиÑÑŒ"
-#: gtk2_ardour/ardour_ui_ed.cc:210
+#: gtk2_ardour/ardour_ui_ed.cc:217
msgid "Transport"
msgstr "ТранÑпорт"
-#: gtk2_ardour/ardour_ui_ed.cc:216 gtk2_ardour/sfdb_ui.cc:60
+#: gtk2_ardour/ardour_ui_ed.cc:223 gtk2_ardour/sfdb_ui.cc:59
msgid "Stop"
msgstr "Стоп"
-#: gtk2_ardour/ardour_ui_ed.cc:219
+#: gtk2_ardour/ardour_ui_ed.cc:226
msgid "Roll"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:223
+#: gtk2_ardour/ardour_ui_ed.cc:230
msgid "Start/Stop"
msgstr "Старт/Стоп"
-#: gtk2_ardour/ardour_ui_ed.cc:226
+#: gtk2_ardour/ardour_ui_ed.cc:233
msgid "Stop + Forget Capture"
msgstr "Стоп+ Забыть захват"
-#: gtk2_ardour/ardour_ui_ed.cc:229
+#: gtk2_ardour/ardour_ui_ed.cc:236
msgid "Play Loop Range"
msgstr "ВоÑпроизвеÑти петлю"
-#: gtk2_ardour/ardour_ui_ed.cc:232
+#: gtk2_ardour/ardour_ui_ed.cc:239
msgid "Play Selection"
msgstr "ВоÑпроизвеÑти выделение"
-#: gtk2_ardour/ardour_ui_ed.cc:236
+#: gtk2_ardour/ardour_ui_ed.cc:243
msgid "Enable Record"
msgstr "Разрешить запиÑÑŒ"
-#: gtk2_ardour/ardour_ui_ed.cc:239
+#: gtk2_ardour/ardour_ui_ed.cc:246
msgid "Rewind"
msgstr "Перемотать назад"
-#: gtk2_ardour/ardour_ui_ed.cc:242
+#: gtk2_ardour/ardour_ui_ed.cc:249
msgid "Rewind (Slow)"
msgstr "Перемотать назад (медленно)"
-#: gtk2_ardour/ardour_ui_ed.cc:245
+#: gtk2_ardour/ardour_ui_ed.cc:252
msgid "Rewind (Fast)"
msgstr "Перемотать назад (быÑтро)"
-#: gtk2_ardour/ardour_ui_ed.cc:248
+#: gtk2_ardour/ardour_ui_ed.cc:255
msgid "Forward"
msgstr "Перемотать вперёд"
-#: gtk2_ardour/ardour_ui_ed.cc:251
+#: gtk2_ardour/ardour_ui_ed.cc:258
msgid "Forward (Slow)"
msgstr "Перемотать вперёд (медленно)"
-#: gtk2_ardour/ardour_ui_ed.cc:254
+#: gtk2_ardour/ardour_ui_ed.cc:261
msgid "Forward (Fast)"
msgstr "Перемотать вперёд (быÑтро)"
-#: gtk2_ardour/ardour_ui_ed.cc:257
+#: gtk2_ardour/ardour_ui_ed.cc:264
msgid "Goto Zero"
msgstr "К нулевой отметке"
-#: gtk2_ardour/ardour_ui_ed.cc:260
+#: gtk2_ardour/ardour_ui_ed.cc:267
msgid "Goto Start"
msgstr "К началу"
-#: gtk2_ardour/ardour_ui_ed.cc:263
+#: gtk2_ardour/ardour_ui_ed.cc:270
msgid "Goto End"
msgstr "В конец"
-#: gtk2_ardour/ardour_ui_ed.cc:279
+#: gtk2_ardour/ardour_ui_ed.cc:286
msgid "Auto Play"
msgstr "ÐвтовоÑпроизведение"
-#: gtk2_ardour/ardour_ui_ed.cc:286
+#: gtk2_ardour/ardour_ui_ed.cc:293
msgid "Sync startup to video"
msgstr "Синхронизировать начало Ñ Ð²Ð¸Ð´ÐµÐ¾"
-#: gtk2_ardour/ardour_ui_ed.cc:287
+#: gtk2_ardour/ardour_ui_ed.cc:294
#, fuzzy
msgid "Time master"
msgstr "JACK-Ñчётчик - маÑтер"
-#: gtk2_ardour/ardour_ui_ed.cc:290
+#: gtk2_ardour/ardour_ui_ed.cc:297
msgid "Toggle Record Enable Track1"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:292
+#: gtk2_ardour/ardour_ui_ed.cc:299
msgid "Toggle Record Enable Track2"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:294
+#: gtk2_ardour/ardour_ui_ed.cc:301
msgid "Toggle Record Enable Track3"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:296
+#: gtk2_ardour/ardour_ui_ed.cc:303
msgid "Toggle Record Enable Track4"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:298
+#: gtk2_ardour/ardour_ui_ed.cc:305
msgid "Toggle Record Enable Track5"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:300
+#: gtk2_ardour/ardour_ui_ed.cc:307
msgid "Toggle Record Enable Track6"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:302
+#: gtk2_ardour/ardour_ui_ed.cc:309
msgid "Toggle Record Enable Track7"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:304
+#: gtk2_ardour/ardour_ui_ed.cc:311
msgid "Toggle Record Enable Track8"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:306
+#: gtk2_ardour/ardour_ui_ed.cc:313
msgid "Toggle Record Enable Track9"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:308
+#: gtk2_ardour/ardour_ui_ed.cc:315
msgid "Toggle Record Enable Track10"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:310
+#: gtk2_ardour/ardour_ui_ed.cc:317
msgid "Toggle Record Enable Track11"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:312
+#: gtk2_ardour/ardour_ui_ed.cc:319
msgid "Toggle Record Enable Track12"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:314
+#: gtk2_ardour/ardour_ui_ed.cc:321
msgid "Toggle Record Enable Track13"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:316
+#: gtk2_ardour/ardour_ui_ed.cc:323
msgid "Toggle Record Enable Track14"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:318
+#: gtk2_ardour/ardour_ui_ed.cc:325
msgid "Toggle Record Enable Track15"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:320
+#: gtk2_ardour/ardour_ui_ed.cc:327
msgid "Toggle Record Enable Track16"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:322
+#: gtk2_ardour/ardour_ui_ed.cc:329
msgid "Toggle Record Enable Track17"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:324
+#: gtk2_ardour/ardour_ui_ed.cc:331
msgid "Toggle Record Enable Track18"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:326
+#: gtk2_ardour/ardour_ui_ed.cc:333
msgid "Toggle Record Enable Track19"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:328
+#: gtk2_ardour/ardour_ui_ed.cc:335
msgid "Toggle Record Enable Track20"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:330
+#: gtk2_ardour/ardour_ui_ed.cc:337
msgid "Toggle Record Enable Track21"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:332
+#: gtk2_ardour/ardour_ui_ed.cc:339
msgid "Toggle Record Enable Track22"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:334
+#: gtk2_ardour/ardour_ui_ed.cc:341
msgid "Toggle Record Enable Track23"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:336
+#: gtk2_ardour/ardour_ui_ed.cc:343
msgid "Toggle Record Enable Track24"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:338
+#: gtk2_ardour/ardour_ui_ed.cc:345
msgid "Toggle Record Enable Track25"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:340
+#: gtk2_ardour/ardour_ui_ed.cc:347
msgid "Toggle Record Enable Track26"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:342
+#: gtk2_ardour/ardour_ui_ed.cc:349
msgid "Toggle Record Enable Track27"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:344
+#: gtk2_ardour/ardour_ui_ed.cc:351
msgid "Toggle Record Enable Track28"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:346
+#: gtk2_ardour/ardour_ui_ed.cc:353
msgid "Toggle Record Enable Track29"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:348
+#: gtk2_ardour/ardour_ui_ed.cc:355
msgid "Toggle Record Enable Track30"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:350
+#: gtk2_ardour/ardour_ui_ed.cc:357
msgid "Toggle Record Enable Track31"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:352
+#: gtk2_ardour/ardour_ui_ed.cc:359
msgid "Toggle Record Enable Track32"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:357
+#: gtk2_ardour/ardour_ui_ed.cc:364
msgid "Percentage"
msgstr "Процентов"
-#: gtk2_ardour/ardour_ui_ed.cc:358
+#: gtk2_ardour/ardour_ui_ed.cc:365
msgid "Semitones"
msgstr "Полутонов"
-#: gtk2_ardour/ardour_ui_ed.cc:362
+#: gtk2_ardour/ardour_ui_ed.cc:369
msgid "Send MTC"
msgstr "Передавать MTC"
-#: gtk2_ardour/ardour_ui_ed.cc:364
+#: gtk2_ardour/ardour_ui_ed.cc:371
msgid "Send MMC"
msgstr "Передавать MMC"
-#: gtk2_ardour/ardour_ui_ed.cc:366
+#: gtk2_ardour/ardour_ui_ed.cc:373
msgid "Use MMC"
msgstr "ИÑпользовать MMC"
-#: gtk2_ardour/ardour_ui_ed.cc:368
+#: gtk2_ardour/ardour_ui_ed.cc:375
msgid "Send MIDI feedback"
msgstr "Передавать отклик MIDI"
-#: gtk2_ardour/ardour_ui_ed.cc:370
+#: gtk2_ardour/ardour_ui_ed.cc:377
msgid "Use MIDI control"
msgstr "ИÑпользовать управление по MIDI"
-#: gtk2_ardour/ardour_ui_ed.cc:373
-msgid "Connect new track inputs to hardware"
-msgstr "Подключать входы новых дорожек к уÑтройÑтву"
-
-#: gtk2_ardour/ardour_ui_ed.cc:392
-msgid "Connect new track outputs to hardware"
-msgstr "Подключать выходы новых дорожек к уÑтройÑтву"
-
-#: gtk2_ardour/ardour_ui_ed.cc:394
-msgid "Connect new track outputs to master"
-msgstr "Подключать выходы новых дорожек к маÑтеру"
-
-#: gtk2_ardour/ardour_ui_ed.cc:396
-msgid "Manually connect new track outputs"
-msgstr "Ручное подключение дорожек к выходам"
-
-#: gtk2_ardour/ardour_ui_ed.cc:401
-msgid "Hardware monitoring"
-msgstr "Ðппаратный контроль"
-
-#: gtk2_ardour/ardour_ui_ed.cc:402
-msgid "Software monitoring"
-msgstr "Программный контроль"
-
-#: gtk2_ardour/ardour_ui_ed.cc:403
-msgid "External monitoring"
-msgstr "Внешний контроль"
-
-#: gtk2_ardour/ardour_ui_ed.cc:407
+#: gtk2_ardour/ardour_ui_ed.cc:380
msgid "Stop plugins with transport"
msgstr "ОÑтанавливать раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ñ Ñ‚Ñ€Ð°Ð½Ñпортом"
-#: gtk2_ardour/ardour_ui_ed.cc:408
+#: gtk2_ardour/ardour_ui_ed.cc:381
msgid "Verify remove last capture"
msgstr "Проверить удаление поÑледней запиÑи"
-#: gtk2_ardour/ardour_ui_ed.cc:409
+#: gtk2_ardour/ardour_ui_ed.cc:382
msgid "Stop recording on xrun"
msgstr "ОÑтановить запиÑÑŒ при потере отÑчётов"
-#: gtk2_ardour/ardour_ui_ed.cc:410
+#: gtk2_ardour/ardour_ui_ed.cc:383
msgid "Stop transport at session end"
msgstr "ОÑтанавливать транÑпорт в конце ÑеÑÑии"
-#: gtk2_ardour/ardour_ui_ed.cc:411
+#: gtk2_ardour/ardour_ui_ed.cc:384
msgid "-12dB gain reduce ffwd/rewind"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:412
+#: gtk2_ardour/ardour_ui_ed.cc:385
msgid "Rec-enable stays engaged at stop"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:416
-#, fuzzy
+#: gtk2_ardour/ardour_ui_ed.cc:387
msgid "Do not run plugins while recording"
-msgstr "ИÑпользовать модули (plugins) во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи"
+msgstr "Ðе запуÑкать раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð²Ð¾ Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи"
-#: gtk2_ardour/ardour_ui_ed.cc:419
+#: gtk2_ardour/ardour_ui_ed.cc:390
msgid "Latched solo"
-msgstr ""
+msgstr "Запертое Ñоло"
-#: gtk2_ardour/ardour_ui_ed.cc:424
+#: gtk2_ardour/ardour_ui_ed.cc:398 gtk2_ardour/ardour_ui_ed.cc:406
+#: gtk2_ardour/audio_clock.cc:1805 gtk2_ardour/gain_meter.cc:159
+#: gtk2_ardour/ladspa_pluginui.cc:330 gtk2_ardour/ladspa_pluginui.cc:573
+#: gtk2_ardour/panner_ui.cc:89
+msgid "Off"
+msgstr "Выкл"
+
+#: gtk2_ardour/ardour_ui_ed.cc:399 gtk2_ardour/editor.cc:1357
+#: gtk2_ardour/editor.cc:1374
+msgid "Slowest"
+msgstr "Медленнее вÑего"
+
+#: gtk2_ardour/ardour_ui_ed.cc:400 gtk2_ardour/editor.cc:1358
+#: gtk2_ardour/editor.cc:1375
+msgid "Slow"
+msgstr "Медленно"
+
+#: gtk2_ardour/ardour_ui_ed.cc:401 gtk2_ardour/ardour_ui_ed.cc:408
+msgid "Medium"
+msgstr "Средне"
+
+#: gtk2_ardour/ardour_ui_ed.cc:402 gtk2_ardour/editor.cc:1359
+#: gtk2_ardour/editor.cc:1376
+msgid "Fast"
+msgstr "БыÑтро"
+
+#: gtk2_ardour/ardour_ui_ed.cc:403
+msgid "Faster"
+msgstr "БыÑтрее"
+
+#: gtk2_ardour/ardour_ui_ed.cc:404 gtk2_ardour/editor.cc:1360
+#: gtk2_ardour/editor.cc:1377
+msgid "Fastest"
+msgstr "БыÑтрее вÑего"
+
+#: gtk2_ardour/ardour_ui_ed.cc:407 gtk2_ardour/editor_actions.cc:58
+msgid "Short"
+msgstr "КороткаÑ"
+
+#: gtk2_ardour/ardour_ui_ed.cc:409
+msgid "Long"
+msgstr "ДолгаÑ"
+
+#: gtk2_ardour/ardour_ui_ed.cc:427
+msgid "Hardware monitoring"
+msgstr "Ðппаратный контроль"
+
+#: gtk2_ardour/ardour_ui_ed.cc:428
+msgid "Software monitoring"
+msgstr "Программный контроль"
+
+#: gtk2_ardour/ardour_ui_ed.cc:429
+msgid "External monitoring"
+msgstr "Внешний контроль"
+
+#: gtk2_ardour/ardour_ui_ed.cc:433
#, fuzzy
msgid "Solo in-place"
msgstr "Соло"
-#: gtk2_ardour/ardour_ui_ed.cc:426
+#: gtk2_ardour/ardour_ui_ed.cc:435
msgid "Solo via bus"
msgstr ""
-#: gtk2_ardour/ardour_ui_ed.cc:429
-#, fuzzy
-msgid "Automatically create crossfades"
-msgstr "ÐвтоматичеÑкий кроÑÑфейд на перекрытии"
+#: gtk2_ardour/ardour_ui_ed.cc:440
+msgid "Auto-connect inputs to physical inputs"
+msgstr "ÐвтоÑоединить входы Ñ Ñ„Ð¸Ð·Ð¸Ñ‡ÐµÑкими входами"
+
+#: gtk2_ardour/ardour_ui_ed.cc:442
+msgid "Manually connect inputs"
+msgstr "Вручную подключитьÑÑ Ðº входам"
+
+#: gtk2_ardour/ardour_ui_ed.cc:447
+msgid "Auto-connect outputs to physical outs"
+msgstr "Ðвтомат. Ñоединить выходы Ñ Ñ„Ð¸Ð·Ð¸Ñ‡ÐµÑкими выходами"
+
+#: gtk2_ardour/ardour_ui_ed.cc:449
+msgid "Auto-connect outputs to master bus"
+msgstr "Ðвтомат. Ñоединить выходы Ñ Ð¼Ð°Ñтером"
+
+#: gtk2_ardour/ardour_ui_ed.cc:451
+msgid "Manually connect outputs"
+msgstr "Вручную подключить выходы"
+
+#: gtk2_ardour/ardour_ui_ed.cc:549 gtk2_ardour/ladspa_pluginui.cc:168
+msgid "Controls"
+msgstr "Управление"
+
+#: gtk2_ardour/ardour_ui_ed.cc:553
+msgid "Feedback"
+msgstr "Отклик"
-#: gtk2_ardour/ardour_ui_ed.cc:431
-msgid "Unmute new full crossfades"
+#: gtk2_ardour/ardour_ui_ed.cc:633
+msgid "ardour: clock"
+msgstr "ardour: Ñчётчик"
+
+#: gtk2_ardour/ardour_ui_options.cc:205
+msgid "programming error: unknown solo model in ARDOUR_UI::set_solo_model: %1"
msgstr ""
-#: gtk2_ardour/ardour_ui_options.cc:423 gtk2_ardour/ardour_ui_options.cc:433
-#: gtk2_ardour/ardour_ui_options.cc:501
-#, fuzzy
-msgid "Internal"
-msgstr "внутренний"
+#: gtk2_ardour/ardour_ui_options.cc:239
+msgid "programming error: unknown monitor model in ARDOUR_UI::set_monitor_model: %1"
+msgstr ""
+
+#: gtk2_ardour/ardour_ui_options.cc:492
+msgid ""
+"programming error: unknown file header format passed to ARDOUR_UI::"
+"map_file_data_format: %1"
+msgstr ""
+
+#: gtk2_ardour/ardour_ui_options.cc:524
+msgid ""
+"programming error: unknown file data format passed to ARDOUR_UI::"
+"map_file_data_format: %1"
+msgstr ""
-#: gtk2_ardour/ardour_ui_options.cc:424 gtk2_ardour/ardour_ui_options.cc:504
+#: gtk2_ardour/ardour_ui_options.cc:824
#, fuzzy
-msgid "MTC"
-msgstr "MMC"
+msgid "ST"
+msgstr "УСТÐÐОВИТЬ"
-#: gtk2_ardour/audio_clock.cc:1742 gtk2_ardour/editor.cc:189
-msgid "SMPTE"
-msgstr "SMPTE"
+#: gtk2_ardour/audio_clock.cc:1801 gtk2_ardour/editor.cc:180
+msgid "Timecode"
+msgstr "Тайм-код"
-#: gtk2_ardour/audio_clock.cc:1743 gtk2_ardour/editor.cc:188
-#: gtk2_ardour/editor_rulers.cc:359
+#: gtk2_ardour/audio_clock.cc:1802 gtk2_ardour/editor.cc:179
+#: gtk2_ardour/editor_rulers.cc:386
msgid "Bars:Beats"
msgstr "Такт:ДолÑ"
-#: gtk2_ardour/audio_clock.cc:1744
+#: gtk2_ardour/audio_clock.cc:1803
msgid "Minutes:Seconds"
msgstr "Минуты:Секунды"
-#: gtk2_ardour/audio_clock.cc:1745
+#: gtk2_ardour/audio_clock.cc:1804
msgid "Audio Frames"
msgstr "Ðудио кадры"
-#: gtk2_ardour/audio_clock.cc:1746 gtk2_ardour/editor_actions.cc:379
-#: gtk2_ardour/editor_actions.cc:387 gtk2_ardour/gain_meter.cc:167
-#: gtk2_ardour/ladspa_pluginui.cc:330 gtk2_ardour/ladspa_pluginui.cc:573
-#: gtk2_ardour/panner_ui.cc:87
-msgid "Off"
-msgstr "Выкл"
-
-#: gtk2_ardour/audio_clock.cc:1748
+#: gtk2_ardour/audio_clock.cc:1807
msgid "Mode"
msgstr "Режим"
-#: gtk2_ardour/route_time_axis.cc:86
+#: gtk2_ardour/route_time_axis.cc:87
msgid "m"
msgstr "Ñ‚"
-#: gtk2_ardour/route_time_axis.cc:86
+#: gtk2_ardour/route_time_axis.cc:87
msgid "s"
msgstr "Ñ"
-#: gtk2_ardour/route_time_axis.cc:86
+#: gtk2_ardour/route_time_axis.cc:87
msgid "r"
msgstr "з"
-#: gtk2_ardour/route_time_axis.cc:90
+#: gtk2_ardour/route_time_axis.cc:91
msgid "g"
msgstr "г"
-#: gtk2_ardour/route_time_axis.cc:91
+#: gtk2_ardour/route_time_axis.cc:92
msgid "p"
msgstr "Ñп"
-#: gtk2_ardour/route_time_axis.cc:92 gtk2_ardour/automation_time_axis.cc:33
+#: gtk2_ardour/route_time_axis.cc:93 gtk2_ardour/automation_time_axis.cc:36
#: gtk2_ardour/visual_time_axis.cc:74
msgid "h"
msgstr "в"
-#: gtk2_ardour/route_time_axis.cc:93
+#: gtk2_ardour/route_time_axis.cc:94
msgid "a"
msgstr "а"
-#: gtk2_ardour/route_time_axis.cc:94 gtk2_ardour/visual_time_axis.cc:73
+#: gtk2_ardour/route_time_axis.cc:95 gtk2_ardour/visual_time_axis.cc:73
msgid "v"
msgstr "п"
-#: gtk2_ardour/route_time_axis.cc:138 gtk2_ardour/mixer_strip.cc:83
+#: gtk2_ardour/route_time_axis.cc:150 gtk2_ardour/mixer_strip.cc:85
msgid "Record"
msgstr "ЗапиÑÑŒ"
-#: gtk2_ardour/route_time_axis.cc:146 gtk2_ardour/editor_actions.cc:37
-#: gtk2_ardour/mixer_strip.cc:83
+#: gtk2_ardour/route_time_axis.cc:158 gtk2_ardour/editor_actions.cc:38
+#: gtk2_ardour/mixer_strip.cc:85 gtk2_ardour/mixer_strip.cc:433
msgid "Solo"
msgstr "Соло"
-#: gtk2_ardour/route_time_axis.cc:147 gtk2_ardour/editor.cc:1710
-#: gtk2_ardour/editor.cc:1809 gtk2_ardour/mixer_strip.cc:83
-#: gtk2_ardour/panner_ui.cc:417
+#: gtk2_ardour/route_time_axis.cc:159 gtk2_ardour/editor.cc:1660
+#: gtk2_ardour/editor.cc:1750 gtk2_ardour/mixer_strip.cc:85
+#: gtk2_ardour/mixer_strip.cc:432 gtk2_ardour/panner_ui.cc:430
msgid "Mute"
msgstr "Тихо"
-#: gtk2_ardour/route_time_axis.cc:148
+#: gtk2_ardour/route_time_axis.cc:160
msgid "Edit Group"
msgstr "Группы"
-#: gtk2_ardour/route_time_axis.cc:149 gtk2_ardour/visual_time_axis.cc:92
+#: gtk2_ardour/route_time_axis.cc:161 gtk2_ardour/visual_time_axis.cc:92
msgid "Display Height"
msgstr "Ð’Ñ‹Ñота дорожки"
-#: gtk2_ardour/route_time_axis.cc:150
+#: gtk2_ardour/route_time_axis.cc:162
msgid "Playlist"
msgstr "СпиÑок"
-#: gtk2_ardour/route_time_axis.cc:151 gtk2_ardour/route_time_axis.cc:428
+#: gtk2_ardour/route_time_axis.cc:163 gtk2_ardour/route_time_axis.cc:425
msgid "Automation"
msgstr "Ðвтомат"
-#: gtk2_ardour/route_time_axis.cc:152 gtk2_ardour/visual_time_axis.cc:93
+#: gtk2_ardour/route_time_axis.cc:164 gtk2_ardour/visual_time_axis.cc:93
msgid "Visual options"
msgstr "Параметры отображениÑ"
-#: gtk2_ardour/route_time_axis.cc:153 gtk2_ardour/visual_time_axis.cc:94
+#: gtk2_ardour/route_time_axis.cc:165 gtk2_ardour/visual_time_axis.cc:94
msgid "Hide this track"
-msgstr "Скрыть трек"
+msgstr "Скрыть дорожку"
-#: gtk2_ardour/route_time_axis.cc:272 gtk2_ardour/mixer_strip.cc:887
+#: gtk2_ardour/route_time_axis.cc:276 gtk2_ardour/mixer_strip.cc:917
msgid "No group"
msgstr "Ðет группы"
-#: gtk2_ardour/route_time_axis.cc:389
-#, fuzzy
+#: gtk2_ardour/route_time_axis.cc:386
msgid "Show all automation"
-msgstr "автомат"
+msgstr "Показать вÑÑŽ автоматизацию"
-#: gtk2_ardour/route_time_axis.cc:392
-#, fuzzy
+#: gtk2_ardour/route_time_axis.cc:389
msgid "Show existing automation"
-msgstr "иÑпользовать имеющийÑÑ ÑˆÐ°Ð±Ð»Ð¾Ð½"
+msgstr "Показать ÑущеÑтвующую автоматизацию"
-#: gtk2_ardour/route_time_axis.cc:395
-#, fuzzy
+#: gtk2_ardour/route_time_axis.cc:392
msgid "Hide all automation"
-msgstr "очиÑтить интервалы"
+msgstr "СпрÑтать вÑÑŽ автоматизацию"
-#: gtk2_ardour/route_time_axis.cc:398
+#: gtk2_ardour/route_time_axis.cc:395
msgid "Plugins"
-msgstr "Модули (плагины)"
+msgstr "РаÑширениÑ"
-#: gtk2_ardour/route_time_axis.cc:419 gtk2_ardour/automation_time_axis.cc:426
+#: gtk2_ardour/route_time_axis.cc:416 gtk2_ardour/automation_time_axis.cc:430
#: gtk2_ardour/imageframe_time_axis.cc:255 gtk2_ardour/marker_time_axis.cc:211
msgid "Height"
msgstr "Ð’Ñ‹Ñота"
-#: gtk2_ardour/route_time_axis.cc:420 gtk2_ardour/color_manager.cc:41
+#: gtk2_ardour/route_time_axis.cc:417 gtk2_ardour/color_manager.cc:41
#: gtk2_ardour/imageframe_time_axis.cc:256 gtk2_ardour/marker_time_axis.cc:212
msgid "Color"
msgstr "Цвет"
-#: gtk2_ardour/route_time_axis.cc:425 gtk2_ardour/mixer_strip.cc:971
-#, fuzzy
+#: gtk2_ardour/route_time_axis.cc:422 gtk2_ardour/mixer_strip.cc:1002
msgid "Remote Control ID"
-msgstr "иÑпользовать контрольные выходы"
+msgstr ""
-#: gtk2_ardour/route_time_axis.cc:443
+#: gtk2_ardour/route_time_axis.cc:440
#, fuzzy
msgid "Align with existing material"
msgstr "СущеÑтвующий материал"
-#: gtk2_ardour/route_time_axis.cc:449
+#: gtk2_ardour/route_time_axis.cc:446
#, fuzzy
msgid "Align with capture time"
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи"
-#: gtk2_ardour/route_time_axis.cc:455
+#: gtk2_ardour/route_time_axis.cc:452
#, fuzzy
msgid "Alignment"
msgstr "ВыровнÑÑ‚ÑŒ"
-#: gtk2_ardour/route_time_axis.cc:462 gtk2_ardour/editor.cc:480
-#: gtk2_ardour/editor_actions.cc:62 gtk2_ardour/mixer_strip.cc:960
+#: gtk2_ardour/route_time_axis.cc:458
+#, fuzzy
+msgid "Normal mode"
+msgstr "Ðорм."
+
+#: gtk2_ardour/route_time_axis.cc:461
+msgid "Tape mode"
+msgstr ""
+
+#: gtk2_ardour/route_time_axis.cc:477 gtk2_ardour/editor.cc:480
+#: gtk2_ardour/editor_actions.cc:61 gtk2_ardour/mixer_strip.cc:991
#: gtk2_ardour/mixer_ui.cc:109
msgid "Active"
msgstr "Ðктивны"
-#: gtk2_ardour/route_time_axis.cc:467 gtk2_ardour/editor.cc:1872
-#: gtk2_ardour/editor_actions.cc:322 gtk2_ardour/editor_markers.cc:511
+#: gtk2_ardour/route_time_axis.cc:482 gtk2_ardour/editor.cc:1840
+#: gtk2_ardour/editor_actions.cc:326 gtk2_ardour/editor_markers.cc:512
#: gtk2_ardour/imageframe_time_axis.cc:259 gtk2_ardour/location_ui.cc:58
-#: gtk2_ardour/marker_time_axis.cc:215 gtk2_ardour/mixer_strip.cc:974
+#: gtk2_ardour/marker_time_axis.cc:215 gtk2_ardour/mixer_strip.cc:1005
msgid "Remove"
msgstr "Удалить"
-#: gtk2_ardour/route_time_axis.cc:733
-#, fuzzy
+#: gtk2_ardour/route_time_axis.cc:508 gtk2_ardour/route_time_axis.cc:563
+#: gtk2_ardour/route_time_axis.cc:828 gtk2_ardour/editor_actions.cc:1015
+msgid "programming error: %1 %2"
+msgstr "ошибка в программе: %1 %2"
+
+#: gtk2_ardour/route_time_axis.cc:852
msgid "Name for playlist"
-msgstr "Ð˜Ð¼Ñ Ñнимка"
+msgstr "Ð˜Ð¼Ñ ÑпиÑка воÑпроизведениÑ"
-#: gtk2_ardour/route_time_axis.cc:735 gtk2_ardour/route_time_axis.cc:1136
-#: gtk2_ardour/editor_markers.cc:830 gtk2_ardour/editor_mouse.cc:4723
+#: gtk2_ardour/route_time_axis.cc:854 gtk2_ardour/route_time_axis.cc:1306
+#: gtk2_ardour/editor_markers.cc:857 gtk2_ardour/editor_mouse.cc:4757
#: gtk2_ardour/imageframe_time_axis.cc:248 gtk2_ardour/marker_time_axis.cc:208
-#: gtk2_ardour/mixer_strip.cc:958 gtk2_ardour/redirect_box.cc:752
-#: gtk2_ardour/redirect_box.cc:1080 gtk2_ardour/route_ui.cc:746
-#: gtk2_ardour/visual_time_axis.cc:326
+#: gtk2_ardour/mixer_strip.cc:989 gtk2_ardour/redirect_box.cc:823
+#: gtk2_ardour/redirect_box.cc:1149 gtk2_ardour/route_ui.cc:760
+#: gtk2_ardour/visual_time_axis.cc:331
msgid "Rename"
msgstr "Переименовать"
-#: gtk2_ardour/route_time_axis.cc:770 gtk2_ardour/route_time_axis.cc:811
-#, fuzzy
+#: gtk2_ardour/route_time_axis.cc:896 gtk2_ardour/route_time_axis.cc:942
msgid "Name for Playlist"
-msgstr "Ð˜Ð¼Ñ Ñнимка"
+msgstr "Ð˜Ð¼Ñ ÑпиÑка воÑпроизведениÑ"
-#: gtk2_ardour/route_time_axis.cc:990 gtk2_ardour/visual_time_axis.cc:383
-msgid "a track already exists with that name"
+#: gtk2_ardour/route_time_axis.cc:1134 gtk2_ardour/visual_time_axis.cc:341
+#: gtk2_ardour/visual_time_axis.cc:388
+msgid "A track already exists with that name"
msgstr "Дорожка Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует"
-#: gtk2_ardour/route_time_axis.cc:1133
-msgid "Current: %1"
-msgstr ""
-
-#: gtk2_ardour/route_time_axis.cc:1140
+#: gtk2_ardour/route_time_axis.cc:1310
msgid "New Copy"
msgstr "ÐÐ¾Ð²Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ"
-#: gtk2_ardour/route_time_axis.cc:1142
+#: gtk2_ardour/route_time_axis.cc:1312
msgid "Clear Current"
msgstr "ОчиÑтить текущий"
-#: gtk2_ardour/route_time_axis.cc:1144 gtk2_ardour/editor.cc:1974
-#: gtk2_ardour/editor.cc:2050
-msgid "Select"
-msgstr "Выделить"
+#: gtk2_ardour/route_time_axis.cc:1315
+msgid "Select from all ..."
+msgstr "Выбрать из вÑех..."
-#: gtk2_ardour/route_time_axis.cc:1333 gtk2_ardour/editor.cc:1432
+#: gtk2_ardour/route_time_axis.cc:1521 gtk2_ardour/editor.cc:1382
#: gtk2_ardour/selection.cc:642
msgid "programming error: "
msgstr "Ошибка в программе: "
-#: gtk2_ardour/audio_time_axis.cc:229
+#: gtk2_ardour/audio_time_axis.cc:222
msgid "Fader"
msgstr "Фейдер"
-#: gtk2_ardour/audio_time_axis.cc:234
+#: gtk2_ardour/audio_time_axis.cc:227
msgid "Pan"
msgstr "Пан."
-#: gtk2_ardour/audio_time_axis.cc:249
+#: gtk2_ardour/audio_time_axis.cc:242
msgid "Hide all crossfades"
msgstr "Скрыть вÑе кроÑÑфейды"
-#: gtk2_ardour/audio_time_axis.cc:250
+#: gtk2_ardour/audio_time_axis.cc:243
msgid "Show all crossfades"
msgstr "Показать вÑе кроÑÑфейды"
-#: gtk2_ardour/audio_time_axis.cc:257
+#: gtk2_ardour/audio_time_axis.cc:250
msgid "Show waveforms"
-msgstr "Показывать форму Ñигнала"
+msgstr "Показать форму Ñигнала"
-#: gtk2_ardour/audio_time_axis.cc:265
+#: gtk2_ardour/audio_time_axis.cc:260
msgid "Traditional"
msgstr "ОбычнаÑ"
-#: gtk2_ardour/audio_time_axis.cc:268
+#: gtk2_ardour/audio_time_axis.cc:263
msgid "Rectified"
msgstr "УвеличеннаÑ"
-#: gtk2_ardour/audio_time_axis.cc:271
+#: gtk2_ardour/audio_time_axis.cc:270 gtk2_ardour/editor.cc:1356
+#: gtk2_ardour/editor.cc:1373
+msgid "Linear"
+msgstr "ЛинейнаÑ"
+
+#: gtk2_ardour/audio_time_axis.cc:273
+msgid "Logarithmic"
+msgstr "ЛогарифмичеÑкаÑ"
+
+#: gtk2_ardour/audio_time_axis.cc:290
msgid "Waveform"
msgstr "Форма Ñигнала"
-#: gtk2_ardour/audio_time_axis.cc:331
+#: gtk2_ardour/audio_time_axis.cc:362
msgid "gain"
msgstr "уÑил."
-#: gtk2_ardour/audio_time_axis.cc:371
+#: gtk2_ardour/audio_time_axis.cc:402
msgid "pan"
msgstr "пан."
-#: gtk2_ardour/automation_line.cc:888
+#: gtk2_ardour/automation_line.cc:795
#, fuzzy
msgid "automation event move"
msgstr "автомат"
-#: gtk2_ardour/automation_line.cc:890
+#: gtk2_ardour/automation_line.cc:797
#, fuzzy
msgid "automation range drag"
msgstr "автомат"
-#: gtk2_ardour/automation_line.cc:1019 gtk2_ardour/region_gain_line.cc:64
+#: gtk2_ardour/automation_line.cc:1022 gtk2_ardour/region_gain_line.cc:64
#, fuzzy
msgid "remove control point"
msgstr "иÑпользовать контрольные выходы"
-#: gtk2_ardour/automation_time_axis.cc:34 gtk2_ardour/editor_ops.cc:2922
+#: gtk2_ardour/automation_time_axis.cc:37 gtk2_ardour/editor_ops.cc:2840
msgid "clear"
msgstr "очиÑтить"
-#: gtk2_ardour/automation_time_axis.cc:79
+#: gtk2_ardour/automation_time_axis.cc:78
msgid "track height"
msgstr "Ð’Ñ‹Ñота дорожки"
-#: gtk2_ardour/automation_time_axis.cc:80
+#: gtk2_ardour/automation_time_axis.cc:79
msgid "automation state"
msgstr "СоÑтоÑние автоматизации"
-#: gtk2_ardour/automation_time_axis.cc:81
+#: gtk2_ardour/automation_time_axis.cc:80
msgid "clear track"
msgstr "ОчиÑтить дорожку"
-#: gtk2_ardour/automation_time_axis.cc:82
+#: gtk2_ardour/automation_time_axis.cc:81
msgid "hide track"
msgstr "Скрыть дорожку"
-#: gtk2_ardour/automation_time_axis.cc:188
-#: gtk2_ardour/automation_time_axis.cc:217
-#: gtk2_ardour/automation_time_axis.cc:437
+#: gtk2_ardour/automation_time_axis.cc:187
+#: gtk2_ardour/automation_time_axis.cc:216
+#: gtk2_ardour/automation_time_axis.cc:441
msgid "Manual"
msgstr ""
-#: gtk2_ardour/automation_time_axis.cc:190
-#: gtk2_ardour/automation_time_axis.cc:228
-#: gtk2_ardour/automation_time_axis.cc:441 gtk2_ardour/editor.cc:1951
-#: gtk2_ardour/editor.cc:2032 gtk2_ardour/gain_meter.cc:169
+#: gtk2_ardour/automation_time_axis.cc:189
+#: gtk2_ardour/automation_time_axis.cc:227
+#: gtk2_ardour/automation_time_axis.cc:445 gtk2_ardour/editor.cc:1918
+#: gtk2_ardour/editor.cc:1999 gtk2_ardour/gain_meter.cc:161
#: gtk2_ardour/ladspa_pluginui.cc:333 gtk2_ardour/ladspa_pluginui.cc:575
-#: gtk2_ardour/panner_ui.cc:89 gtk2_ardour/sfdb_ui.cc:59
+#: gtk2_ardour/panner_ui.cc:91 gtk2_ardour/sfdb_ui.cc:58
msgid "Play"
msgstr "ВоÑпроизвеÑти"
-#: gtk2_ardour/automation_time_axis.cc:192
-#: gtk2_ardour/automation_time_axis.cc:239
-#: gtk2_ardour/automation_time_axis.cc:445 gtk2_ardour/gain_meter.cc:171
+#: gtk2_ardour/automation_time_axis.cc:191
+#: gtk2_ardour/automation_time_axis.cc:238
+#: gtk2_ardour/automation_time_axis.cc:449 gtk2_ardour/gain_meter.cc:163
#: gtk2_ardour/ladspa_pluginui.cc:336 gtk2_ardour/ladspa_pluginui.cc:577
-#: gtk2_ardour/panner_ui.cc:91
+#: gtk2_ardour/panner_ui.cc:93
msgid "Write"
msgstr "ЗапиÑать"
-#: gtk2_ardour/automation_time_axis.cc:194
-#: gtk2_ardour/automation_time_axis.cc:250
-#: gtk2_ardour/automation_time_axis.cc:449 gtk2_ardour/gain_meter.cc:173
+#: gtk2_ardour/automation_time_axis.cc:193
+#: gtk2_ardour/automation_time_axis.cc:249
+#: gtk2_ardour/automation_time_axis.cc:453 gtk2_ardour/gain_meter.cc:165
#: gtk2_ardour/ladspa_pluginui.cc:339 gtk2_ardour/ladspa_pluginui.cc:579
-#: gtk2_ardour/panner_ui.cc:93
+#: gtk2_ardour/panner_ui.cc:95
#, fuzzy
msgid "Touch"
msgstr "Врезка"
-#: gtk2_ardour/automation_time_axis.cc:261 gtk2_ardour/ladspa_pluginui.cc:342
+#: gtk2_ardour/automation_time_axis.cc:260 gtk2_ardour/ladspa_pluginui.cc:342
msgid "???"
msgstr "???"
-#: gtk2_ardour/automation_time_axis.cc:275
+#: gtk2_ardour/automation_time_axis.cc:274
msgid "clear automation"
msgstr "ОчиÑтить автоматизацию"
-#: gtk2_ardour/automation_time_axis.cc:428 gtk2_ardour/editor_actions.cc:320
+#: gtk2_ardour/automation_time_axis.cc:432 gtk2_ardour/editor_actions.cc:324
msgid "Hide"
msgstr "Скрыть"
-#: gtk2_ardour/automation_time_axis.cc:430 gtk2_ardour/crossfade_edit.cc:79
-#: gtk2_ardour/redirect_box.cc:1072 gtk2_ardour/connection_editor.cc:57
+#: gtk2_ardour/automation_time_axis.cc:434 gtk2_ardour/crossfade_edit.cc:79
+#: gtk2_ardour/redirect_box.cc:1141 gtk2_ardour/connection_editor.cc:57
msgid "Clear"
msgstr "ОчиÑтить"
-#: gtk2_ardour/automation_time_axis.cc:453
+#: gtk2_ardour/automation_time_axis.cc:457
msgid "State"
msgstr "СоÑтоÑние"
@@ -1650,7 +1787,7 @@ msgstr ""
#: gtk2_ardour/canvas-imageframe.c:120
msgid "y"
-msgstr ""
+msgstr "y"
#: gtk2_ardour/canvas-imageframe.c:121 gtk2_ardour/canvas-simpleline.c:121
#: gtk2_ardour/canvas-simplerect.c:117
@@ -1658,9 +1795,8 @@ msgid "y coordinate of upper left corner of rect "
msgstr ""
#: gtk2_ardour/canvas-imageframe.c:129
-#, fuzzy
msgid "width"
-msgstr "запиÑÑŒ"
+msgstr "Ширина"
#: gtk2_ardour/canvas-imageframe.c:130
msgid "the width"
@@ -1768,7 +1904,7 @@ msgstr ""
#: gtk2_ardour/canvas-simplerect.c:199
msgid "fill color rgba"
-msgstr ""
+msgstr "Цвет заливки в RGBA"
#: gtk2_ardour/canvas-simplerect.c:200
msgid "color of fill"
@@ -1787,7 +1923,7 @@ msgstr "не удалоÑÑŒ отобразить заÑтавку (файл \"%1
msgid "ardour: x-fade edit"
msgstr "ardour: редактор кроÑÑфейдов"
-#: gtk2_ardour/crossfade_edit.cc:80 gtk2_ardour/panner_ui.cc:433
+#: gtk2_ardour/crossfade_edit.cc:80 gtk2_ardour/panner_ui.cc:446
msgid "Reset"
msgstr "СброÑить"
@@ -1829,1528 +1965,1463 @@ msgstr "ÐараÑтание"
msgid "Fade Out"
msgstr "Затухание"
-#: gtk2_ardour/crossfade_edit.cc:173 gtk2_ardour/editor.cc:1785
-#: gtk2_ardour/editor_actions.cc:318 gtk2_ardour/option_editor.cc:129
+#: gtk2_ardour/crossfade_edit.cc:173 gtk2_ardour/editor.cc:1735
+#: gtk2_ardour/editor_actions.cc:322 gtk2_ardour/option_editor.cc:127
msgid "Audition"
msgstr "Контроль"
-#: gtk2_ardour/editor.cc:105 gtk2_ardour/editor.cc:3521
-#, fuzzy
-msgid "Slide Edit"
-msgstr "Скольжение"
-
-#: gtk2_ardour/editor.cc:106 gtk2_ardour/editor.cc:3519
-#, fuzzy
-msgid "Splice Edit"
-msgstr "Стыковка"
-
-#: gtk2_ardour/editor.cc:111 gtk2_ardour/editor.cc:3576
-#: gtk2_ardour/editor_actions.cc:417 gtk2_ardour/export_dialog.cc:78
-#: gtk2_ardour/export_dialog.cc:92 gtk2_ardour/export_dialog.cc:893
-#: gtk2_ardour/export_dialog.cc:1225 gtk2_ardour/route_ui.cc:438
+#: gtk2_ardour/editor.cc:102 gtk2_ardour/editor.cc:3600
+#: gtk2_ardour/editor_actions.cc:400 gtk2_ardour/export_dialog.cc:76
+#: gtk2_ardour/export_dialog.cc:90 gtk2_ardour/export_dialog.cc:891
+#: gtk2_ardour/export_dialog.cc:1223 gtk2_ardour/route_ui.cc:459
msgid "None"
msgstr "Ðет"
-#: gtk2_ardour/editor.cc:112 gtk2_ardour/editor.cc:3564
+#: gtk2_ardour/editor.cc:103 gtk2_ardour/editor.cc:3588
msgid "CD Frames"
msgstr "Выборка CD"
-#: gtk2_ardour/editor.cc:113 gtk2_ardour/editor.cc:3566
+#: gtk2_ardour/editor.cc:104 gtk2_ardour/editor.cc:3590
msgid "SMPTE Frames"
msgstr "SMPTE кадры"
-#: gtk2_ardour/editor.cc:114 gtk2_ardour/editor.cc:3568
+#: gtk2_ardour/editor.cc:105 gtk2_ardour/editor.cc:3592
msgid "SMPTE Seconds"
msgstr "SMPTE Ñекунды"
-#: gtk2_ardour/editor.cc:115 gtk2_ardour/editor.cc:3570
+#: gtk2_ardour/editor.cc:106 gtk2_ardour/editor.cc:3594
msgid "SMPTE Minutes"
msgstr "SMPTE минуты"
-#: gtk2_ardour/editor.cc:116 gtk2_ardour/editor.cc:3572
+#: gtk2_ardour/editor.cc:107 gtk2_ardour/editor.cc:3596
msgid "Seconds"
msgstr "Секунд"
-#: gtk2_ardour/editor.cc:117 gtk2_ardour/editor.cc:3574
+#: gtk2_ardour/editor.cc:108 gtk2_ardour/editor.cc:3598
msgid "Minutes"
msgstr "Минут"
-#: gtk2_ardour/editor.cc:118 gtk2_ardour/editor.cc:3546
+#: gtk2_ardour/editor.cc:109 gtk2_ardour/editor.cc:3570
msgid "Beats/32"
msgstr "долÑм/32"
-#: gtk2_ardour/editor.cc:119 gtk2_ardour/editor.cc:3544
+#: gtk2_ardour/editor.cc:110 gtk2_ardour/editor.cc:3568
msgid "Beats/16"
msgstr "долÑм/16"
-#: gtk2_ardour/editor.cc:120 gtk2_ardour/editor.cc:3542
+#: gtk2_ardour/editor.cc:111 gtk2_ardour/editor.cc:3566
msgid "Beats/8"
msgstr "долÑм/8"
-#: gtk2_ardour/editor.cc:121 gtk2_ardour/editor.cc:3540
+#: gtk2_ardour/editor.cc:112 gtk2_ardour/editor.cc:3564
msgid "Beats/4"
msgstr "долÑм/4"
-#: gtk2_ardour/editor.cc:122 gtk2_ardour/editor.cc:3538
+#: gtk2_ardour/editor.cc:113 gtk2_ardour/editor.cc:3562
msgid "Beats/3"
msgstr "долÑм/3"
-#: gtk2_ardour/editor.cc:123 gtk2_ardour/editor.cc:3548
+#: gtk2_ardour/editor.cc:114 gtk2_ardour/editor.cc:3572
msgid "Beats"
msgstr "долÑм"
-#: gtk2_ardour/editor.cc:124 gtk2_ardour/editor.cc:3550
+#: gtk2_ardour/editor.cc:115 gtk2_ardour/editor.cc:3574
msgid "Bars"
msgstr "тактам"
-#: gtk2_ardour/editor.cc:125 gtk2_ardour/editor.cc:3552
+#: gtk2_ardour/editor.cc:116 gtk2_ardour/editor.cc:3576
msgid "Marks"
msgstr "маркерам"
-#: gtk2_ardour/editor.cc:126 gtk2_ardour/editor.cc:3554
+#: gtk2_ardour/editor.cc:117 gtk2_ardour/editor.cc:136
+#: gtk2_ardour/editor.cc:3578 gtk2_ardour/editor.cc:3643
msgid "Edit Cursor"
msgstr "курÑору"
-#: gtk2_ardour/editor.cc:127 gtk2_ardour/editor.cc:3556
+#: gtk2_ardour/editor.cc:118 gtk2_ardour/editor.cc:3580
msgid "Region starts"
msgstr "нач. облаÑтей"
-#: gtk2_ardour/editor.cc:128 gtk2_ardour/editor.cc:3558
+#: gtk2_ardour/editor.cc:119 gtk2_ardour/editor.cc:3582
msgid "Region ends"
msgstr "оконч. облаÑтей"
-#: gtk2_ardour/editor.cc:129 gtk2_ardour/editor.cc:3562
+#: gtk2_ardour/editor.cc:120 gtk2_ardour/editor.cc:3586
msgid "Region syncs"
msgstr ""
-#: gtk2_ardour/editor.cc:130 gtk2_ardour/editor.cc:3560
+#: gtk2_ardour/editor.cc:121 gtk2_ardour/editor.cc:3584
msgid "Region bounds"
msgstr ""
-#: gtk2_ardour/editor.cc:135 gtk2_ardour/editor.cc:3593
-#, fuzzy
-msgid "Normal Snap"
-msgstr "Ðорм."
-
-#: gtk2_ardour/editor.cc:136 gtk2_ardour/editor.cc:3595
-#, fuzzy
-msgid "Magnetic Snap"
-msgstr "Магн."
+#: gtk2_ardour/editor.cc:127 gtk2_ardour/editor.cc:3618
+#: gtk2_ardour/editor_actions.cc:287
+msgid "Magnetic"
+msgstr "Магнитное"
-#: gtk2_ardour/editor.cc:141 gtk2_ardour/editor.cc:3612
-#, fuzzy
-msgid "Focus Left"
-msgstr "МаÑштабировать к"
-
-#: gtk2_ardour/editor.cc:142 gtk2_ardour/editor.cc:3614
-#, fuzzy
-msgid "Focus Right"
-msgstr "МаÑштабировать к"
+#: gtk2_ardour/editor.cc:132 gtk2_ardour/editor.cc:3635
+#: gtk2_ardour/export_dialog.cc:138 gtk2_ardour/export_dialog.cc:154
+#: gtk2_ardour/export_dialog.cc:1066 gtk2_ardour/export_dialog.cc:1070
+msgid "Left"
+msgstr "Левый"
-#: gtk2_ardour/editor.cc:143 gtk2_ardour/editor.cc:3616
-#, fuzzy
-msgid "Focus Center"
-msgstr "МаÑштабировать к"
+#: gtk2_ardour/editor.cc:133 gtk2_ardour/editor.cc:3637
+#: gtk2_ardour/export_dialog.cc:139 gtk2_ardour/export_dialog.cc:155
+msgid "Right"
+msgstr "Правый"
-#: gtk2_ardour/editor.cc:144
+#: gtk2_ardour/editor.cc:134 gtk2_ardour/editor.cc:3639
#, fuzzy
-msgid "Focus Play"
-msgstr "МаÑштабировать к"
+msgid "Center"
+msgstr "Размер"
-#: gtk2_ardour/editor.cc:145
+#: gtk2_ardour/editor.cc:135 gtk2_ardour/editor.cc:3641
#, fuzzy
-msgid "Focus Edit"
-msgstr "МаÑштабировать к"
+msgid "Playhead"
+msgstr "УÑтановить указатель"
-#: gtk2_ardour/editor.cc:187
+#: gtk2_ardour/editor.cc:178
msgid "Mins:Secs"
msgstr "Мин:Сек"
-#: gtk2_ardour/editor.cc:190 gtk2_ardour/editor_rulers.cc:353
+#: gtk2_ardour/editor.cc:181 gtk2_ardour/editor_rulers.cc:380
msgid "Frames"
msgstr "Кадры"
-#: gtk2_ardour/editor.cc:191 gtk2_ardour/editor_rulers.cc:373
+#: gtk2_ardour/editor.cc:182 gtk2_ardour/editor_rulers.cc:400
msgid "Tempo"
msgstr "Темп"
-#: gtk2_ardour/editor.cc:192 gtk2_ardour/editor_rulers.cc:367
+#: gtk2_ardour/editor.cc:183 gtk2_ardour/editor_rulers.cc:394
msgid "Meter"
msgstr "Размер"
-#: gtk2_ardour/editor.cc:193 gtk2_ardour/editor_rulers.cc:379
+#: gtk2_ardour/editor.cc:184 gtk2_ardour/editor_rulers.cc:406
msgid "Location Markers"
msgstr "Маркеры интервалов"
-#: gtk2_ardour/editor.cc:194 gtk2_ardour/editor_rulers.cc:385
+#: gtk2_ardour/editor.cc:185 gtk2_ardour/editor_rulers.cc:412
msgid "Range Markers"
msgstr "Маркеры облаÑтей"
-#: gtk2_ardour/editor.cc:195 gtk2_ardour/editor_rulers.cc:391
+#: gtk2_ardour/editor.cc:186 gtk2_ardour/editor_rulers.cc:418
msgid "Loop/Punch Ranges"
msgstr "ОблаÑти колец/врезок"
-#: gtk2_ardour/editor.cc:213
+#: gtk2_ardour/editor.cc:204
msgid "mode"
msgstr "режим"
-#: gtk2_ardour/editor.cc:214
+#: gtk2_ardour/editor.cc:205
msgid "automation"
msgstr "автомат"
#: gtk2_ardour/editor.cc:455 gtk2_ardour/editor.cc:481
-#: gtk2_ardour/editor_actions.cc:64 gtk2_ardour/mixer_ui.cc:84
+#: gtk2_ardour/editor_actions.cc:63 gtk2_ardour/mixer_ui.cc:84
#: gtk2_ardour/mixer_ui.cc:110 gtk2_ardour/analysis_window.cc:64
-msgid "Visible"
-msgstr "Видимы"
+msgid "Show"
+msgstr "Показать"
#: gtk2_ardour/editor.cc:456 gtk2_ardour/editor.cc:479
msgid "Name"
msgstr "ИмÑ"
-#: gtk2_ardour/editor.cc:555 gtk2_ardour/editor.cc:622
+#: gtk2_ardour/editor.cc:555 gtk2_ardour/editor.cc:621
msgid "Regions"
msgstr "ОблаÑти"
-#: gtk2_ardour/editor.cc:595 gtk2_ardour/editor.cc:634
+#: gtk2_ardour/editor.cc:594 gtk2_ardour/editor.cc:633
msgid "Chunks"
msgstr "Фрагменты"
-#: gtk2_ardour/editor.cc:625
+#: gtk2_ardour/editor.cc:624
msgid "Tracks/Busses"
msgstr "Дорожки/Шины"
-#: gtk2_ardour/editor.cc:628
+#: gtk2_ardour/editor.cc:627
msgid "Snapshots"
msgstr "Снимки"
-#: gtk2_ardour/editor.cc:631
+#: gtk2_ardour/editor.cc:630
+#, fuzzy
msgid "Edit Groups"
-msgstr ""
-"Ред.\n"
-"группы"
+msgstr "Ред. группы"
-#: gtk2_ardour/editor.cc:680
+#: gtk2_ardour/editor.cc:681
msgid "Nudge Region/Selection Forwards"
-msgstr ""
+msgstr "Подвинуть облаÑÑ‚ÑŒ выделение вперёд"
-#: gtk2_ardour/editor.cc:681
-#, fuzzy
+#: gtk2_ardour/editor.cc:682
msgid "Nudge Region/Selection Backwards"
-msgstr "Скрыть трек"
+msgstr "Подвинуть облаÑÑ‚ÑŒ выделение назад"
-#: gtk2_ardour/editor.cc:688 gtk2_ardour/editor_mixer.cc:296
+#: gtk2_ardour/editor.cc:710 gtk2_ardour/editor_mixer.cc:305
msgid "ardour: editor"
msgstr "ardour: редактор"
-#: gtk2_ardour/editor.cc:689
-msgid "ardour_editor"
-msgstr "ardour_редактор"
-
-#: gtk2_ardour/editor.cc:1122
+#: gtk2_ardour/editor.cc:1116
msgid "ardour: editor: "
msgstr "ardour: редактор: "
-#: gtk2_ardour/editor.cc:1208 gtk2_ardour/editor.cc:1217
-#: gtk2_ardour/editor_markers.cc:874
+#: gtk2_ardour/editor.cc:1189 gtk2_ardour/editor.cc:1198
+#: gtk2_ardour/editor_markers.cc:901
msgid "Loop"
msgstr "Кольцо"
-#: gtk2_ardour/editor.cc:1222 gtk2_ardour/editor.cc:1231
-#: gtk2_ardour/editor_markers.cc:902
+#: gtk2_ardour/editor.cc:1203 gtk2_ardour/editor.cc:1212
+#: gtk2_ardour/editor_markers.cc:929
msgid "Punch"
msgstr "Врезка"
-#: gtk2_ardour/editor.cc:1387 gtk2_ardour/editor_mouse.cc:1748
+#: gtk2_ardour/editor.cc:1337 gtk2_ardour/editor_mouse.cc:1751
#, fuzzy
msgid "programming error: fade in canvas item has no regionview data pointer!"
msgstr "ошибка в программе: line canvas item has no line pointer!"
-#: gtk2_ardour/editor.cc:1400 gtk2_ardour/editor.cc:1417
-#: gtk2_ardour/redirect_box.cc:1088
+#: gtk2_ardour/editor.cc:1349 gtk2_ardour/editor.cc:1366
+#: gtk2_ardour/redirect_box.cc:1157
msgid "Deactivate"
msgstr "Деактивировать"
-#: gtk2_ardour/editor.cc:1402 gtk2_ardour/editor.cc:1419
-#: gtk2_ardour/redirect_box.cc:1086
+#: gtk2_ardour/editor.cc:1351 gtk2_ardour/editor.cc:1368
+#: gtk2_ardour/redirect_box.cc:1155
msgid "Activate"
msgstr "Ðктивировать"
-#: gtk2_ardour/editor.cc:1407 gtk2_ardour/editor.cc:1424
-#, fuzzy
-msgid "Linear"
-msgstr "линейное"
-
-#: gtk2_ardour/editor.cc:1408 gtk2_ardour/editor.cc:1425
-#: gtk2_ardour/editor_actions.cc:380
-msgid "Slowest"
-msgstr "Медленнее вÑего"
-
-#: gtk2_ardour/editor.cc:1409 gtk2_ardour/editor.cc:1426
-#: gtk2_ardour/editor_actions.cc:381
-msgid "Slow"
-msgstr "Медленно"
-
-#: gtk2_ardour/editor.cc:1410 gtk2_ardour/editor.cc:1427
-#: gtk2_ardour/editor_actions.cc:383
-msgid "Fast"
-msgstr "БыÑтро"
-
-#: gtk2_ardour/editor.cc:1411 gtk2_ardour/editor.cc:1428
-#: gtk2_ardour/editor_actions.cc:385
-msgid "Fastest"
-msgstr "БыÑтрее вÑего"
-
-#: gtk2_ardour/editor.cc:1539 gtk2_ardour/editor.cc:1547
+#: gtk2_ardour/editor.cc:1489 gtk2_ardour/editor.cc:1497
msgid "Freeze"
msgstr "Заморозить"
-#: gtk2_ardour/editor.cc:1543
+#: gtk2_ardour/editor.cc:1493
msgid "Unfreeze"
msgstr "Разморозить"
-#: gtk2_ardour/editor.cc:1712 gtk2_ardour/editor.cc:1807
+#: gtk2_ardour/editor.cc:1662
msgid "Unmute"
msgstr "СнÑÑ‚ÑŒ глушение"
-#: gtk2_ardour/editor.cc:1716 gtk2_ardour/editor.cc:1996
-#: gtk2_ardour/editor_actions.cc:27 gtk2_ardour/editor_markers.cc:510
-#: gtk2_ardour/mixer_strip.cc:496 gtk2_ardour/mixer_strip.cc:559
-#: gtk2_ardour/redirect_box.cc:1094
+#: gtk2_ardour/editor.cc:1666 gtk2_ardour/editor.cc:1963
+#: gtk2_ardour/editor_actions.cc:28 gtk2_ardour/editor_markers.cc:511
+#: gtk2_ardour/mixer_strip.cc:515 gtk2_ardour/mixer_strip.cc:577
+#: gtk2_ardour/redirect_box.cc:1163
msgid "Edit"
msgstr "Правка"
-#: gtk2_ardour/editor.cc:1721
+#: gtk2_ardour/editor.cc:1671
msgid "Convert to short"
msgstr ""
-#: gtk2_ardour/editor.cc:1723
+#: gtk2_ardour/editor.cc:1673
msgid "Convert to full"
msgstr ""
-#: gtk2_ardour/editor.cc:1734
+#: gtk2_ardour/editor.cc:1684
msgid "Crossfade"
msgstr "КроÑÑфейд"
-#: gtk2_ardour/editor.cc:1777
+#: gtk2_ardour/editor.cc:1727
msgid "Popup region editor"
msgstr "Открыть редактор облаÑти"
-#: gtk2_ardour/editor.cc:1778
-#, fuzzy
+#: gtk2_ardour/editor.cc:1728
msgid "Raise to top layer"
-msgstr "ПоднÑÑ‚ÑŒ облаÑÑ‚ÑŒ в верхний Ñлой"
+msgstr "ПоднÑÑ‚ÑŒ в верхний Ñлой"
-#: gtk2_ardour/editor.cc:1779
-#, fuzzy
+#: gtk2_ardour/editor.cc:1729
msgid "Lower to bottom layer"
-msgstr "ОпуÑтить облаÑÑ‚ÑŒ в нижний Ñлой"
+msgstr "ОпуÑтить в нижний Ñлой"
-#: gtk2_ardour/editor.cc:1781
+#: gtk2_ardour/editor.cc:1731
msgid "Define sync point"
-msgstr ""
+msgstr "Определить точку Ñинхронизации"
-#: gtk2_ardour/editor.cc:1782
+#: gtk2_ardour/editor.cc:1732
msgid "Remove sync point"
-msgstr ""
+msgstr "Удалить точку Ñинхронизации"
-#: gtk2_ardour/editor.cc:1787
+#: gtk2_ardour/editor.cc:1737
#, fuzzy
msgid "Bounce"
msgstr "СвеÑти выделенное"
-#: gtk2_ardour/editor.cc:1790
+#: gtk2_ardour/editor.cc:1740
#, fuzzy
msgid "Analyze region"
msgstr "ВоÑпроизвеÑти облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:1802
+#: gtk2_ardour/editor.cc:1745
msgid "Lock"
msgstr "Запереть"
-#: gtk2_ardour/editor.cc:1803
-msgid "Unlock"
-msgstr "Отпереть"
+#: gtk2_ardour/editor.cc:1755
+#, fuzzy
+msgid "Opaque"
+msgstr "затенить"
-#: gtk2_ardour/editor.cc:1813
+#: gtk2_ardour/editor.cc:1761
msgid "Original position"
msgstr "ИÑходное положение"
-#: gtk2_ardour/editor.cc:1819
-msgid "Toggle envelope visibility"
-msgstr ""
+#: gtk2_ardour/editor.cc:1773
+msgid "Reset Envelope"
+msgstr "СброÑить огибающую"
-#: gtk2_ardour/editor.cc:1820
-msgid "Toggle envelope active"
-msgstr ""
+#: gtk2_ardour/editor.cc:1775
+msgid "Envelope Visible"
+msgstr "ÐžÐ³Ð¸Ð±Ð°ÑŽÑ‰Ð°Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð°"
-#: gtk2_ardour/editor.cc:1824
+#: gtk2_ardour/editor.cc:1782
+msgid "Envelope Active"
+msgstr "ÐžÐ³Ð¸Ð±Ð°ÑŽÑ‰Ð°Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð°"
+
+#: gtk2_ardour/editor.cc:1792
msgid "DeNormalize"
msgstr "Денормализовать"
-#: gtk2_ardour/editor.cc:1826
+#: gtk2_ardour/editor.cc:1794
msgid "Normalize"
msgstr "Ðормализовать"
-#: gtk2_ardour/editor.cc:1829
+#: gtk2_ardour/editor.cc:1797
msgid "Reverse"
-msgstr ""
+msgstr "Развернуть"
-#: gtk2_ardour/editor.cc:1835
+#: gtk2_ardour/editor.cc:1803 gtk2_ardour/editor.cc:1885
msgid "Add Range Markers"
msgstr "Добавить маркеры облаÑтей"
-#: gtk2_ardour/editor.cc:1836
+#: gtk2_ardour/editor.cc:1804
#, fuzzy
-msgid "Set Range"
-msgstr "Разделить облаÑÑ‚ÑŒ"
+msgid "Set Range Selection"
+msgstr "ВоÑпроизвеÑти выделенное"
-#: gtk2_ardour/editor.cc:1845
+#: gtk2_ardour/editor.cc:1813
msgid "Nudge fwd"
msgstr "Подвинуть вперёд"
-#: gtk2_ardour/editor.cc:1846
+#: gtk2_ardour/editor.cc:1814
msgid "Nudge bwd"
msgstr "Подвинуть назад"
-#: gtk2_ardour/editor.cc:1847
+#: gtk2_ardour/editor.cc:1815
msgid "Nudge fwd by capture offset"
msgstr ""
-#: gtk2_ardour/editor.cc:1848
+#: gtk2_ardour/editor.cc:1816
msgid "Nudge bwd by capture offset"
msgstr ""
-#: gtk2_ardour/editor.cc:1850 gtk2_ardour/editor.cc:2016
-#: gtk2_ardour/editor.cc:2072
+#: gtk2_ardour/editor.cc:1818 gtk2_ardour/editor.cc:1983
+#: gtk2_ardour/editor.cc:2039
msgid "Nudge"
msgstr "Подвинуть"
-#: gtk2_ardour/editor.cc:1857
+#: gtk2_ardour/editor.cc:1825
msgid "Start to edit cursor"
msgstr "От начала до курÑора"
-#: gtk2_ardour/editor.cc:1858
+#: gtk2_ardour/editor.cc:1826
msgid "Edit cursor to end"
msgstr "От курÑора до конца"
-#: gtk2_ardour/editor.cc:1860 gtk2_ardour/gain_meter.cc:176
-#: gtk2_ardour/gain_meter.cc:808 gtk2_ardour/panner_ui.cc:96
-#: gtk2_ardour/panner_ui.cc:793
+#: gtk2_ardour/editor.cc:1828 gtk2_ardour/gain_meter.cc:168
+#: gtk2_ardour/gain_meter.cc:868 gtk2_ardour/panner_ui.cc:98
+#: gtk2_ardour/panner_ui.cc:806
msgid "Trim"
-msgstr ""
+msgstr "Обрезать"
-#: gtk2_ardour/editor.cc:1863
+#: gtk2_ardour/editor.cc:1831
msgid "Split"
-msgstr "Склеить"
+msgstr "Разделить"
-#: gtk2_ardour/editor.cc:1866
+#: gtk2_ardour/editor.cc:1834
msgid "Make mono regions"
msgstr "Создать моно-облаÑти"
-#: gtk2_ardour/editor.cc:1869
+#: gtk2_ardour/editor.cc:1837
msgid "Duplicate"
msgstr "Размножить"
-#: gtk2_ardour/editor.cc:1870
+#: gtk2_ardour/editor.cc:1838
msgid "Fill Track"
msgstr "Заполнить трек"
-#: gtk2_ardour/editor.cc:1874
-msgid "Destroy"
-msgstr ""
-
-#: gtk2_ardour/editor.cc:1904
-#, fuzzy
+#: gtk2_ardour/editor.cc:1870
msgid "Play range"
-msgstr "ВоÑпроизвеÑти \"кольцо\""
+msgstr "ВоÑпроизвеÑти «кольцо»"
-#: gtk2_ardour/editor.cc:1905
+#: gtk2_ardour/editor.cc:1871
msgid "Loop range"
msgstr ""
-#: gtk2_ardour/editor.cc:1909
-#, fuzzy
+#: gtk2_ardour/editor.cc:1875
msgid "Analyze range"
-msgstr "ВоÑпроизвеÑти \"кольцо\""
+msgstr "Проанализировать «кольцо»"
-#: gtk2_ardour/editor.cc:1913
+#: gtk2_ardour/editor.cc:1879
#, fuzzy
msgid "Separate range to track"
msgstr "Разделить облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:1914
+#: gtk2_ardour/editor.cc:1880
#, fuzzy
msgid "Separate range to region list"
msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:1917
-#, fuzzy
+#: gtk2_ardour/editor.cc:1883
msgid "Select all in range"
-msgstr "Выделить вÑÑ‘"
+msgstr "Выделить вÑÑ‘ выделении"
-#: gtk2_ardour/editor.cc:1919 gtk2_ardour/editor.cc:1964
+#: gtk2_ardour/editor.cc:1886 gtk2_ardour/editor.cc:1931
#, fuzzy
msgid "Set range to loop range"
msgstr "выбрать окно проÑмотра"
-#: gtk2_ardour/editor.cc:1920 gtk2_ardour/editor.cc:1965
+#: gtk2_ardour/editor.cc:1887 gtk2_ardour/editor.cc:1932
#, fuzzy
msgid "Set range to punch range"
msgstr "Выбрать текущий интервал"
-#: gtk2_ardour/editor.cc:1922
-#, fuzzy
+#: gtk2_ardour/editor.cc:1889
msgid "Crop region to range"
-msgstr "Обрезать облаÑÑ‚ÑŒ по выделенному"
+msgstr "Обрезать облаÑÑ‚ÑŒ по выделению"
-#: gtk2_ardour/editor.cc:1923
-#, fuzzy
+#: gtk2_ardour/editor.cc:1890
msgid "Fill range with region"
-msgstr "Создать облаÑÑ‚ÑŒ"
+msgstr "Заполнить выделение облаÑтью"
-#: gtk2_ardour/editor.cc:1924
-#, fuzzy
+#: gtk2_ardour/editor.cc:1891
msgid "Duplicate range"
-msgstr "Размножить"
+msgstr "Продублировать выделение"
-#: gtk2_ardour/editor.cc:1925
-#, fuzzy
+#: gtk2_ardour/editor.cc:1892
msgid "Create chunk from range"
-msgstr "Создать фрагмент из выделенного"
+msgstr "Создать фрагмент из выделениÑ"
-#: gtk2_ardour/editor.cc:1927
+#: gtk2_ardour/editor.cc:1894
msgid "Bounce range"
-msgstr ""
+msgstr "СвеÑти выделение"
-#: gtk2_ardour/editor.cc:1928
-#, fuzzy
+#: gtk2_ardour/editor.cc:1895
msgid "Export range"
-msgstr "ЭкÑпорт облаÑти"
+msgstr "ЭкÑпортировать выделение"
-#: gtk2_ardour/editor.cc:1930
-#, fuzzy
+#: gtk2_ardour/editor.cc:1897
msgid "Range"
-msgstr "выделÑÑ‚ÑŒ"
+msgstr "Выделение"
-#: gtk2_ardour/editor.cc:1945 gtk2_ardour/editor.cc:2030
+#: gtk2_ardour/editor.cc:1912 gtk2_ardour/editor.cc:1997
msgid "Play from edit cursor"
msgstr "ВоÑпроизвеÑти от курÑора"
-#: gtk2_ardour/editor.cc:1946 gtk2_ardour/editor.cc:2031
+#: gtk2_ardour/editor.cc:1913 gtk2_ardour/editor.cc:1998
msgid "Play from start"
msgstr "ВоÑпроизвеÑти Ñначала"
-#: gtk2_ardour/editor.cc:1947
+#: gtk2_ardour/editor.cc:1914
msgid "Play region"
msgstr "ВоÑпроизвеÑти облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:1949
+#: gtk2_ardour/editor.cc:1916
msgid "Loop Region"
msgstr "«Закольцевать» облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:1959 gtk2_ardour/editor.cc:2040
+#: gtk2_ardour/editor.cc:1926 gtk2_ardour/editor.cc:2007
msgid "Select All in track"
msgstr "Выделить вÑÑ‘ в дорожке"
-#: gtk2_ardour/editor.cc:1960 gtk2_ardour/editor.cc:2041
-#: gtk2_ardour/redirect_box.cc:1082
+#: gtk2_ardour/editor.cc:1927 gtk2_ardour/editor.cc:2008
+#: gtk2_ardour/redirect_box.cc:1151
msgid "Select All"
msgstr "Выделить вÑÑ‘"
-#: gtk2_ardour/editor.cc:1961 gtk2_ardour/editor.cc:2042
+#: gtk2_ardour/editor.cc:1928 gtk2_ardour/editor.cc:2009
msgid "Invert selection in track"
msgstr "Обратить выделение в дорожке"
-#: gtk2_ardour/editor.cc:1962 gtk2_ardour/editor.cc:2043
+#: gtk2_ardour/editor.cc:1929 gtk2_ardour/editor.cc:2010
msgid "Invert selection"
msgstr "Обратить выделение"
-#: gtk2_ardour/editor.cc:1967 gtk2_ardour/editor.cc:2045
+#: gtk2_ardour/editor.cc:1934 gtk2_ardour/editor.cc:2012
msgid "Select all after edit cursor"
msgstr "Выделить вÑÑ‘ поÑле курÑора"
-#: gtk2_ardour/editor.cc:1968 gtk2_ardour/editor.cc:2046
+#: gtk2_ardour/editor.cc:1935 gtk2_ardour/editor.cc:2013
msgid "Select all before edit cursor"
msgstr "Выделить вÑÑ‘ до курÑора"
-#: gtk2_ardour/editor.cc:1969 gtk2_ardour/editor.cc:2047
+#: gtk2_ardour/editor.cc:1936 gtk2_ardour/editor.cc:2014
msgid "Select all after playhead"
msgstr "Выделить вÑÑ‘ поÑле указателÑ"
-#: gtk2_ardour/editor.cc:1970 gtk2_ardour/editor.cc:2048
+#: gtk2_ardour/editor.cc:1937 gtk2_ardour/editor.cc:2015
msgid "Select all before playhead"
msgstr "Выделить вÑÑ‘ до указателÑ"
-#: gtk2_ardour/editor.cc:1971
+#: gtk2_ardour/editor.cc:1938
msgid "Select all between cursors"
msgstr "Выделить вÑÑ‘ между курÑорами"
-#: gtk2_ardour/editor.cc:1982 gtk2_ardour/editor.cc:2058
-#: gtk2_ardour/editor.cc:3388 gtk2_ardour/editor_actions.cc:216
-#: gtk2_ardour/redirect_box.cc:1075
+#: gtk2_ardour/editor.cc:1941 gtk2_ardour/editor.cc:2017
+msgid "Select"
+msgstr "Выделить"
+
+#: gtk2_ardour/editor.cc:1949 gtk2_ardour/editor.cc:2025
+#: gtk2_ardour/editor_actions.cc:215 gtk2_ardour/redirect_box.cc:1144
msgid "Cut"
msgstr "Вырезать"
-#: gtk2_ardour/editor.cc:1983 gtk2_ardour/editor.cc:2059
-#: gtk2_ardour/editor.cc:3390 gtk2_ardour/editor_actions.cc:221
-#: gtk2_ardour/redirect_box.cc:1077
+#: gtk2_ardour/editor.cc:1950 gtk2_ardour/editor.cc:2026
+#: gtk2_ardour/editor_actions.cc:220 gtk2_ardour/redirect_box.cc:1146
msgid "Copy"
msgstr "Копировать"
-#: gtk2_ardour/editor.cc:1984
+#: gtk2_ardour/editor.cc:1951
msgid "Paste at edit cursor"
msgstr "Ð’Ñтавить под курÑор редактора"
-#: gtk2_ardour/editor.cc:1985
+#: gtk2_ardour/editor.cc:1952
msgid "Paste at mouse"
msgstr "Ð’Ñтавить под курÑор мыши"
-#: gtk2_ardour/editor.cc:1989 gtk2_ardour/editor.cc:3395
+#: gtk2_ardour/editor.cc:1956
msgid "Align"
msgstr "ВыровнÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:1990 gtk2_ardour/editor.cc:3397
+#: gtk2_ardour/editor.cc:1957
msgid "Align Relative"
msgstr "ВыровнÑÑ‚ÑŒ отноÑительно"
-#: gtk2_ardour/editor.cc:1994
+#: gtk2_ardour/editor.cc:1961
msgid "Insert chunk"
msgstr "Ð’Ñтавить фрагмент"
-#: gtk2_ardour/editor.cc:2001
-#, fuzzy
+#: gtk2_ardour/editor.cc:1968
msgid "Insert Selected Region"
-msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
+msgstr "Ð’Ñтавить выделенную облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:2002
+#: gtk2_ardour/editor.cc:1969
msgid "Insert Existing Audio"
-msgstr ""
+msgstr "Ð’Ñтавить звуковой файл"
-#: gtk2_ardour/editor.cc:2011 gtk2_ardour/editor.cc:2067
+#: gtk2_ardour/editor.cc:1978 gtk2_ardour/editor.cc:2034
msgid "Nudge entire track fwd"
-msgstr ""
+msgstr "Подвинуть вÑÑŽ дорожку вперёд"
-#: gtk2_ardour/editor.cc:2012 gtk2_ardour/editor.cc:2068
+#: gtk2_ardour/editor.cc:1979 gtk2_ardour/editor.cc:2035
msgid "Nudge track after edit cursor fwd"
-msgstr ""
+msgstr "Подвинуть вÑÑŽ дорожку поÑле курÑора правки вперёд"
-#: gtk2_ardour/editor.cc:2013 gtk2_ardour/editor.cc:2069
+#: gtk2_ardour/editor.cc:1980 gtk2_ardour/editor.cc:2036
msgid "Nudge entire track bwd"
-msgstr ""
+msgstr "Подвинуть вÑÑŽ дорожку назад"
-#: gtk2_ardour/editor.cc:2014 gtk2_ardour/editor.cc:2070
+#: gtk2_ardour/editor.cc:1981 gtk2_ardour/editor.cc:2037
msgid "Nudge track after edit cursor bwd"
-msgstr ""
+msgstr "Подвинуть вÑÑŽ дорожку поÑле курÑора правки назад"
-#: gtk2_ardour/editor.cc:2060 gtk2_ardour/editor.cc:3392
-#: gtk2_ardour/editor_actions.cc:223 gtk2_ardour/redirect_box.cc:1079
+#: gtk2_ardour/editor.cc:2027 gtk2_ardour/editor_actions.cc:222
+#: gtk2_ardour/redirect_box.cc:1148
msgid "Paste"
msgstr "Ð’Ñтавить"
-#: gtk2_ardour/editor.cc:2612
-#, fuzzy
+#: gtk2_ardour/editor.cc:2585
msgid "Select/Move Objects"
-msgstr "выбирать/двигать объекты"
+msgstr "Выбирать/двигать объекты"
-#: gtk2_ardour/editor.cc:2613
-#, fuzzy
+#: gtk2_ardour/editor.cc:2586
msgid "Select/Move Ranges"
-msgstr "выбирать/двигать диапазоны"
+msgstr "Выбирать/двигать облаÑти"
-#: gtk2_ardour/editor.cc:2614
-#, fuzzy
+#: gtk2_ardour/editor.cc:2587
msgid "Draw Gain Automation"
-msgstr "автомат"
+msgstr "РиÑовать автоматизацию уÑилениÑ"
-#: gtk2_ardour/editor.cc:2615
-#, fuzzy
+#: gtk2_ardour/editor.cc:2588
msgid "Select Zoom Range"
-msgstr "выбрать окно проÑмотра"
+msgstr "ОтмаÑштабировать вид в выделенную облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:2616
-#, fuzzy
+#: gtk2_ardour/editor.cc:2589
msgid "Stretch/Shrink Regions"
-msgstr "раÑÑ‚Ñнуть/Ñжать облаÑти"
+msgstr "РаÑÑ‚Ñнуть/Ñжать облаÑти"
-#: gtk2_ardour/editor.cc:2617
-#, fuzzy
+#: gtk2_ardour/editor.cc:2590
msgid "Listen to Specific Regions"
msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:2646 gtk2_ardour/editor_actions.cc:144
+#: gtk2_ardour/editor.cc:2620 gtk2_ardour/editor_actions.cc:143
msgid "Zoom In"
msgstr "Увеличить"
-#: gtk2_ardour/editor.cc:2651 gtk2_ardour/editor_actions.cc:142
+#: gtk2_ardour/editor.cc:2626 gtk2_ardour/editor_actions.cc:141
msgid "Zoom Out"
msgstr "Уменьшить"
-#: gtk2_ardour/editor.cc:2656 gtk2_ardour/editor_actions.cc:146
+#: gtk2_ardour/editor.cc:2632 gtk2_ardour/editor_actions.cc:145
msgid "Zoom to Session"
msgstr "Показать вÑÑ‘"
-#: gtk2_ardour/editor.cc:2663
-msgid ""
-"Current Zoom Range\n"
-"(Width of visible area)"
-msgstr ""
+#: gtk2_ardour/editor.cc:2638
+#, fuzzy
+msgid "Zoom focus"
+msgstr "Ð¤Ð¾ÐºÑƒÑ Ð¿Ñ€Ð¸ маÑштабировании"
-#: gtk2_ardour/editor.cc:2682
+#: gtk2_ardour/editor.cc:2654
msgid "Unit to snap cursors and ranges to"
msgstr ""
-#: gtk2_ardour/editor.cc:3267 gtk2_ardour/editor.cc:3307
+#: gtk2_ardour/editor.cc:3348 gtk2_ardour/editor.cc:3397
#, fuzzy
msgid "set selected regions"
msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor.cc:3363 gtk2_ardour/editor_actions.cc:206
+#: gtk2_ardour/editor.cc:3437 gtk2_ardour/editor_actions.cc:205
msgid "Undo"
msgstr "Отменить"
-#: gtk2_ardour/editor.cc:3365
+#: gtk2_ardour/editor.cc:3439
msgid "Undo (%1)"
msgstr "Отменить (%1)"
-#: gtk2_ardour/editor.cc:3375 gtk2_ardour/editor_actions.cc:208
+#: gtk2_ardour/editor.cc:3446 gtk2_ardour/editor_actions.cc:207
msgid "Redo"
msgstr "Повторить"
-#: gtk2_ardour/editor.cc:3377
+#: gtk2_ardour/editor.cc:3448
msgid "Redo (%1)"
msgstr "Повторить (%1)"
-#: gtk2_ardour/editor.cc:3411
-msgid "... as new track"
-msgstr "... как новую дорожку"
-
-#: gtk2_ardour/editor.cc:3412
-msgid "... as new region"
-msgstr "... как новую облаÑÑ‚ÑŒ"
-
-#: gtk2_ardour/editor.cc:3414
-msgid "Import audio (copy)"
-msgstr "Импортировать аудио (копией)"
-
-#: gtk2_ardour/editor.cc:3417
-msgid "Remove last capture"
-msgstr "Удалить поÑледнюю запиÑÑŒ"
-
-#: gtk2_ardour/editor.cc:3441
+#: gtk2_ardour/editor.cc:3469
msgid "Duplicate how many times?"
msgstr "КоличеÑтво повторов?"
-#: gtk2_ardour/editor.cc:3618
+#: gtk2_ardour/editor.cc:3547
#, fuzzy
-msgid "Focus Playhead"
-msgstr "МаÑштабировать к"
+msgid "Splice Edit"
+msgstr "Стыковка"
-#: gtk2_ardour/editor.cc:3620
+#: gtk2_ardour/editor.cc:3549
#, fuzzy
-msgid "Focus Edit Cursor"
-msgstr "курÑору"
+msgid "Slide Edit"
+msgstr "Скольжение"
-#: gtk2_ardour/editor.cc:3929
+#: gtk2_ardour/editor.cc:3959
msgid ""
"Playlist %1 is currently unused.\n"
"If left alone, no audio files used by it will be cleaned.\n"
"If deleted, audio files used by it alone by will cleaned."
msgstr ""
-#: gtk2_ardour/editor.cc:3937
+#: gtk2_ardour/editor.cc:3969
msgid "Delete playlist"
msgstr "Удалить ÑпиÑок воÑпроизведениÑ"
-#: gtk2_ardour/editor.cc:3938
+#: gtk2_ardour/editor.cc:3970
msgid "Keep playlist"
msgstr "Сохранить ÑпиÑок воÑпроизведениÑ"
-#: gtk2_ardour/editor.cc:3939 gtk2_ardour/editor_audio_import.cc:239
-#: gtk2_ardour/editor_ops.cc:2061 gtk2_ardour/editor_timefx.cc:72
-#: gtk2_ardour/export_dialog.cc:971 gtk2_ardour/io_selector.cc:61
-#: gtk2_ardour/io_selector.cc:795 gtk2_ardour/redirect_box.cc:901
+#: gtk2_ardour/editor.cc:3971 gtk2_ardour/editor_audio_import.cc:315
+#: gtk2_ardour/editor_ops.cc:1979 gtk2_ardour/editor_timefx.cc:72
+#: gtk2_ardour/export_dialog.cc:969 gtk2_ardour/io_selector.cc:61
+#: gtk2_ardour/io_selector.cc:749 gtk2_ardour/redirect_box.cc:975
#: gtk2_ardour/tempo_dialog.cc:20 gtk2_ardour/tempo_dialog.cc:37
#: gtk2_ardour/tempo_dialog.cc:202 gtk2_ardour/tempo_dialog.cc:220
#: gtk2_ardour/connection_editor.cc:60
msgid "Cancel"
msgstr "Отмена"
-#: gtk2_ardour/editor.cc:4107
+#: gtk2_ardour/editor.cc:4174
msgid "new playlists"
msgstr "Создать ÑпиÑки воÑпроизведениÑ"
-#: gtk2_ardour/editor.cc:4115
+#: gtk2_ardour/editor.cc:4182
msgid "copy playlists"
msgstr "Скопировать ÑпиÑки воÑпроизведениÑ"
-#: gtk2_ardour/editor.cc:4123
+#: gtk2_ardour/editor.cc:4190
msgid "clear playlists"
msgstr "ОчиÑтить ÑпиÑки воÑпроизведениÑ"
-#: gtk2_ardour/editor_actions.cc:28
+#: gtk2_ardour/editor_actions.cc:29
msgid "Select regions"
msgstr "Выделение облаÑтей"
-#: gtk2_ardour/editor_actions.cc:29
+#: gtk2_ardour/editor_actions.cc:30
msgid "Select range operations"
msgstr "ДейÑÑ‚Ð²Ð¸Ñ Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð½Ð¾Ð¹ облаÑтью"
-#: gtk2_ardour/editor_actions.cc:30
+#: gtk2_ardour/editor_actions.cc:31
msgid "Move edit cursor"
msgstr "ПеремеÑтить курÑор редактора"
-#: gtk2_ardour/editor_actions.cc:31
+#: gtk2_ardour/editor_actions.cc:32
msgid "Region operations"
msgstr "ДейÑÑ‚Ð²Ð¸Ñ Ñ Ð¾Ð±Ð»Ð°ÑÑ‚Ñми"
-#: gtk2_ardour/editor_actions.cc:32
+#: gtk2_ardour/editor_actions.cc:33
msgid "Tools"
msgstr "ИнÑтрументы"
-#: gtk2_ardour/editor_actions.cc:33
+#: gtk2_ardour/editor_actions.cc:34
msgid "View"
msgstr "Вид"
-#: gtk2_ardour/editor_actions.cc:34
+#: gtk2_ardour/editor_actions.cc:35
msgid "ZoomFocus"
msgstr "Ð¤Ð¾ÐºÑƒÑ Ð¿Ñ€Ð¸ маÑштабировании"
-#: gtk2_ardour/editor_actions.cc:35
+#: gtk2_ardour/editor_actions.cc:36
msgid "Meter hold"
msgstr "Задержка индикатора"
-#: gtk2_ardour/editor_actions.cc:36
+#: gtk2_ardour/editor_actions.cc:37
msgid "Meter falloff"
-msgstr "Спадание индикатора"
+msgstr "Спад индикатора"
-#: gtk2_ardour/editor_actions.cc:38
+#: gtk2_ardour/editor_actions.cc:39
msgid "Crossfades"
msgstr "КроÑÑфейды"
-#: gtk2_ardour/editor_actions.cc:39
+#: gtk2_ardour/editor_actions.cc:40
msgid "Monitoring"
msgstr "Контроль"
-#: gtk2_ardour/editor_actions.cc:40
+#: gtk2_ardour/editor_actions.cc:41
msgid "Autoconnect"
msgstr "ÐвтоÑоединение"
-#: gtk2_ardour/editor_actions.cc:41
+#: gtk2_ardour/editor_actions.cc:42
msgid "Layering"
msgstr "Слои"
-#: gtk2_ardour/editor_actions.cc:42
-msgid "SMPTE fps"
-msgstr "Кадров в Ñекунду SMPTE"
-
#: gtk2_ardour/editor_actions.cc:43
-msgid "Pullup / Pulldown"
-msgstr ""
+msgid "Timecode fps"
+msgstr "СкороÑÑ‚ÑŒ (FPS) тайм-кода"
#: gtk2_ardour/editor_actions.cc:44
-msgid "Metering"
-msgstr "Индикаторы"
+msgid "Pullup / Pulldown"
+msgstr ""
#: gtk2_ardour/editor_actions.cc:45
-msgid "Fall off rate"
-msgstr "ЧаÑтота Ñпада"
+msgid "Subframes"
+msgstr "Подвыборки"
#: gtk2_ardour/editor_actions.cc:46
-msgid "Hold Time"
-msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð´ÐµÑ€Ð¶ÐºÐ¸"
-
-#: gtk2_ardour/editor_actions.cc:47
msgid "Add Existing Audio"
msgstr "Добавить ÑущеÑтвующий файл"
-#: gtk2_ardour/editor_actions.cc:52
+#: gtk2_ardour/editor_actions.cc:51
msgid "Show Editor Mixer"
msgstr "Показать микшер редактора"
-#: gtk2_ardour/editor_actions.cc:57
+#: gtk2_ardour/editor_actions.cc:56
#, fuzzy
msgid "Span Entire Overlap"
msgstr "ПоднÑÑ‚ÑŒ облаÑÑ‚ÑŒ на один Ñлой"
-#: gtk2_ardour/editor_actions.cc:59 gtk2_ardour/editor_actions.cc:388
-msgid "Short"
-msgstr "КороткаÑ"
-
-#: gtk2_ardour/editor_actions.cc:66
+#: gtk2_ardour/editor_actions.cc:65
msgid "Created Automatically"
msgstr "Создано автоматичеÑки"
-#: gtk2_ardour/editor_actions.cc:69
+#: gtk2_ardour/editor_actions.cc:68
msgid "Playhead to Next Region Start"
msgstr "Указатель к началу Ñледующей облаÑти"
-#: gtk2_ardour/editor_actions.cc:71
+#: gtk2_ardour/editor_actions.cc:70
msgid "Playhead to Next Region End"
msgstr "Указатель к концу Ñледующей облаÑти"
-#: gtk2_ardour/editor_actions.cc:73
+#: gtk2_ardour/editor_actions.cc:72
msgid "Playhead to Next Region Sync"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:76
+#: gtk2_ardour/editor_actions.cc:75
msgid "Playhead to Previous Region Start"
msgstr "Указатель к началу предыдущей облаÑти"
-#: gtk2_ardour/editor_actions.cc:78
+#: gtk2_ardour/editor_actions.cc:77
msgid "Playhead to Previous Region End"
msgstr "Указатель к концу предыдущей облаÑти"
-#: gtk2_ardour/editor_actions.cc:80
+#: gtk2_ardour/editor_actions.cc:79
msgid "Playhead to Previous Region Sync"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:83
+#: gtk2_ardour/editor_actions.cc:82
msgid "Edit Cursor to Next Region Start"
msgstr "КурÑор редактора к началу Ñледующей облаÑти"
-#: gtk2_ardour/editor_actions.cc:85
+#: gtk2_ardour/editor_actions.cc:84
msgid "Edit Cursor to Next Region End"
msgstr "КурÑор редактора к концу Ñледующей облаÑти"
-#: gtk2_ardour/editor_actions.cc:87
+#: gtk2_ardour/editor_actions.cc:86
#, fuzzy
msgid "Edit Cursor to Next Region Sync"
msgstr "От курÑора до конца"
-#: gtk2_ardour/editor_actions.cc:90
+#: gtk2_ardour/editor_actions.cc:89
msgid "Edit Cursor to Previous Region Start"
msgstr "КурÑор редактора к началу предыдущей облаÑти"
-#: gtk2_ardour/editor_actions.cc:92
+#: gtk2_ardour/editor_actions.cc:91
msgid "Edit Cursor to Previous Region End"
msgstr "КурÑор редактора к концу предыдущей облаÑти"
-#: gtk2_ardour/editor_actions.cc:94
+#: gtk2_ardour/editor_actions.cc:93
msgid "Edit Cursor to Previous Region Sync"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:97
+#: gtk2_ardour/editor_actions.cc:96
msgid "Playhead to Range Start"
msgstr "Указатель к началу облаÑти"
-#: gtk2_ardour/editor_actions.cc:99
+#: gtk2_ardour/editor_actions.cc:98
msgid "Playhead to Range End"
msgstr "Указатель к концу облаÑти"
-#: gtk2_ardour/editor_actions.cc:102
+#: gtk2_ardour/editor_actions.cc:101
msgid "Edit Cursor to Range Start"
msgstr "КурÑор редактора к началу облаÑти"
-#: gtk2_ardour/editor_actions.cc:104
+#: gtk2_ardour/editor_actions.cc:103
msgid "Edit Cursor to Range End"
msgstr "КурÑор редактора к концу облаÑти"
-#: gtk2_ardour/editor_actions.cc:107 gtk2_ardour/editor_ops.cc:1373
+#: gtk2_ardour/editor_actions.cc:106 gtk2_ardour/editor_ops.cc:1292
msgid "select all"
msgstr "Выделить вÑÑ‘"
-#: gtk2_ardour/editor_actions.cc:109
+#: gtk2_ardour/editor_actions.cc:108
msgid "Select All After Edit Cursor"
msgstr "Выделить вÑÑ‘ поÑле курÑора редактора"
-#: gtk2_ardour/editor_actions.cc:111
+#: gtk2_ardour/editor_actions.cc:110
msgid "Select All Before Edit Cursor"
msgstr "Выделить вÑÑ‘ перед курÑором редактора"
-#: gtk2_ardour/editor_actions.cc:114
+#: gtk2_ardour/editor_actions.cc:113
msgid "Select All After Playhead"
msgstr "Выделить вÑÑ‘ поÑле указателÑ"
-#: gtk2_ardour/editor_actions.cc:116
+#: gtk2_ardour/editor_actions.cc:115
msgid "Select All Before Playhead"
msgstr "Выделить вÑÑ‘ до указателÑ"
-#: gtk2_ardour/editor_actions.cc:118
+#: gtk2_ardour/editor_actions.cc:117
#, fuzzy
msgid "Select All Between Cursors"
msgstr "ВоÑпроизвеÑти от курÑора"
-#: gtk2_ardour/editor_actions.cc:121
+#: gtk2_ardour/editor_actions.cc:120
#, fuzzy
msgid "Select All in Punch Range"
msgstr "Выбрать текущий интервал"
-#: gtk2_ardour/editor_actions.cc:123
+#: gtk2_ardour/editor_actions.cc:122
msgid "Select All in Loop Range"
msgstr "Выделить вÑÑ‘ в закольцованной облаÑти"
-#: gtk2_ardour/editor_actions.cc:126
+#: gtk2_ardour/editor_actions.cc:125
msgid "Jump Forward to Mark"
msgstr "К Ñледующей метке"
-#: gtk2_ardour/editor_actions.cc:128
+#: gtk2_ardour/editor_actions.cc:127
msgid "Jump Backward to Mark"
msgstr "К предыдущей метке"
-#: gtk2_ardour/editor_actions.cc:130
+#: gtk2_ardour/editor_actions.cc:129
#, fuzzy
msgid "Add Location from Playhead"
msgstr "ВоÑпроизвеÑти от указателÑ"
-#: gtk2_ardour/editor_actions.cc:133
+#: gtk2_ardour/editor_actions.cc:132
msgid "Nudge Forward"
msgstr "Подвинуть вперёд"
-#: gtk2_ardour/editor_actions.cc:135
+#: gtk2_ardour/editor_actions.cc:134
msgid "Nudge Next Forward"
-msgstr ""
+msgstr "Подвинуть Ñледующую вперёд"
-#: gtk2_ardour/editor_actions.cc:137
+#: gtk2_ardour/editor_actions.cc:136
msgid "Nudge Backward"
msgstr "Подвинуть назад"
-#: gtk2_ardour/editor_actions.cc:139
-#, fuzzy
+#: gtk2_ardour/editor_actions.cc:138
msgid "Nudge Next Backward"
-msgstr "Скрыть трек"
+msgstr "Подвинуть Ñледующую назад"
-#: gtk2_ardour/editor_actions.cc:149
+#: gtk2_ardour/editor_actions.cc:148
msgid "Scroll Tracks Up"
msgstr "Прокрутить дорожки вверх"
-#: gtk2_ardour/editor_actions.cc:151
+#: gtk2_ardour/editor_actions.cc:150
msgid "Scroll Tracks Down"
msgstr "Прокрутить дорожки вниз"
-#: gtk2_ardour/editor_actions.cc:153
+#: gtk2_ardour/editor_actions.cc:152
#, fuzzy
msgid "Step Tracks Up"
msgstr "Скрыть трек"
-#: gtk2_ardour/editor_actions.cc:155
+#: gtk2_ardour/editor_actions.cc:154
msgid "Step Tracks Down"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:158
+#: gtk2_ardour/editor_actions.cc:157
msgid "Scroll Backward"
msgstr "Прокрутить назад"
-#: gtk2_ardour/editor_actions.cc:160
+#: gtk2_ardour/editor_actions.cc:159
msgid "Scroll Forward"
msgstr "Прокрутить вперёд"
-#: gtk2_ardour/editor_actions.cc:162
+#: gtk2_ardour/editor_actions.cc:161
msgid "goto"
msgstr "Перейти"
-#: gtk2_ardour/editor_actions.cc:164
+#: gtk2_ardour/editor_actions.cc:163
msgid "Center Playhead"
msgstr "Указатель по центру"
-#: gtk2_ardour/editor_actions.cc:166
+#: gtk2_ardour/editor_actions.cc:165
msgid "Center Edit Cursor"
msgstr "КурÑор редактора по центру"
-#: gtk2_ardour/editor_actions.cc:168
+#: gtk2_ardour/editor_actions.cc:167
msgid "Playhead Forward"
msgstr "Указатель вперёд"
-#: gtk2_ardour/editor_actions.cc:170
+#: gtk2_ardour/editor_actions.cc:169
msgid "Playhead Backward"
msgstr "Указатель назад"
-#: gtk2_ardour/editor_actions.cc:172
+#: gtk2_ardour/editor_actions.cc:171
msgid "Playhead to Edit"
msgstr "Указатель к курÑору редактора"
-#: gtk2_ardour/editor_actions.cc:174
+#: gtk2_ardour/editor_actions.cc:173
msgid "Edit to Playhead"
msgstr "КурÑор редактора к указателю"
-#: gtk2_ardour/editor_actions.cc:177
+#: gtk2_ardour/editor_actions.cc:176
msgid "Align Regions Start"
msgstr "ВыровнÑÑ‚ÑŒ начало облаÑтей"
-#: gtk2_ardour/editor_actions.cc:179
+#: gtk2_ardour/editor_actions.cc:178
#, fuzzy
msgid "Align Regions Start Relative"
msgstr "ВыровнÑÑ‚ÑŒ отноÑительно"
-#: gtk2_ardour/editor_actions.cc:181
+#: gtk2_ardour/editor_actions.cc:180
msgid "Align Regions End"
msgstr "ВыровнÑÑ‚ÑŒ конец облаÑтей"
-#: gtk2_ardour/editor_actions.cc:183
+#: gtk2_ardour/editor_actions.cc:182
#, fuzzy
msgid "Align Regions End Relative"
msgstr "ВыровнÑÑ‚ÑŒ отноÑительно"
-#: gtk2_ardour/editor_actions.cc:186
+#: gtk2_ardour/editor_actions.cc:185
#, fuzzy
msgid "Align Regions Sync"
msgstr "проÑлушать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_actions.cc:188
+#: gtk2_ardour/editor_actions.cc:187
#, fuzzy
msgid "Align Regions Sync Relative"
msgstr "ВыровнÑÑ‚ÑŒ отноÑительно"
-#: gtk2_ardour/editor_actions.cc:191
+#: gtk2_ardour/editor_actions.cc:190
msgid "Audition at Mouse"
msgstr "Контроль по курÑору мыши"
-#: gtk2_ardour/editor_actions.cc:193
+#: gtk2_ardour/editor_actions.cc:192
msgid "Brush at Mouse"
msgstr "КиÑточка по курÑору"
-#: gtk2_ardour/editor_actions.cc:195
+#: gtk2_ardour/editor_actions.cc:194
msgid "Set Edit Cursor"
msgstr "УÑтановить курÑор редактора"
-#: gtk2_ardour/editor_actions.cc:197
+#: gtk2_ardour/editor_actions.cc:196
msgid "Mute/Unmute Region"
msgstr "Приглушить /вернуть звук облаÑти"
-#: gtk2_ardour/editor_actions.cc:199
+#: gtk2_ardour/editor_actions.cc:198
msgid "Set Playhead"
msgstr "УÑтановить указатель"
-#: gtk2_ardour/editor_actions.cc:201
+#: gtk2_ardour/editor_actions.cc:200
msgid "Split Region"
msgstr "Разделить облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_actions.cc:203
+#: gtk2_ardour/editor_actions.cc:202
#, fuzzy
msgid "Set Region Sync Position"
msgstr "по раÑположению облаÑти"
-#: gtk2_ardour/editor_actions.cc:211
+#: gtk2_ardour/editor_actions.cc:210
msgid "Export Session"
msgstr "ЭкÑпортировать ÑеÑÑию"
-#: gtk2_ardour/editor_actions.cc:213
+#: gtk2_ardour/editor_actions.cc:212
msgid "Export Range"
msgstr "ЭкÑпортировать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_actions.cc:219 gtk2_ardour/connection_editor.cc:56
+#: gtk2_ardour/editor_actions.cc:218 gtk2_ardour/connection_editor.cc:56
msgid "Delete"
msgstr "Удалить"
-#: gtk2_ardour/editor_actions.cc:225
+#: gtk2_ardour/editor_actions.cc:224
msgid "Duplicate Region"
msgstr "Продублировать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_actions.cc:227
+#: gtk2_ardour/editor_actions.cc:226
msgid "Duplicate Range"
msgstr "Продублировать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_actions.cc:229
+#: gtk2_ardour/editor_actions.cc:228
msgid "Insert Region"
msgstr "Ð’Ñтавить облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_actions.cc:231
+#: gtk2_ardour/editor_actions.cc:230
msgid "Reverse Region"
msgstr "Развернуть облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_actions.cc:233
+#: gtk2_ardour/editor_actions.cc:232
msgid "Normalize Region"
msgstr "Ðормализовать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_actions.cc:235
+#: gtk2_ardour/editor_actions.cc:234
msgid "crop"
msgstr "Обрезать"
-#: gtk2_ardour/editor_actions.cc:237
+#: gtk2_ardour/editor_actions.cc:236
msgid "Insert Chunk"
msgstr "Ð’Ñтавить фрагмент"
-#: gtk2_ardour/editor_actions.cc:240
+#: gtk2_ardour/editor_actions.cc:239
msgid "Split at edit cursor"
msgstr "Разделить по курÑору редактора"
-#: gtk2_ardour/editor_actions.cc:243
+#: gtk2_ardour/editor_actions.cc:242
msgid "Start Range"
-msgstr ""
+msgstr "Ðачать выделение"
-#: gtk2_ardour/editor_actions.cc:245
+#: gtk2_ardour/editor_actions.cc:244
msgid "Finish Range"
-msgstr ""
+msgstr "Закончить выделение"
-#: gtk2_ardour/editor_actions.cc:247
+#: gtk2_ardour/editor_actions.cc:246
msgid "Finish add Range"
-msgstr ""
+msgstr "Закончить добавку выделениÑ"
-#: gtk2_ardour/editor_actions.cc:250
+#: gtk2_ardour/editor_actions.cc:249
msgid "Extend Range to End of Region"
-msgstr ""
+msgstr "РаÑширить выделение до конца облаÑти"
-#: gtk2_ardour/editor_actions.cc:252
-#, fuzzy
+#: gtk2_ardour/editor_actions.cc:251
msgid "Extend Range to Start of Region"
-msgstr "Ð’ начало ÑеÑÑии"
+msgstr "РаÑширить выделение до начала облаÑти"
-#: gtk2_ardour/editor_actions.cc:255
+#: gtk2_ardour/editor_actions.cc:254
msgid "Follow Playhead"
msgstr "Следовать за указателем"
-#: gtk2_ardour/editor_actions.cc:263
+#: gtk2_ardour/editor_actions.cc:262
msgid "Zoom Focus Left"
msgstr "Ð¤Ð¾ÐºÑƒÑ Ð²Ð»ÐµÐ²Ð¾"
-#: gtk2_ardour/editor_actions.cc:265
+#: gtk2_ardour/editor_actions.cc:264
msgid "Zoom Focus Right"
msgstr "Ð¤Ð¾ÐºÑƒÑ Ð²Ð¿Ñ€Ð°Ð²Ð¾"
-#: gtk2_ardour/editor_actions.cc:267
+#: gtk2_ardour/editor_actions.cc:266
msgid "Zoom Focus Center"
msgstr "Ð¤Ð¾ÐºÑƒÑ Ð¿Ð¾ центру"
-#: gtk2_ardour/editor_actions.cc:269
+#: gtk2_ardour/editor_actions.cc:268
msgid "Zoom Focus Playhead"
msgstr "Ð¤Ð¾ÐºÑƒÑ Ð¿Ð¾ указателю"
-#: gtk2_ardour/editor_actions.cc:271
+#: gtk2_ardour/editor_actions.cc:270
msgid "Zoom Focus Edit"
msgstr "Ð¤Ð¾ÐºÑƒÑ Ð¿Ð¾ курÑору"
-#: gtk2_ardour/editor_actions.cc:277
+#: gtk2_ardour/editor_actions.cc:276
msgid "Object Tool"
msgstr "Объект"
-#: gtk2_ardour/editor_actions.cc:278
+#: gtk2_ardour/editor_actions.cc:277
msgid "Range Tool"
-msgstr "ОблаÑÑ‚ÑŒ"
+msgstr "Выделение"
-#: gtk2_ardour/editor_actions.cc:279
+#: gtk2_ardour/editor_actions.cc:278
msgid "Gain Tool"
msgstr "УÑиление"
-#: gtk2_ardour/editor_actions.cc:280
+#: gtk2_ardour/editor_actions.cc:279
msgid "Zoom Tool"
msgstr "Лупа"
-#: gtk2_ardour/editor_actions.cc:281
+#: gtk2_ardour/editor_actions.cc:280
msgid "Timefx Tool"
msgstr "ВремÑ"
-#: gtk2_ardour/editor_actions.cc:286
+#: gtk2_ardour/editor_actions.cc:282
msgid "Snap To"
-msgstr "ПривÑзка"
+msgstr "Прилипание"
+
+#: gtk2_ardour/editor_actions.cc:283
+msgid "Snap Mode"
+msgstr "Режим привÑзки"
-#: gtk2_ardour/editor_actions.cc:288
+#: gtk2_ardour/editor_actions.cc:292
msgid "Snap to frame"
-msgstr "ПривÑзка к выборке"
+msgstr "Прилипание к выборке"
-#: gtk2_ardour/editor_actions.cc:289
+#: gtk2_ardour/editor_actions.cc:293
msgid "Snap to cd frame"
-msgstr "ПривÑзка к выборке CD"
+msgstr "Прилипание к выборке CD"
-#: gtk2_ardour/editor_actions.cc:290
+#: gtk2_ardour/editor_actions.cc:294
msgid "Snap to SMPTE frame"
-msgstr "ПривÑзка к кадру SMPTE"
+msgstr "Прилипание к кадру SMPTE"
-#: gtk2_ardour/editor_actions.cc:291
+#: gtk2_ardour/editor_actions.cc:295
msgid "Snap to SMPTE seconds"
-msgstr "ПривÑзка к Ñекундам SMPTE"
+msgstr "Прилипание к Ñекундам SMPTE"
-#: gtk2_ardour/editor_actions.cc:292
+#: gtk2_ardour/editor_actions.cc:296
msgid "Snap to SMPTE minutes"
-msgstr "ПривÑзка к минутам SMPTE"
+msgstr "Прилипание к минутам SMPTE"
-#: gtk2_ardour/editor_actions.cc:293
+#: gtk2_ardour/editor_actions.cc:297
msgid "Snap to seconds"
-msgstr "ПривÑзка к Ñекундам"
+msgstr "Прилипание к Ñекундам"
-#: gtk2_ardour/editor_actions.cc:294
+#: gtk2_ardour/editor_actions.cc:298
msgid "Snap to minutes"
-msgstr "ПривÑзка к минутам"
+msgstr "Прилипание к минутам"
-#: gtk2_ardour/editor_actions.cc:295
+#: gtk2_ardour/editor_actions.cc:299
msgid "Snap to thirtyseconds"
-msgstr "ПривÑзка по 30 Ñекундам"
+msgstr "Прилипание по 30 Ñекундам"
-#: gtk2_ardour/editor_actions.cc:296
+#: gtk2_ardour/editor_actions.cc:300
msgid "Snap to asixteenthbeat"
-msgstr "ПривÑзка к 1/16"
+msgstr "Прилипание к 1/16"
-#: gtk2_ardour/editor_actions.cc:297
+#: gtk2_ardour/editor_actions.cc:301
msgid "Snap to eighths"
-msgstr "ПривÑзка к 1/8"
+msgstr "Прилипание к 1/8"
-#: gtk2_ardour/editor_actions.cc:298
+#: gtk2_ardour/editor_actions.cc:302
msgid "Snap to quarters"
-msgstr "ПривÑзка к 1/4"
+msgstr "Прилипание к 1/4"
-#: gtk2_ardour/editor_actions.cc:299
+#: gtk2_ardour/editor_actions.cc:303
msgid "Snap to thirds"
-msgstr "ПривÑзка к 1/3"
+msgstr "Прилипание к 1/3"
-#: gtk2_ardour/editor_actions.cc:300
+#: gtk2_ardour/editor_actions.cc:304
msgid "Snap to beat"
-msgstr "ПривÑзка к доле"
+msgstr "Прилипание к доле"
-#: gtk2_ardour/editor_actions.cc:301
+#: gtk2_ardour/editor_actions.cc:305
msgid "Snap to bar"
-msgstr "ПривÑзка к такту"
+msgstr "Прилипание к такту"
-#: gtk2_ardour/editor_actions.cc:302
+#: gtk2_ardour/editor_actions.cc:306
msgid "Snap to mark"
-msgstr "ПривÑзка к маркеру"
+msgstr "Прилипание к маркеру"
-#: gtk2_ardour/editor_actions.cc:303
+#: gtk2_ardour/editor_actions.cc:307
msgid "Snap to edit cursor"
-msgstr "ПривÑзка к курÑору редактора"
+msgstr "Прилипание к курÑору редактора"
-#: gtk2_ardour/editor_actions.cc:304
+#: gtk2_ardour/editor_actions.cc:308
msgid "Snap to region start"
-msgstr "ПривÑзка к началу облаÑти"
+msgstr "Прилипание к началу облаÑти"
-#: gtk2_ardour/editor_actions.cc:305
+#: gtk2_ardour/editor_actions.cc:309
msgid "Snap to region end"
-msgstr "ПривÑзка к концу облаÑти"
+msgstr "Прилипание к концу облаÑти"
-#: gtk2_ardour/editor_actions.cc:306
+#: gtk2_ardour/editor_actions.cc:310
msgid "Snap to region sync"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:307
+#: gtk2_ardour/editor_actions.cc:311
msgid "Snap to region boundary"
-msgstr "ПривÑзка к границам облаÑти"
+msgstr "Прилипание к границам облаÑти"
-#: gtk2_ardour/editor_actions.cc:316
+#: gtk2_ardour/editor_actions.cc:320
msgid "Sort"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:324
+#: gtk2_ardour/editor_actions.cc:328
msgid "Show all"
msgstr "Показать вÑÑ‘"
-#: gtk2_ardour/editor_actions.cc:325
+#: gtk2_ardour/editor_actions.cc:329
msgid "Show automatic regions"
msgstr "Показать автомат. облаÑти"
-#: gtk2_ardour/editor_actions.cc:327
+#: gtk2_ardour/editor_actions.cc:331
msgid "Ascending"
msgstr "По возраÑтанию"
-#: gtk2_ardour/editor_actions.cc:329
+#: gtk2_ardour/editor_actions.cc:333
msgid "Descending"
msgstr "По убыванию"
-#: gtk2_ardour/editor_actions.cc:332
+#: gtk2_ardour/editor_actions.cc:336
msgid "By Region Name"
msgstr "По имени облаÑти"
-#: gtk2_ardour/editor_actions.cc:334
+#: gtk2_ardour/editor_actions.cc:338
msgid "By Region Length"
msgstr "По длительноÑти облаÑти"
-#: gtk2_ardour/editor_actions.cc:336
+#: gtk2_ardour/editor_actions.cc:340
msgid "By Region Position"
msgstr "По раÑположению облаÑти"
-#: gtk2_ardour/editor_actions.cc:338
+#: gtk2_ardour/editor_actions.cc:342
msgid "By Region Timestamp"
msgstr "По времени ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±Ð»Ð°Ñти"
-#: gtk2_ardour/editor_actions.cc:340
+#: gtk2_ardour/editor_actions.cc:344
msgid "By Region Start in File"
msgstr "По началу облаÑти в файле"
-#: gtk2_ardour/editor_actions.cc:342
+#: gtk2_ardour/editor_actions.cc:346
msgid "By Region End in File"
msgstr "По концу облаÑти в файле"
-#: gtk2_ardour/editor_actions.cc:344
+#: gtk2_ardour/editor_actions.cc:348
msgid "By Source File Name"
msgstr "По имени иÑходного файла"
-#: gtk2_ardour/editor_actions.cc:346
+#: gtk2_ardour/editor_actions.cc:350
msgid "By Source File Length"
msgstr "По длительноÑти иÑходного файла"
-#: gtk2_ardour/editor_actions.cc:348
+#: gtk2_ardour/editor_actions.cc:352
msgid "By Source File Creation Date"
msgstr "По дате ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸Ñходного файла"
-#: gtk2_ardour/editor_actions.cc:350
+#: gtk2_ardour/editor_actions.cc:354
msgid "By Source Filesystem"
msgstr "По иÑходной файловой ÑиÑтеме"
-#: gtk2_ardour/editor_actions.cc:356
+#: gtk2_ardour/editor_actions.cc:360
msgid "Add External Audio"
msgstr "Добавить внешний звуковой файл"
-#: gtk2_ardour/editor_actions.cc:358
+#: gtk2_ardour/editor_actions.cc:362
msgid "as Region(s)"
msgstr "как облаÑÑ‚ÑŒ(-и)"
-#: gtk2_ardour/editor_actions.cc:360
+#: gtk2_ardour/editor_actions.cc:364
msgid "as Tracks"
msgstr "как дорожки"
-#: gtk2_ardour/editor_actions.cc:362
+#: gtk2_ardour/editor_actions.cc:366
msgid "as Tape Tracks"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:364
+#: gtk2_ardour/editor_actions.cc:368
msgid "to Tracks"
msgstr "в дорожки"
-#: gtk2_ardour/editor_actions.cc:367
+#: gtk2_ardour/editor_actions.cc:371
msgid "Show Waveforms"
msgstr "Показывать форму Ñигнала"
-#: gtk2_ardour/editor_actions.cc:368
+#: gtk2_ardour/editor_actions.cc:372
msgid "Show Waveforms While Recording"
msgstr "Показывать форму Ñигнала при запиÑи"
-#: gtk2_ardour/editor_actions.cc:369
+#: gtk2_ardour/editor_actions.cc:373
msgid "Show Measures"
msgstr "Показывать линии тактов"
-#: gtk2_ardour/editor_actions.cc:382 gtk2_ardour/editor_actions.cc:389
-msgid "Medium"
-msgstr "Средне"
-
-#: gtk2_ardour/editor_actions.cc:384
-msgid "Faster"
-msgstr "БыÑтрее"
-
-#: gtk2_ardour/editor_actions.cc:390
-msgid "Long"
-msgstr "ДолгаÑ"
-
-#: gtk2_ardour/editor_actions.cc:394
-#, fuzzy
+#: gtk2_ardour/editor_actions.cc:377
msgid "Later is Higher"
-msgstr "ОпуÑтить облаÑÑ‚ÑŒ на один Ñлой"
+msgstr "Более поздние выше"
-#: gtk2_ardour/editor_actions.cc:395
-#, fuzzy
+#: gtk2_ardour/editor_actions.cc:378
msgid "Most Recently Moved/Added is Higher"
-msgstr "ОпуÑтить облаÑÑ‚ÑŒ на один Ñлой"
+msgstr "Ðедавно Ñмещённые/добавленные выше"
-#: gtk2_ardour/editor_actions.cc:396
-#, fuzzy
+#: gtk2_ardour/editor_actions.cc:379
msgid "Most Recently Added is Higher"
-msgstr "ОпуÑтить облаÑÑ‚ÑŒ на один Ñлой"
+msgstr "Ðедавно добавленные выше"
-#: gtk2_ardour/editor_actions.cc:400
+#: gtk2_ardour/editor_actions.cc:383
msgid "23.976"
-msgstr ""
+msgstr "23.976"
-#: gtk2_ardour/editor_actions.cc:401
+#: gtk2_ardour/editor_actions.cc:384
msgid "24"
-msgstr ""
+msgstr "24"
-#: gtk2_ardour/editor_actions.cc:402
+#: gtk2_ardour/editor_actions.cc:385
msgid "24.976"
-msgstr ""
+msgstr "24.976"
-#: gtk2_ardour/editor_actions.cc:403
+#: gtk2_ardour/editor_actions.cc:386
msgid "25"
-msgstr ""
+msgstr "25"
-#: gtk2_ardour/editor_actions.cc:404
+#: gtk2_ardour/editor_actions.cc:387
msgid "29.97"
-msgstr ""
+msgstr "29.97"
-#: gtk2_ardour/editor_actions.cc:405
+#: gtk2_ardour/editor_actions.cc:388
msgid "29.97 drop"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:406
+#: gtk2_ardour/editor_actions.cc:389
msgid "30"
-msgstr ""
+msgstr "30"
-#: gtk2_ardour/editor_actions.cc:407
+#: gtk2_ardour/editor_actions.cc:390
msgid "30 drop"
msgstr ""
-#: gtk2_ardour/editor_actions.cc:408
+#: gtk2_ardour/editor_actions.cc:391
msgid "59.94"
-msgstr ""
+msgstr "59.94"
-#: gtk2_ardour/editor_actions.cc:409
+#: gtk2_ardour/editor_actions.cc:392
msgid "60"
-msgstr ""
+msgstr "60"
-#: gtk2_ardour/editor_actions.cc:413
-#, c-format
+#: gtk2_ardour/editor_actions.cc:396
msgid "+4.1667% + 0.1%"
-msgstr ""
+msgstr "+4.1667% + 0.1%"
-#: gtk2_ardour/editor_actions.cc:414
+#: gtk2_ardour/editor_actions.cc:397
msgid "+4.1667%"
-msgstr ""
+msgstr "+4.1667%"
-#: gtk2_ardour/editor_actions.cc:415
-#, c-format
+#: gtk2_ardour/editor_actions.cc:398
msgid "+4.1667% - 0.1%"
-msgstr ""
+msgstr "+4.1667% - 0.1%"
-#: gtk2_ardour/editor_actions.cc:416
+#: gtk2_ardour/editor_actions.cc:399
msgid "+ 0.1%"
-msgstr ""
+msgstr "+ 0.1%"
-#: gtk2_ardour/editor_actions.cc:418
+#: gtk2_ardour/editor_actions.cc:401
msgid "- 0.1%"
-msgstr ""
+msgstr "- 0.1%"
-#: gtk2_ardour/editor_actions.cc:419
-#, c-format
+#: gtk2_ardour/editor_actions.cc:402
msgid "-4.1667% + 0.1%"
-msgstr ""
+msgstr "-4.1667% + 0.1%"
-#: gtk2_ardour/editor_actions.cc:420
+#: gtk2_ardour/editor_actions.cc:403
msgid "-4.1667%"
-msgstr ""
+msgstr "-4.1667%"
-#: gtk2_ardour/editor_actions.cc:421
-#, c-format
+#: gtk2_ardour/editor_actions.cc:404
msgid "-4.1667% - 0.1%"
+msgstr "-4.1667% - 0.1%"
+
+#: gtk2_ardour/editor_actions.cc:408
+msgid "80 per frame"
+msgstr "800 на выборку"
+
+#: gtk2_ardour/editor_actions.cc:409
+msgid "100 per frame"
+msgstr "100 на выборку"
+
+#: gtk2_ardour/editor_actions.cc:712 gtk2_ardour/editor_actions.cc:757
+#: gtk2_ardour/editor_actions.cc:768 gtk2_ardour/editor_actions.cc:812
+#: gtk2_ardour/editor_actions.cc:822
+#, fuzzy
+msgid "programming error: %1: %2"
+msgstr "ошибка в программе: "
+
+#: gtk2_ardour/editor_actions.cc:723 gtk2_ardour/editor_actions.cc:951
+#: gtk2_ardour/editor_actions.cc:964 gtk2_ardour/editor_actions.cc:1028
+#: gtk2_ardour/sfdb_ui.cc:395
+#, fuzzy
+msgid "programming error: %1"
+msgstr "ошибка в программе: "
+
+#: gtk2_ardour/editor_actions.cc:983
+msgid "Configuraton is using unhandled subframes per frame value: %1"
msgstr ""
-#: gtk2_ardour/editor_audio_import.cc:75
+#: gtk2_ardour/editor_audio_import.cc:76
#, fuzzy
msgid "You can't import or embed an audiofile until you have a session loaded."
msgstr "Ð’Ñ‹ не можете импортировать аудиофайл пока ÑеÑÑÐ¸Ñ Ð½Ðµ загружена."
-#: gtk2_ardour/editor_audio_import.cc:80
-#, fuzzy
+#: gtk2_ardour/editor_audio_import.cc:81
msgid "Add existing audio to session"
-msgstr "иÑпользовать имеющийÑÑ ÑˆÐ°Ð±Ð»Ð¾Ð½"
+msgstr "Добавить ÑущеÑтвующий файл в ÑеÑÑию"
+
+#: gtk2_ardour/editor_audio_import.cc:166
+msgid "Import as a %1 region"
+msgstr "Импортировать как %1 облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_audio_import.cc:145
+#: gtk2_ardour/editor_audio_import.cc:167
#, fuzzy
+msgid "multichannel"
+msgstr "отмена"
+
+#: gtk2_ardour/editor_audio_import.cc:167 gtk2_ardour/export_dialog.cc:84
+msgid "stereo"
+msgstr "Ñтерео"
+
+#: gtk2_ardour/editor_audio_import.cc:168
+msgid "Import as multiple regions"
+msgstr "Импортировать как неÑколько облаÑтей"
+
+#: gtk2_ardour/editor_audio_import.cc:170
+msgid ""
+"Paired files detected (%1, %2 ...).\n"
+"Do you want to:"
+msgstr ""
+
+#: gtk2_ardour/editor_audio_import.cc:216
msgid "ardour: importing %1"
-msgstr "ardour: ÑкÑпорт"
+msgstr "ardour: ÑкÑпортируетÑÑ %1"
-#: gtk2_ardour/editor_audio_import.cc:149
+#: gtk2_ardour/editor_audio_import.cc:220
msgid "Cancel Import"
msgstr "Отменить импорт"
-#: gtk2_ardour/editor_audio_import.cc:227
+#: gtk2_ardour/editor_audio_import.cc:303
#, fuzzy
msgid "Editor: cannot open file \"%1\", (%2)"
msgstr "Редактор: не удалоÑÑŒ открыть файл \"%1\" (%2)"
-#: gtk2_ardour/editor_audio_import.cc:235
-#, fuzzy
+#: gtk2_ardour/editor_audio_import.cc:311
msgid "Cancel entire import"
-msgstr "Отменить импорт"
+msgstr "Отменить веÑÑŒ импорт"
-#: gtk2_ardour/editor_audio_import.cc:236
-#, fuzzy
+#: gtk2_ardour/editor_audio_import.cc:312
msgid "Don't embed it"
-msgstr "Отмена"
+msgstr "Ðе вÑтраивать"
-#: gtk2_ardour/editor_audio_import.cc:237
+#: gtk2_ardour/editor_audio_import.cc:313
msgid "Embed all without questions"
-msgstr ""
+msgstr "Ð’Ñтроить без лишних вопроÑов"
-#: gtk2_ardour/editor_audio_import.cc:242
+#: gtk2_ardour/editor_audio_import.cc:318
msgid "Embed it anyway"
-msgstr ""
+msgstr "Ð’ÑÑ‘ равно вÑтроить"
-#: gtk2_ardour/editor_audio_import.cc:245
+#: gtk2_ardour/editor_audio_import.cc:321
#, fuzzy
msgid ""
"%1\n"
@@ -3359,11 +3430,11 @@ msgstr ""
"Выбранный аудиофайл имеет чаÑтоту диÑкретизации данных\n"
"отличную от текущей ÑеÑÑии!"
-#: gtk2_ardour/editor_audio_import.cc:278
+#: gtk2_ardour/editor_audio_import.cc:360
msgid "could not open %1"
msgstr "не удалоÑÑŒ открыть %1"
-#: gtk2_ardour/editor_audio_import.cc:323
+#: gtk2_ardour/editor_audio_import.cc:407
#, fuzzy
msgid "insert sndfile"
msgstr "Ð’Ñтавить внешний аудиофайл"
@@ -3372,27 +3443,26 @@ msgstr "Ð’Ñтавить внешний аудиофайл"
msgid "VerboseCanvasCursor"
msgstr ""
-#: gtk2_ardour/editor_edit_groups.cc:53 gtk2_ardour/mixer_ui.cc:754
+#: gtk2_ardour/editor_edit_groups.cc:53 gtk2_ardour/mixer_ui.cc:751
#, fuzzy
msgid "Activate All"
msgstr "Ðктивировать"
-#: gtk2_ardour/editor_edit_groups.cc:54 gtk2_ardour/mixer_ui.cc:755
+#: gtk2_ardour/editor_edit_groups.cc:54 gtk2_ardour/mixer_ui.cc:752
#, fuzzy
msgid "Disable All"
msgstr "ОтÑоединить"
-#: gtk2_ardour/editor_edit_groups.cc:56 gtk2_ardour/mixer_ui.cc:757
+#: gtk2_ardour/editor_edit_groups.cc:56 gtk2_ardour/mixer_ui.cc:754
#, fuzzy
msgid "Add group"
msgstr "Ðет группы"
-#: gtk2_ardour/editor_edit_groups.cc:229 gtk2_ardour/mixer_ui.cc:988
-#, fuzzy
+#: gtk2_ardour/editor_edit_groups.cc:229 gtk2_ardour/mixer_ui.cc:985
msgid "unnamed"
-msgstr "Переименовать"
+msgstr "безымÑнный"
-#: gtk2_ardour/editor_edit_groups.cc:258 gtk2_ardour/mixer_ui.cc:852
+#: gtk2_ardour/editor_edit_groups.cc:258 gtk2_ardour/mixer_ui.cc:849
msgid "-all-"
msgstr "-вÑе-"
@@ -3410,11 +3480,11 @@ msgid ""
"Create 1 or more ranges by dragging the mouse in the range bar"
msgstr ""
-#: gtk2_ardour/editor_imageframe.cc:625 gtk2_ardour/editor_imageframe.cc:655
+#: gtk2_ardour/editor_imageframe.cc:623 gtk2_ardour/editor_imageframe.cc:653
msgid "programming error: no ImageFrameView selected"
msgstr "ошибка в программе: no ImageFrameView selected"
-#: gtk2_ardour/editor_imageframe.cc:848 gtk2_ardour/editor_imageframe.cc:870
+#: gtk2_ardour/editor_imageframe.cc:846 gtk2_ardour/editor_imageframe.cc:868
msgid "programming error: no MarkerView selected"
msgstr "ошибка в программе: no MarkerView selected"
@@ -3428,20 +3498,20 @@ msgstr "отключить воÑпроизведение Ñтой облаÑÑ‚Ð
msgid "keyboard selection"
msgstr "Выделить по интервалу"
-#: gtk2_ardour/editor_markers.cc:293 gtk2_ardour/editor_ops.cc:1297
-#: gtk2_ardour/editor_ops.cc:1311 gtk2_ardour/editor_ops.cc:1330
+#: gtk2_ardour/editor_markers.cc:293 gtk2_ardour/editor_ops.cc:1213
+#: gtk2_ardour/editor_ops.cc:1227 gtk2_ardour/editor_ops.cc:1246
#: gtk2_ardour/location_ui.cc:776
msgid "add marker"
msgstr "добавить маркер"
#: gtk2_ardour/editor_markers.cc:309 gtk2_ardour/editor_markers.cc:383
-#: gtk2_ardour/editor_markers.cc:555 gtk2_ardour/editor_markers.cc:573
-#: gtk2_ardour/editor_markers.cc:592 gtk2_ardour/editor_markers.cc:611
-#: gtk2_ardour/editor_markers.cc:641 gtk2_ardour/editor_markers.cc:669
-#: gtk2_ardour/editor_markers.cc:697 gtk2_ardour/editor_markers.cc:735
-#: gtk2_ardour/editor_markers.cc:762 gtk2_ardour/editor_markers.cc:785
-#: gtk2_ardour/editor_markers.cc:804 gtk2_ardour/editor_mouse.cc:2027
-#: gtk2_ardour/editor_mouse.cc:4322
+#: gtk2_ardour/editor_markers.cc:556 gtk2_ardour/editor_markers.cc:574
+#: gtk2_ardour/editor_markers.cc:593 gtk2_ardour/editor_markers.cc:612
+#: gtk2_ardour/editor_markers.cc:642 gtk2_ardour/editor_markers.cc:670
+#: gtk2_ardour/editor_markers.cc:698 gtk2_ardour/editor_markers.cc:737
+#: gtk2_ardour/editor_markers.cc:762 gtk2_ardour/editor_markers.cc:789
+#: gtk2_ardour/editor_markers.cc:812 gtk2_ardour/editor_markers.cc:831
+#: gtk2_ardour/editor_mouse.cc:2038 gtk2_ardour/editor_mouse.cc:4356
msgid "programming error: marker canvas item has no marker object pointer!"
msgstr "ошибка в программе: marker canvas item has no marker object pointer!"
@@ -3474,89 +3544,90 @@ msgstr "Скрыть маркер"
msgid "Remove Mark"
msgstr "Удалить маркер"
-#: gtk2_ardour/editor_markers.cc:482 gtk2_ardour/editor_markers.cc:538
+#: gtk2_ardour/editor_markers.cc:482 gtk2_ardour/editor_markers.cc:539
#, fuzzy
msgid "Locate to Range Mark"
msgstr "Маркеры интервалов"
-#: gtk2_ardour/editor_markers.cc:483 gtk2_ardour/editor_markers.cc:539
+#: gtk2_ardour/editor_markers.cc:483 gtk2_ardour/editor_markers.cc:540
#, fuzzy
msgid "Play from Range Mark"
msgstr "ВоÑпроизвеÑти \"кольцо\""
#: gtk2_ardour/editor_markers.cc:484
#, fuzzy
+msgid "Play Range"
+msgstr "ВоÑпроизвеÑти \"кольцо\""
+
+#: gtk2_ardour/editor_markers.cc:485
+#, fuzzy
msgid "Loop Range"
msgstr "ВоÑпроизвеÑти \"кольцо\""
-#: gtk2_ardour/editor_markers.cc:485 gtk2_ardour/editor_markers.cc:540
+#: gtk2_ardour/editor_markers.cc:486 gtk2_ardour/editor_markers.cc:541
#, fuzzy
msgid "Set Range Mark from Playhead"
msgstr "ВоÑпроизвеÑти от указателÑ"
-#: gtk2_ardour/editor_markers.cc:486 gtk2_ardour/editor_markers.cc:541
+#: gtk2_ardour/editor_markers.cc:487 gtk2_ardour/editor_markers.cc:542
#, fuzzy
msgid "Set Range from Range Selection"
msgstr "ВоÑпроизвеÑти выделенное"
-#: gtk2_ardour/editor_markers.cc:490
-#, fuzzy
+#: gtk2_ardour/editor_markers.cc:491
msgid "Rename Range"
-msgstr "Переименовать"
+msgstr "Переименовать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_markers.cc:491 gtk2_ardour/editor_markers.cc:543
+#: gtk2_ardour/editor_markers.cc:492 gtk2_ardour/editor_markers.cc:544
#, fuzzy
msgid "Hide Range"
msgstr "выделÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_markers.cc:492
+#: gtk2_ardour/editor_markers.cc:493
#, fuzzy
msgid "Remove Range"
msgstr "Удалить поле"
-#: gtk2_ardour/editor_markers.cc:496 gtk2_ardour/editor_markers.cc:545
+#: gtk2_ardour/editor_markers.cc:497 gtk2_ardour/editor_markers.cc:546
#, fuzzy
msgid "Separate Regions in Range"
msgstr "Создать облаÑÑ‚ÑŒ из выделенного"
-#: gtk2_ardour/editor_markers.cc:497 gtk2_ardour/editor_markers.cc:546
+#: gtk2_ardour/editor_markers.cc:498 gtk2_ardour/editor_markers.cc:547
#, fuzzy
msgid "Select All in Range"
msgstr "Выделить вÑÑ‘"
-#: gtk2_ardour/editor_markers.cc:523
+#: gtk2_ardour/editor_markers.cc:524
msgid "Set Loop Range"
msgstr ""
-#: gtk2_ardour/editor_markers.cc:524
+#: gtk2_ardour/editor_markers.cc:525
msgid "Set Punch Range"
msgstr ""
-#: gtk2_ardour/editor_markers.cc:818
-#, fuzzy
+#: gtk2_ardour/editor_markers.cc:845
msgid "New Name:"
-msgstr "новое имÑ: "
+msgstr "Ðовое имÑ: "
-#: gtk2_ardour/editor_markers.cc:821
+#: gtk2_ardour/editor_markers.cc:848
msgid "ardour: rename mark"
msgstr "ardour: переименовать маркер"
-#: gtk2_ardour/editor_markers.cc:823
-#, fuzzy
+#: gtk2_ardour/editor_markers.cc:850
msgid "ardour: rename range"
msgstr "ardour: переименовать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_markers.cc:843
-#, fuzzy
+#: gtk2_ardour/editor_markers.cc:870
msgid "rename marker"
-msgstr "добавить маркер"
+msgstr "переименовать маркер"
-#: gtk2_ardour/editor_markers.cc:869
+#: gtk2_ardour/editor_markers.cc:896
#, fuzzy
msgid "set loop range"
msgstr "выбрать окно проÑмотра"
-#: gtk2_ardour/editor_markers.cc:897
+#: gtk2_ardour/editor_markers.cc:924
#, fuzzy
msgid "set punch range"
msgstr "Выбрать текущий интервал"
@@ -3570,72 +3641,72 @@ msgstr "Editor::event_frame() used on unhandled event type %1"
msgid "select on click"
msgstr "ИÑпользовать как щелчок метронома"
-#: gtk2_ardour/editor_mouse.cc:1596
+#: gtk2_ardour/editor_mouse.cc:1599
msgid "programming error: start_grab called without drag item"
msgstr "ошибка в программе: start_grab called without drag item"
-#: gtk2_ardour/editor_mouse.cc:1820
+#: gtk2_ardour/editor_mouse.cc:1823
#, fuzzy
msgid "change fade in length"
msgstr "редактировать введение в уровень"
-#: gtk2_ardour/editor_mouse.cc:1841
+#: gtk2_ardour/editor_mouse.cc:1845
#, fuzzy
msgid "programming error: fade out canvas item has no regionview data pointer!"
msgstr "ошибка в программе: cursor canvas item has no cursor data pointer!"
-#: gtk2_ardour/editor_mouse.cc:1915
+#: gtk2_ardour/editor_mouse.cc:1919
#, fuzzy
msgid "change fade out length"
msgstr "редактировать Ñведение в ноль"
-#: gtk2_ardour/editor_mouse.cc:1937
+#: gtk2_ardour/editor_mouse.cc:1942
msgid "programming error: cursor canvas item has no cursor data pointer!"
msgstr "ошибка в программе: cursor canvas item has no cursor data pointer!"
-#: gtk2_ardour/editor_mouse.cc:2162
+#: gtk2_ardour/editor_mouse.cc:2173
#, fuzzy
msgid "move marker"
msgstr "Удалить поле"
-#: gtk2_ardour/editor_mouse.cc:2190 gtk2_ardour/editor_mouse.cc:2221
-#: gtk2_ardour/editor_tempodisplay.cc:490
+#: gtk2_ardour/editor_mouse.cc:2201 gtk2_ardour/editor_mouse.cc:2232
+#: gtk2_ardour/editor_tempodisplay.cc:492
msgid "programming error: meter marker canvas item has no marker object pointer!"
msgstr "ошибка в программе: meter marker canvas item has no marker object pointer!"
-#: gtk2_ardour/editor_mouse.cc:2289
+#: gtk2_ardour/editor_mouse.cc:2300
#, fuzzy
msgid "copy meter mark"
msgstr "добавить маркер"
-#: gtk2_ardour/editor_mouse.cc:2300
+#: gtk2_ardour/editor_mouse.cc:2311
msgid "move meter mark"
msgstr ""
-#: gtk2_ardour/editor_mouse.cc:2316 gtk2_ardour/editor_mouse.cc:2349
-#: gtk2_ardour/editor_tempodisplay.cc:353
-#: gtk2_ardour/editor_tempodisplay.cc:437
-#: gtk2_ardour/editor_tempodisplay.cc:456
+#: gtk2_ardour/editor_mouse.cc:2327 gtk2_ardour/editor_mouse.cc:2360
+#: gtk2_ardour/editor_tempodisplay.cc:355
+#: gtk2_ardour/editor_tempodisplay.cc:439
+#: gtk2_ardour/editor_tempodisplay.cc:458
msgid "programming error: tempo marker canvas item has no marker object pointer!"
msgstr "ошибка в программе: tempo marker canvas item has no marker object pointer!"
-#: gtk2_ardour/editor_mouse.cc:2321 gtk2_ardour/editor_mouse.cc:2354
-#: gtk2_ardour/editor_tempodisplay.cc:358
-#: gtk2_ardour/editor_tempodisplay.cc:442
+#: gtk2_ardour/editor_mouse.cc:2332 gtk2_ardour/editor_mouse.cc:2365
+#: gtk2_ardour/editor_tempodisplay.cc:360
+#: gtk2_ardour/editor_tempodisplay.cc:444
msgid "programming error: marker for tempo is not a tempo marker!"
msgstr "ошибка в программе: marker for tempo is not a tempo marker!"
-#: gtk2_ardour/editor_mouse.cc:2421
+#: gtk2_ardour/editor_mouse.cc:2432
#, fuzzy
msgid "copy tempo mark"
msgstr "добавить маркер"
-#: gtk2_ardour/editor_mouse.cc:2432
+#: gtk2_ardour/editor_mouse.cc:2443
msgid "move tempo mark"
msgstr ""
-#: gtk2_ardour/editor_mouse.cc:2447 gtk2_ardour/editor_mouse.cc:2466
-#: gtk2_ardour/editor_mouse.cc:2479
+#: gtk2_ardour/editor_mouse.cc:2458 gtk2_ardour/editor_mouse.cc:2477
+#: gtk2_ardour/editor_mouse.cc:2490
msgid ""
"programming error: control point canvas item has no control point object "
"pointer!"
@@ -3643,344 +3714,344 @@ msgstr ""
"ошибка в программе: control point canvas item has no control point object "
"pointer!"
-#: gtk2_ardour/editor_mouse.cc:2585
+#: gtk2_ardour/editor_mouse.cc:2596
msgid "programming error: line canvas item has no line pointer!"
msgstr "ошибка в программе: line canvas item has no line pointer!"
-#: gtk2_ardour/editor_mouse.cc:2694
+#: gtk2_ardour/editor_mouse.cc:2705
#, fuzzy
msgid "move region(s)"
msgstr "Создать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_mouse.cc:2757
+#: gtk2_ardour/editor_mouse.cc:2771
#, fuzzy
msgid "Drag region brush"
msgstr "проÑлушать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_mouse.cc:2781
+#: gtk2_ardour/editor_mouse.cc:2793
msgid "Drag region copy"
msgstr ""
-#: gtk2_ardour/editor_mouse.cc:3641
+#: gtk2_ardour/editor_mouse.cc:3673
#, fuzzy
msgid "selection grab"
msgstr "Выделенное"
-#: gtk2_ardour/editor_mouse.cc:3683
+#: gtk2_ardour/editor_mouse.cc:3715
#, fuzzy
msgid "cancel selection"
msgstr "ВоÑпроизвеÑти выделенное"
-#: gtk2_ardour/editor_mouse.cc:3793
+#: gtk2_ardour/editor_mouse.cc:3825
#, fuzzy
msgid "range selection"
msgstr "ВоÑпроизвеÑти выделенное"
-#: gtk2_ardour/editor_mouse.cc:3809
+#: gtk2_ardour/editor_mouse.cc:3841
#, fuzzy
msgid "trim selection start"
msgstr "Выделить по интервалу"
-#: gtk2_ardour/editor_mouse.cc:3825
+#: gtk2_ardour/editor_mouse.cc:3857
#, fuzzy
msgid "trim selection end"
msgstr "Выделить по интервалу"
-#: gtk2_ardour/editor_mouse.cc:3842
+#: gtk2_ardour/editor_mouse.cc:3874
#, fuzzy
msgid "move selection"
msgstr "СвеÑти выделенное"
-#: gtk2_ardour/editor_mouse.cc:4231
+#: gtk2_ardour/editor_mouse.cc:4265
#, fuzzy
msgid "Start point trim"
msgstr "От начала до курÑора"
-#: gtk2_ardour/editor_mouse.cc:4263
+#: gtk2_ardour/editor_mouse.cc:4297
msgid "End point trim"
msgstr ""
-#: gtk2_ardour/editor_mouse.cc:4306
+#: gtk2_ardour/editor_mouse.cc:4340
msgid "trimmed region"
msgstr ""
-#: gtk2_ardour/editor_mouse.cc:4448
+#: gtk2_ardour/editor_mouse.cc:4482
msgid "new range marker"
msgstr "Ðовый маркер облаÑти"
-#: gtk2_ardour/editor_mouse.cc:4692
+#: gtk2_ardour/editor_mouse.cc:4726
#, fuzzy
msgid "select regions"
msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_mouse.cc:4721
+#: gtk2_ardour/editor_mouse.cc:4755
msgid "Name for region:"
msgstr "Ð˜Ð¼Ñ Ð¾Ð±Ð»Ð°Ñти: "
-#: gtk2_ardour/editor_mouse.cc:4785
+#: gtk2_ardour/editor_mouse.cc:4819
#, fuzzy
msgid "timestretch"
msgstr "ardour: Ñффект timestretch"
-#: gtk2_ardour/editor_ops.cc:196
+#: gtk2_ardour/editor_ops.cc:115
#, fuzzy
msgid "split"
msgstr "Склеить"
-#: gtk2_ardour/editor_ops.cc:235
+#: gtk2_ardour/editor_ops.cc:154
#, fuzzy
msgid "remove region"
msgstr "Создать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_ops.cc:255
+#: gtk2_ardour/editor_ops.cc:174
msgid ""
" This is destructive, will possibly delete audio files\n"
"It cannot be undone\n"
"Do you really want to destroy %1 ?"
msgstr ""
-#: gtk2_ardour/editor_ops.cc:259
+#: gtk2_ardour/editor_ops.cc:178
#, fuzzy
msgid "these regions"
msgstr "ВоÑпроизвеÑти выделенную облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_ops.cc:259
+#: gtk2_ardour/editor_ops.cc:178
#, fuzzy
msgid "this region"
msgstr "отключить воÑпроизведение Ñтой облаÑти"
-#: gtk2_ardour/editor_ops.cc:261 gtk2_ardour/editor_ops.cc:3364
-#: gtk2_ardour/route_ui.cc:715 gtk2_ardour/visual_time_axis.cc:278
+#: gtk2_ardour/editor_ops.cc:180 gtk2_ardour/editor_ops.cc:3300
+#: gtk2_ardour/route_ui.cc:736 gtk2_ardour/visual_time_axis.cc:283
msgid "No, do nothing."
msgstr "Ðет"
-#: gtk2_ardour/editor_ops.cc:264
+#: gtk2_ardour/editor_ops.cc:183
#, fuzzy
msgid "Yes, destroy them."
msgstr "Да"
-#: gtk2_ardour/editor_ops.cc:266 gtk2_ardour/editor_ops.cc:3365
+#: gtk2_ardour/editor_ops.cc:185 gtk2_ardour/editor_ops.cc:3301
msgid "Yes, destroy it."
msgstr "Да"
-#: gtk2_ardour/editor_ops.cc:355 gtk2_ardour/editor_ops.cc:383
+#: gtk2_ardour/editor_ops.cc:271 gtk2_ardour/editor_ops.cc:299
#, fuzzy
msgid "extend selection"
msgstr "Выделить по интервалу"
-#: gtk2_ardour/editor_ops.cc:399 gtk2_ardour/editor_ops.cc:434
-#: gtk2_ardour/editor_ops.cc:479 gtk2_ardour/editor_ops.cc:506
+#: gtk2_ardour/editor_ops.cc:315 gtk2_ardour/editor_ops.cc:350
+#: gtk2_ardour/editor_ops.cc:395 gtk2_ardour/editor_ops.cc:422
msgid "nudge forward"
msgstr ""
-#: gtk2_ardour/editor_ops.cc:571
+#: gtk2_ardour/editor_ops.cc:487
msgid "build_region_boundary_cache called with snap_type = %1"
msgstr "build_region_boundary_cache called with snap_type = %1"
-#: gtk2_ardour/editor_ops.cc:1430
+#: gtk2_ardour/editor_ops.cc:1350
#, fuzzy
msgid "select all within"
msgstr "Выделить вÑÑ‘"
-#: gtk2_ardour/editor_ops.cc:1462
+#: gtk2_ardour/editor_ops.cc:1383
#, fuzzy
msgid "set selection from region"
msgstr "Создать облаÑÑ‚ÑŒ из выделенного"
-#: gtk2_ardour/editor_ops.cc:1495
+#: gtk2_ardour/editor_ops.cc:1416
#, fuzzy
msgid "set selection from range"
msgstr "Создать облаÑÑ‚ÑŒ из выделенного"
-#: gtk2_ardour/editor_ops.cc:1525
+#: gtk2_ardour/editor_ops.cc:1446
#, fuzzy
msgid "select all from range"
msgstr "выбрать окно проÑмотра"
-#: gtk2_ardour/editor_ops.cc:1547
+#: gtk2_ardour/editor_ops.cc:1468
#, fuzzy
msgid "select all from punch"
msgstr "Выделить вÑÑ‘"
-#: gtk2_ardour/editor_ops.cc:1569
+#: gtk2_ardour/editor_ops.cc:1490
#, fuzzy
msgid "select all from loop"
msgstr "Выделить вÑÑ‘"
-#: gtk2_ardour/editor_ops.cc:1583
+#: gtk2_ardour/editor_ops.cc:1504
#, fuzzy
msgid "select all after cursor"
msgstr "От начала до курÑора"
-#: gtk2_ardour/editor_ops.cc:1588
+#: gtk2_ardour/editor_ops.cc:1509
#, fuzzy
msgid "select all before cursor"
msgstr "ВоÑпроизвеÑти от курÑора"
-#: gtk2_ardour/editor_ops.cc:1618
+#: gtk2_ardour/editor_ops.cc:1539
#, fuzzy
msgid "select all between cursors"
msgstr "ВоÑпроизвеÑти от курÑора"
-#: gtk2_ardour/editor_ops.cc:1749
+#: gtk2_ardour/editor_ops.cc:1670
msgid "clear markers"
msgstr "очиÑтить маркеры"
-#: gtk2_ardour/editor_ops.cc:1762
+#: gtk2_ardour/editor_ops.cc:1683
msgid "clear ranges"
msgstr ""
-#: gtk2_ardour/editor_ops.cc:1782
+#: gtk2_ardour/editor_ops.cc:1703
msgid "clear locations"
msgstr "очиÑтить интервалы"
-#: gtk2_ardour/editor_ops.cc:1833
+#: gtk2_ardour/editor_ops.cc:1756
#, fuzzy
msgid "insert dragged region"
msgstr "Ð’Ñтавить облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_ops.cc:1869
+#: gtk2_ardour/editor_ops.cc:1803
#, fuzzy
msgid "insert region"
msgstr "Ð’Ñтавить облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_ops.cc:2060 gtk2_ardour/io_selector.cc:60
-#: gtk2_ardour/io_selector.cc:794 gtk2_ardour/connection_editor.cc:86
+#: gtk2_ardour/editor_ops.cc:1978 gtk2_ardour/io_selector.cc:60
+#: gtk2_ardour/io_selector.cc:748 gtk2_ardour/connection_editor.cc:86
msgid "OK"
msgstr "ОК"
-#: gtk2_ardour/editor_ops.cc:2067
+#: gtk2_ardour/editor_ops.cc:1985
msgid "ardour: rename region"
msgstr "ardour: переименовать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_ops.cc:2292 gtk2_ardour/editor_ops.cc:2345
+#: gtk2_ardour/editor_ops.cc:2210 gtk2_ardour/editor_ops.cc:2263
#, fuzzy
msgid "separate"
msgstr "Разделить облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_ops.cc:2410
+#: gtk2_ardour/editor_ops.cc:2328
#, fuzzy
msgid "trim to selection"
msgstr "Выделить по интервалу"
-#: gtk2_ardour/editor_ops.cc:2451
+#: gtk2_ardour/editor_ops.cc:2369
msgid "region fill"
msgstr ""
-#: gtk2_ardour/editor_ops.cc:2515
+#: gtk2_ardour/editor_ops.cc:2433
#, fuzzy
msgid "fill selection"
msgstr "Закольцевать выделенное"
-#: gtk2_ardour/editor_ops.cc:2536
+#: gtk2_ardour/editor_ops.cc:2454
#, fuzzy
msgid "Programming error. that region doesn't cover that position"
msgstr "ошибка в программе: location/marker map does not contain location!"
-#: gtk2_ardour/editor_ops.cc:2539
+#: gtk2_ardour/editor_ops.cc:2457
#, fuzzy
msgid "set region sync position"
msgstr "ОблаÑти/положение"
-#: gtk2_ardour/editor_ops.cc:2555
+#: gtk2_ardour/editor_ops.cc:2473
msgid "Place the edit cursor at the desired sync point"
msgstr "ПомеÑтите курÑор на точку Ñинхронизации"
-#: gtk2_ardour/editor_ops.cc:2560
+#: gtk2_ardour/editor_ops.cc:2478
#, fuzzy
msgid "set sync from edit cursor"
msgstr "ВоÑпроизвеÑти от курÑора"
-#: gtk2_ardour/editor_ops.cc:2573
+#: gtk2_ardour/editor_ops.cc:2491
msgid "remove sync"
msgstr ""
-#: gtk2_ardour/editor_ops.cc:2588
+#: gtk2_ardour/editor_ops.cc:2506
msgid "naturalize"
msgstr ""
-#: gtk2_ardour/editor_ops.cc:2653
+#: gtk2_ardour/editor_ops.cc:2571
#, fuzzy
msgid "align selection (relative)"
msgstr "ВыровнÑÑ‚ÑŒ отноÑительно"
-#: gtk2_ardour/editor_ops.cc:2682
+#: gtk2_ardour/editor_ops.cc:2600
#, fuzzy
msgid "align selection"
msgstr "СвеÑти выделенное"
-#: gtk2_ardour/editor_ops.cc:2694
+#: gtk2_ardour/editor_ops.cc:2612
#, fuzzy
msgid "align region"
msgstr "проÑлушать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_ops.cc:2742 gtk2_ardour/editor_ops.cc:2768
+#: gtk2_ardour/editor_ops.cc:2660 gtk2_ardour/editor_ops.cc:2686
#, fuzzy
msgid "trim to edit"
msgstr "От начала до курÑора"
-#: gtk2_ardour/editor_ops.cc:2820
+#: gtk2_ardour/editor_ops.cc:2738
#, fuzzy
msgid "ardour: freeze"
msgstr "ardour: "
-#: gtk2_ardour/editor_ops.cc:2825
+#: gtk2_ardour/editor_ops.cc:2743
#, fuzzy
msgid "Cancel Freeze"
msgstr "Отмена"
-#: gtk2_ardour/editor_ops.cc:2862
+#: gtk2_ardour/editor_ops.cc:2780
#, fuzzy
msgid "bounce range"
msgstr "Выбрать текущий интервал"
-#: gtk2_ardour/editor_ops.cc:2916
+#: gtk2_ardour/editor_ops.cc:2834
msgid "cut"
msgstr "вырезать"
-#: gtk2_ardour/editor_ops.cc:2919
+#: gtk2_ardour/editor_ops.cc:2837
msgid "copy"
msgstr "копировать"
-#: gtk2_ardour/editor_ops.cc:2932
+#: gtk2_ardour/editor_ops.cc:2850
msgid " objects"
msgstr "объекты"
-#: gtk2_ardour/editor_ops.cc:2958
+#: gtk2_ardour/editor_ops.cc:2876
msgid " range"
msgstr ""
-#: gtk2_ardour/editor_ops.cc:3121
+#: gtk2_ardour/editor_ops.cc:3057
#, fuzzy
msgid "paste"
msgstr "Ð’Ñтавить"
-#: gtk2_ardour/editor_ops.cc:3159
+#: gtk2_ardour/editor_ops.cc:3095
#, fuzzy
msgid "paste chunk"
msgstr "Создать фрагмент"
-#: gtk2_ardour/editor_ops.cc:3200
+#: gtk2_ardour/editor_ops.cc:3136
#, fuzzy
msgid "duplicate region"
msgstr "Разделить облаÑÑ‚ÑŒ"
-#: gtk2_ardour/editor_ops.cc:3245
+#: gtk2_ardour/editor_ops.cc:3181
#, fuzzy
msgid "duplicate selection"
msgstr "СвеÑти выделенное"
-#: gtk2_ardour/editor_ops.cc:3303
+#: gtk2_ardour/editor_ops.cc:3239
#, fuzzy
msgid "clear playlist"
msgstr "Ð˜Ð¼Ñ Ñнимка"
-#: gtk2_ardour/editor_ops.cc:3333
+#: gtk2_ardour/editor_ops.cc:3269
#, fuzzy
msgid "nudge track"
msgstr "Скрыть трек"
-#: gtk2_ardour/editor_ops.cc:3361
+#: gtk2_ardour/editor_ops.cc:3297
msgid ""
"Do you really want to destroy the last capture?\n"
"(This is destructive and cannot be undone)"
@@ -3988,85 +4059,87 @@ msgstr ""
"ПоÑледнюю запиÑÑŒ будет удалена. Ð’Ñ‹ уверены?\n"
"(отмена операции невозможна)"
-#: gtk2_ardour/editor_ops.cc:3389
-#, fuzzy
+#: gtk2_ardour/editor_ops.cc:3325
msgid "normalize"
-msgstr "Ðорм."
+msgstr "нормализовать"
-#: gtk2_ardour/editor_ops.cc:3442
+#: gtk2_ardour/editor_ops.cc:3378
msgid "reverse regions"
msgstr ""
-#: gtk2_ardour/editor_region_list.cc:98 gtk2_ardour/editor_region_list.cc:103
-#: gtk2_ardour/editor_region_list.cc:106 gtk2_ardour/location_ui.cc:57
+#: gtk2_ardour/editor_ops.cc:3491
+#, fuzzy
+msgid "reset region gain"
+msgstr "Создать облаÑÑ‚ÑŒ"
+
+#: gtk2_ardour/editor_region_list.cc:103 gtk2_ardour/editor_region_list.cc:109
+#: gtk2_ardour/editor_region_list.cc:112 gtk2_ardour/location_ui.cc:57
msgid "Hidden"
msgstr "Скрытый"
#: gtk2_ardour/editor_route_list.cc:100 gtk2_ardour/editor_route_list.cc:101
-#: gtk2_ardour/editor_route_list.cc:246
+#: gtk2_ardour/editor_route_list.cc:250
msgid "editor"
msgstr "редактор"
-#: gtk2_ardour/editor_route_list.cc:313 gtk2_ardour/mixer_ui.cc:717
+#: gtk2_ardour/editor_route_list.cc:317 gtk2_ardour/mixer_ui.cc:714
msgid "Show All"
msgstr "Показать вÑÑ‘"
-#: gtk2_ardour/editor_route_list.cc:314 gtk2_ardour/mixer_ui.cc:718
+#: gtk2_ardour/editor_route_list.cc:318 gtk2_ardour/mixer_ui.cc:715
msgid "Hide All"
msgstr "Скрыть вÑÑ‘"
-#: gtk2_ardour/editor_route_list.cc:315 gtk2_ardour/mixer_ui.cc:719
+#: gtk2_ardour/editor_route_list.cc:319 gtk2_ardour/mixer_ui.cc:716
#, fuzzy
msgid "Show All Audio Tracks"
msgstr "Показать вÑе аудиошины"
-#: gtk2_ardour/editor_route_list.cc:316 gtk2_ardour/mixer_ui.cc:720
+#: gtk2_ardour/editor_route_list.cc:320 gtk2_ardour/mixer_ui.cc:717
#, fuzzy
msgid "Hide All Audio Tracks"
msgstr "Скрыть вÑе аудиошины"
-#: gtk2_ardour/editor_route_list.cc:317 gtk2_ardour/mixer_ui.cc:721
-#, fuzzy
+#: gtk2_ardour/editor_route_list.cc:321 gtk2_ardour/mixer_ui.cc:718
msgid "Show All Audio Busses"
msgstr "Показать вÑе аудиошины"
-#: gtk2_ardour/editor_route_list.cc:318 gtk2_ardour/mixer_ui.cc:722
-#, fuzzy
+#: gtk2_ardour/editor_route_list.cc:322 gtk2_ardour/mixer_ui.cc:719
msgid "Hide All Audio Busses"
msgstr "Скрыть вÑе аудиошины"
-#: gtk2_ardour/editor_rulers.cc:311
+#: gtk2_ardour/editor_rulers.cc:338
#, fuzzy
msgid "New location marker"
msgstr "Маркеры интервалов"
-#: gtk2_ardour/editor_rulers.cc:312
+#: gtk2_ardour/editor_rulers.cc:339
#, fuzzy
msgid "Clear all locations"
msgstr "очиÑтить интервалы"
-#: gtk2_ardour/editor_rulers.cc:317
+#: gtk2_ardour/editor_rulers.cc:344
msgid "Clear all ranges"
msgstr "ОчиÑтить вÑе облаÑти"
-#: gtk2_ardour/editor_rulers.cc:326
+#: gtk2_ardour/editor_rulers.cc:353
#, fuzzy
msgid "New Tempo"
msgstr "Ðовый темп"
-#: gtk2_ardour/editor_rulers.cc:327
+#: gtk2_ardour/editor_rulers.cc:354
msgid "Clear tempo"
msgstr "ОчиÑтить темп"
-#: gtk2_ardour/editor_rulers.cc:332
+#: gtk2_ardour/editor_rulers.cc:359
msgid "New Meter"
-msgstr ""
+msgstr "Ðовый Ñчётчик"
-#: gtk2_ardour/editor_rulers.cc:333
+#: gtk2_ardour/editor_rulers.cc:360
msgid "Clear meter"
-msgstr ""
+msgstr "СброÑить Ñчётчик"
-#: gtk2_ardour/editor_rulers.cc:341
+#: gtk2_ardour/editor_rulers.cc:368
msgid "Min:Secs"
msgstr "Мин:С"
@@ -4082,38 +4155,38 @@ msgstr "Создать фрагмент"
msgid "Forget it"
msgstr "Забыть"
-#: gtk2_ardour/editor_tempodisplay.cc:270
-#: gtk2_ardour/editor_tempodisplay.cc:313
+#: gtk2_ardour/editor_tempodisplay.cc:272
+#: gtk2_ardour/editor_tempodisplay.cc:315
msgid "add"
msgstr "добавить"
-#: gtk2_ardour/editor_tempodisplay.cc:292
+#: gtk2_ardour/editor_tempodisplay.cc:294
#, fuzzy
msgid "add tempo mark"
msgstr "добавить маркер"
-#: gtk2_ardour/editor_tempodisplay.cc:335
+#: gtk2_ardour/editor_tempodisplay.cc:337
#, fuzzy
msgid "add meter mark"
msgstr "добавить маркер"
-#: gtk2_ardour/editor_tempodisplay.cc:370
-#: gtk2_ardour/editor_tempodisplay.cc:401
+#: gtk2_ardour/editor_tempodisplay.cc:372
+#: gtk2_ardour/editor_tempodisplay.cc:403
msgid "done"
msgstr "готово"
-#: gtk2_ardour/editor_tempodisplay.cc:388
-#: gtk2_ardour/editor_tempodisplay.cc:419
+#: gtk2_ardour/editor_tempodisplay.cc:390
+#: gtk2_ardour/editor_tempodisplay.cc:421
msgid "replace tempo mark"
-msgstr ""
+msgstr "Ñменить метку темпа"
-#: gtk2_ardour/editor_tempodisplay.cc:461
-#: gtk2_ardour/editor_tempodisplay.cc:495
+#: gtk2_ardour/editor_tempodisplay.cc:463
+#: gtk2_ardour/editor_tempodisplay.cc:497
msgid "programming error: marker for meter is not a meter marker!"
msgstr "ошибка в программе: marker for meter is not a meter marker!"
-#: gtk2_ardour/editor_tempodisplay.cc:471
-#: gtk2_ardour/editor_tempodisplay.cc:507
+#: gtk2_ardour/editor_tempodisplay.cc:473
+#: gtk2_ardour/editor_tempodisplay.cc:509
#, fuzzy
msgid "remove tempo mark"
msgstr "Да, удалить вÑÑ‘"
@@ -4150,198 +4223,175 @@ msgstr "TimeStretchProgress"
msgid "timestretch cannot be started - thread creation error"
msgstr ""
-#: gtk2_ardour/export_dialog.cc:59 gtk2_ardour/export_dialog.cc:399
-#: gtk2_ardour/export_dialog.cc:1027 gtk2_ardour/export_dialog.cc:1195
+#: gtk2_ardour/export_dialog.cc:57 gtk2_ardour/export_dialog.cc:397
+#: gtk2_ardour/export_dialog.cc:1025 gtk2_ardour/export_dialog.cc:1193
msgid "22.05kHz"
msgstr "22.05кГц"
-#: gtk2_ardour/export_dialog.cc:60 gtk2_ardour/export_dialog.cc:402
-#: gtk2_ardour/export_dialog.cc:417 gtk2_ardour/export_dialog.cc:1029
-#: gtk2_ardour/export_dialog.cc:1197
+#: gtk2_ardour/export_dialog.cc:58 gtk2_ardour/export_dialog.cc:400
+#: gtk2_ardour/export_dialog.cc:415 gtk2_ardour/export_dialog.cc:1027
+#: gtk2_ardour/export_dialog.cc:1195
msgid "44.1kHz"
msgstr "44.1кГц"
-#: gtk2_ardour/export_dialog.cc:61 gtk2_ardour/export_dialog.cc:405
-#: gtk2_ardour/export_dialog.cc:1031 gtk2_ardour/export_dialog.cc:1199
+#: gtk2_ardour/export_dialog.cc:59 gtk2_ardour/export_dialog.cc:403
+#: gtk2_ardour/export_dialog.cc:1029 gtk2_ardour/export_dialog.cc:1197
msgid "48kHz"
msgstr "48кГц"
-#: gtk2_ardour/export_dialog.cc:62 gtk2_ardour/export_dialog.cc:408
-#: gtk2_ardour/export_dialog.cc:1033 gtk2_ardour/export_dialog.cc:1201
+#: gtk2_ardour/export_dialog.cc:60 gtk2_ardour/export_dialog.cc:406
+#: gtk2_ardour/export_dialog.cc:1031 gtk2_ardour/export_dialog.cc:1199
msgid "88.2kHz"
msgstr "88.2кГц"
-#: gtk2_ardour/export_dialog.cc:63 gtk2_ardour/export_dialog.cc:411
-#: gtk2_ardour/export_dialog.cc:1035 gtk2_ardour/export_dialog.cc:1203
+#: gtk2_ardour/export_dialog.cc:61 gtk2_ardour/export_dialog.cc:409
+#: gtk2_ardour/export_dialog.cc:1033 gtk2_ardour/export_dialog.cc:1201
msgid "96kHz"
msgstr "96кГц"
-#: gtk2_ardour/export_dialog.cc:64 gtk2_ardour/export_dialog.cc:414
-#: gtk2_ardour/export_dialog.cc:1037 gtk2_ardour/export_dialog.cc:1205
+#: gtk2_ardour/export_dialog.cc:62 gtk2_ardour/export_dialog.cc:412
+#: gtk2_ardour/export_dialog.cc:1035 gtk2_ardour/export_dialog.cc:1203
msgid "192kHz"
msgstr "192кГц"
-#: gtk2_ardour/export_dialog.cc:69
+#: gtk2_ardour/export_dialog.cc:67
msgid "best"
msgstr "выÑокое"
-#: gtk2_ardour/export_dialog.cc:70 gtk2_ardour/export_dialog.cc:1212
+#: gtk2_ardour/export_dialog.cc:68 gtk2_ardour/export_dialog.cc:1210
msgid "fastest"
msgstr "быÑтрое"
-#: gtk2_ardour/export_dialog.cc:71 gtk2_ardour/export_dialog.cc:1214
+#: gtk2_ardour/export_dialog.cc:69 gtk2_ardour/export_dialog.cc:1212
msgid "linear"
msgstr "линейное"
-#: gtk2_ardour/export_dialog.cc:72 gtk2_ardour/export_dialog.cc:1216
+#: gtk2_ardour/export_dialog.cc:70 gtk2_ardour/export_dialog.cc:1214
msgid "better"
msgstr "нормальное"
-#: gtk2_ardour/export_dialog.cc:73 gtk2_ardour/export_dialog.cc:1218
+#: gtk2_ardour/export_dialog.cc:71 gtk2_ardour/export_dialog.cc:1216
msgid "intermediate"
msgstr "Ñреднее"
-#: gtk2_ardour/export_dialog.cc:79 gtk2_ardour/export_dialog.cc:1227
+#: gtk2_ardour/export_dialog.cc:77 gtk2_ardour/export_dialog.cc:1225
msgid "Rectangular"
-msgstr "Rectangular"
+msgstr "ПрÑмоугольный"
-#: gtk2_ardour/export_dialog.cc:80
+#: gtk2_ardour/export_dialog.cc:78
msgid "Shaped Noise"
-msgstr "Shaped Noise"
+msgstr "По очертаниÑм"
-#: gtk2_ardour/export_dialog.cc:81 gtk2_ardour/export_dialog.cc:1229
+#: gtk2_ardour/export_dialog.cc:79 gtk2_ardour/export_dialog.cc:1227
msgid "Triangular"
-msgstr "Triangular"
+msgstr "Треугольный"
-#: gtk2_ardour/export_dialog.cc:86
-msgid "stereo"
-msgstr "Ñтерео"
-
-#: gtk2_ardour/export_dialog.cc:87 gtk2_ardour/export_dialog.cc:486
-#: gtk2_ardour/export_dialog.cc:1055 gtk2_ardour/export_dialog.cc:1177
+#: gtk2_ardour/export_dialog.cc:85 gtk2_ardour/export_dialog.cc:484
+#: gtk2_ardour/export_dialog.cc:1053 gtk2_ardour/export_dialog.cc:1175
msgid "mono"
msgstr "моно"
-#: gtk2_ardour/export_dialog.cc:93
+#: gtk2_ardour/export_dialog.cc:91
msgid "CUE"
-msgstr ""
+msgstr "CUE"
-#: gtk2_ardour/export_dialog.cc:94
+#: gtk2_ardour/export_dialog.cc:92
msgid "TOC"
-msgstr ""
+msgstr "TOC"
-#: gtk2_ardour/export_dialog.cc:102
-#, fuzzy
+#: gtk2_ardour/export_dialog.cc:100
msgid "Format"
-msgstr "Ðорм."
+msgstr "Формат"
-#: gtk2_ardour/export_dialog.cc:103
+#: gtk2_ardour/export_dialog.cc:101
msgid "CD Marker File Type"
-msgstr ""
+msgstr "Тип файла маркеров CD"
-#: gtk2_ardour/export_dialog.cc:104
-#, fuzzy
+#: gtk2_ardour/export_dialog.cc:102
msgid "Channels"
-msgstr "отмена"
+msgstr "Каналов"
-#: gtk2_ardour/export_dialog.cc:105
-#, fuzzy
+#: gtk2_ardour/export_dialog.cc:103
msgid "File Type"
-msgstr "Тип"
+msgstr "Тип файла"
-#: gtk2_ardour/export_dialog.cc:106
-#, fuzzy
+#: gtk2_ardour/export_dialog.cc:104
msgid "Sample Format"
-msgstr "Разделить облаÑÑ‚ÑŒ"
+msgstr "Формат ÑÑмпла"
-#: gtk2_ardour/export_dialog.cc:107
+#: gtk2_ardour/export_dialog.cc:105
msgid "Sample Endianness"
-msgstr ""
+msgstr "Байтовый порÑдок ÑÑмпла"
-#: gtk2_ardour/export_dialog.cc:108
-#, fuzzy
+#: gtk2_ardour/export_dialog.cc:106
msgid "Sample Rate"
-msgstr "Разделить облаÑÑ‚ÑŒ"
+msgstr "ЧаÑтота ÑÑмплированиÑ"
-#: gtk2_ardour/export_dialog.cc:109
+#: gtk2_ardour/export_dialog.cc:107
msgid "Conversion Quality"
-msgstr ""
+msgstr "КачеÑтво преобразованиÑ"
-#: gtk2_ardour/export_dialog.cc:110
+#: gtk2_ardour/export_dialog.cc:108
msgid "Dither Type"
-msgstr ""
+msgstr "Тип дитеринга"
-#: gtk2_ardour/export_dialog.cc:111
+#: gtk2_ardour/export_dialog.cc:109
msgid "Export CD Marker File Only"
-msgstr ""
+msgstr "ЭкÑпортировать только файл маркеров CD"
-#: gtk2_ardour/export_dialog.cc:112
-#, fuzzy
+#: gtk2_ardour/export_dialog.cc:110
msgid "Export to File"
-msgstr "ЭкÑпорт на CD"
+msgstr "ЭкÑпорт в файл"
-#: gtk2_ardour/export_dialog.cc:113 gtk2_ardour/option_editor.cc:82
-#: gtk2_ardour/option_editor.cc:83
+#: gtk2_ardour/export_dialog.cc:111 gtk2_ardour/option_editor.cc:80
+#: gtk2_ardour/option_editor.cc:81
msgid "Browse"
msgstr "Обзор"
-#: gtk2_ardour/export_dialog.cc:114
+#: gtk2_ardour/export_dialog.cc:112
msgid "Specific tracks ..."
-msgstr ""
+msgstr "СпецифичеÑкие задачи"
-#: gtk2_ardour/export_dialog.cc:125
+#: gtk2_ardour/export_dialog.cc:123
msgid "ardour: export"
msgstr "ardour: ÑкÑпорт"
-#: gtk2_ardour/export_dialog.cc:126
-msgid "ardour_export"
-msgstr "ardour_ÑкÑпорт"
-
-#: gtk2_ardour/export_dialog.cc:139 gtk2_ardour/export_dialog.cc:155
-#: gtk2_ardour/mixer_strip.cc:121 gtk2_ardour/mixer_strip.cc:727
+#: gtk2_ardour/export_dialog.cc:137 gtk2_ardour/export_dialog.cc:153
+#: gtk2_ardour/mixer_strip.cc:123 gtk2_ardour/mixer_strip.cc:746
msgid "Output"
msgstr "Выход"
-#: gtk2_ardour/export_dialog.cc:140 gtk2_ardour/export_dialog.cc:156
-#: gtk2_ardour/export_dialog.cc:1068 gtk2_ardour/export_dialog.cc:1072
-msgid "Left"
-msgstr "Левый"
-
-#: gtk2_ardour/export_dialog.cc:141 gtk2_ardour/export_dialog.cc:157
-msgid "Right"
-msgstr "Правый"
-
-#: gtk2_ardour/export_dialog.cc:633
+#: gtk2_ardour/export_dialog.cc:631
#, fuzzy
msgid "Editor: cannot open \"%1\" as export file for CD toc file"
msgstr "Редакор: не могу открыть \"%1\" как файл ÑкÑпорта маркеров Ð´Ð»Ñ CD-треков"
-#: gtk2_ardour/export_dialog.cc:759
+#: gtk2_ardour/export_dialog.cc:757
#, fuzzy
msgid "Editor: cannot open \"%1\" as export file for CD cue file"
msgstr "Редакор: не могу открыть \"%1\" как файл ÑкÑпорта маркеров Ð´Ð»Ñ CD-треков"
-#: gtk2_ardour/export_dialog.cc:778
+#: gtk2_ardour/export_dialog.cc:776
msgid "WAV"
msgstr "WAV"
-#: gtk2_ardour/export_dialog.cc:912
+#: gtk2_ardour/export_dialog.cc:910
msgid "Stop Export"
msgstr "ОÑтановить ÑкÑпорт"
-#: gtk2_ardour/export_dialog.cc:1131
+#: gtk2_ardour/export_dialog.cc:1129
msgid "Please enter a valid filename."
msgstr "Введите корректное Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°"
-#: gtk2_ardour/export_dialog.cc:1141
+#: gtk2_ardour/export_dialog.cc:1139
msgid "Please specify a complete filename for the audio file."
msgstr "Укажите полное Ð¸Ð¼Ñ Ð·Ð²ÑƒÐºÐ¾Ð²Ð¾Ð³Ð¾ файла"
-#: gtk2_ardour/export_dialog.cc:1147
+#: gtk2_ardour/export_dialog.cc:1145
msgid "File already exists, do you want to overwrite it?"
msgstr "Файл Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже еÑÑ‚ÑŒ. ПерезапиÑать его?"
-#: gtk2_ardour/export_dialog.cc:1159
+#: gtk2_ardour/export_dialog.cc:1157
#: gtk2_ardour/export_range_markers_dialog.cc:153
msgid "Cannot write file in: "
msgstr "Ðевозможно запиÑать файлв в:"
@@ -4361,51 +4411,48 @@ msgstr ""
msgid "add gain automation event"
msgstr "автомат"
-#: gtk2_ardour/gain_meter.cc:67
-msgid "cannot find images for fader slider"
-msgstr ""
-
-#: gtk2_ardour/gain_meter.cc:74
-msgid "cannot find images for fader rail"
-msgstr ""
-
-#: gtk2_ardour/gain_meter.cc:125 gtk2_ardour/gain_meter.cc:334
-#: gtk2_ardour/gain_meter.cc:489 gtk2_ardour/gain_meter.cc:534
+#: gtk2_ardour/gain_meter.cc:112 gtk2_ardour/gain_meter.cc:330
+#: gtk2_ardour/gain_meter.cc:511 gtk2_ardour/gain_meter.cc:578
#, fuzzy
msgid "-inf"
msgstr "в"
-#: gtk2_ardour/gain_meter.cc:135
+#: gtk2_ardour/gain_meter.cc:123
msgid "Fader automation mode"
msgstr "Режим автоматизации фейдера"
-#: gtk2_ardour/gain_meter.cc:136
+#: gtk2_ardour/gain_meter.cc:124
msgid "Fader automation type"
msgstr "Тип автоматизации фейдера"
-#: gtk2_ardour/gain_meter.cc:177 gtk2_ardour/gain_meter.cc:812
-#: gtk2_ardour/panner_ui.cc:97 gtk2_ardour/panner_ui.cc:797
+#: gtk2_ardour/gain_meter.cc:169 gtk2_ardour/gain_meter.cc:872
+#: gtk2_ardour/panner_ui.cc:99 gtk2_ardour/panner_ui.cc:810
msgid "Abs"
msgstr "ÐбÑ"
-#: gtk2_ardour/gain_meter.cc:467
+#: gtk2_ardour/gain_meter.cc:489
msgid "-Inf"
msgstr "-Inf"
-#: gtk2_ardour/gain_meter.cc:776 gtk2_ardour/mixer_strip.cc:730
-#: gtk2_ardour/panner_ui.cc:761
+#: gtk2_ardour/gain_meter.cc:688 gtk2_ardour/gain_meter.cc:703
+#, fuzzy
+msgid "meter point change"
+msgstr "Выбрать текущий интервал"
+
+#: gtk2_ardour/gain_meter.cc:836 gtk2_ardour/mixer_strip.cc:749
+#: gtk2_ardour/panner_ui.cc:774
msgid "O"
msgstr "O"
-#: gtk2_ardour/gain_meter.cc:779 gtk2_ardour/panner_ui.cc:764
+#: gtk2_ardour/gain_meter.cc:839 gtk2_ardour/panner_ui.cc:777
msgid "P"
msgstr "P"
-#: gtk2_ardour/gain_meter.cc:782 gtk2_ardour/panner_ui.cc:767
+#: gtk2_ardour/gain_meter.cc:842 gtk2_ardour/panner_ui.cc:780
msgid "T"
msgstr "T"
-#: gtk2_ardour/gain_meter.cc:785 gtk2_ardour/panner_ui.cc:770
+#: gtk2_ardour/gain_meter.cc:845 gtk2_ardour/panner_ui.cc:783
msgid "W"
msgstr "W"
@@ -4496,10 +4543,10 @@ msgstr "Кадр"
msgid "Rename Track"
msgstr "Переименовать дорожку"
-#: gtk2_ardour/io_selector.cc:62 gtk2_ardour/io_selector.cc:796
+#: gtk2_ardour/io_selector.cc:62 gtk2_ardour/io_selector.cc:750
#: gtk2_ardour/connection_editor.cc:61 gtk2_ardour/connection_editor.cc:110
msgid "Rescan"
-msgstr ""
+msgstr "ПроÑканировать заново"
#: gtk2_ardour/io_selector.cc:70
msgid "%1 input"
@@ -4511,11 +4558,11 @@ msgstr "%1 выход"
#: gtk2_ardour/io_selector.cc:144 gtk2_ardour/route_params_ui.cc:103
msgid "Inputs"
-msgstr "Входов"
+msgstr "Входы"
#: gtk2_ardour/io_selector.cc:144 gtk2_ardour/route_params_ui.cc:104
msgid "Outputs"
-msgstr "Выходов"
+msgstr "Выходы"
#: gtk2_ardour/io_selector.cc:145
msgid "Add Input"
@@ -4541,16 +4588,11 @@ msgstr "ОтÑоединить вÑе"
msgid "Available connections"
msgstr "ДоÑтупные ÑоединениÑ"
-#: gtk2_ardour/io_selector.cc:557 gtk2_ardour/io_selector.cc:576
+#: gtk2_ardour/io_selector.cc:549 gtk2_ardour/io_selector.cc:560
msgid "There are no more JACK ports available."
-msgstr ""
+msgstr "ДоÑтупных портов JACK не оÑталоÑÑŒ."
-#: gtk2_ardour/io_selector.cc:651 gtk2_ardour/io_selector.cc:678
-#: gtk2_ardour/io_selector.cc:731
-msgid "port"
-msgstr "порт"
-
-#: gtk2_ardour/io_selector.cc:800
+#: gtk2_ardour/io_selector.cc:754
msgid "ardour: "
msgstr "ardour: "
@@ -4592,11 +4634,7 @@ msgstr "Ð”Ð»Ñ \"mod5\" назначено кнопок: %1"
#: gtk2_ardour/ladspa_pluginui.cc:77
msgid "<span size=\"large\">Presets</span>"
-msgstr ""
-
-#: gtk2_ardour/ladspa_pluginui.cc:168
-msgid "Controls"
-msgstr "Управление"
+msgstr "<span size=\"large\">ПредуÑтановки</span>"
#: gtk2_ardour/ladspa_pluginui.cc:205
msgid "Plugin Editor: could not build control element for port %1"
@@ -4604,7 +4642,7 @@ msgstr "Редактор модулей: невозможно Ñоздать ÑÑ
#: gtk2_ardour/ladspa_pluginui.cc:296
msgid "Automation control"
-msgstr "Контроль атовматизации"
+msgstr "Контроль автоматизации"
#: gtk2_ardour/location_ui.cc:49 gtk2_ardour/location_ui.cc:52
msgid "Set"
@@ -4620,7 +4658,7 @@ msgstr "CD"
#: gtk2_ardour/location_ui.cc:59
msgid "SCMS"
-msgstr ""
+msgstr "SCMS"
#: gtk2_ardour/location_ui.cc:60
msgid "Pre-Emphasis"
@@ -4632,16 +4670,12 @@ msgstr "Добавить новый интервал"
#: gtk2_ardour/location_ui.cc:572
msgid "Add New Range"
-msgstr ""
+msgstr "Добавить новую облаÑÑ‚ÑŒ"
#: gtk2_ardour/location_ui.cc:576
msgid "ardour: locations"
msgstr "ardour: интервалы"
-#: gtk2_ardour/location_ui.cc:577
-msgid "ardour_locations"
-msgstr "ardour_интервалы"
-
#: gtk2_ardour/location_ui.cc:605
#, fuzzy
msgid "Location (CD Index) Markers"
@@ -4655,32 +4689,28 @@ msgstr ""
msgid "add range marker"
msgstr "Добавить маркер облаÑти"
-#: gtk2_ardour/main.cc:72
+#: gtk2_ardour/main.cc:73
msgid "ardour is killing itself for a clean exit\n"
msgstr "ardour: принудительное завершение работы\n"
-#: gtk2_ardour/main.cc:81
-msgid "stopping user interface\n"
-msgstr "завершение работы...\n"
-
-#: gtk2_ardour/main.cc:100
+#: gtk2_ardour/main.cc:99
#, c-format
msgid "%d(%d): received signal %d\n"
msgstr "%d(%d): принÑÑ‚ Ñигнал %d\n"
-#: gtk2_ardour/main.cc:180
+#: gtk2_ardour/main.cc:179
msgid "cannot become new process group leader (%1)"
msgstr ""
-#: gtk2_ardour/main.cc:207
+#: gtk2_ardour/main.cc:206
msgid "cannot setup signal handling for %1"
msgstr "cannot setup signal handling for %1"
-#: gtk2_ardour/main.cc:218
+#: gtk2_ardour/main.cc:217
msgid "cannot set default signal mask (%1)"
msgstr "cannot set default signal mask (%1)"
-#: gtk2_ardour/main.cc:248
+#: gtk2_ardour/main.cc:247
msgid ""
"Without a UI style file, ardour will look strange.\n"
" Please set ARDOUR2_UI_RC to point to a valid UI style file"
@@ -4689,11 +4719,11 @@ msgstr ""
"без файла, определÑющего Ñтиль оформлениÑ.\n"
"ПожалуйÑта, укажите его [файл] в переменной Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ ARDOUR_UI_RC"
-#: gtk2_ardour/main.cc:270
+#: gtk2_ardour/main.cc:268
msgid "Ardour could not connect to JACK."
msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK."
-#: gtk2_ardour/main.cc:274
+#: gtk2_ardour/main.cc:272
#, fuzzy
msgid ""
"There are several possible reasons:\n"
@@ -4713,11 +4743,11 @@ msgstr ""
"\n"
"ПожалуйÑта, проверьте вÑе варианты, возможно потребуетÑÑ (пере)запуÑк JACK."
-#: gtk2_ardour/main.cc:316
+#: gtk2_ardour/main.cc:314
msgid "could not load command line session \"%1\""
msgstr "не удалоÑÑŒ загрузить ÑеÑÑию \"%1\", указанную в командной Ñтроке"
-#: gtk2_ardour/main.cc:324
+#: gtk2_ardour/main.cc:322
msgid ""
"\n"
"\n"
@@ -4725,52 +4755,52 @@ msgid ""
"To create it from the command line, start ardour as \"ardour --new %1"
msgstr ""
-#: gtk2_ardour/main.cc:383
+#: gtk2_ardour/main.cc:386
msgid "Ardour/GTK "
msgstr "Ardour/GTK "
-#: gtk2_ardour/main.cc:385
+#: gtk2_ardour/main.cc:388
msgid ""
"\n"
" (built using "
msgstr ""
+"\n"
+" (Ñобран Ñ Ð¸Ñпользованием "
-#: gtk2_ardour/main.cc:389
-msgid " with libardour "
-msgstr " Ñ libardour "
-
-#: gtk2_ardour/main.cc:394
+#: gtk2_ardour/main.cc:391
msgid " and GCC version "
msgstr " и верÑией GCC "
-#: gtk2_ardour/main.cc:404
+#: gtk2_ardour/main.cc:401
msgid "Copyright (C) 1999-2006 Paul Davis"
msgstr "ÐвторÑкие права © 1999-2006 Paul Davis"
-#: gtk2_ardour/main.cc:405
+#: gtk2_ardour/main.cc:402
msgid ""
"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel "
"Baker"
-msgstr "ЧаÑтичные авторÑкие права © Steve Harris, Ari Johnson, Brett Viren, Joel Baker"
+msgstr ""
+"ЧаÑтичные авторÑкие права © Steve Harris, Ari Johnson, Brett Viren, Joel "
+"Baker"
-#: gtk2_ardour/main.cc:407
+#: gtk2_ardour/main.cc:404
msgid "Ardour comes with ABSOLUTELY NO WARRANTY"
msgstr "Ardour раÑпроÑтранÑетÑÑ Ð‘Ð•Ð—Ðž ВСЯКИХ ГÐРÐÐТИЙ"
-#: gtk2_ardour/main.cc:408
+#: gtk2_ardour/main.cc:405
msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
msgstr ""
-#: gtk2_ardour/main.cc:409
+#: gtk2_ardour/main.cc:406
msgid "This is free software, and you are welcome to redistribute it "
msgstr "Это Ñвободное программное обеÑпечение, Ð’Ñ‹ можете раÑпроÑтранÑÑ‚ÑŒ его"
-#: gtk2_ardour/main.cc:410
+#: gtk2_ardour/main.cc:407
#, fuzzy
msgid "under certain conditions; see the source for copying conditions."
msgstr "на определённых уÑловиÑÑ…; подробнее об Ñтом читайте в файле COPYING."
-#: gtk2_ardour/main.cc:420
+#: gtk2_ardour/main.cc:417
msgid "could not create ARDOUR GUI"
msgstr "не удалоÑÑŒ Ñоздать графичеÑкий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ ARDOUR"
@@ -4778,7 +4808,7 @@ msgstr "не удалоÑÑŒ Ñоздать графичеÑкий интерфе
msgid "Could not connect to JACK server as \"%1\""
msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\""
-#: gtk2_ardour/main.cc:446
+#: gtk2_ardour/main.cc:447
msgid "could not initialize Ardour."
msgstr "не удалоÑÑŒ запуÑтить Ardour."
@@ -4795,118 +4825,110 @@ msgstr "Удалить поле"
msgid "Marker"
msgstr "Маркер"
-#: gtk2_ardour/mixer_strip.cc:92 gtk2_ardour/mixer_strip.cc:137
-#: gtk2_ardour/mixer_strip.cc:1191
+#: gtk2_ardour/mixer_strip.cc:94 gtk2_ardour/mixer_strip.cc:139
+#: gtk2_ardour/mixer_strip.cc:1218
msgid "pre"
msgstr ""
-#: gtk2_ardour/mixer_strip.cc:93 gtk2_ardour/mixer_strip.cc:782
+#: gtk2_ardour/mixer_strip.cc:95 gtk2_ardour/mixer_strip.cc:796
msgid "Comments"
msgstr "Комментарии"
-#: gtk2_ardour/mixer_strip.cc:116
+#: gtk2_ardour/mixer_strip.cc:118
msgid "Input"
msgstr "Вход"
-#: gtk2_ardour/mixer_strip.cc:133 gtk2_ardour/mixer_strip.cc:1187
+#: gtk2_ardour/mixer_strip.cc:135 gtk2_ardour/mixer_strip.cc:1214
msgid "input"
msgstr "вход"
-#: gtk2_ardour/mixer_strip.cc:141 gtk2_ardour/mixer_strip.cc:1195
+#: gtk2_ardour/mixer_strip.cc:143 gtk2_ardour/mixer_strip.cc:1222
msgid "post"
msgstr ""
-#: gtk2_ardour/mixer_strip.cc:149
+#: gtk2_ardour/mixer_strip.cc:150
msgid "tupni"
msgstr ""
-#: gtk2_ardour/mixer_strip.cc:205
+#: gtk2_ardour/mixer_strip.cc:204
msgid "Varispeed"
msgstr ""
-#: gtk2_ardour/mixer_strip.cc:231 gtk2_ardour/mixer_strip.cc:796
+#: gtk2_ardour/mixer_strip.cc:230 gtk2_ardour/mixer_strip.cc:812
msgid "Click to Add/Edit Comments"
msgstr "Ðажмите Ð´Ð»Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ/правки комментариев"
-#: gtk2_ardour/mixer_strip.cc:371
+#: gtk2_ardour/mixer_strip.cc:386
msgid "unknown strip width \"%1\" in XML GUI information"
msgstr "неизвеÑÑ‚Ð½Ð°Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ð° трека \"%1\" в XML опиÑании"
-#: gtk2_ardour/mixer_strip.cc:415
+#: gtk2_ardour/mixer_strip.cc:430
#, fuzzy
msgid "record"
msgstr "ЗапиÑÑŒ"
-#: gtk2_ardour/mixer_strip.cc:417 gtk2_ardour/audio_region_editor.cc:46
-msgid "mute"
-msgstr "тихо"
-
-#: gtk2_ardour/mixer_strip.cc:418
-msgid "solo"
-msgstr "Ñоло"
-
-#: gtk2_ardour/mixer_strip.cc:421
+#: gtk2_ardour/mixer_strip.cc:437
msgid "comments"
msgstr "комментарии"
-#: gtk2_ardour/mixer_strip.cc:423
+#: gtk2_ardour/mixer_strip.cc:440
msgid "*comments*"
msgstr "*комментарии*"
-#: gtk2_ardour/mixer_strip.cc:438
+#: gtk2_ardour/mixer_strip.cc:455
msgid "Rec"
msgstr "Зап"
-#: gtk2_ardour/mixer_strip.cc:440
+#: gtk2_ardour/mixer_strip.cc:457
msgid "M"
msgstr "M"
-#: gtk2_ardour/mixer_strip.cc:441
+#: gtk2_ardour/mixer_strip.cc:458
msgid "S"
msgstr "S"
-#: gtk2_ardour/mixer_strip.cc:444 gtk2_ardour/mixer_strip.cc:790
+#: gtk2_ardour/mixer_strip.cc:462 gtk2_ardour/mixer_strip.cc:806
msgid "Cmt"
msgstr ""
-#: gtk2_ardour/mixer_strip.cc:446 gtk2_ardour/mixer_strip.cc:788
+#: gtk2_ardour/mixer_strip.cc:465 gtk2_ardour/mixer_strip.cc:803
msgid "*Cmt*"
msgstr ""
-#: gtk2_ardour/mixer_strip.cc:484 gtk2_ardour/mixer_strip.cc:550
-#: gtk2_ardour/redirect_box.cc:1021
+#: gtk2_ardour/mixer_strip.cc:503 gtk2_ardour/mixer_strip.cc:569
+#: gtk2_ardour/redirect_box.cc:1086
msgid "Not connected to JACK - no I/O changes are possible"
msgstr ""
-#: gtk2_ardour/mixer_strip.cc:584 gtk2_ardour/mixer_strip.cc:600
+#: gtk2_ardour/mixer_strip.cc:603 gtk2_ardour/mixer_strip.cc:619
msgid "could not register new ports required for that connection"
msgstr "Ðе удалоÑÑŒ зарегиÑтрировать новые порты Ð´Ð»Ñ Ñтого ÑоединениÑ"
-#: gtk2_ardour/mixer_strip.cc:707
+#: gtk2_ardour/mixer_strip.cc:726
msgid " Input"
msgstr " Вход"
-#: gtk2_ardour/mixer_strip.cc:710
+#: gtk2_ardour/mixer_strip.cc:729
msgid "I"
msgstr "Ð’Ð¥"
-#: gtk2_ardour/mixer_strip.cc:780
+#: gtk2_ardour/mixer_strip.cc:793
msgid "*Comments*"
msgstr "*Комментарии*"
-#: gtk2_ardour/mixer_strip.cc:819
+#: gtk2_ardour/mixer_strip.cc:848
msgid ": comment editor"
msgstr ": редактор комментариев"
-#: gtk2_ardour/mixer_strip.cc:913
+#: gtk2_ardour/mixer_strip.cc:943
msgid "Grp"
-msgstr ""
+msgstr "Грп"
-#: gtk2_ardour/mixer_strip.cc:916
+#: gtk2_ardour/mixer_strip.cc:946
msgid "~G"
msgstr "нГр"
-#: gtk2_ardour/mixer_strip.cc:964
+#: gtk2_ardour/mixer_strip.cc:995
msgid "Invert Polarity"
msgstr "Развернуть полÑрноÑÑ‚ÑŒ"
@@ -4918,194 +4940,187 @@ msgstr "Каналы"
msgid "Group"
msgstr "Группа"
-#: gtk2_ardour/mixer_ui.cc:209 gtk2_ardour/mixer_ui.cc:389
+#: gtk2_ardour/mixer_ui.cc:206 gtk2_ardour/mixer_ui.cc:386
msgid "ardour: mixer"
msgstr "ardour: микшер"
-#: gtk2_ardour/mixer_ui.cc:210
-msgid "ardour_mixer"
-msgstr "ardour_микшер"
-
-#: gtk2_ardour/mixer_ui.cc:361
+#: gtk2_ardour/mixer_ui.cc:358
msgid "ardour: mixer: "
msgstr "ardour: микшер: "
-#: gtk2_ardour/mixer_ui.cc:592
+#: gtk2_ardour/mixer_ui.cc:589
msgid "signal"
msgstr "Ñигнал"
-#: gtk2_ardour/mixer_ui.cc:741
+#: gtk2_ardour/mixer_ui.cc:738
msgid "track display list item for renamed strip not found!"
msgstr ""
#: gtk2_ardour/new_session_dialog.cc:41
-msgid "New Session Name :"
-msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð¹ ÑеÑÑии:"
+msgid "Name :"
+msgstr "ИмÑ:"
+
+#: gtk2_ardour/new_session_dialog.cc:45 gtk2_ardour/new_session_dialog.cc:46
+#: gtk2_ardour/new_session_dialog.cc:47 gtk2_ardour/new_session_dialog.cc:48
+msgid "channels"
+msgstr "канал(-ов)"
-#: gtk2_ardour/new_session_dialog.cc:45
-msgid "Create Session Directory In :"
-msgstr "Создать каталог ÑеÑÑии в:"
+#: gtk2_ardour/new_session_dialog.cc:66
+msgid "<b>Busses</b>"
+msgstr "<b>Шины</b>"
+
+#: gtk2_ardour/new_session_dialog.cc:67
+msgid "<b>Inputs</b>"
+msgstr "<b>Входы</b>"
+
+#: gtk2_ardour/new_session_dialog.cc:68
+msgid "<b>Outputs</b>"
+msgstr "<b>Выходы</b>"
-#: gtk2_ardour/new_session_dialog.cc:47
-msgid "Use Session Template :"
-msgstr "ИÑпользовать шаблон:"
+#: gtk2_ardour/new_session_dialog.cc:70
+msgid "Create Folder In :"
+msgstr "Создать папку ÑеÑÑии в:"
-#: gtk2_ardour/new_session_dialog.cc:49
-msgid "Channel Count"
-msgstr "ЧиÑло каналов"
+#: gtk2_ardour/new_session_dialog.cc:72
+msgid "Template :"
+msgstr "Шаблон:"
-#: gtk2_ardour/new_session_dialog.cc:50
+#: gtk2_ardour/new_session_dialog.cc:74
msgid "Create Monitor Bus"
msgstr "Создать контрольную шину"
-#: gtk2_ardour/new_session_dialog.cc:57
+#: gtk2_ardour/new_session_dialog.cc:81
msgid "Create Master Bus"
msgstr "Создать маÑтер-шину"
-#: gtk2_ardour/new_session_dialog.cc:59
-msgid "Automatically Connect Inputs"
-msgstr "ÐвтоматичеÑкое подключение ко входам"
-
-#: gtk2_ardour/new_session_dialog.cc:60 gtk2_ardour/new_session_dialog.cc:71
-msgid "Port Limit"
-msgstr "Портов не более чем"
+#: gtk2_ardour/new_session_dialog.cc:83
+msgid "Automatically Connect to Physical Inputs"
+msgstr "ÐвтоматичеÑки подключитьÑÑ Ðº физичеÑким входам"
-#: gtk2_ardour/new_session_dialog.cc:68
-msgid "<b>Track/Bus Inputs</b>"
-msgstr "<b>Входы дорожек/шин</b>"
+#: gtk2_ardour/new_session_dialog.cc:84 gtk2_ardour/new_session_dialog.cc:97
+msgid "Use only"
+msgstr "ИÑпользовать только"
-#: gtk2_ardour/new_session_dialog.cc:70
+#: gtk2_ardour/new_session_dialog.cc:96
msgid "Automatically Connect Outputs"
-msgstr "ÐвтоматичеÑкое подключение к выходам"
+msgstr "ÐвтоматичеÑки подключитьÑÑ Ðº выходам"
-#: gtk2_ardour/new_session_dialog.cc:79
-msgid "Connect to Master Bus"
-msgstr "СоединитьÑÑ Ñ Ð¼Ð°Ñтер-шиной"
+#: gtk2_ardour/new_session_dialog.cc:105
+msgid "... to Master Bus"
+msgstr "... к маÑтер-шине"
-#: gtk2_ardour/new_session_dialog.cc:80
-msgid "Connect to Physical Outputs"
-msgstr "СоединитьÑÑ Ñ Ñ„Ð¸Ð·Ð¸Ñ‡ÐµÑкими выходами"
+#: gtk2_ardour/new_session_dialog.cc:106
+msgid "... to Physical Outputs"
+msgstr "... к физичеÑким выходам"
-#: gtk2_ardour/new_session_dialog.cc:84
-msgid "<b>Track/Bus Outputs</b>"
-msgstr "<b>Выходы дорожек/шин</b>"
-
-#: gtk2_ardour/new_session_dialog.cc:87
+#: gtk2_ardour/new_session_dialog.cc:112
msgid "Advanced Options"
msgstr "РаÑширенные параметры"
-#: gtk2_ardour/new_session_dialog.cc:95
-msgid "Open Recent Session"
-msgstr "Открыть недавнюю ÑеÑÑию"
+#: gtk2_ardour/new_session_dialog.cc:120
+msgid "Recent:"
+msgstr "Ðедавние:"
-#: gtk2_ardour/new_session_dialog.cc:131
-msgid "Open Session File :"
-msgstr "Открыть файл ÑеÑÑии:"
+#: gtk2_ardour/new_session_dialog.cc:157
+msgid "Browse:"
+msgstr "Обзор:"
-#: gtk2_ardour/new_session_dialog.cc:281
+#: gtk2_ardour/new_session_dialog.cc:335
msgid "New Session"
msgstr "Создать ÑеÑÑию"
-#: gtk2_ardour/new_session_dialog.cc:283
+#: gtk2_ardour/new_session_dialog.cc:337
msgid "Open Session"
msgstr "Открыть ÑеÑÑию"
-#: gtk2_ardour/new_session_dialog.cc:288
+#: gtk2_ardour/new_session_dialog.cc:342
msgid "ardour: session control"
msgstr "СеÑÑии Ardour"
-#: gtk2_ardour/new_session_dialog.cc:317
+#: gtk2_ardour/new_session_dialog.cc:383
msgid "select template"
msgstr "Выберите шаблон"
-#: gtk2_ardour/new_session_dialog.cc:323
+#: gtk2_ardour/new_session_dialog.cc:389
msgid "select session file"
msgstr "Выберите файл ÑеÑÑии"
-#: gtk2_ardour/new_session_dialog.cc:332
+#: gtk2_ardour/new_session_dialog.cc:398
msgid "select directory"
msgstr "Выберите каталог"
-#: gtk2_ardour/option_editor.cc:75
+#: gtk2_ardour/option_editor.cc:73
msgid "SMPTE offset is negative"
msgstr "Смещение SMPTE отрицательно"
-#: gtk2_ardour/option_editor.cc:101
+#: gtk2_ardour/option_editor.cc:99
msgid "ardour: options editor"
-msgstr "Редактор параметров"
-
-#: gtk2_ardour/option_editor.cc:102
-msgid "ardour_option_editor"
-msgstr "ardour_редактор_параметров"
+msgstr "ardour: параметры программы"
-#: gtk2_ardour/option_editor.cc:126
+#: gtk2_ardour/option_editor.cc:124
msgid "Paths/Files"
-msgstr "Пути/Файлы"
+msgstr "Пути/файлы"
-#: gtk2_ardour/option_editor.cc:127
+#: gtk2_ardour/option_editor.cc:125
msgid "Kbd/Mouse"
-msgstr "Клавиатура/Мышь"
+msgstr "Клавиатура/мышь"
-#: gtk2_ardour/option_editor.cc:130
+#: gtk2_ardour/option_editor.cc:128
msgid "Layers & Fades"
msgstr "Слои и фейды"
-#: gtk2_ardour/option_editor.cc:134
+#: gtk2_ardour/option_editor.cc:132
msgid "MIDI"
msgstr "MIDI"
-#: gtk2_ardour/option_editor.cc:222
+#: gtk2_ardour/option_editor.cc:220
msgid "session RAID path"
msgstr "Путь к файлам RAID-ÑеÑÑий"
-#: gtk2_ardour/option_editor.cc:227
-msgid "Soundfile Search Paths"
-msgstr "Путь к звуковым файлам"
-
-#: gtk2_ardour/option_editor.cc:252 gtk2_ardour/option_editor.cc:258
-#: gtk2_ardour/option_editor.cc:670 gtk2_ardour/option_editor.cc:697
+#: gtk2_ardour/option_editor.cc:236 gtk2_ardour/option_editor.cc:242
+#: gtk2_ardour/option_editor.cc:652 gtk2_ardour/option_editor.cc:672
msgid "internal"
msgstr "внутренний"
-#: gtk2_ardour/option_editor.cc:271
+#: gtk2_ardour/option_editor.cc:255
msgid "Short crossfade length (msecs)"
-msgstr ""
+msgstr "ДлительноÑÑ‚ÑŒ короткого кроÑÑфейда (мÑ)"
-#: gtk2_ardour/option_editor.cc:283
+#: gtk2_ardour/option_editor.cc:267
msgid "Destructive crossfade length (msecs)"
-msgstr ""
+msgstr "ДлительноÑÑ‚ÑŒ деÑтруктивного кроÑÑфейда (мÑ)"
-#: gtk2_ardour/option_editor.cc:342
+#: gtk2_ardour/option_editor.cc:327
msgid "SMPTE Offset"
msgstr "Смещение SMPTE"
-#: gtk2_ardour/option_editor.cc:409 gtk2_ardour/option_editor.cc:416
-#: gtk2_ardour/option_editor.cc:419 gtk2_ardour/option_editor.cc:565
+#: gtk2_ardour/option_editor.cc:394 gtk2_ardour/option_editor.cc:401
+#: gtk2_ardour/option_editor.cc:404 gtk2_ardour/option_editor.cc:552
msgid "online"
msgstr ""
-#: gtk2_ardour/option_editor.cc:416 gtk2_ardour/option_editor.cc:417
-#: gtk2_ardour/option_editor.cc:562
+#: gtk2_ardour/option_editor.cc:401 gtk2_ardour/option_editor.cc:402
+#: gtk2_ardour/option_editor.cc:549
msgid "offline"
msgstr ""
-#: gtk2_ardour/option_editor.cc:617
+#: gtk2_ardour/option_editor.cc:605
msgid "Choose Click"
msgstr "Выберите щелчок метронома"
-#: gtk2_ardour/option_editor.cc:636
+#: gtk2_ardour/option_editor.cc:624
msgid "Choose Click Emphasis"
msgstr "Выберите акцентирующий щелчок метронома"
-#: gtk2_ardour/option_editor.cc:750
+#: gtk2_ardour/option_editor.cc:724
msgid "Click audio file"
msgstr "Файл щелчков метронома"
-#: gtk2_ardour/option_editor.cc:756
+#: gtk2_ardour/option_editor.cc:730
msgid "Click emphasis audiofile"
msgstr "Файл акцентирующих щелчков метронома"
-#: gtk2_ardour/option_editor.cc:793
+#: gtk2_ardour/option_editor.cc:767
msgid ""
"The auditioner is a dedicated mixer strip used\n"
"for listening to specific regions outside the context\n"
@@ -5116,35 +5131,35 @@ msgstr ""
"Ð´Ð»Ñ Ð¿Ñ€Ð¾ÑÐ»ÑƒÑˆÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ‘Ð½Ð½Ñ‹Ñ… облаÑтей вне общего контекÑта микÑа. \n"
"Его можно Ñоединить как любой другой канал микшера."
-#: gtk2_ardour/option_editor.cc:866
+#: gtk2_ardour/option_editor.cc:840
msgid "Edit using"
msgstr "Редактировать Ñ"
-#: gtk2_ardour/option_editor.cc:873 gtk2_ardour/option_editor.cc:900
+#: gtk2_ardour/option_editor.cc:847 gtk2_ardour/option_editor.cc:874
msgid "+ button"
msgstr "+ клавиша"
-#: gtk2_ardour/option_editor.cc:893
+#: gtk2_ardour/option_editor.cc:867
msgid "Delete using"
msgstr "УдалÑÑ‚ÑŒ Ñ"
-#: gtk2_ardour/option_editor.cc:920
+#: gtk2_ardour/option_editor.cc:894
msgid "Ignore snap using"
msgstr "Игнорировать привÑзку Ñ"
-#: gtk2_ardour/opts.cc:46
+#: gtk2_ardour/opts.cc:47
msgid "Usage: "
msgstr "ИÑпользование: "
-#: gtk2_ardour/opts.cc:47
+#: gtk2_ardour/opts.cc:48
msgid " -v, --version Show version information\n"
msgstr " -v, --version Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ верÑии программы\n"
-#: gtk2_ardour/opts.cc:48
+#: gtk2_ardour/opts.cc:49
msgid " -h, --help Print this message\n"
msgstr " -h, --help Показать Ñто Ñообщение\n"
-#: gtk2_ardour/opts.cc:49
+#: gtk2_ardour/opts.cc:50
msgid ""
" -b, --bindings Print all possible keyboard binding "
"names\n"
@@ -5152,45 +5167,46 @@ msgstr ""
" -b, --bindings Показать вÑе доÑтупные \"горÑчие\" "
"клавиши\n"
-#: gtk2_ardour/opts.cc:50
+#: gtk2_ardour/opts.cc:51
msgid " -n, --show-splash Show splash screen\n"
msgstr " -n, --no-splash Ðе показывать заÑтавку\n"
-#: gtk2_ardour/opts.cc:51
+#: gtk2_ardour/opts.cc:52
msgid ""
" -c, --name name Use a specific jack client name, default "
"is ardour\n"
msgstr ""
-" -c, --jack-client-name Ð¸Ð¼Ñ Ð˜Ñпользовать другое Ð¸Ð¼Ñ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ð° к JACK, "
-"по умолчанию — Ardour\n"
+" -c, --jack-client-name Ð¸Ð¼Ñ Ð˜Ñпользовать другое Ð¸Ð¼Ñ ÐºÐ»Ð¸ÐµÐ½Ñ‚Ð° к JACK, по "
+"умолчанию — Ardour\n"
-#: gtk2_ardour/opts.cc:52
+#: gtk2_ardour/opts.cc:53
msgid ""
" -N, --new session-name Create a new session from the command "
"line\n"
msgstr " -N, --new имÑ-ÑеÑÑии Создать новую ÑеÑÑию из командной Ñтроки\n"
-#: gtk2_ardour/opts.cc:53
-msgid " -o, --use-hw-optimizations Try to use h/w specific optimizations\n"
+#: gtk2_ardour/opts.cc:54
+msgid " -O, --no-hw-optimizations Disable h/w specific optimizations\n"
msgstr ""
-#: gtk2_ardour/opts.cc:55
+#: gtk2_ardour/opts.cc:56
#, fuzzy
msgid " -V, --novst Do not use VST support\n"
msgstr " -n, --no-splash Ðе показывать заÑтавку\n"
-#: gtk2_ardour/opts.cc:57
+#: gtk2_ardour/opts.cc:58
msgid " [session-name] Name of session to load\n"
msgstr " [имÑ-ÑеÑÑии] Загрузить ÑеÑÑию Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ именем\n"
-#: gtk2_ardour/opts.cc:58
+#: gtk2_ardour/opts.cc:59
msgid " -C, --curvetest filename Curve algorithm debugger\n"
msgstr ""
-#: gtk2_ardour/opts.cc:59
-#, fuzzy
-msgid " -g, --gtktheme Allow GTK to load a theme\n"
-msgstr " -h, --help Показать Ñто Ñообщение\n"
+#: gtk2_ardour/opts.cc:60
+msgid ""
+" -k, --keybindings filename Name of key bindings to load (default is "
+"~/.ardour2/ardour.bindings)\n"
+msgstr ""
#: gtk2_ardour/pan_automation_time_axis.cc:70
msgid "You need to select which line to edit"
@@ -5200,42 +5216,42 @@ msgstr ""
msgid "add pan automation event"
msgstr "добавить автомат. Ñобытие панорамы"
-#: gtk2_ardour/panner2d.cc:589 gtk2_ardour/panner_ui.cc:425
-#: gtk2_ardour/plugin_ui.cc:146
+#: gtk2_ardour/panner2d.cc:589 gtk2_ardour/panner_ui.cc:438
+#: gtk2_ardour/plugin_ui.cc:152
msgid "Bypass"
msgstr "Обход"
-#: gtk2_ardour/panner_ui.cc:56 gtk2_ardour/panner_ui.cc:223
+#: gtk2_ardour/panner_ui.cc:58 gtk2_ardour/panner_ui.cc:225
#, fuzzy
msgid "link"
msgstr "в"
-#: gtk2_ardour/panner_ui.cc:67
+#: gtk2_ardour/panner_ui.cc:69
msgid "Pan automation mode"
msgstr "Режим автоматизации панорамы"
-#: gtk2_ardour/panner_ui.cc:68
+#: gtk2_ardour/panner_ui.cc:70
msgid "Pan automation type"
msgstr "Тип автоматизации панорамы"
-#: gtk2_ardour/panner_ui.cc:79
+#: gtk2_ardour/panner_ui.cc:81
msgid "panning link control"
msgstr ""
-#: gtk2_ardour/panner_ui.cc:81
+#: gtk2_ardour/panner_ui.cc:83
msgid "panning link direction"
msgstr ""
-#: gtk2_ardour/panner_ui.cc:233
+#: gtk2_ardour/panner_ui.cc:235
msgid "L"
msgstr "L"
-#: gtk2_ardour/panner_ui.cc:328
+#: gtk2_ardour/panner_ui.cc:341
#, c-format
msgid "panner for channel %zu"
msgstr ""
-#: gtk2_ardour/panner_ui.cc:435
+#: gtk2_ardour/panner_ui.cc:448
msgid "Reset all"
msgstr "СброÑить вÑе"
@@ -5247,15 +5263,15 @@ msgstr "СпиÑки воÑпроизведениÑ"
msgid "Playlists grouped by track"
msgstr "СпиÑки, Ñгруппированные по дорожке"
-#: gtk2_ardour/playlist_selector.cc:98
+#: gtk2_ardour/playlist_selector.cc:108
msgid "ardour: playlist for "
msgstr "ardour: ÑпиÑок воÑÐ¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð´Ð»Ñ "
-#: gtk2_ardour/playlist_selector.cc:114
+#: gtk2_ardour/playlist_selector.cc:124
msgid "Other tracks"
msgstr "Другие дорожки"
-#: gtk2_ardour/playlist_selector.cc:130
+#: gtk2_ardour/playlist_selector.cc:141
msgid "unassigned"
msgstr ""
@@ -5283,7 +5299,7 @@ msgstr "# выходов"
#: gtk2_ardour/plugin_selector.cc:68
msgid "Plugins to be Connected to Insert"
-msgstr ""
+msgstr "РаÑширениÑ, подключаемые к возврату"
#: gtk2_ardour/plugin_selector.cc:80 gtk2_ardour/plugin_selector.cc:98
msgid "Available plugins"
@@ -5319,11 +5335,11 @@ msgid ""
"version of ardour)"
msgstr ""
-#: gtk2_ardour/plugin_ui.cc:166
+#: gtk2_ardour/plugin_ui.cc:172
msgid "Plugin preset %1 not found"
msgstr ""
-#: gtk2_ardour/plugin_ui.cc:176
+#: gtk2_ardour/plugin_ui.cc:182
msgid "Name of New Preset:"
msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð¹ предуÑтановки:"
@@ -5335,15 +5351,15 @@ msgstr ""
msgid "add automation event to "
msgstr ""
-#: gtk2_ardour/redirect_box.cc:226
+#: gtk2_ardour/redirect_box.cc:235
msgid "New send"
msgstr "Ðовый поÑыл"
-#: gtk2_ardour/redirect_box.cc:227
+#: gtk2_ardour/redirect_box.cc:236
msgid "Show send controls"
msgstr ""
-#: gtk2_ardour/redirect_box.cc:386
+#: gtk2_ardour/redirect_box.cc:417
msgid ""
"You attempted to add a plugin (%1).\n"
"The plugin has %2 inputs\n"
@@ -5354,7 +5370,7 @@ msgid ""
"part of the signal."
msgstr ""
-#: gtk2_ardour/redirect_box.cc:398
+#: gtk2_ardour/redirect_box.cc:429
msgid ""
"You attempted to add a plugin (%1).\n"
"The plugin has %2 inputs\n"
@@ -5366,7 +5382,7 @@ msgid ""
"support this type of configuration."
msgstr ""
-#: gtk2_ardour/redirect_box.cc:411
+#: gtk2_ardour/redirect_box.cc:442
msgid ""
"You attempted to add a plugin (%1).\n"
"\n"
@@ -5379,34 +5395,34 @@ msgid ""
"Ardour does not understand what to do in such situations.\n"
msgstr ""
-#: gtk2_ardour/redirect_box.cc:499
+#: gtk2_ardour/redirect_box.cc:539
msgid "Pre-fader inserts, sends & plugins:"
msgstr ""
-#: gtk2_ardour/redirect_box.cc:502
+#: gtk2_ardour/redirect_box.cc:542
msgid "Post-fader inserts, sends & plugins:"
msgstr ""
-#: gtk2_ardour/redirect_box.cc:650
+#: gtk2_ardour/redirect_box.cc:708
msgid ""
"You cannot reorder this set of redirects\n"
"in that way because the inputs and\n"
"outputs do not work correctly."
msgstr ""
-#: gtk2_ardour/redirect_box.cc:750
+#: gtk2_ardour/redirect_box.cc:821
#, fuzzy
msgid "rename redirect"
msgstr "ardour: переименовать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/redirect_box.cc:824 gtk2_ardour/redirect_box.cc:872
+#: gtk2_ardour/redirect_box.cc:898 gtk2_ardour/redirect_box.cc:946
msgid ""
"Copying the set of redirects on the clipboard failed,\n"
"probably because the I/O configuration of the plugins\n"
"could not match the configuration of this track."
msgstr ""
-#: gtk2_ardour/redirect_box.cc:894
+#: gtk2_ardour/redirect_box.cc:968
#, fuzzy
msgid ""
"Do you really want to remove all redirects from this track?\n"
@@ -5415,7 +5431,7 @@ msgstr ""
"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n"
"(отмена невозможна)"
-#: gtk2_ardour/redirect_box.cc:897
+#: gtk2_ardour/redirect_box.cc:971
#, fuzzy
msgid ""
"Do you really want to remove all redirects from this bus?\n"
@@ -5424,174 +5440,107 @@ msgstr ""
"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n"
"(отмена невозможна)"
-#: gtk2_ardour/redirect_box.cc:902
+#: gtk2_ardour/redirect_box.cc:976
msgid "Yes, remove them all"
msgstr "Да, удалить их вÑе"
-#: gtk2_ardour/redirect_box.cc:938
+#: gtk2_ardour/redirect_box.cc:1012
#, fuzzy
msgid "ardour: %1"
msgstr "ardour: "
-#: gtk2_ardour/redirect_box.cc:983
-#, fuzzy
-msgid "ardour: %1: %2 (by %3)"
-msgstr "ardour: "
-
-#: gtk2_ardour/redirect_box.cc:1069
+#: gtk2_ardour/redirect_box.cc:1134
msgid "New Plugin ..."
-msgstr "Ðовое раÑширение..."
+msgstr "Добавить раÑширение..."
-#: gtk2_ardour/redirect_box.cc:1070
+#: gtk2_ardour/redirect_box.cc:1136
msgid "New Insert"
-msgstr "Ðовый возврат"
+msgstr "Добавить возврат"
-#: gtk2_ardour/redirect_box.cc:1071
+#: gtk2_ardour/redirect_box.cc:1138
msgid "New Send ..."
-msgstr "Ðовый поÑыл..."
+msgstr "Добавить поÑыл..."
-#: gtk2_ardour/redirect_box.cc:1083
+#: gtk2_ardour/redirect_box.cc:1152
msgid "Deselect All"
msgstr "СнÑÑ‚ÑŒ вÑе выделениÑ"
-#: gtk2_ardour/redirect_box.cc:1090
+#: gtk2_ardour/redirect_box.cc:1159
msgid "Activate all"
msgstr "Ðктивировать вÑе"
-#: gtk2_ardour/redirect_box.cc:1091
+#: gtk2_ardour/redirect_box.cc:1160
msgid "Deactivate all"
msgstr "Деактивировать вÑе"
-#: gtk2_ardour/audio_region_editor.cc:44
-msgid "NAME:"
-msgstr "ИМЯ:"
-
-#: gtk2_ardour/audio_region_editor.cc:45
-msgid "lock"
-msgstr "запереть"
+#: gtk2_ardour/redirect_box.cc:1339
+#, fuzzy
+msgid "ardour: %1: %2 (by %3)"
+msgstr "ardour: "
#: gtk2_ardour/audio_region_editor.cc:47
-msgid "opaque"
-msgstr "затенить"
+msgid "NAME:"
+msgstr "ИМЯ:"
#: gtk2_ardour/audio_region_editor.cc:48
-#: gtk2_ardour/audio_region_editor.cc:191
-#: gtk2_ardour/audio_region_editor.cc:225
-msgid "active"
-msgstr "активно"
-
-#: gtk2_ardour/audio_region_editor.cc:49
-msgid "visible"
-msgstr "Видимы"
-
-#: gtk2_ardour/audio_region_editor.cc:52
-msgid "Layer"
-msgstr "Слой"
-
-#: gtk2_ardour/audio_region_editor.cc:53
msgid "play"
msgstr "воÑпроизвеÑти"
-#: gtk2_ardour/audio_region_editor.cc:60
-msgid "ENVELOPE"
-msgstr "ОГИБÐЮЩÐЯ"
-
-#: gtk2_ardour/audio_region_editor.cc:106
-msgid "mute this region"
-msgstr "отключить воÑпроизведение Ñтой облаÑти"
-
-#: gtk2_ardour/audio_region_editor.cc:107
-msgid "regions underneath this one cannot be heard"
-msgstr "облаÑти ниже Ñтой не могут быть проÑлушаны"
-
-#: gtk2_ardour/audio_region_editor.cc:108
-msgid "prevent any changes to this region"
-msgstr "запретить любые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñтой облаÑти"
-
-#: gtk2_ardour/audio_region_editor.cc:109
-msgid "use the gain envelope during playback"
-msgstr "иÑпользовать огибающую при воÑпроизведении"
-
-#: gtk2_ardour/audio_region_editor.cc:110
-msgid "show the gain envelope"
-msgstr "отображать огибающую"
-
-#: gtk2_ardour/audio_region_editor.cc:111
-msgid "use fade in curve during playback"
-msgstr "иÑпользовать вводную кривую при воÑпроизведении"
-
-#: gtk2_ardour/audio_region_editor.cc:112
-msgid "use fade out curve during playback"
-msgstr "иÑпользовать выводную кривую при воÑпроизведении"
-
-#: gtk2_ardour/audio_region_editor.cc:113
+#: gtk2_ardour/audio_region_editor.cc:67
msgid "audition this region"
msgstr "проÑлушать облаÑÑ‚ÑŒ"
-#: gtk2_ardour/audio_region_editor.cc:146
+#: gtk2_ardour/audio_region_editor.cc:82
msgid "START:"
msgstr "ÐÐЧÐЛО:"
-#: gtk2_ardour/audio_region_editor.cc:148
+#: gtk2_ardour/audio_region_editor.cc:84
msgid "END:"
msgstr "КОÐЕЦ:"
-#: gtk2_ardour/audio_region_editor.cc:150
+#: gtk2_ardour/audio_region_editor.cc:86
msgid "LENGTH:"
msgstr "ДЛИÐÐ:"
-#: gtk2_ardour/audio_region_editor.cc:190
-msgid "FADE IN"
-msgstr "ВВЕДЕÐИЕ Ð’ УРОВЕÐЬ"
-
-#: gtk2_ardour/audio_region_editor.cc:192
-#: gtk2_ardour/audio_region_editor.cc:226
-msgid "msecs"
-msgstr "мÑ"
-
-#: gtk2_ardour/audio_region_editor.cc:224
-msgid "FADE OUT"
-msgstr "СВЕДЕÐИЕ Ð’ ÐОЛЬ"
-
-#: gtk2_ardour/audio_region_editor.cc:264
+#: gtk2_ardour/audio_region_editor.cc:122
msgid "ardour: region "
msgstr "ardour: облаÑÑ‚ÑŒ "
-#: gtk2_ardour/audio_region_editor.cc:401
-msgid "fade in edit"
-msgstr "редактировать введение в уровень"
+#: gtk2_ardour/audio_region_editor.cc:202
+#, fuzzy
+msgid "change region start position"
+msgstr "ОблаÑти/положение"
-#: gtk2_ardour/audio_region_editor.cc:413
-msgid "fade out edit"
-msgstr "редактировать Ñведение в ноль"
+#: gtk2_ardour/audio_region_editor.cc:219
+#, fuzzy
+msgid "change region end position"
+msgstr "ОблаÑти/положение"
-#: gtk2_ardour/audio_region_view.cc:901
+#: gtk2_ardour/audio_region_editor.cc:240
+#, fuzzy
+msgid "change region length"
+msgstr "редактировать введение в уровень"
+
+#: gtk2_ardour/audio_region_view.cc:939
#, fuzzy
msgid "add gain control point"
msgstr "иÑпользовать контрольные выходы"
#: gtk2_ardour/route_params_ui.cc:85
msgid "Tracks/Buses"
-msgstr "Дорожи/Шины"
+msgstr "Дорожи/шины"
#: gtk2_ardour/route_params_ui.cc:105
-#, fuzzy
msgid "Pre-fader Redirects"
-msgstr "Предобработка"
+msgstr "Предфейдерные перенаправлениÑ"
#: gtk2_ardour/route_params_ui.cc:106
-#, fuzzy
msgid "Post-fader Redirects"
-msgstr "ПоÑтобработка"
+msgstr "ПоÑлефейдерные перенаправлениÑ"
#: gtk2_ardour/route_params_ui.cc:140
-#, fuzzy
msgid "ardour: track/bus inspector"
-msgstr "ardour: добавить трек/шину"
-
-#: gtk2_ardour/route_params_ui.cc:141
-msgid "ardour_route_parameters"
-msgstr "ardour_параметры_маршрутов"
+msgstr "ardour: добавить дорожку/шину"
#: gtk2_ardour/route_params_ui.cc:202
msgid "route display list item for renamed route not found!"
@@ -5599,12 +5548,11 @@ msgstr ""
#: gtk2_ardour/route_params_ui.cc:449
msgid "NO TRACK"
-msgstr "ÐЕТ ТРЕКОВ"
+msgstr "ÐЕТ ДОРОЖЕК"
#: gtk2_ardour/route_params_ui.cc:672
-#, fuzzy
msgid "ardour: track/bus inspector: "
-msgstr "ardour: добавить трек/шину"
+msgstr "ardour: инÑпектор дорожек/шин"
#: gtk2_ardour/route_params_ui.cc:676
msgid "No Route Selected"
@@ -5615,56 +5563,60 @@ msgstr "Ðет выбранных маршрутов"
msgid "ardour: track/bus/inspector: no route selected"
msgstr "ardour: параметры маршрутов: нет выбранных маршрутов"
-#: gtk2_ardour/route_ui.cc:131
+#: gtk2_ardour/route_ui.cc:144
msgid "mute change"
msgstr ""
-#: gtk2_ardour/route_ui.cc:207 gtk2_ardour/route_ui.cc:218
+#: gtk2_ardour/route_ui.cc:222 gtk2_ardour/route_ui.cc:233
msgid "solo change"
msgstr ""
-#: gtk2_ardour/route_ui.cc:282
+#: gtk2_ardour/route_ui.cc:291
+msgid "Not connected to JACK - cannot engage record"
+msgstr ""
+
+#: gtk2_ardour/route_ui.cc:303
msgid "rec-enable change"
msgstr ""
-#: gtk2_ardour/route_ui.cc:480
+#: gtk2_ardour/route_ui.cc:501
#, fuzzy
msgid "Solo-safe"
msgstr "Соло"
-#: gtk2_ardour/route_ui.cc:502
+#: gtk2_ardour/route_ui.cc:523
msgid "Pre Fader"
-msgstr "Пред фейдер"
+msgstr "Предфейдер"
-#: gtk2_ardour/route_ui.cc:509
+#: gtk2_ardour/route_ui.cc:530
msgid "Post Fader"
-msgstr "ПоÑÑ‚ фейдер"
+msgstr "ПоÑлефейдер"
-#: gtk2_ardour/route_ui.cc:516
+#: gtk2_ardour/route_ui.cc:537
msgid "Control Outs"
msgstr "Контрольные выходы"
-#: gtk2_ardour/route_ui.cc:523
+#: gtk2_ardour/route_ui.cc:544
msgid "Main Outs"
msgstr "Главные выходы"
-#: gtk2_ardour/route_ui.cc:560
+#: gtk2_ardour/route_ui.cc:581
msgid "mix group solo change"
msgstr ""
-#: gtk2_ardour/route_ui.cc:599
+#: gtk2_ardour/route_ui.cc:620
msgid "mix group mute change"
msgstr ""
-#: gtk2_ardour/route_ui.cc:616
+#: gtk2_ardour/route_ui.cc:637
msgid "mix group rec-enable change"
msgstr ""
-#: gtk2_ardour/route_ui.cc:634 gtk2_ardour/visual_time_axis.cc:237
+#: gtk2_ardour/route_ui.cc:655 gtk2_ardour/visual_time_axis.cc:242
msgid "ardour: color selection"
msgstr "ardour: выбор цвета"
-#: gtk2_ardour/route_ui.cc:710
+#: gtk2_ardour/route_ui.cc:731
#, fuzzy
msgid ""
"Do you really want to remove track \"%1\" ?\n"
@@ -5675,7 +5627,7 @@ msgstr ""
"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n"
"(отмена невозможна)"
-#: gtk2_ardour/route_ui.cc:712
+#: gtk2_ardour/route_ui.cc:733
msgid ""
"Do you really want to remove bus \"%1\" ?\n"
"(cannot be undone)"
@@ -5683,98 +5635,91 @@ msgstr ""
"Ð’Ñ‹ дейÑтвительно хотите удалить шину \"%1\" ?\n"
"(отмена невозможна)"
-#: gtk2_ardour/route_ui.cc:716 gtk2_ardour/visual_time_axis.cc:279
+#: gtk2_ardour/route_ui.cc:737 gtk2_ardour/visual_time_axis.cc:284
msgid "Yes, remove it."
msgstr "Да, удалить."
-#: gtk2_ardour/route_ui.cc:744
+#: gtk2_ardour/route_ui.cc:758
#, fuzzy
msgid "New Name: "
msgstr "новое имÑ: "
-#: gtk2_ardour/sfdb_ui.cc:61
-msgid "Add Field..."
-msgstr "Добавить поле..."
-
-#: gtk2_ardour/sfdb_ui.cc:62
-msgid "Remove Field"
-msgstr "Удалить поле"
+#: gtk2_ardour/sfdb_ui.cc:60
+#, fuzzy
+msgid "Apply"
+msgstr "воÑпроизвеÑти"
-#: gtk2_ardour/sfdb_ui.cc:65
+#: gtk2_ardour/sfdb_ui.cc:63
msgid "Soundfile Info"
msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ файле"
-#: gtk2_ardour/sfdb_ui.cc:83
-msgid "Field"
-msgstr "Критерий"
-
-#: gtk2_ardour/sfdb_ui.cc:84
-msgid "Value"
-msgstr "Значение"
+#: gtk2_ardour/sfdb_ui.cc:120
+msgid "Length: %1"
+msgstr ""
-#: gtk2_ardour/sfdb_ui.cc:167
+#: gtk2_ardour/sfdb_ui.cc:126
#, fuzzy
-msgid "channels"
+msgid "Channels: %1"
msgstr "отмена"
-#: gtk2_ardour/sfdb_ui.cc:167
+#: gtk2_ardour/sfdb_ui.cc:129
#, fuzzy
-msgid "samplerate"
+msgid "Samplerate: %1"
msgstr "Разделить облаÑÑ‚ÑŒ"
-#: gtk2_ardour/sfdb_ui.cc:168
-#, fuzzy
-msgid "resolution"
-msgstr "ВоÑпроизвеÑти выделенное"
-
-#: gtk2_ardour/sfdb_ui.cc:168
-#, fuzzy
-msgid "format"
-msgstr "Ðорм."
+#: gtk2_ardour/sfdb_ui.cc:132
+msgid "Timecode: %1"
+msgstr ""
-#: gtk2_ardour/sfdb_ui.cc:189
+#: gtk2_ardour/sfdb_ui.cc:166
#, fuzzy
msgid "Could not read file: %1 (%2)."
msgstr "Редактор: не удалоÑÑŒ открыть файл \"%1\" (%2)"
-#: gtk2_ardour/sfdb_ui.cc:205
+#: gtk2_ardour/sfdb_ui.cc:184
msgid "Could not access soundfile: "
msgstr "Файл недоÑтупен: "
-#: gtk2_ardour/sfdb_ui.cc:244
+#: gtk2_ardour/sfdb_ui.cc:267
+msgid "Add to Region list"
+msgstr "Добавить в ÑпиÑок облаÑтей"
+
+#: gtk2_ardour/sfdb_ui.cc:268
+msgid "Add to selected Track(s)"
+msgstr "Добавить в выделенные дорожки"
+
+#: gtk2_ardour/sfdb_ui.cc:269
+msgid "Add as new Track(s)"
+msgstr "Добавить как новую дорожку(-и)"
+
+#: gtk2_ardour/sfdb_ui.cc:270
#, fuzzy
-msgid "Name for Field"
-msgstr "Ð˜Ð¼Ñ Ð¾Ð±Ð»Ð°Ñти: "
+msgid "Add as new Tape Track(s)"
+msgstr "Добавить как новую tape дорожку(-и)"
-#: gtk2_ardour/sfdb_ui.cc:356
+#: gtk2_ardour/sfdb_ui.cc:313
msgid "Split Channels"
-msgstr ""
+msgstr "Разделить каналы"
-#: gtk2_ardour/sfdb_ui.cc:363
+#: gtk2_ardour/sfdb_ui.cc:320
msgid "Create a region for each channel"
-msgstr ""
+msgstr "Создать облаÑÑ‚ÑŒ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ канала"
-#: gtk2_ardour/sfdb_ui.cc:365
+#: gtk2_ardour/sfdb_ui.cc:322
msgid "Embed"
-msgstr ""
+msgstr "Ð’Ñтроить"
-#: gtk2_ardour/sfdb_ui.cc:367
-#, fuzzy
+#: gtk2_ardour/sfdb_ui.cc:324
msgid "Link to an external file"
-msgstr "Ð’Ñтавить внешний аудиофайл"
+msgstr "СоÑлатьÑÑ Ð½Ð° внешний файл"
-#: gtk2_ardour/sfdb_ui.cc:369
+#: gtk2_ardour/sfdb_ui.cc:328
msgid "Import"
-msgstr "Импорт"
+msgstr "Импортировать"
-#: gtk2_ardour/sfdb_ui.cc:371
+#: gtk2_ardour/sfdb_ui.cc:330
msgid "Copy a file to the session folder"
-msgstr ""
-
-#: gtk2_ardour/sfdb_ui.cc:438
-#, fuzzy
-msgid "programming error: %1"
-msgstr "ошибка в программе: "
+msgstr "Скопировать файл в папку проекта"
#: gtk2_ardour/tempo_dialog.cc:18 gtk2_ardour/tempo_dialog.cc:35
msgid "Beats per minute"
@@ -5844,27 +5789,27 @@ msgstr "некорректное определение ноты (%1)"
msgid "gTortnam"
msgstr ""
-#: gtk2_ardour/time_axis_view.cc:550
+#: gtk2_ardour/time_axis_view.cc:583
msgid "Largest"
msgstr "ОгромнаÑ"
-#: gtk2_ardour/time_axis_view.cc:551
+#: gtk2_ardour/time_axis_view.cc:584
msgid "Large"
msgstr "БольшаÑ"
-#: gtk2_ardour/time_axis_view.cc:552
+#: gtk2_ardour/time_axis_view.cc:585
msgid "Larger"
msgstr "Больше"
-#: gtk2_ardour/time_axis_view.cc:554
+#: gtk2_ardour/time_axis_view.cc:587
msgid "Smaller"
msgstr "Меньше"
-#: gtk2_ardour/time_axis_view.cc:555
+#: gtk2_ardour/time_axis_view.cc:588
msgid "Small"
msgstr "МаленькаÑ"
-#: gtk2_ardour/time_axis_view.cc:869
+#: gtk2_ardour/time_axis_view.cc:903
msgid "unknown track height name \"%1\" in XML GUI information"
msgstr "неизвеÑтное Ð¸Ð¼Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ñ‹ трека \"%1\" в XML опиÑании"
@@ -5880,15 +5825,20 @@ msgstr ""
msgid "programming error: request for non-existent audio range (%1)!"
msgstr "ошибка в программе: request for non-existent audio range (%1)!"
-#: gtk2_ardour/utils.cc:107 gtk2_ardour/utils.cc:150
+#: gtk2_ardour/utils.cc:118 gtk2_ardour/utils.cc:161
msgid "bad XPM header %1"
msgstr "ошибка в XPM заголовке %1"
-#: gtk2_ardour/utils.cc:332
+#: gtk2_ardour/utils.cc:285
msgid "missing RGBA style for \"%1\""
msgstr ""
-#: gtk2_ardour/visual_time_axis.cc:276
+#: gtk2_ardour/utils.cc:467
+#, fuzzy
+msgid "cannot find icon image for %1"
+msgstr "cannot setup signal handling for %1"
+
+#: gtk2_ardour/visual_time_axis.cc:281
msgid ""
"Do you really want to remove track \"%1\" ?\n"
"(cannot be undone)"
@@ -5896,14 +5846,10 @@ msgstr ""
"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n"
"(отмена невозможна)"
-#: gtk2_ardour/visual_time_axis.cc:325
+#: gtk2_ardour/visual_time_axis.cc:330
msgid "new name: "
msgstr "новое имÑ: "
-#: gtk2_ardour/visual_time_axis.cc:336
-msgid "A track already exists with that name"
-msgstr "Трек Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует"
-
#: gtk2_ardour/connection_editor.cc:51
msgid "ardour: connections"
msgstr "ardour: ÑоединениÑ"
diff --git a/gtk2_ardour/prompter.cc b/gtk2_ardour/prompter.cc
index a10bd92f72..0e1732b237 100644
--- a/gtk2_ardour/prompter.cc
+++ b/gtk2_ardour/prompter.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include "prompter.h"
diff --git a/gtk2_ardour/prompter.h b/gtk2_ardour/prompter.h
index 5e8e71f3c5..4e97e64e6f 100644
--- a/gtk2_ardour/prompter.h
+++ b/gtk2_ardour/prompter.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_prompter_h__
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index 5821110b6c..0baecd43d9 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -14,7 +14,6 @@
#include <pbd/statefuldestructible.h>
#include "editing.h"
-#include "keyboard_target.h"
#include "canvas.h"
#include "selection.h"
@@ -74,11 +73,11 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
virtual void set_mouse_mode (Editing::MouseMode, bool force = false) = 0;
virtual void step_mouse_mode (bool next) = 0;
virtual Editing::MouseMode current_mouse_mode () = 0;
- virtual void add_imageframe_time_axis(const string & track_name, void*) = 0;
- virtual void add_imageframe_marker_time_axis(const string & track_name, TimeAxisView* marked_track, void*) = 0;
+ virtual void add_imageframe_time_axis(const std::string & track_name, void*) = 0;
+ virtual void add_imageframe_marker_time_axis(const std::string & track_name, TimeAxisView* marked_track, void*) = 0;
virtual void connect_to_image_compositor() = 0;
virtual void scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) = 0;
- virtual TimeAxisView* get_named_time_axis(const string & name) = 0;
+ virtual TimeAxisView* get_named_time_axis(const std::string & name) = 0;
virtual void consider_auditioning (boost::shared_ptr<ARDOUR::Region>) = 0;
virtual void set_show_waveforms (bool yn) = 0;
virtual bool show_waveforms() const = 0;
@@ -113,6 +112,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
virtual void new_playlists () = 0;
virtual void copy_playlists () = 0;
virtual void clear_playlists () = 0;
+ virtual void select_all_tracks () = 0;
virtual bool set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove = false) = 0;
virtual void set_selected_mixer_strip (TimeAxisView&) = 0;
virtual void hide_track_in_display (TimeAxisView& tv) = 0;
@@ -135,8 +135,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
virtual void remove_last_capture () = 0;
virtual void maximise_editing_space() = 0;
virtual void restore_editing_space() = 0;
+ virtual nframes_t edit_cursor_position(bool sync) = 0;
- sigc::signal<void,Editing::DisplayControl> DisplayControlChanged;
sigc::signal<void> ZoomFocusChanged;
sigc::signal<void> ZoomChanged;
sigc::signal<void> Resized;
diff --git a/gtk2_ardour/redirect_automation_line.cc b/gtk2_ardour/redirect_automation_line.cc
index 1ea5013295..b1b19d530f 100644
--- a/gtk2_ardour/redirect_automation_line.cc
+++ b/gtk2_ardour/redirect_automation_line.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include "public_editor.h"
diff --git a/gtk2_ardour/redirect_automation_line.h b/gtk2_ardour/redirect_automation_line.h
index ad39f6625c..71e4d23e64 100644
--- a/gtk2_ardour/redirect_automation_line.h
+++ b/gtk2_ardour/redirect_automation_line.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_redirect_automation_line_h__
diff --git a/gtk2_ardour/redirect_automation_time_axis.cc b/gtk2_ardour/redirect_automation_time_axis.cc
index 529c0b565d..acffda4ff1 100644
--- a/gtk2_ardour/redirect_automation_time_axis.cc
+++ b/gtk2_ardour/redirect_automation_time_axis.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/redirect.h>
diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc
index fac6ede6f3..63d3ec9d8e 100644
--- a/gtk2_ardour/redirect_box.cc
+++ b/gtk2_ardour/redirect_box.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -398,16 +397,16 @@ RedirectBox::insert_plugin_chosen (boost::shared_ptr<Plugin> plugin)
uint32_t err_streams;
if (_route->add_redirect (redirect, this, &err_streams)) {
- wierd_plugin_dialog (*plugin, err_streams, _route);
+ weird_plugin_dialog (*plugin, err_streams, _route);
// XXX SHAREDPTR delete plugin here .. do we even need to care?
}
}
}
void
-RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr<IO> io)
+RedirectBox::weird_plugin_dialog (Plugin& p, uint32_t streams, boost::shared_ptr<IO> io)
{
- ArdourDialog dialog ("wierd plugin dialog");
+ ArdourDialog dialog (_("ardour: weird plugin dialog"));
Label label;
/* i hate this kind of code */
@@ -703,7 +702,7 @@ RedirectBox::compute_redirect_sort_keys ()
/* now tell them about the problem */
- ArdourDialog dialog ("wierd plugin dialog");
+ ArdourDialog dialog (_("ardour: weird plugin dialog"));
Label label;
label.set_text (_("\
diff --git a/gtk2_ardour/redirect_box.h b/gtk2_ardour/redirect_box.h
index 7ab7d03cac..7e93efee1b 100644
--- a/gtk2_ardour/redirect_box.h
+++ b/gtk2_ardour/redirect_box.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_redirect_box__
@@ -195,7 +194,7 @@ class RedirectBox : public Gtk::HBox
gint idle_delete_redirect (boost::weak_ptr<ARDOUR::Redirect>);
- void wierd_plugin_dialog (ARDOUR::Plugin& p, uint32_t streams, boost::shared_ptr<ARDOUR::IO> io);
+ void weird_plugin_dialog (ARDOUR::Plugin& p, uint32_t streams, boost::shared_ptr<ARDOUR::IO> io);
static RedirectBox* _current_redirect_box;
static bool enter_box (GdkEventCrossing*, RedirectBox*);
diff --git a/gtk2_ardour/region_editor.h b/gtk2_ardour/region_editor.h
index 70590b0db5..394ad6bcfb 100644
--- a/gtk2_ardour/region_editor.h
+++ b/gtk2_ardour/region_editor.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: /local/undo/gtk2_ardour/region_editor.h 5 2006-05-31T02:48:48.738745Z paul $
*/
#ifndef __gtk_ardour_region_edit_h__
diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc
index aff5866c8d..f11ec2a307 100644
--- a/gtk2_ardour/region_view.cc
+++ b/gtk2_ardour/region_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -68,7 +67,6 @@ RegionView::RegionView (ArdourCanvas::Group* parent,
TimeAxisViewItem::ShowFrame))
, _region (r)
, sync_mark(0)
- , no_wave_msg(0)
, editor(0)
, current_visible_sync_position(0.0)
, valid(false)
@@ -79,6 +77,19 @@ RegionView::RegionView (ArdourCanvas::Group* parent,
{
}
+RegionView::RegionView (const RegionView& other)
+ : TimeAxisViewItem (other)
+{
+ /* derived concrete type will call init () */
+
+ _region = other._region;
+ editor = other.editor;
+ current_visible_sync_position = other.current_visible_sync_position;
+ valid = false;
+ _pixel_width = other._pixel_width;
+ _height = other._height;
+}
+
RegionView::RegionView (ArdourCanvas::Group* parent,
TimeAxisView& tv,
boost::shared_ptr<ARDOUR::Region> r,
@@ -88,7 +99,6 @@ RegionView::RegionView (ArdourCanvas::Group* parent,
: TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(), visibility)
, _region (r)
, sync_mark(0)
- , no_wave_msg(0)
, editor(0)
, current_visible_sync_position(0.0)
, valid(false)
@@ -102,7 +112,6 @@ RegionView::RegionView (ArdourCanvas::Group* parent,
void
RegionView::init (Gdk::Color& basic_color, bool wfd)
{
- editor = 0;
valid = true;
in_destructor = false;
_height = 0;
@@ -376,6 +385,18 @@ RegionView::set_frame_color ()
}
void
+RegionView::fake_set_opaque (bool yn)
+{
+ if (yn) {
+ fill_opacity = 130;
+ } else {
+ fill_opacity = 60;
+ }
+
+ TimeAxisViewItem::set_frame_color ();
+}
+
+void
RegionView::hide_region_editor()
{
if (editor) {
diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h
index 435e878bc8..74073b404e 100644
--- a/gtk2_ardour/region_view.h
+++ b/gtk2_ardour/region_view.h
@@ -47,6 +47,8 @@ class RegionView : public TimeAxisViewItem
double samples_per_unit,
Gdk::Color& basic_color);
+ RegionView (const RegionView& other);
+
~RegionView ();
virtual void init (Gdk::Color& base_color, bool wait_for_data);
@@ -68,6 +70,7 @@ class RegionView : public TimeAxisViewItem
void lower_to_bottom ();
bool set_position(nframes_t pos, void* src, double* delta = 0);
+ void fake_set_opaque (bool yn);
virtual void show_region_editor () = 0;
virtual void hide_region_editor();
@@ -82,14 +85,14 @@ class RegionView : public TimeAxisViewItem
virtual void entered () {}
virtual void exited () {}
- static sigc::signal<void,RegionView*> RegionViewGoingAway;
+ static sigc::signal<void,RegionView*> RegionViewGoingAway;
sigc::signal<void> GoingAway;
protected:
/** Allows derived types to specify their visibility requirements
* to the TimeAxisViewItem parent class
- */
+ */
RegionView (ArdourCanvas::Group *,
TimeAxisView&,
boost::shared_ptr<ARDOUR::Region>,
@@ -119,7 +122,6 @@ class RegionView : public TimeAxisViewItem
boost::shared_ptr<ARDOUR::Region> _region;
ArdourCanvas::Polygon* sync_mark; ///< polgyon for sync position
- ArdourCanvas::Text* no_wave_msg;
RegionEditor* editor;
diff --git a/gtk2_ardour/rgb_macros.h b/gtk2_ardour/rgb_macros.h
index 310e0a224d..5660e90ee6 100644
--- a/gtk2_ardour/rgb_macros.h
+++ b/gtk2_ardour/rgb_macros.h
@@ -18,7 +18,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_rgb_macros_h__
diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc
index 14d9fa02cb..386815ea27 100644
--- a/gtk2_ardour/route_params_ui.cc
+++ b/gtk2_ardour/route_params_ui.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -56,9 +55,8 @@ using namespace PBD;
using namespace Gtk;
using namespace sigc;
-RouteParams_UI::RouteParams_UI (AudioEngine& eng)
+RouteParams_UI::RouteParams_UI ()
: ArdourDialog ("track/bus inspector"),
- engine (eng),
track_menu(0)
{
pre_redirect_box = 0;
@@ -508,7 +506,7 @@ RouteParams_UI::show_track_menu()
track_menu->set_name ("ArdourContextMenu");
track_menu->items().push_back
(MenuElem (_("Add Track/Bus"),
- mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::add_route)));
+ bind (mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::add_route), (Gtk::Window*) 0)));
}
track_menu->popup (1, gtk_get_current_event_time());
}
diff --git a/gtk2_ardour/route_params_ui.h b/gtk2_ardour/route_params_ui.h
index 394383de6b..c0b70cbdb1 100644
--- a/gtk2_ardour/route_params_ui.h
+++ b/gtk2_ardour/route_params_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_route_params_ui_h__
@@ -41,7 +40,6 @@
#include "io_selector.h"
#include "ardour_dialog.h"
-#include "keyboard_target.h"
#include "redirect_box.h"
#include "route_redirect_selection.h"
@@ -60,7 +58,7 @@ class PluginSelector;
class RouteParams_UI : public ArdourDialog
{
public:
- RouteParams_UI (ARDOUR::AudioEngine&);
+ RouteParams_UI ();
~RouteParams_UI();
void set_session (ARDOUR::Session *);
@@ -68,8 +66,6 @@ class RouteParams_UI : public ArdourDialog
PluginSelector& plugin_selector() { return *_plugin_selector; }
private:
- ARDOUR::AudioEngine& engine;
-
Gtk::HBox global_hpacker;
Gtk::VBox global_vpacker;
Gtk::ScrolledWindow scroller;
diff --git a/gtk2_ardour/route_redirect_selection.cc b/gtk2_ardour/route_redirect_selection.cc
index 76f202dd92..5ad795c6f5 100644
--- a/gtk2_ardour/route_redirect_selection.cc
+++ b/gtk2_ardour/route_redirect_selection.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/gtk2_ardour/route_redirect_selection.h b/gtk2_ardour/route_redirect_selection.h
index 60d301e762..8f0cfaf543 100644
--- a/gtk2_ardour/route_redirect_selection.h
+++ b/gtk2_ardour/route_redirect_selection.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_route_redirect_selection_h__
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index 9684f74024..b2f9ebf13f 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -105,11 +105,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
ignore_toggle = false;
- mute_button->set_active (false);
- solo_button->set_active (false);
-
- mute_button->set_name ("TrackMuteButton");
- solo_button->set_name ("SoloButton");
edit_group_button.set_name ("TrackGroupButton");
playlist_button.set_name ("TrackPlaylistButton");
automation_button.set_name ("TrackAutomationButton");
@@ -127,9 +122,9 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
visual_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::visual_click));
hide_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::hide_click));
- solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press));
+ solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release));
- mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press));
+ mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release));
if (is_track()) {
@@ -147,8 +142,8 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
}
rec_enable_button->show_all ();
- rec_enable_button->set_name ("TrackRecordEnableButton");
- rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
+ rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press), false);
+ rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release));
controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
}
@@ -180,15 +175,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
/* remove focus from the buttons */
- automation_button.unset_flags (Gtk::CAN_FOCUS);
- solo_button->unset_flags (Gtk::CAN_FOCUS);
- mute_button->unset_flags (Gtk::CAN_FOCUS);
- edit_group_button.unset_flags (Gtk::CAN_FOCUS);
- size_button.unset_flags (Gtk::CAN_FOCUS);
- playlist_button.unset_flags (Gtk::CAN_FOCUS);
- hide_button.unset_flags (Gtk::CAN_FOCUS);
- visual_button.unset_flags (Gtk::CAN_FOCUS);
-
y_position = -1;
_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
@@ -491,7 +477,6 @@ RouteTimeAxisView::build_display_menu ()
static bool __reset_item (RadioMenuItem* item)
{
- cerr << "reset item to true\n";
item->set_active ();
return false;
}
@@ -1006,6 +991,18 @@ RouteTimeAxisView::update_diskstream_display ()
void
RouteTimeAxisView::selection_click (GdkEventButton* ev)
{
+ if (Keyboard::modifier_state_equals (ev->state, (Keyboard::Shift|Keyboard::Control))) {
+
+ /* special case: select/deselect all tracks */
+ if (editor.get_selection().selected (this)) {
+ editor.get_selection().clear_tracks ();
+ } else {
+ editor.select_all_tracks ();
+ }
+
+ return;
+ }
+
PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route->edit_group());
switch (Keyboard::selection_type (ev->state)) {
diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h
index c597f2893c..a72bc5a2cf 100644
--- a/gtk2_ardour/route_time_axis.h
+++ b/gtk2_ardour/route_time_axis.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: audio_time_axis.h 664 2006-07-05 19:47:25Z drobilla $
*/
#ifndef __ardour_route_time_axis_h__
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
index e7fa77f4da..303d05dc86 100644
--- a/gtk2_ardour/route_ui.cc
+++ b/gtk2_ardour/route_ui.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <gtkmm2ext/gtk_ui.h>
@@ -65,24 +64,32 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
ignore_toggle = false;
wait_for_release = false;
route_active_menu_item = 0;
+ was_solo_safe = false;
if (set_color_from_route()) {
set_color (unique_random_color());
}
- new Shiva<Route,RouteUI> (*_route, *this);
+ new PairedShiva<Route,RouteUI> (*_route, *this);
_route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
- mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
- solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
+ mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
+ mute_button->set_self_managed (true);
- // mute_button->unset_flags (Gtk::CAN_FOCUS);
- // solo_button->unset_flags (Gtk::CAN_FOCUS);
+ solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
+ solo_button->set_self_managed (true);
+
+ mute_button->set_name ("MuteButton");
+ solo_button->set_name ("SoloButton");
_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
+
+ /* when solo changes, update mute state too, in case the user wants us to display it */
+
+ _session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
if (is_track()) {
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
@@ -92,14 +99,17 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
_session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
- rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
-
+ rec_enable_button->set_name ("RecordEnableButton");
+ rec_enable_button->set_self_managed (true);
+
update_rec_display ();
}
mute_button->unset_flags (Gtk::CAN_FOCUS);
solo_button->unset_flags (Gtk::CAN_FOCUS);
+ _route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu));
+
/* map the current state */
map_frozen ();
@@ -298,9 +308,10 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
if (!ignore_toggle && is_track() && rec_enable_button) {
if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
+
// do nothing on midi bind event
- }
- else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
+
+ } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
_session.begin_reversible_command (_("rec-enable change"));
Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
@@ -322,16 +333,16 @@ RouteUI::rec_enable_press(GdkEventButton* ev)
} else {
reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !track()->record_enabled(), this);
-
- ignore_toggle = true;
- rec_enable_button->set_active(track()->record_enabled());
- ignore_toggle = false;
}
-
- stop_signal (*rec_enable_button, "button-press-event");
}
- return TRUE;
+ return true;
+}
+
+bool
+RouteUI::rec_enable_release (GdkEventButton* ev)
+{
+ return true;
}
void
@@ -344,23 +355,31 @@ void
RouteUI::update_solo_display ()
{
bool x;
-
+ vector<Gdk::Color> fg_colors;
+ Gdk::Color c;
+
if (solo_button->get_active() != (x = _route->soloed())){
ignore_toggle = true;
solo_button->set_active(x);
ignore_toggle = false;
}
- /* show solo safe */
-
- if (_route->solo_safe()){
- solo_button->set_name(safe_solo_button_name());
+ if (_route->solo_safe()) {
+ solo_button->set_visual_state (2);
+ } else if (_route->soloed()) {
+ solo_button->set_visual_state (1);
} else {
- solo_button->set_name(solo_button_name());
+ solo_button->set_visual_state (0);
}
}
void
+RouteUI::solo_changed_so_update_mute ()
+{
+ Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
+}
+
+void
RouteUI::mute_changed(void* src)
{
Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
@@ -369,13 +388,38 @@ RouteUI::mute_changed(void* src)
void
RouteUI::update_mute_display ()
{
- bool x;
+ bool model = _route->muted();
+ bool view = mute_button->get_active();
- if (mute_button->get_active() != (x = _route->muted())){
+ /* first make sure the button's "depressed" visual
+ is correct.
+ */
+
+ if (model != view) {
ignore_toggle = true;
- mute_button->set_active(x);
+ mute_button->set_active (model);
ignore_toggle = false;
}
+
+ /* now attend to visual state */
+
+ if (Config->get_show_solo_mutes()) {
+ if (_route->muted()) {
+ mute_button->set_visual_state (2);
+ } else if (!_route->soloed() && _route->solo_muted()) {
+
+ mute_button->set_visual_state (1);
+ } else {
+ mute_button->set_visual_state (0);
+ }
+ } else {
+ if (_route->muted()) {
+ mute_button->set_visual_state (2);
+ } else {
+ mute_button->set_visual_state (0);
+ }
+ }
+
}
void
@@ -399,7 +443,7 @@ RouteUI::update_rec_display ()
/* first make sure the button's "depressed" visual
is correct.
*/
-
+
if (model != view) {
ignore_toggle = true;
rec_enable_button->set_active (model);
@@ -411,24 +455,19 @@ RouteUI::update_rec_display ()
if (model) {
switch (_session.record_status ()) {
+ case Session::Recording:
+ rec_enable_button->set_visual_state (1);
+ break;
+
case Session::Disabled:
case Session::Enabled:
- if (rec_enable_button->get_state() != Gtk::STATE_ACTIVE) {
- rec_enable_button->set_state (Gtk::STATE_ACTIVE);
- }
+ rec_enable_button->set_visual_state (2);
break;
- case Session::Recording:
- if (rec_enable_button->get_state() != Gtk::STATE_SELECTED) {
- rec_enable_button->set_state (Gtk::STATE_SELECTED);
- }
- break;
}
} else {
- if (rec_enable_button->get_state() != Gtk::STATE_NORMAL) {
- rec_enable_button->set_state (Gtk::STATE_NORMAL);
- }
+ rec_enable_button->set_visual_state (0);
}
}
@@ -442,6 +481,14 @@ RouteUI::build_remote_control_menu ()
void
RouteUI::refresh_remote_control_menu ()
{
+ ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
+
+ // only refresh the menu if it has been instantiated
+
+ if (remote_control_menu == 0) {
+ return;
+ }
+
using namespace Menu_Helpers;
RadioMenuItem::Group rc_group;
diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h
index bad47ac274..f7749b0b4b 100644
--- a/gtk2_ardour/route_ui.h
+++ b/gtk2_ardour/route_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_route_ui__
@@ -95,8 +94,10 @@ class RouteUI : public virtual AxisView
bool solo_press(GdkEventButton*);
bool solo_release(GdkEventButton*);
bool rec_enable_press(GdkEventButton*);
+ bool rec_enable_release(GdkEventButton*);
void solo_changed(void*);
+ void solo_changed_so_update_mute ();
void mute_changed(void*);
virtual void redirects_changed (void *) {}
void route_rec_enable_changed();
@@ -149,7 +150,10 @@ class RouteUI : public virtual AxisView
void update_rec_display ();
void update_mute_display ();
+
+ bool was_solo_safe;
void update_solo_display ();
+
virtual void map_frozen ();
void set_remote_control_id (uint32_t id, Gtk::CheckMenuItem* item);
diff --git a/gtk2_ardour/selectable.h b/gtk2_ardour/selectable.h
index b52214c9c9..51fc5da027 100644
--- a/gtk2_ardour/selectable.h
+++ b/gtk2_ardour/selectable.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_selectable_h__
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index 8a34752cdd..8a9d27a4ed 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h
index 5422888536..00bc6eeaaa 100644
--- a/gtk2_ardour/selection.h
+++ b/gtk2_ardour/selection.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_selection_h__
diff --git a/gtk2_ardour/selection_templates.h b/gtk2_ardour/selection_templates.h
index 5440112ad6..4e02ab9061 100644
--- a/gtk2_ardour/selection_templates.h
+++ b/gtk2_ardour/selection_templates.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_selection_templates_h__
diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc
index c4656834a6..8faa315848 100644
--- a/gtk2_ardour/send_ui.cc
+++ b/gtk2_ardour/send_ui.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/send.h>
diff --git a/gtk2_ardour/send_ui.h b/gtk2_ardour/send_ui.h
index b64e3c8e58..2d041bb4fe 100644
--- a/gtk2_ardour/send_ui.h
+++ b/gtk2_ardour/send_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_send_ui_h__
diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
index f18b543e0c..19e265b79e 100644
--- a/gtk2_ardour/sfdb_ui.cc
+++ b/gtk2_ardour/sfdb_ui.cc
@@ -50,6 +50,8 @@ using namespace ARDOUR;
using namespace PBD;
using namespace std;
+Glib::ustring SoundFileBrowser::persistent_folder;
+
SoundFileBox::SoundFileBox ()
:
_session(0),
@@ -308,6 +310,11 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
chooser.set_filter (filter);
chooser.set_select_multiple (true);
chooser.signal_update_preview().connect(mem_fun(*this, &SoundFileBrowser::update_preview));
+
+ if (!persistent_folder.empty()) {
+ chooser.set_current_folder (persistent_folder);
+ }
+
found_list_view.get_selection()->signal_changed().connect(mem_fun(*this, &SoundFileBrowser::found_list_view_selected));
found_search_btn.signal_clicked().connect(mem_fun(*this, &SoundFileBrowser::found_search_clicked));
@@ -318,6 +325,11 @@ SoundFileBrowser::SoundFileBrowser (string title, ARDOUR::Session* s)
set_session (s);
}
+SoundFileBrowser::~SoundFileBrowser ()
+{
+ persistent_folder = chooser.get_current_folder();
+}
+
void
SoundFileBrowser::set_session (Session* s)
{
@@ -548,3 +560,4 @@ SoundFileOmega::mode_changed ()
break;
}
}
+
diff --git a/gtk2_ardour/sfdb_ui.h b/gtk2_ardour/sfdb_ui.h
index fb0b7da600..bbc6e2edd4 100644
--- a/gtk2_ardour/sfdb_ui.h
+++ b/gtk2_ardour/sfdb_ui.h
@@ -88,7 +88,7 @@ class SoundFileBrowser : public ArdourDialog
{
public:
SoundFileBrowser (std::string title, ARDOUR::Session* _s = 0);
- virtual ~SoundFileBrowser () {};
+ virtual ~SoundFileBrowser ();
virtual void set_session (ARDOUR::Session*);
@@ -96,7 +96,9 @@ class SoundFileBrowser : public ArdourDialog
Gtk::FileChooserWidget chooser;
Gtk::FileFilter filter;
SoundFileBox preview;
-
+
+ static Glib::ustring persistent_folder;
+
class FoundTagColumns : public Gtk::TreeModel::ColumnRecord
{
public:
@@ -110,7 +112,7 @@ class SoundFileBrowser : public ArdourDialog
Gtk::TreeView found_list_view;
Gtk::Entry found_entry;
Gtk::Button found_search_btn;
-
+
Gtk::Notebook notebook;
void update_preview ();
diff --git a/gtk2_ardour/simpleline.cc b/gtk2_ardour/simpleline.cc
index 4a50ccb4aa..b1fecba840 100644
--- a/gtk2_ardour/simpleline.cc
+++ b/gtk2_ardour/simpleline.cc
@@ -3,7 +3,6 @@
#include "simpleline.h"
#include "simpleline_p.h"
-/* $Id$ */
/* line.ccg
*
diff --git a/gtk2_ardour/simpleline.h b/gtk2_ardour/simpleline.h
index 92afa49975..3e23ace83b 100644
--- a/gtk2_ardour/simpleline.h
+++ b/gtk2_ardour/simpleline.h
@@ -4,7 +4,6 @@
#include <glibmm.h>
-/* $Id$ */
/* line.h
*
diff --git a/gtk2_ardour/simplerect.cc b/gtk2_ardour/simplerect.cc
index b9bedbefd9..bb69fc34ca 100644
--- a/gtk2_ardour/simplerect.cc
+++ b/gtk2_ardour/simplerect.cc
@@ -4,7 +4,6 @@
#include "simplerect_p.h"
#include <libgnomecanvasmm/private/shape_p.h>
-/* $Id$ */
/* rect.c
*
diff --git a/gtk2_ardour/simplerect.h b/gtk2_ardour/simplerect.h
index 329823ab2f..299b27a868 100644
--- a/gtk2_ardour/simplerect.h
+++ b/gtk2_ardour/simplerect.h
@@ -4,7 +4,6 @@
#include <glibmm.h>
-/* $Id$ */
/* rect.h
*
diff --git a/gtk2_ardour/tape_region_view.cc b/gtk2_ardour/tape_region_view.cc
index e697afddb9..f46d1c05dc 100644
--- a/gtk2_ardour/tape_region_view.cc
+++ b/gtk2_ardour/tape_region_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
diff --git a/gtk2_ardour/tape_region_view.h b/gtk2_ardour/tape_region_view.h
index fbedf19ebc..048c9bcc5b 100644
--- a/gtk2_ardour/tape_region_view.h
+++ b/gtk2_ardour/tape_region_view.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_tape_audio_region_view_h__
diff --git a/gtk2_ardour/tempo_dialog.cc b/gtk2_ardour/tempo_dialog.cc
index c5816e36d1..4dae108149 100644
--- a/gtk2_ardour/tempo_dialog.cc
+++ b/gtk2_ardour/tempo_dialog.cc
@@ -14,7 +14,9 @@ using namespace ARDOUR;
using namespace PBD;
TempoDialog::TempoDialog (TempoMap& map, nframes_t frame, const string & action)
- : ArdourDialog ("tempo dialog"),
+ : ArdourDialog (_("edit tempo")),
+ bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0, 1.0),
+ bpm_spinner (bpm_adjustment),
bpm_frame (_("Beats per minute")),
ok_button (action),
cancel_button (_("Cancel")),
@@ -32,6 +34,8 @@ TempoDialog::TempoDialog (TempoMap& map, nframes_t frame, const string & action)
TempoDialog::TempoDialog (TempoSection& section, const string & action)
: ArdourDialog ("tempo dialog"),
+ bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0, 1.0),
+ bpm_spinner (bpm_adjustment),
bpm_frame (_("Beats per minute")),
ok_button (action),
cancel_button (_("Cancel")),
@@ -46,12 +50,13 @@ TempoDialog::TempoDialog (TempoSection& section, const string & action)
void
TempoDialog::init (const BBT_Time& when, double bpm, bool movable)
{
- snprintf (buf, sizeof (buf), "%.2f", bpm);
- bpm_entry.set_text (buf);
- bpm_entry.select_region (0, -1);
-
+ bpm_spinner.set_numeric (true);
+ bpm_spinner.set_digits (1);
+ bpm_spinner.set_wrap (true);
+ bpm_spinner.set_value (bpm);
+
hspacer1.set_border_width (5);
- hspacer1.pack_start (bpm_entry, false, false);
+ hspacer1.pack_start (bpm_spinner, false, false);
vspacer1.set_border_width (5);
vspacer1.pack_start (hspacer1, false, false);
@@ -90,7 +95,7 @@ TempoDialog::init (const BBT_Time& when, double bpm, bool movable)
}
bpm_frame.set_name ("MetricDialogFrame");
- bpm_entry.set_name ("MetricEntry");
+ bpm_spinner.set_name ("MetricEntry");
get_vbox()->pack_start (bpm_frame, false, false);
@@ -100,83 +105,34 @@ TempoDialog::init (const BBT_Time& when, double bpm, bool movable)
set_default_response (RESPONSE_ACCEPT);
get_vbox()->show_all();
- bpm_entry.show();
+ bpm_spinner.show();
set_name ("MetricDialog");
- bpm_entry.signal_activate().connect (bind (mem_fun (*this, &TempoDialog::response), RESPONSE_ACCEPT));
- bpm_entry.signal_key_release_event().connect (mem_fun (*this, &TempoDialog::bpm_key_release));
- bpm_entry.signal_key_press_event().connect (mem_fun (*this, &TempoDialog::bpm_key_press), false);
+
+ bpm_spinner.signal_activate().connect (bind (mem_fun (*this, &TempoDialog::response), RESPONSE_ACCEPT));
+ bpm_spinner.signal_button_press_event().connect (mem_fun (*this, &TempoDialog::bpm_button_press), false);
+ bpm_spinner.signal_button_release_event().connect (mem_fun (*this, &TempoDialog::bpm_button_release), false);
}
bool
-TempoDialog::bpm_key_press (GdkEventKey* ev)
+TempoDialog::bpm_button_press (GdkEventButton* ev)
{
-
-switch (ev->keyval) {
-
- case GDK_0:
- case GDK_1:
- case GDK_2:
- case GDK_3:
- case GDK_4:
- case GDK_5:
- case GDK_6:
- case GDK_7:
- case GDK_8:
- case GDK_9:
- case GDK_KP_0:
- case GDK_KP_1:
- case GDK_KP_2:
- case GDK_KP_3:
- case GDK_KP_4:
- case GDK_KP_5:
- case GDK_KP_6:
- case GDK_KP_7:
- case GDK_KP_8:
- case GDK_KP_9:
- case GDK_period:
- case GDK_comma:
- case GDK_KP_Delete:
- case GDK_KP_Enter:
- case GDK_Delete:
- case GDK_BackSpace:
- case GDK_Escape:
- case GDK_Return:
- case GDK_Home:
- case GDK_End:
- case GDK_Left:
- case GDK_Right:
- case GDK_Num_Lock:
- case GDK_Tab:
- return FALSE;
- default:
- break;
- }
-
- return TRUE;
+ return false;
}
bool
-TempoDialog::bpm_key_release (GdkEventKey* ev)
-{
- if (bpm_entry.get_text() != "") {
- set_response_sensitive (Gtk::RESPONSE_ACCEPT, true);
- } else {
- set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
- }
+TempoDialog::bpm_button_release (GdkEventButton* ev)
+{
+ /* the value has been modified, accept should work now */
+
+ set_response_sensitive (Gtk::RESPONSE_ACCEPT, true);
return false;
}
double
TempoDialog::get_bpm ()
{
- double bpm;
-
- if (sscanf (bpm_entry.get_text().c_str(), "%lf", &bpm) != 1) {
- return 0;
- }
-
- return bpm;
+ return bpm_spinner.get_value ();
}
bool
diff --git a/gtk2_ardour/tempo_dialog.h b/gtk2_ardour/tempo_dialog.h
index 720a87c4ba..09a91dd3e3 100644
--- a/gtk2_ardour/tempo_dialog.h
+++ b/gtk2_ardour/tempo_dialog.h
@@ -8,6 +8,7 @@
#include <gtkmm/label.h>
#include <gtkmm/table.h>
#include <gtkmm/entry.h>
+#include <gtkmm/spinbutton.h>
#include <gtkmm/comboboxtext.h>
#include <ardour/types.h>
@@ -17,8 +18,9 @@
struct TempoDialog : public ArdourDialog
{
- Gtk::Entry bpm_entry;
- Gtk::Frame bpm_frame;
+ Gtk::Adjustment bpm_adjustment;
+ Gtk::SpinButton bpm_spinner;
+ Gtk::Frame bpm_frame;
Gtk::VBox vpacker;
Gtk::Button ok_button;
Gtk::Button cancel_button;
@@ -41,8 +43,9 @@ struct TempoDialog : public ArdourDialog
private:
void init (const ARDOUR::BBT_Time& start, double, bool);
- bool bpm_key_press (GdkEventKey* );
- bool bpm_key_release (GdkEventKey* );
+ void bpm_changed ();
+ bool bpm_button_press (GdkEventButton* );
+ bool bpm_button_release (GdkEventButton* );
};
struct MeterDialog : public ArdourDialog
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index 53a0ee4553..a0267d7e86 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
@@ -969,12 +968,10 @@ TimeAxisView::compute_controls_size_info ()
buttons[i]->set_name ("TrackMuteButton");
}
- Gtk::Requisition req;
-
one_row_table.attach (*buttons[0], 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
one_row_table.show_all ();
- one_row_table.size_request (req);
+ Gtk::Requisition req(one_row_table.size_request ());
// height required to show 1 row of buttons
@@ -990,7 +987,7 @@ TimeAxisView::compute_controls_size_info ()
two_row_table.attach (*buttons[4], 8, 9, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
two_row_table.show_all ();
- two_row_table.size_request (req);
+ req = two_row_table.size_request ();
// height required to show all normal buttons
diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h
index 96437a9991..1f401967eb 100644
--- a/gtk2_ardour/time_axis_view.h
+++ b/gtk2_ardour/time_axis_view.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_time_axis_h__
diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc
index a008e2af1a..87eac74ccf 100644
--- a/gtk2_ardour/time_axis_view_item.cc
+++ b/gtk2_ardour/time_axis_view_item.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <pbd/error.h>
@@ -89,13 +88,42 @@ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group&
layout->set_font_description (NAME_FONT);
Gtkmm2ext::get_ink_pixel_size (layout, width, height);
- NAME_Y_OFFSET = height + 4;
+ NAME_Y_OFFSET = height + 6;
NAME_HIGHLIGHT_SIZE = height + 6;
NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_SIZE * 2;
have_name_font = true;
}
+ group = new ArdourCanvas::Group (parent);
+
+ init (it_name, spu, base_color, start, duration, vis);
+
+}
+
+TimeAxisViewItem::TimeAxisViewItem (const TimeAxisViewItem& other)
+ : trackview (other.trackview)
+{
+
+ Gdk::Color c;
+ int r,g,b,a;
+
+ UINT_TO_RGBA (other.fill_color, &r, &g, &b, &a);
+ c.set_rgb_p (r/255.0, g/255.0, b/255.0);
+
+ /* share the other's parent, but still create a new group */
+
+ Gnome::Canvas::Group* parent = other.group->property_parent();
+
+ group = new ArdourCanvas::Group (*parent);
+
+ init (other.item_name, other.samples_per_unit, c, other.frame_position, other.item_duration, other.visibility);
+}
+
+
+void
+TimeAxisViewItem::init (const string& it_name, double spu, Gdk::Color& base_color, nframes_t start, nframes_t duration, Visibility vis)
+{
item_name = it_name ;
samples_per_unit = spu ;
should_show_selection = true;
@@ -113,8 +141,6 @@ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group&
warning << "Time Axis Item Duration == 0" << endl ;
}
- group = new ArdourCanvas::Group (parent);
-
vestigial_frame = new ArdourCanvas::SimpleRect (*group);
vestigial_frame->property_x1() = (double) 0.0;
vestigial_frame->property_y1() = (double) 1.0;
@@ -221,7 +247,6 @@ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group&
set_position (start, this) ;
}
-
/**
* Destructor
*/
diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h
index 80d9177041..d41ad5a327 100644
--- a/gtk2_ardour/time_axis_view_item.h
+++ b/gtk2_ardour/time_axis_view_item.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtk_ardour_time_axis_view_item_h__
@@ -340,6 +339,10 @@ class TimeAxisViewItem : public Selectable
*/
TimeAxisViewItem(const std::string & it_name, ArdourCanvas::Group& parent, TimeAxisView& tv, double spu, Gdk::Color& base_color,
nframes_t start, nframes_t duration, Visibility v = Visibility (0));
+
+ TimeAxisViewItem (const TimeAxisViewItem& other);
+
+ void init (const std::string& it_name, double spu, Gdk::Color& base_color, nframes_t start, nframes_t duration, Visibility vis);
/**
* Calculates some contrasting color for displaying various parts of this item, based upon the base color
diff --git a/gtk2_ardour/time_selection.cc b/gtk2_ardour/time_selection.cc
index c0a05abc45..eac7bd70f5 100644
--- a/gtk2_ardour/time_selection.cc
+++ b/gtk2_ardour/time_selection.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc
index 887494829e..fbebf0d51a 100644
--- a/gtk2_ardour/utils.cc
+++ b/gtk2_ardour/utils.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
@@ -120,7 +119,7 @@ xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h)
return 0;
}
- savergb = rgb = (unsigned char*)art_alloc (h * w * 3);
+ savergb = rgb = (unsigned char*) malloc (h * w * 3);
// LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
for (t = 0; t < colors; ++t) {
@@ -163,7 +162,7 @@ xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h)
return 0;
}
- savergb = rgb = (unsigned char*)art_alloc (h * w * 4);
+ savergb = rgb = (unsigned char*) malloc (h * w * 4);
// LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION
@@ -233,7 +232,21 @@ get_font_for_style (string widgetname)
foobar.ensure_style();
style = foobar.get_style ();
- return style->get_font();
+
+ Glib::RefPtr<const Pango::Layout> layout = foobar.get_layout();
+
+ PangoFontDescription *pfd = (PangoFontDescription *)pango_layout_get_font_description((PangoLayout *)layout->gobj());
+
+ if (!pfd) {
+
+ /* layout inherited its font description from a PangoContext */
+
+ PangoContext* ctxt = (PangoContext*) pango_layout_get_context ((PangoLayout*) layout->gobj());
+ pfd = pango_context_get_font_description (ctxt);
+ return Pango::FontDescription (pfd, true); /* make a copy */
+ }
+
+ return Pango::FontDescription (pfd, true); /* make a copy */
}
uint32_t
@@ -263,6 +276,7 @@ rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a, s
r = waverc->fg[state].red / 257;
g = waverc->fg[state].green / 257;
b = waverc->fg[state].blue / 257;
+
/* what a hack ... "a" is for "active" */
if (state == Gtk::STATE_NORMAL && rgba) {
a = waverc->fg[GTK_STATE_ACTIVE].red / 257;
@@ -547,3 +561,56 @@ key_is_legal_for_numeric_entry (guint keyval)
return false;
}
+
+ustring
+short_path (ustring path, uint32_t target_characters)
+{
+ ustring::size_type last_sep;
+ ustring::size_type len = path.length();
+ const char separator = '/';
+
+ if (len <= target_characters) {
+ return path;
+ }
+
+ if ((last_sep = path.find_last_of (separator)) == ustring::npos) {
+
+ /* just a filename, but its too long anyway */
+
+ if (target_characters > 3) {
+ return path.substr (0, target_characters - 3) + ustring ("...");
+ } else {
+ /* stupid caller, just hand back the whole thing */
+ return path;
+ }
+ }
+
+ if (len - last_sep >= target_characters) {
+
+ /* even the filename itself is too long */
+
+ if (target_characters > 3) {
+ return path.substr (last_sep+1, target_characters - 3) + ustring ("...");
+ } else {
+ /* stupid caller, just hand back the whole thing */
+ return path;
+ }
+ }
+
+ uint32_t so_far = (len - last_sep);
+ uint32_t space_for = target_characters - so_far;
+
+ if (space_for >= 3) {
+ ustring res = "...";
+ res += path.substr (last_sep - space_for);
+ return res;
+ } else {
+ /* remove part of the end */
+ ustring res = "...";
+ res += path.substr (last_sep - space_for, len - last_sep + space_for - 3);
+ res += "...";
+ return res;
+
+ }
+}
+
diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h
index 6d5ff0702d..2d2f879073 100644
--- a/gtk2_ardour/utils.h
+++ b/gtk2_ardour/utils.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_utils_h__
@@ -81,5 +80,6 @@ static std::map<std::string, Glib::RefPtr<Gdk::Pixbuf> > xpm_map;
const char* const *get_xpm_data (std::string path);
std::string longest (std::vector<std::string>&);
bool key_is_legal_for_numeric_entry (guint keyval);
+Glib::ustring short_path (Glib::ustring, uint32_t target_characters);
#endif /* __ardour_gtk_utils_h__ */
diff --git a/gtk2_ardour/visual_time_axis.cc b/gtk2_ardour/visual_time_axis.cc
index 20fe13603e..b685971144 100644
--- a/gtk2_ardour/visual_time_axis.cc
+++ b/gtk2_ardour/visual_time_axis.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdlib>
diff --git a/gtk2_ardour/visual_time_axis.h b/gtk2_ardour/visual_time_axis.h
index d569ca3733..6d1396bc54 100644
--- a/gtk2_ardour/visual_time_axis.h
+++ b/gtk2_ardour/visual_time_axis.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_visual_time_axis_h__
diff --git a/gtk2_ardour/vst_pluginui.cc b/gtk2_ardour/vst_pluginui.cc
index 5e65475c46..1320ccdc7a 100644
--- a/gtk2_ardour/vst_pluginui.cc
+++ b/gtk2_ardour/vst_pluginui.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <fst.h>
diff --git a/gtk2_ardour/waveview.cc b/gtk2_ardour/waveview.cc
index 92e4fdd24a..d9316c110e 100644
--- a/gtk2_ardour/waveview.cc
+++ b/gtk2_ardour/waveview.cc
@@ -1,7 +1,6 @@
#include "waveview.h"
#include "waveview_p.h"
-/* $Id$ */
/* waveview.cc
*
diff --git a/gtk2_ardour/waveview.h b/gtk2_ardour/waveview.h
index 56d0ed7675..cfa7fd416d 100644
--- a/gtk2_ardour/waveview.h
+++ b/gtk2_ardour/waveview.h
@@ -4,7 +4,6 @@
#include <glibmm.h>
-/* $Id$ */
/* waveview.h
*
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index 878b41e82a..772f847400 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -101,6 +101,7 @@ session_state.cc
session_time.cc
session_timefx.cc
session_transport.cc
+silentfilesource.cc
sndfile_helpers.cc
sndfilesource.cc
source.cc
@@ -296,16 +297,29 @@ env['BUILDERS']['SharedAsmObject'] = Builder (action = '$CXX -c -fPIC $SOURCE -o
suffix = '$SHOBJSUFFIX',
src_suffix = '.s',
single_source = 1)
+#
+# handle objects that should always be compiled with -msse in their own
+# special environment, which is exactly like "ardour" but unconditionally
+# includes -msse
+#
+
+
+always_sse_objects = []
+sse_env = ardour.Copy()
+sse_env.Append (CXXFLAGS="-msse")
if env['FPU_OPTIMIZATION']:
if env['DIST_TARGET'] == "i386":
arch_specific_objects = env.SharedAsmObject('sse_functions.os', 'sse_functions.s')
+ always_sse_objects += [ sse_env.SharedObject (source = 'sse_functions_xmm.cc') ]
if env['DIST_TARGET'] == "i686":
arch_specific_objects = env.SharedAsmObject('sse_functions.os', 'sse_functions.s')
+ always_sse_objects += [ sse_env.SharedObject (source = 'sse_functions_xmm.cc') ]
if env['DIST_TARGET'] == "x86_64":
arch_specific_objects = env.SharedAsmObject('sse_functions_64bit.os', 'sse_functions_64bit.s')
+ always_sse_objects += [ sse_env.SharedObject (source = 'sse_functions_xmm.cc') ]
-libardour = ardour.SharedLibrary('ardour', ardour_files + extra_sources + arch_specific_objects)
+libardour = ardour.SharedLibrary('ardour', ardour_files + always_sse_objects + extra_sources + arch_specific_objects)
Default(libardour)
@@ -318,6 +332,6 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar
env.Alias('version', ardour.VersionBuild(['version.cc', 'ardour/version.h'], []))
env.Alias('tarball', env.Distribute (env['DISTTREE'],
- [ 'SConscript', 'i18n.h', 'gettext.h', 'sse_functions.s', 'sse_functions_64bit.s' ] +
+ [ 'SConscript', 'i18n.h', 'gettext.h', 'sse_functions_xmm.cc', 'sse_functions.s', 'sse_functions_64bit.s' ] +
ardour_files + osc_files + vst_files + coreaudio_files + audiounit_files +
glob.glob('po/*.po') + glob.glob('ardour/*.h')))
diff --git a/libs/ardour/ardour/ardour.h b/libs/ardour/ardour/ardour.h
index 5cc2359632..332b9af733 100644
--- a/libs/ardour/ardour/ardour.h
+++ b/libs/ardour/ardour/ardour.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_ardour_h__
diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h
index 1da8903a41..4846a20cbd 100644
--- a/libs/ardour/ardour/audio_diskstream.h
+++ b/libs/ardour/ardour/audio_diskstream.h
@@ -32,6 +32,7 @@
#include <pbd/fastlog.h>
#include <pbd/ringbufferNPT.h>
#include <pbd/stateful.h>
+#include <pbd/rcu.h>
#include <ardour/ardour.h>
#include <ardour/configuration.h>
@@ -65,24 +66,28 @@ class AudioDiskstream : public Diskstream
float capture_buffer_load() const;
string input_source (uint32_t n=0) const {
- if (n < channels.size()) {
- return channels[n].source ? channels[n].source->name() : "";
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ if (n < c->size()) {
+ return (*c)[n]->source ? (*c)[n]->source->name() : "";
} else {
return "";
}
}
Port *input_source_port (uint32_t n=0) const {
- if (n < channels.size()) return channels[n].source; return 0;
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ if (n < c->size()) return (*c)[n]->source; return 0;
}
void set_record_enabled (bool yn);
int set_destructive (bool yn);
bool can_become_destructive (bool& requires_bounce) const;
- float peak_power(uint32_t n=0) {
- float x = channels[n].peak_power;
- channels[n].peak_power = 0.0f;
+ float peak_power(uint32_t n = 0) {
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ ChannelInfo* chaninfo = (*c)[n];
+ float x = chaninfo->peak_power;
+ chaninfo->peak_power = 0.0f;
if (x > 0.0f) {
return 20.0f * fast_log10(x);
} else {
@@ -96,27 +101,29 @@ class AudioDiskstream : public Diskstream
int use_new_playlist ();
int use_copy_playlist ();
- Sample *playback_buffer (uint32_t n=0) {
- if (n < channels.size())
- return channels[n].current_playback_buffer;
+ Sample *playback_buffer (uint32_t n = 0) {
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ if (n < c->size())
+ return (*c)[n]->current_playback_buffer;
return 0;
}
- Sample *capture_buffer (uint32_t n=0) {
- if (n < channels.size())
- return channels[n].current_capture_buffer;
+ Sample *capture_buffer (uint32_t n = 0) {
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ if (n < c->size())
+ return (*c)[n]->current_capture_buffer;
return 0;
}
boost::shared_ptr<AudioFileSource> write_source (uint32_t n=0) {
- if (n < channels.size())
- return channels[n].write_source;
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ if (n < c->size())
+ return (*c)[n]->write_source;
return boost::shared_ptr<AudioFileSource>();
}
- int add_channel ();
- int remove_channel ();
-
+ int add_channel (uint32_t how_many);
+ int remove_channel (uint32_t how_many);
/* stateful */
@@ -174,12 +181,9 @@ class AudioDiskstream : public Diskstream
struct ChannelInfo {
- ChannelInfo ();
+ ChannelInfo (nframes_t buffer_size, nframes_t speed_buffer_size, nframes_t wrap_buffer_size);
~ChannelInfo ();
- void init (nframes_t buffer_size, nframes_t speed_buffer_size, nframes_t wrap_buffer_size);
- void release ();
-
Sample *playback_wrap_buffer;
Sample *capture_wrap_buffer;
Sample *speed_buffer;
@@ -208,17 +212,19 @@ class AudioDiskstream : public Diskstream
nframes_t curr_capture_cnt;
};
+ typedef std::vector<ChannelInfo*> ChannelList;
+
/* The two central butler operations */
int do_flush (Session::RunContext context, bool force = false);
int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer); }
- int do_refill_with_alloc();
+ int do_refill_with_alloc ();
int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
- nframes_t& start, nframes_t cnt,
- ChannelInfo& channel_info, int channel, bool reversed);
+ nframes_t& start, nframes_t cnt,
+ ChannelInfo* channel_info, int channel, bool reversed);
- void finish_capture (bool rec_monitors_input);
+ void finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList>);
void transport_stopped (struct tm&, time_t, bool abort);
void init (Diskstream::Flag);
@@ -251,14 +257,17 @@ class AudioDiskstream : public Diskstream
static Sample* _mixdown_buffer;
static gain_t* _gain_buffer;
- // Uh, /really/ private? (there should probably be less friends of Diskstream)
- int _do_refill (Sample *mixdown_buffer, float *gain_buffer);
-
-
std::vector<boost::shared_ptr<AudioFileSource> > capturing_sources;
- typedef vector<ChannelInfo> ChannelList;
- ChannelList channels;
+ SerializedRCUManager<ChannelList> channels;
+
+ /* really */
+ private:
+ int _do_refill (Sample *mixdown_buffer, float *gain_buffer);
+
+ int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many);
+ int remove_channel_from (boost::shared_ptr<ChannelList>, uint32_t how_many);
+
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h
index e87434b0fb..3546545329 100644
--- a/libs/ardour/ardour/audio_track.h
+++ b/libs/ardour/ardour/audio_track.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_audio_track_h__
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 3dbd30f841..48a3426d53 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_audioengine_h__
@@ -53,6 +52,8 @@ class AudioEngine : public sigc::trackable
jack_client_t* jack() const { return _jack; }
bool connected() const { return _jack != 0; }
+ bool is_realtime () const;
+
std::string client_name() const { return jack_client_name; }
int reconnect_to_jack ();
diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h
index 0e1caf5245..913cd7d5ed 100644
--- a/libs/ardour/ardour/audiofilesource.h
+++ b/libs/ardour/ardour/audiofilesource.h
@@ -20,12 +20,19 @@
#ifndef __ardour_audiofilesource_h__
#define __ardour_audiofilesource_h__
+#include <exception>
+
#include <time.h>
#include <ardour/audiosource.h>
namespace ARDOUR {
+class non_existent_source : public std::exception {
+ public:
+ virtual const char *what() const throw() { return "audio file does not exist"; }
+};
+
struct SoundFileInfo {
float samplerate;
uint16_t channels;
@@ -49,17 +56,19 @@ class AudioFileSource : public AudioSource {
virtual ~AudioFileSource ();
- int set_name (string newname, bool destructive);
+ int set_name (Glib::ustring newname, bool destructive);
+
+ Glib::ustring path() const { return _path; }
+ Glib::ustring peak_path (Glib::ustring audio_path);
+ Glib::ustring old_peak_path (Glib::ustring audio_path);
- string path() const { return _path; }
- string peak_path (string audio_path);
- string old_peak_path (string audio_path);
+ uint16_t channel() const { return _channel; }
- static void set_peak_dir (string dir) { peak_dir = dir; }
+ static void set_peak_dir (Glib::ustring dir) { peak_dir = dir; }
- static bool get_soundfile_info (string path, SoundFileInfo& _info, string& error);
+ static bool get_soundfile_info (Glib::ustring path, SoundFileInfo& _info, std::string& error);
- static bool safe_file_extension (string path);
+ static bool safe_file_extension (Glib::ustring path);
void set_allow_remove_if_empty (bool yn);
void mark_for_remove();
@@ -76,19 +85,19 @@ class AudioFileSource : public AudioSource {
virtual int update_header (nframes_t when, struct tm&, time_t) = 0;
virtual int flush_header () = 0;
- int move_to_trash (const string trash_dir_name);
+ int move_to_trash (const Glib::ustring& trash_dir_name);
- static bool is_empty (Session&, string path);
+ static bool is_empty (Session&, Glib::ustring path);
void mark_streaming_write_completed ();
- void mark_take (string);
- string take_id() const { return _take_id; }
+ void mark_take (Glib::ustring);
+ Glib::ustring take_id() const { return _take_id; }
bool is_embedded() const { return _is_embedded; }
static void set_bwf_serial_number (int);
- static void set_search_path (string);
+ static void set_search_path (Glib::ustring string);
static void set_header_position_offset (nframes_t offset );
int setup_peakfile ();
@@ -100,6 +109,7 @@ class AudioFileSource : public AudioSource {
bool destructive() const { return (_flags & Destructive); }
virtual bool set_destructive (bool yn) { return false; }
+ bool can_truncate_peaks() const { return !destructive(); }
Flag flags() const { return _flags; }
@@ -116,31 +126,31 @@ class AudioFileSource : public AudioSource {
/* constructor to be called for existing external-to-session files */
- AudioFileSource (Session&, std::string path, Flag flags);
+ AudioFileSource (Session&, Glib::ustring path, Flag flags);
/* constructor to be called for new in-session files */
- AudioFileSource (Session&, std::string path, Flag flags,
+ AudioFileSource (Session&, Glib::ustring path, Flag flags,
SampleFormat samp_format, HeaderFormat hdr_format);
/* constructor to be called for existing in-session files */
- AudioFileSource (Session&, const XMLNode&);
+ AudioFileSource (Session&, const XMLNode&, bool must_exit = true);
- int init (string idstr, bool must_exist);
+ int init (Glib::ustring idstr, bool must_exist);
- string _path;
+ Glib::ustring _path;
Flag _flags;
- string _take_id;
+ Glib::ustring _take_id;
int64_t timeline_position;
bool file_is_new;
- uint16_t channel;
+ uint16_t _channel;
bool _is_embedded;
- static bool determine_embeddedness(string path);
+ static bool determine_embeddedness(Glib::ustring path);
- static string peak_dir;
- static string search_path;
+ static Glib::ustring peak_dir;
+ static Glib::ustring search_path;
static char bwf_country_code[3];
static char bwf_organization_code[4];
@@ -151,7 +161,7 @@ class AudioFileSource : public AudioSource {
virtual void set_timeline_position (int64_t pos);
virtual void set_header_timeline_position () = 0;
- bool find (std::string path, bool must_exist, bool& is_new);
+ bool find (Glib::ustring& path, bool must_exist, bool& is_new);
bool removable() const;
bool writable() const { return _flags & Writable; }
};
diff --git a/libs/ardour/ardour/audiofilter.h b/libs/ardour/ardour/audiofilter.h
index c8762dbf69..6b60544942 100644
--- a/libs/ardour/ardour/audiofilter.h
+++ b/libs/ardour/ardour/audiofilter.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_audiofilter_h__
diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h
index 36fe027a6f..39f41d5d1c 100644
--- a/libs/ardour/ardour/audioplaylist.h
+++ b/libs/ardour/ardour/audioplaylist.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_audio_playlist_h__
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index e3c5db561d..3b592a54ee 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_audio_region_h__
diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h
index 0734a66319..812c30e8c2 100644
--- a/libs/ardour/ardour/audiosource.h
+++ b/libs/ardour/ardour/audiosource.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: audio_source.h 486 2006-04-27 09:04:24Z pauld $
*/
#ifndef __ardour_audio_source_h__
@@ -23,7 +22,6 @@
#include <list>
#include <vector>
-#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
@@ -31,6 +29,7 @@
#include <time.h>
#include <glibmm/thread.h>
+#include <glibmm/ustring.h>
#include <sigc++/signal.h>
@@ -41,7 +40,7 @@
using std::list;
using std::vector;
-using std::string;
+using Glib::ustring;
namespace ARDOUR {
@@ -50,7 +49,7 @@ const nframes_t frames_per_peak = 256;
class AudioSource : public Source, public boost::enable_shared_from_this<ARDOUR::AudioSource>
{
public:
- AudioSource (Session&, string name);
+ AudioSource (Session&, ustring name);
AudioSource (Session&, const XMLNode&);
virtual ~AudioSource ();
@@ -64,8 +63,10 @@ const nframes_t frames_per_peak = 256;
virtual void mark_for_remove() = 0;
virtual void mark_streaming_write_completed () {}
- void set_captured_for (string str) { _captured_for = str; }
- string captured_for() const { return _captured_for; }
+ virtual bool can_truncate_peaks() const { return true; }
+
+ void set_captured_for (ustring str) { _captured_for = str; }
+ ustring captured_for() const { return _captured_for; }
uint32_t read_data_count() const { return _read_data_count; }
uint32_t write_data_count() const { return _write_data_count; }
@@ -80,10 +81,7 @@ const nframes_t frames_per_peak = 256;
XMLNode& get_state ();
int set_state (const XMLNode&);
- static int start_peak_thread ();
- static void stop_peak_thread ();
-
- int rename_peakfile (std::string newpath);
+ int rename_peakfile (ustring newpath);
void touch_peakfile ();
static void set_build_missing_peakfiles (bool yn) {
@@ -96,67 +94,41 @@ const nframes_t frames_per_peak = 256;
virtual int setup_peakfile () { return 0; }
+ int prepare_for_peakfile_writes ();
+ void done_with_peakfile_writes ();
+
protected:
static bool _build_missing_peakfiles;
static bool _build_peakfiles;
bool _peaks_built;
mutable Glib::Mutex _lock;
- bool next_peak_clear_should_notify;
- string peakpath;
- string _captured_for;
+ ustring peakpath;
+ ustring _captured_for;
mutable uint32_t _read_data_count; // modified in read()
mutable uint32_t _write_data_count; // modified in write()
- int initialize_peakfile (bool newfile, string path);
- void build_peaks_from_scratch ();
-
- int do_build_peak (nframes_t, nframes_t);
+ int initialize_peakfile (bool newfile, ustring path);
+ int build_peaks_from_scratch ();
+ int compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force);
void truncate_peakfile();
- mutable off_t _peak_byte_max; // modified in do_build_peaks()
+ mutable off_t _peak_byte_max; // modified in compute_and_write_peak()
virtual nframes_t read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const = 0;
virtual nframes_t write_unlocked (Sample *dst, nframes_t cnt) = 0;
- virtual string peak_path(string audio_path) = 0;
- virtual string old_peak_path(string audio_path) = 0;
+ virtual ustring peak_path(ustring audio_path) = 0;
+ virtual ustring old_peak_path(ustring audio_path) = 0;
- static pthread_t peak_thread;
- static bool have_peak_thread;
- static void* peak_thread_work(void*);
-
- static int peak_request_pipe[2];
-
- struct PeakRequest {
- enum Type {
- Build,
- Quit
- };
- };
-
- static vector<boost::shared_ptr<AudioSource> > pending_peak_sources;
- static Glib::Mutex* pending_peak_sources_lock;
-
- static void queue_for_peaks (boost::shared_ptr<AudioSource>, bool notify=true);
- static void clear_queue_for_peaks ();
-
- struct PeakBuildRecord {
- nframes_t frame;
- nframes_t cnt;
-
- PeakBuildRecord (nframes_t f, nframes_t c)
- : frame (f), cnt (c) {}
- PeakBuildRecord (const PeakBuildRecord& other) {
- frame = other.frame;
- cnt = other.cnt;
- }
- };
-
- list<AudioSource::PeakBuildRecord *> pending_peak_builds;
-
private:
- bool file_changed (string path);
+ int peakfile;
+ nframes_t peak_leftover_cnt;
+ nframes_t peak_leftover_size;
+ Sample* peak_leftovers;
+ nframes_t peak_leftover_frame;
+
+ bool file_changed (ustring path);
};
}
diff --git a/libs/ardour/ardour/auditioner.h b/libs/ardour/ardour/auditioner.h
index e6091cfba0..06d521ea21 100644
--- a/libs/ardour/ardour/auditioner.h
+++ b/libs/ardour/ardour/auditioner.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_auditioner_h__
diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h
index a2cfb23e61..007bad7259 100644
--- a/libs/ardour/ardour/automation_event.h
+++ b/libs/ardour/ardour/automation_event.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_automation_event_h__
diff --git a/libs/ardour/ardour/click.h b/libs/ardour/ardour/click.h
index 71214978a5..60499b98da 100644
--- a/libs/ardour/ardour/click.h
+++ b/libs/ardour/ardour/click.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_click_h__
diff --git a/libs/ardour/ardour/configuration.h b/libs/ardour/ardour/configuration.h
index bb49b2dce4..31cb74ab33 100644
--- a/libs/ardour/ardour/configuration.h
+++ b/libs/ardour/ardour/configuration.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_configuration_h__
diff --git a/libs/ardour/ardour/configuration_variable.h b/libs/ardour/ardour/configuration_variable.h
index 8710369a64..81e282ff64 100644
--- a/libs/ardour/ardour/configuration_variable.h
+++ b/libs/ardour/ardour/configuration_variable.h
@@ -27,10 +27,13 @@ class ConfigVariableBase {
virtual void add_to_node (XMLNode& node) = 0;
virtual bool set_from_node (const XMLNode& node, Owner owner) = 0;
+ void show_stored_value (const std::string&);
+ static void set_show_stored_values (bool yn);
protected:
std::string _name;
Owner _owner;
+ static bool show_stores;
void notify ();
void miss ();
@@ -61,7 +64,7 @@ class ConfigVariable : public ConfigVariableBase
void add_to_node (XMLNode& node) {
std::stringstream ss;
ss << value;
- cerr << "Config variable " << _name << " stored as " << ss.str() << endl;
+ show_stored_value (ss.str());
XMLNode* child = new XMLNode ("Option");
child->add_property ("name", _name);
child->add_property ("value", ss.str());
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 703352b305..674a9232b5 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -18,11 +18,14 @@ CONFIG_VARIABLE (bool, send_mmc, "send-mmc", false)
CONFIG_VARIABLE (bool, mmc_control, "mmc-control", false)
CONFIG_VARIABLE (bool, midi_feedback, "midi-feedback", false)
CONFIG_VARIABLE (bool, midi_control, "midi-control", false)
+CONFIG_VARIABLE (uint8_t, mmc_device_id, "mmc-device-id", 0)
/* control surfaces */
CONFIG_VARIABLE (uint32_t, feedback_interval_ms, "feedback-interval-ms", 100)
CONFIG_VARIABLE (bool, use_tranzport, "use-tranzport", false)
+CONFIG_VARIABLE (std::string, mackie_emulation, "mackie-emulation", "mcu")
+CONFIG_VARIABLE (RemoteModel, remote_model, "remote-model", MixerOrdered)
/* disk operations */
@@ -35,7 +38,7 @@ CONFIG_VARIABLE (HeaderFormat, native_file_header_format, "native-file-header-f
/* OSC */
CONFIG_VARIABLE (uint32_t, osc_port, "osc-port", 3819)
-CONFIG_VARIABLE (bool, use_osc, "use-osc", true)
+CONFIG_VARIABLE (bool, use_osc, "use-osc", false)
/* crossfades */
@@ -62,6 +65,7 @@ CONFIG_VARIABLE (SoloModel, solo_model, "solo-model", InverseMute)
CONFIG_VARIABLE (bool, solo_latched, "solo-latched", true)
CONFIG_VARIABLE (bool, latched_record_enable, "latched-record-enable", false)
CONFIG_VARIABLE (bool, all_safe, "all-safe", false)
+CONFIG_VARIABLE (bool, show_solo_mutes, "show-solo-mutes", false)
/* click */
diff --git a/libs/ardour/ardour/connection.h b/libs/ardour/ardour/connection.h
index da4d4e2684..d2f1cb4294 100644
--- a/libs/ardour/ardour/connection.h
+++ b/libs/ardour/ardour/connection.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_connection_h__
diff --git a/libs/ardour/ardour/crossfade.h b/libs/ardour/ardour/crossfade.h
index 3eafed818c..7346e645fb 100644
--- a/libs/ardour/ardour/crossfade.h
+++ b/libs/ardour/ardour/crossfade.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_overlap_h__
diff --git a/libs/ardour/ardour/crossfade_compare.h b/libs/ardour/ardour/crossfade_compare.h
index 2ecf79c04c..b92806a6bb 100644
--- a/libs/ardour/ardour/crossfade_compare.h
+++ b/libs/ardour/ardour/crossfade_compare.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_crossfade_compare_h__
diff --git a/libs/ardour/ardour/curve.h b/libs/ardour/ardour/curve.h
index df984b74e0..dd63439f08 100644
--- a/libs/ardour/ardour/curve.h
+++ b/libs/ardour/ardour/curve.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_curve_h__
diff --git a/libs/ardour/ardour/cycle_timer.h b/libs/ardour/ardour/cycle_timer.h
index b9cbbbf0a8..4e1a50e602 100644
--- a/libs/ardour/ardour/cycle_timer.h
+++ b/libs/ardour/ardour/cycle_timer.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_cycle_timer_h__
diff --git a/libs/ardour/ardour/cycles.h b/libs/ardour/ardour/cycles.h
index a6f34d59be..f1422880b8 100644
--- a/libs/ardour/ardour/cycles.h
+++ b/libs/ardour/ardour/cycles.h
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_cycles_h__
diff --git a/libs/ardour/ardour/dB.h b/libs/ardour/ardour/dB.h
index 703de6fb1a..b67e581067 100644
--- a/libs/ardour/ardour/dB.h
+++ b/libs/ardour/ardour/dB.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_dB_h__
diff --git a/libs/ardour/ardour/destructive_filesource.h b/libs/ardour/ardour/destructive_filesource.h
deleted file mode 100644
index 2e6f5d0e57..0000000000
--- a/libs/ardour/ardour/destructive_filesource.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- Copyright (C) 2006 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
-
-#ifndef __ardour_destructive_file_source_h__
-#define __ardour_destructive_file_source_h__
-
-#include <string>
-
-#include <ardour/sndfilesource.h>
-
-struct tm;
-
-namespace ARDOUR {
-
-class DestructiveFileSource : public SndFileSource {
- public:
- DestructiveFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, nframes_t rate,
- Flag flags = AudioFileSource::Flag (AudioFileSource::Writable));
-
- DestructiveFileSource (Session&, std::string path, Flag flags);
-
- DestructiveFileSource (Session&, const XMLNode&);
- ~DestructiveFileSource ();
-
- nframes_t last_capture_start_frame() const;
- void mark_capture_start (nframes_t);
- void mark_capture_end ();
- void clear_capture_marks();
-
- XMLNode& get_state ();
-
- static void setup_standard_crossfades (nframes_t sample_rate);
-
- int read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit) const;
-
- protected:
- nframes_t write_unlocked (Sample *src, nframes_t cnt);
-
- virtual void handle_header_position_change ();
-
- private:
- static nframes_t xfade_frames;
- static gain_t* out_coefficient;
- static gain_t* in_coefficient;
-
- bool _capture_start;
- bool _capture_end;
- nframes_t capture_start_frame;
- nframes_t file_pos; // unit is frames
- Sample* xfade_buf;
-
- void init ();
- nframes_t crossfade (Sample* data, nframes_t cnt, int dir);
- void set_timeline_position (int64_t);
-};
-
-}
-
-#endif /* __ardour_destructive_file_source_h__ */
diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h
index a81921b9f1..10b3bbfe92 100644
--- a/libs/ardour/ardour/diskstream.h
+++ b/libs/ardour/ardour/diskstream.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: diskstream.h 579 2006-06-12 19:56:37Z essej $
*/
#ifndef __ardour_diskstream_h__
@@ -54,7 +53,7 @@ class Session;
class Playlist;
class IO;
- class Diskstream : public PBD::StatefulDestructible
+class Diskstream : public PBD::StatefulDestructible
{
public:
enum Flag {
@@ -199,7 +198,6 @@ class IO;
/** For non-butler contexts (allocates temporary working buffers) */
virtual int do_refill_with_alloc() = 0;
-
/* XXX fix this redundancy ... */
@@ -207,7 +205,6 @@ class IO;
virtual void playlist_modified ();
virtual void playlist_deleted (boost::weak_ptr<Playlist>);
- virtual void finish_capture (bool rec_monitors_input) = 0;
virtual void transport_stopped (struct tm&, time_t, bool abort) = 0;
struct CaptureInfo {
@@ -236,7 +233,7 @@ class IO;
virtual void use_destructive_playlist () {}
static nframes_t disk_io_chunk_frames;
- vector<CaptureInfo*> capture_info;
+ std::vector<CaptureInfo*> capture_info;
Glib::Mutex capture_info_lock;
uint32_t i_am_the_modifier;
diff --git a/libs/ardour/ardour/export.h b/libs/ardour/ardour/export.h
index f66acec893..66e5b1b7d5 100644
--- a/libs/ardour/ardour/export.h
+++ b/libs/ardour/ardour/export.h
@@ -76,9 +76,9 @@ namespace ARDOUR
/* shared between UI thread and audio thread */
- float progress; /* audio thread sets this */
- bool stop; /* UI sets this */
- bool running; /* audio thread sets to false when export is done */
+ volatile float progress; /* audio thread sets this */
+ volatile bool stop; /* UI sets this */
+ volatile bool running; /* audio thread sets to false when export is done */
int status;
diff --git a/libs/ardour/ardour/gain.h b/libs/ardour/ardour/gain.h
index 3613ea1a5a..5832f71101 100644
--- a/libs/ardour/ardour/gain.h
+++ b/libs/ardour/ardour/gain.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gain_h__
diff --git a/libs/ardour/ardour/gdither.h b/libs/ardour/ardour/gdither.h
index 51343b13c4..67efcc3583 100644
--- a/libs/ardour/ardour/gdither.h
+++ b/libs/ardour/ardour/gdither.h
@@ -15,7 +15,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id$
*/
#ifndef GDITHER_H
diff --git a/libs/ardour/ardour/gdither_types.h b/libs/ardour/ardour/gdither_types.h
index 46feb55fbc..bcc0097d7f 100644
--- a/libs/ardour/ardour/gdither_types.h
+++ b/libs/ardour/ardour/gdither_types.h
@@ -15,7 +15,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id$
*/
#ifndef GDITHER_TYPES_H
diff --git a/libs/ardour/ardour/gdither_types_internal.h b/libs/ardour/ardour/gdither_types_internal.h
index 55d5792833..e73a256310 100644
--- a/libs/ardour/ardour/gdither_types_internal.h
+++ b/libs/ardour/ardour/gdither_types_internal.h
@@ -15,7 +15,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id$
*/
#ifndef GDITHER_TYPES_H
diff --git a/libs/ardour/ardour/insert.h b/libs/ardour/ardour/insert.h
index 31e59e6704..e58cb71754 100644
--- a/libs/ardour/ardour/insert.h
+++ b/libs/ardour/ardour/insert.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_insert_h__
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index c4df46415b..51423e9ab2 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_io_h__
@@ -113,7 +112,8 @@ class IO : public PBD::StatefulDestructible
Panner& panner() { return *_panner; }
PeakMeter& peak_meter() { return *_meter; }
-
+ const Panner& panner() const { return *_panner; }
+
int ensure_io (ChanCount in, ChanCount out, bool clear, void *src);
int use_input_connection (Connection&, void *src);
diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h
index 27e8bc5e84..f1f1bb8811 100644
--- a/libs/ardour/ardour/ladspa_plugin.h
+++ b/libs/ardour/ardour/ladspa_plugin.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_ladspa_plugin_h__
diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h
index 57e13de5af..6625b7dbf5 100644
--- a/libs/ardour/ardour/location.h
+++ b/libs/ardour/ardour/location.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_location_h__
@@ -159,11 +158,11 @@ class Locations : public PBD::StatefulDestructible
int set_current (Location *, bool want_lock = true);
Location *current () const { return current_location; }
- Location *first_location_before (nframes_t);
- Location *first_location_after (nframes_t);
+ Location *first_location_before (nframes_t, bool include_special_ranges = false);
+ Location *first_location_after (nframes_t, bool include_special_ranges = false);
- nframes_t first_mark_before (nframes_t);
- nframes_t first_mark_after (nframes_t);
+ nframes_t first_mark_before (nframes_t, bool include_special_ranges = false);
+ nframes_t first_mark_after (nframes_t, bool include_special_ranges = false);
sigc::signal<void,Location*> current_changed;
sigc::signal<void> changed;
diff --git a/libs/ardour/ardour/logcurve.h b/libs/ardour/ardour/logcurve.h
index ac60a10fd7..dd58263313 100644
--- a/libs/ardour/ardour/logcurve.h
+++ b/libs/ardour/ardour/logcurve.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_logcurve_h__
diff --git a/libs/ardour/ardour/mix.h b/libs/ardour/ardour/mix.h
index 653b61cb95..5555f5437e 100644
--- a/libs/ardour/ardour/mix.h
+++ b/libs/ardour/ardour/mix.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_mix_h__
#define __ardour_mix_h__
@@ -28,7 +27,7 @@
extern "C" {
/* SSE functions */
- float x86_sse_compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current);
+ float x86_sse_compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current);
void x86_sse_apply_gain_to_buffer (ARDOUR::Sample *buf, nframes_t nframes, float gain);
@@ -37,9 +36,11 @@ extern "C" {
void x86_sse_mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, nframes_t nframes);
}
+void x86_sse_find_peaks (ARDOUR::Sample *buf, nframes_t nsamples, float *min, float *max);
+
/* debug wrappers for SSE functions */
-float debug_compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current);
+float debug_compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current);
void debug_apply_gain_to_buffer (ARDOUR::Sample *buf, nframes_t nframes, float gain);
@@ -53,6 +54,8 @@ void debug_mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, nfra
float veclib_compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current);
+void veclib_find_peaks (ARDOUR::Sample *buf, nframes_t nsamples, float *min, float *max);
+
void veclib_apply_gain_to_buffer (ARDOUR::Sample *buf, nframes_t nframes, float gain);
void veclib_mix_buffers_with_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, nframes_t nframes, float gain);
@@ -63,12 +66,14 @@ void veclib_mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src
/* non-optimized functions */
-float compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current);
+float compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current);
+
+void find_peaks (ARDOUR::Sample *buf, nframes_t nsamples, float *min, float *max);
-void apply_gain_to_buffer (ARDOUR::Sample *buf, nframes_t nframes, float gain);
+void apply_gain_to_buffer (ARDOUR::Sample *buf, nframes_t nframes, float gain);
-void mix_buffers_with_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, nframes_t nframes, float gain);
+void mix_buffers_with_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, nframes_t nframes, float gain);
-void mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, nframes_t nframes);
+void mix_buffers_no_gain (ARDOUR::Sample *dst, ARDOUR::Sample *src, nframes_t nframes);
#endif /* __ardour_mix_h__ */
diff --git a/libs/ardour/ardour/named_selection.h b/libs/ardour/ardour/named_selection.h
index fd5777ccf6..7636099e1f 100644
--- a/libs/ardour/ardour/named_selection.h
+++ b/libs/ardour/ardour/named_selection.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_named_selection_h__
diff --git a/libs/ardour/ardour/osc.h b/libs/ardour/ardour/osc.h
index 0a34f44a41..ca2f4488dd 100644
--- a/libs/ardour/ardour/osc.h
+++ b/libs/ardour/ardour/osc.h
@@ -15,7 +15,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * $Id$
*/
#ifndef ardour_osc_h
diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h
index 79bff7d2a5..9d6a7e7fb6 100644
--- a/libs/ardour/ardour/panner.h
+++ b/libs/ardour/ardour/panner.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_panner_h__
diff --git a/libs/ardour/ardour/pcm_utils.h b/libs/ardour/ardour/pcm_utils.h
index 6866e53251..5e6436cc94 100644
--- a/libs/ardour/ardour/pcm_utils.h
+++ b/libs/ardour/ardour/pcm_utils.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_pcm_utils_h__
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index 9893f7391a..54863b6fb0 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_playlist_h__
diff --git a/libs/ardour/ardour/playlist_templates.h b/libs/ardour/ardour/playlist_templates.h
index 603e0bef37..bf072a71c1 100644
--- a/libs/ardour/ardour/playlist_templates.h
+++ b/libs/ardour/ardour/playlist_templates.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_playlist_templates_h__
diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h
index 431b55db8b..feb86f1b7b 100644
--- a/libs/ardour/ardour/plugin.h
+++ b/libs/ardour/ardour/plugin.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_plugin_h__
diff --git a/libs/ardour/ardour/plugin_manager.h b/libs/ardour/ardour/plugin_manager.h
index 8e6c0bd1c7..b4d2e5e99d 100644
--- a/libs/ardour/ardour/plugin_manager.h
+++ b/libs/ardour/ardour/plugin_manager.h
@@ -7,7 +7,6 @@
#include <ardour/types.h>
#include <ardour/plugin.h>
-#include <ardour/audio_unit.h>
namespace ARDOUR {
diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h
index 4e4ad0fec6..7891a0e6f2 100644
--- a/libs/ardour/ardour/port.h
+++ b/libs/ardour/ardour/port.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_port_h__
diff --git a/libs/ardour/ardour/redirect.h b/libs/ardour/ardour/redirect.h
index 8c3de09c10..fac2241f14 100644
--- a/libs/ardour/ardour/redirect.h
+++ b/libs/ardour/ardour/redirect.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_redirect_h__
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index 46865d8357..716c7dec20 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_region_h__
diff --git a/libs/ardour/ardour/reverse.h b/libs/ardour/ardour/reverse.h
index c60df990f2..3296c77c62 100644
--- a/libs/ardour/ardour/reverse.h
+++ b/libs/ardour/ardour/reverse.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_reverse_h__
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 2f94e0c80a..70091ef85d 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_route_h__
@@ -78,8 +77,8 @@ class Route : public IO
std::string comment() { return _comment; }
void set_comment (std::string str, void *src);
- long order_key(std::string name) const;
- void set_order_key (std::string name, long n);
+ long order_key (const char* name) const;
+ void set_order_key (const char* name, long n);
bool hidden() const { return _flags & Hidden; }
bool master() const { return _flags & MasterOut; }
@@ -121,6 +120,7 @@ class Route : public IO
void set_mute (bool yn, void *src);
bool muted() const { return _muted; }
+ bool solo_muted() const { return desired_solo_gain == 0.0; }
void set_mute_config (mute_type, bool, void *src);
bool get_mute_config (mute_type);
@@ -256,7 +256,6 @@ class Route : public IO
bool _muted : 1;
bool _soloed : 1;
- bool _solo_muted : 1;
bool _solo_safe : 1;
bool _recordable : 1;
bool _active : 1;
@@ -324,7 +323,16 @@ class Route : public IO
void init ();
static uint32_t order_key_cnt;
- typedef std::map<std::string,long> OrderKeys;
+
+ struct ltstr
+ {
+ bool operator()(const char* s1, const char* s2) const
+ {
+ return strcmp(s1, s2) < 0;
+ }
+ };
+
+ typedef std::map<const char*,long,ltstr> OrderKeys;
OrderKeys order_keys;
void input_change_handler (IOChange, void *src);
diff --git a/libs/ardour/ardour/route_group.h b/libs/ardour/ardour/route_group.h
index d87d3fa3a4..55448df45b 100644
--- a/libs/ardour/ardour/route_group.h
+++ b/libs/ardour/ardour/route_group.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_route_group_h__
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index eceb301bf8..d4c0572811 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_send_h__
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 63fa608499..2022b21a05 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -1,22 +1,21 @@
- /*
- Copyright (C) 2000 Paul Davis
+/*
+ Copyright (C) 2000 Paul Davis
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
- */
+*/
#ifndef __ardour_session_h__
#define __ardour_session_h__
@@ -176,7 +175,7 @@ class Session : public PBD::StatefulDestructible
Route* route;
};
- boost::shared_ptr<Region> region;
+ boost::shared_ptr<Region> region;
list<AudioRange> audio_range;
list<MusicRange> music_range;
@@ -248,6 +247,7 @@ class Session : public PBD::StatefulDestructible
string name() const { return _name; }
string snap_name() const { return _current_snapshot_name; }
string raid_path () const;
+ string export_dir () const;
void set_snap_name ();
@@ -491,6 +491,8 @@ class Session : public PBD::StatefulDestructible
void resort_routes ();
void resort_routes_using (boost::shared_ptr<RouteList>);
+ void set_remote_control_ids();
+
AudioEngine &engine() { return _engine; };
int32_t max_level;
@@ -591,13 +593,14 @@ class Session : public PBD::StatefulDestructible
int start_audio_export (ARDOUR::AudioExportSpecification&);
int stop_audio_export (ARDOUR::AudioExportSpecification&);
-
+ void finalize_audio_export ();
+
void add_source (boost::shared_ptr<Source>);
void remove_source (boost::weak_ptr<Source>);
struct cleanup_report {
vector<string> paths;
- int32_t space;
+ int64_t space;
};
int cleanup_sources (cleanup_report&);
@@ -626,6 +629,7 @@ class Session : public PBD::StatefulDestructible
boost::shared_ptr<MidiSource> create_midi_source_for_session (ARDOUR::MidiDiskstream&);
boost::shared_ptr<Source> source_by_id (const PBD::ID&);
+ boost::shared_ptr<Source> source_by_path_and_channel (const Glib::ustring&, uint16_t);
/* playlist management */
@@ -683,6 +687,7 @@ class Session : public PBD::StatefulDestructible
void set_all_mute (bool);
sigc::signal<void,bool> SoloActive;
+ sigc::signal<void> SoloChanged;
void record_disenable_all ();
void record_enable_all ();
@@ -740,6 +745,8 @@ class Session : public PBD::StatefulDestructible
void deliver_midi (MIDI::Port*, MIDI::byte*, int32_t size);
+ void set_mmc_device_id (uint32_t id);
+
/* Scrubbing */
void start_scrub (nframes_t where);
@@ -920,12 +927,14 @@ class Session : public PBD::StatefulDestructible
void* ptr,
float opt);
- typedef float (*compute_peak_t) (Sample *, nframes_t, float);
+ typedef float (*compute_peak_t) (Sample *, nframes_t, float);
+ typedef void (*find_peaks_t) (Sample *, nframes_t, float *, float*);
typedef void (*apply_gain_to_buffer_t) (Sample *, nframes_t, float);
typedef void (*mix_buffers_with_gain_t) (Sample *, Sample *, nframes_t, float);
typedef void (*mix_buffers_no_gain_t) (Sample *, Sample *, nframes_t);
- static compute_peak_t compute_peak;
+ static compute_peak_t compute_peak;
+ static find_peaks_t find_peaks;
static apply_gain_to_buffer_t apply_gain_to_buffer;
static mix_buffers_with_gain_t mix_buffers_with_gain;
static mix_buffers_no_gain_t mix_buffers_no_gain;
@@ -1283,8 +1292,7 @@ class Session : public PBD::StatefulDestructible
void mmc_record_pause (MIDI::MachineControl &);
void mmc_record_strobe (MIDI::MachineControl &);
void mmc_record_exit (MIDI::MachineControl &);
- void mmc_track_record_status (MIDI::MachineControl &,
- uint32_t track, bool enabled);
+ void mmc_track_record_status (MIDI::MachineControl &, uint32_t track, bool enabled);
void mmc_fast_forward (MIDI::MachineControl &);
void mmc_rewind (MIDI::MachineControl &);
void mmc_locate (MIDI::MachineControl &, const MIDI::byte *);
@@ -1566,7 +1574,9 @@ class Session : public PBD::StatefulDestructible
static const char* dead_sound_dir_name;
static const char* interchange_dir_name;
static const char* peak_dir_name;
-
+ static const char* export_dir_name;
+
+ string old_sound_dir (bool with_path = true) const;
string discover_best_sound_dir (bool destructive = false);
int ensure_sound_dir (string, string&);
void refresh_disk_space ();
diff --git a/libs/ardour/ardour/session_connection.h b/libs/ardour/ardour/session_connection.h
index addc896b0b..d5e32c7904 100644
--- a/libs/ardour/ardour/session_connection.h
+++ b/libs/ardour/ardour/session_connection.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_session_connection_h__
diff --git a/libs/ardour/ardour/session_playlist.h b/libs/ardour/ardour/session_playlist.h
index 20cf4d8f2e..baeb74916d 100644
--- a/libs/ardour/ardour/session_playlist.h
+++ b/libs/ardour/ardour/session_playlist.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_session_playlist_h__
diff --git a/libs/ardour/ardour/session_route.h b/libs/ardour/ardour/session_route.h
index feacc14775..0c70bf407d 100644
--- a/libs/ardour/ardour/session_route.h
+++ b/libs/ardour/ardour/session_route.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_session_route_h__
diff --git a/libs/ardour/ardour/session_selection.h b/libs/ardour/ardour/session_selection.h
index a110c2c3da..4169a3a511 100644
--- a/libs/ardour/ardour/session_selection.h
+++ b/libs/ardour/ardour/session_selection.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_session_named_selection_h__
diff --git a/libs/ardour/ardour/silentfilesource.h b/libs/ardour/ardour/silentfilesource.h
new file mode 100644
index 0000000000..92ef076a9b
--- /dev/null
+++ b/libs/ardour/ardour/silentfilesource.h
@@ -0,0 +1,66 @@
+/*
+ Copyright (C) 2007 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_silentfilesource_h__
+#define __ardour_silentfilesource_h__
+
+#include <ardour/audiofilesource.h>
+
+namespace ARDOUR {
+
+class SilentFileSource : public AudioFileSource {
+ public:
+ virtual ~SilentFileSource ();
+
+ int update_header (nframes_t when, struct tm&, time_t) { return 0; }
+ int flush_header () { return 0; }
+ float sample_rate () const { return _sample_rate; }
+
+ void set_length (nframes_t len);
+
+ int read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit) const {
+ memset (peaks, 0, sizeof (PeakData) * npeaks);
+ return 0;
+ }
+
+ bool destructive() const { return false; }
+
+ protected:
+
+ float _sample_rate;
+
+ SilentFileSource (Session&, const XMLNode&, nframes_t nframes, float sample_rate);
+
+ friend class SourceFactory;
+
+ nframes_t read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const {
+ memset (dst, 0, sizeof (Sample) * cnt);
+ return cnt;
+ }
+
+ nframes_t write_unlocked (Sample *dst, nframes_t cnt) { return 0; }
+
+ void set_header_timeline_position () {}
+
+};
+
+} // namespace ARDOUR
+
+#endif /* __ardour_audiofilesource_h__ */
+
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h
index d4a7e2f22a..170facb1de 100644
--- a/libs/ardour/ardour/slave.h
+++ b/libs/ardour/ardour/slave.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_slave_h__
@@ -70,6 +69,7 @@ class MTC_Slave : public Slave, public sigc::trackable {
Session& session;
MIDI::Port* port;
std::vector<sigc::connection> connections;
+ bool can_notify_on_unknown_rate;
struct SafeTime {
diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h
index a5000a4b63..2fc3872887 100644
--- a/libs/ardour/ardour/sndfilesource.h
+++ b/libs/ardour/ardour/sndfilesource.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __sndfile_source_h__
@@ -31,11 +30,11 @@ class SndFileSource : public AudioFileSource {
public:
/* constructor to be called for existing external-to-session files */
- SndFileSource (Session&, std::string path, int chn, Flag flags);
+ SndFileSource (Session&, Glib::ustring path, int chn, Flag flags);
/* constructor to be called for new in-session files */
- SndFileSource (Session&, std::string path, SampleFormat samp_format, HeaderFormat hdr_format, nframes_t rate,
+ SndFileSource (Session&, Glib::ustring path, SampleFormat samp_format, HeaderFormat hdr_format, nframes_t rate,
Flag flags = SndFileSource::default_writable_flags);
/* constructor to be called for existing in-session files */
@@ -60,7 +59,7 @@ class SndFileSource : public AudioFileSource {
static void setup_standard_crossfades (nframes_t sample_rate);
static const AudioFileSource::Flag default_writable_flags;
- static int get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg);
+ static int get_soundfile_info (const Glib::ustring& path, SoundFileInfo& _info, string& error_msg);
protected:
void set_header_timeline_position ();
diff --git a/libs/ardour/ardour/soundseq.h b/libs/ardour/ardour/soundseq.h
index 4a318e9750..c7157428ee 100644
--- a/libs/ardour/ardour/soundseq.h
+++ b/libs/ardour/ardour/soundseq.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __soundseq_h__
diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h
index 8eaab14ec5..45c91950fc 100644
--- a/libs/ardour/ardour/source.h
+++ b/libs/ardour/ardour/source.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_source_h__
diff --git a/libs/ardour/ardour/source_factory.h b/libs/ardour/ardour/source_factory.h
index b69645b031..a8b0ae54a3 100644
--- a/libs/ardour/ardour/source_factory.h
+++ b/libs/ardour/ardour/source_factory.h
@@ -20,8 +20,8 @@ class SourceFactory {
static sigc::signal<void,boost::shared_ptr<Source> > SourceCreated;
static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
+ static boost::shared_ptr<Source> createSilent (Session&, const XMLNode& node, nframes_t nframes, float sample_rate);
- // MIDI sources will have to be hacked in here somehow
static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string path, int chn, AudioFileSource::Flag flags, bool announce = true);
static boost::shared_ptr<Source> createWritable (DataType type, Session&, std::string name, bool destructive, nframes_t rate, bool announce = true);
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index f8751b5d2b..5e3e93e48b 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_tempo_h__
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 30cdcd8232..b155965cab 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_types_h__
@@ -265,6 +264,12 @@ namespace ARDOUR {
ExternalMonitoring,
};
+ enum RemoteModel {
+ UserOrdered,
+ MixerOrdered,
+ EditorOrdered,
+ };
+
enum CrossfadeModel {
FullCrossfade,
ShortCrossfade
@@ -346,6 +351,7 @@ std::istream& operator>>(std::istream& o, ARDOUR::HeaderFormat& sf);
std::istream& operator>>(std::istream& o, ARDOUR::AutoConnectOption& sf);
std::istream& operator>>(std::istream& o, ARDOUR::EditMode& sf);
std::istream& operator>>(std::istream& o, ARDOUR::MonitorModel& sf);
+std::istream& operator>>(std::istream& o, ARDOUR::RemoteModel& sf);
std::istream& operator>>(std::istream& o, ARDOUR::SoloModel& sf);
std::istream& operator>>(std::istream& o, ARDOUR::LayerModel& sf);
std::istream& operator>>(std::istream& o, ARDOUR::CrossfadeModel& sf);
diff --git a/libs/ardour/ardour/utils.h b/libs/ardour/ardour/utils.h
index de97a5c150..20badf5ea1 100644
--- a/libs/ardour/ardour/utils.h
+++ b/libs/ardour/ardour/utils.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_utils_h__
diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h
index 8034341bcc..f7ec486d36 100644
--- a/libs/ardour/ardour/vst_plugin.h
+++ b/libs/ardour/ardour/vst_plugin.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_vst_plugin_h__
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 7165a58b27..eeaa095fbd 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -36,6 +36,7 @@
#include <pbd/xml++.h>
#include <pbd/memento_command.h>
#include <pbd/enumwriter.h>
+#include <pbd/stacktrace.h>
#include <ardour/ardour.h>
#include <ardour/audioengine.h>
@@ -43,7 +44,6 @@
#include <ardour/utils.h>
#include <ardour/configuration.h>
#include <ardour/audiofilesource.h>
-#include <ardour/destructive_filesource.h>
#include <ardour/send.h>
#include <ardour/region_factory.h>
#include <ardour/audioplaylist.h>
@@ -67,6 +67,7 @@ gain_t* AudioDiskstream::_gain_buffer = 0;
AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
: Diskstream(sess, name, flag)
, deprecated_io_node(NULL)
+ , channels (new ChannelList)
{
/* prevent any write sources from being created */
@@ -81,6 +82,7 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream:
AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
: Diskstream(sess, node)
, deprecated_io_node(NULL)
+ , channels (new ChannelList)
{
in_set_state = true;
init (Recordable);
@@ -110,7 +112,7 @@ AudioDiskstream::init (Diskstream::Flag f)
set_block_size (_session.get_block_size());
allocate_temporary_buffers ();
- add_channel ();
+ add_channel (1);
assert(_n_channels == ChanCount(DataType::AUDIO, 1));
}
@@ -119,16 +121,17 @@ AudioDiskstream::~AudioDiskstream ()
notify_callbacks ();
{
- /* don't be holding this lock as we exit the destructor, glib will wince
- visibly since the mutex gets destroyed before we release it.
- */
-
- Glib::Mutex::Lock lm (state_lock);
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- (*chan).release ();
+ RCUWriter<ChannelList> writer (channels);
+ boost::shared_ptr<ChannelList> c = writer.get_copy();
+
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+ delete *chan;
}
- channels.clear();
+
+ c->clear();
}
+
+ channels.flush ();
}
void
@@ -154,37 +157,26 @@ AudioDiskstream::free_working_buffers()
void
AudioDiskstream::non_realtime_input_change ()
{
- {
+ {
Glib::Mutex::Lock lm (state_lock);
if (input_change_pending == NoChange) {
return;
}
- if (input_change_pending & ConfigurationChanged) {
-
+ {
+ RCUWriter<ChannelList> writer (channels);
+ boost::shared_ptr<ChannelList> c = writer.get_copy();
+
+ _n_channels.set(DataType::AUDIO, c->size());
+
if (_io->n_inputs().get(DataType::AUDIO) > _n_channels.get(DataType::AUDIO)) {
-
- // we need to add new channel infos
-
- int diff = _io->n_inputs().get(DataType::AUDIO) - channels.size();
-
- for (int i = 0; i < diff; ++i) {
- add_channel ();
- }
-
- } else if (_io->n_inputs().get(DataType::AUDIO) < _n_channels.get(DataType::AUDIO)) {
-
- // we need to get rid of channels
-
- int diff = channels.size() - _io->n_inputs().get(DataType::AUDIO);
-
- for (int i = 0; i < diff; ++i) {
- remove_channel ();
- }
+ add_channel_to (c, _io->n_inputs().get(DataType::AUDIO) - _n_channels.get(DataType::AUDIO));
+ } else if (_io->n_inputs().get(DataType::AUDIO) < _n_channels.get(DataType::AUDIO)) {
+ remove_channel_from (c, _n_channels.get(DataType::AUDIO) - _io->n_inputs().get(DataType::AUDIO));
}
- }
-
+ }
+
get_input_sources ();
set_capture_offset ();
@@ -194,10 +186,12 @@ AudioDiskstream::non_realtime_input_change ()
} else {
set_align_style_from_io ();
}
-
+
input_change_pending = NoChange;
- }
+ /* implicit unlock */
+ }
+
/* reset capture files */
reset_write_sources (false);
@@ -214,23 +208,26 @@ AudioDiskstream::non_realtime_input_change ()
void
AudioDiskstream::get_input_sources ()
{
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
+ uint32_t n;
+ ChannelList::iterator chan;
uint32_t ni = _io->n_inputs().get(DataType::AUDIO);
-
- for (uint32_t n = 0; n < ni; ++n) {
+
+ for (n = 0, chan = c->begin(); chan != c->end() && n < ni; ++chan, ++n) {
const char **connections = _io->input(n)->get_connections ();
- ChannelInfo& chan = channels[n];
if (connections == 0 || connections[0] == 0) {
- if (chan.source) {
+ if ((*chan)->source) {
// _source->disable_metering ();
}
- chan.source = 0;
+ (*chan)->source = 0;
} else {
- chan.source = dynamic_cast<AudioPort*>(
+ (*chan)->source = dynamic_cast<AudioPort*>(
_session.engine().get_port_by_name (connections[0]) );
}
@@ -324,9 +321,10 @@ void
AudioDiskstream::setup_destructive_playlist ()
{
SourceList srcs;
-
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- srcs.push_back ((*chan).write_source);
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+ srcs.push_back ((*chan)->write_source);
}
/* a single full-sized region */
@@ -363,15 +361,16 @@ AudioDiskstream::use_destructive_playlist ()
uint32_t n;
ChannelList::iterator chan;
+ boost::shared_ptr<ChannelList> c = channels.reader();
- for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
- (*chan).write_source = boost::dynamic_pointer_cast<AudioFileSource>(region->source (n));
- assert((*chan).write_source);
- (*chan).write_source->set_allow_remove_if_empty (false);
+ for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
+ (*chan)->write_source = boost::dynamic_pointer_cast<AudioFileSource>(region->source (n));
+ assert((*chan)->write_source);
+ (*chan)->write_source->set_allow_remove_if_empty (false);
/* this might be false if we switched modes, so force it */
- (*chan).write_source->set_destructive (true);
+ (*chan)->write_source->set_destructive (true);
}
/* the source list will never be reset for a destructive track */
@@ -467,15 +466,16 @@ AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nfram
}
if (_flags & Recordable) {
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
RingBufferNPT<CaptureTransition>::rw_vector transvec;
- (*chan).capture_transition_buf->get_write_vector(&transvec);
+ (*chan)->capture_transition_buf->get_write_vector(&transvec);
if (transvec.len[0] > 0) {
transvec.buf[0]->type = CaptureStart;
transvec.buf[0]->capture_val = capture_start_frame;
- (*chan).capture_transition_buf->increment_write_ptr(1);
+ (*chan)->capture_transition_buf->increment_write_ptr(1);
}
else {
// bad!
@@ -505,7 +505,8 @@ int
AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t offset, bool can_record, bool rec_monitors_input)
{
uint32_t n;
- ChannelList::iterator c;
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ ChannelList::iterator chan;
int ret = -1;
nframes_t rec_offset = 0;
nframes_t rec_nframes = 0;
@@ -542,13 +543,13 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
// If we can't take the state lock return.
if (!state_lock.trylock()) {
return 1;
- }
+ }
adjust_capture_position = 0;
- for (c = channels.begin(); c != channels.end(); ++c) {
- (*c).current_capture_buffer = 0;
- (*c).current_playback_buffer = 0;
+ for (chan = c->begin(); chan != c->end(); ++chan) {
+ (*chan)->current_capture_buffer = 0;
+ (*chan)->current_playback_buffer = 0;
}
if (nominally_recording || (_session.get_record_enabled() && Config->get_punch_in())) {
@@ -609,15 +610,15 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
if (nominally_recording || rec_nframes) {
- for (n = 0, c = channels.begin(); c != channels.end(); ++c, ++n) {
+ for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
- ChannelInfo& chan (*c);
-
- chan.capture_buf->get_write_vector (&chan.capture_vector);
+ ChannelInfo* chaninfo (*chan);
- if (rec_nframes <= chan.capture_vector.len[0]) {
+ chaninfo->capture_buf->get_write_vector (&chaninfo->capture_vector);
+
+ if (rec_nframes <= chaninfo->capture_vector.len[0]) {
- chan.current_capture_buffer = chan.capture_vector.buf[0];
+ chaninfo->current_capture_buffer = chaninfo->capture_vector.buf[0];
/* note: grab the entire port buffer, but only copy what we were supposed to for recording, and use
rec_offset
@@ -626,12 +627,11 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
AudioPort* const ap = _io->audio_input(n);
assert(ap);
assert(rec_nframes <= ap->get_audio_buffer().capacity());
-
- memcpy (chan.current_capture_buffer, ap->get_audio_buffer().data(rec_nframes, offset + rec_offset), sizeof (Sample) * rec_nframes);
+ memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer().data(rec_nframes, offset + rec_offset), sizeof (Sample) * rec_nframes);
} else {
- nframes_t total = chan.capture_vector.len[0] + chan.capture_vector.len[1];
+ nframes_t total = chaninfo->capture_vector.len[0] + chaninfo->capture_vector.len[1];
if (rec_nframes > total) {
DiskOverrun ();
@@ -642,21 +642,21 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
assert(ap);
Sample* buf = ap->get_audio_buffer().data(nframes, offset);
- nframes_t first = chan.capture_vector.len[0];
+ nframes_t first = chaninfo->capture_vector.len[0];
- memcpy (chan.capture_wrap_buffer, buf, sizeof (Sample) * first);
- memcpy (chan.capture_vector.buf[0], buf, sizeof (Sample) * first);
- memcpy (chan.capture_wrap_buffer+first, buf + first, sizeof (Sample) * (rec_nframes - first));
- memcpy (chan.capture_vector.buf[1], buf + first, sizeof (Sample) * (rec_nframes - first));
+ memcpy (chaninfo->capture_wrap_buffer, buf, sizeof (Sample) * first);
+ memcpy (chaninfo->capture_vector.buf[0], buf, sizeof (Sample) * first);
+ memcpy (chaninfo->capture_wrap_buffer+first, buf + first, sizeof (Sample) * (rec_nframes - first));
+ memcpy (chaninfo->capture_vector.buf[1], buf + first, sizeof (Sample) * (rec_nframes - first));
- chan.current_capture_buffer = chan.capture_wrap_buffer;
+ chaninfo->current_capture_buffer = chaninfo->capture_wrap_buffer;
}
}
} else {
if (was_recording) {
- finish_capture (rec_monitors_input);
+ finish_capture (rec_monitors_input, c);
}
}
@@ -667,8 +667,8 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
if (rec_nframes == nframes && rec_offset == 0) {
- for (c = channels.begin(); c != channels.end(); ++c) {
- (*c).current_playback_buffer = (*c).current_capture_buffer;
+ for (chan = c->begin(); chan != c->end(); ++chan) {
+ (*chan)->current_playback_buffer = (*chan)->current_capture_buffer;
}
playback_distance = nframes;
@@ -690,8 +690,8 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
/* can't do actual capture yet - waiting for latency effects to finish before we start*/
- for (c = channels.begin(); c != channels.end(); ++c) {
- (*c).current_playback_buffer = (*c).current_capture_buffer;
+ for (chan = c->begin(); chan != c->end(); ++chan) {
+ (*chan)->current_playback_buffer = (*chan)->current_capture_buffer;
}
playback_distance = nframes;
@@ -715,22 +715,22 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
necessary_samples = nframes;
}
- for (c = channels.begin(); c != channels.end(); ++c) {
- (*c).playback_buf->get_read_vector (&(*c).playback_vector);
+ for (chan = c->begin(); chan != c->end(); ++chan) {
+ (*chan)->playback_buf->get_read_vector (&(*chan)->playback_vector);
}
n = 0;
- for (c = channels.begin(); c != channels.end(); ++c, ++n) {
-
- ChannelInfo& chan (*c);
+ for (chan = c->begin(); chan != c->end(); ++chan, ++n) {
+
+ ChannelInfo* chaninfo (*chan);
- if (necessary_samples <= chan.playback_vector.len[0]) {
+ if (necessary_samples <= chaninfo->playback_vector.len[0]) {
- chan.current_playback_buffer = chan.playback_vector.buf[0];
+ chaninfo->current_playback_buffer = chaninfo->playback_vector.buf[0];
} else {
- nframes_t total = chan.playback_vector.len[0] + chan.playback_vector.len[1];
+ nframes_t total = chaninfo->playback_vector.len[0] + chaninfo->playback_vector.len[1];
if (necessary_samples > total) {
DiskUnderrun ();
@@ -738,12 +738,12 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
} else {
- memcpy ((char *) chan.playback_wrap_buffer, chan.playback_vector.buf[0],
- chan.playback_vector.len[0] * sizeof (Sample));
- memcpy (chan.playback_wrap_buffer + chan.playback_vector.len[0], chan.playback_vector.buf[1],
- (necessary_samples - chan.playback_vector.len[0]) * sizeof (Sample));
+ memcpy ((char *) chaninfo->playback_wrap_buffer, chaninfo->playback_vector.buf[0],
+ chaninfo->playback_vector.len[0] * sizeof (Sample));
+ memcpy (chaninfo->playback_wrap_buffer + chaninfo->playback_vector.len[0], chaninfo->playback_vector.buf[1],
+ (necessary_samples - chaninfo->playback_vector.len[0]) * sizeof (Sample));
- chan.current_playback_buffer = chan.playback_wrap_buffer;
+ chaninfo->current_playback_buffer = chaninfo->playback_wrap_buffer;
}
}
}
@@ -756,10 +756,10 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
// Linearly interpolate into the alt buffer
// using 40.24 fixp maths (swh)
- for (c = channels.begin(); c != channels.end(); ++c) {
+ for (chan = c->begin(); chan != c->end(); ++chan) {
float fr;
- ChannelInfo& chan (*c);
+ ChannelInfo* chaninfo (*chan);
i = 0;
phase = last_phase;
@@ -767,13 +767,13 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
for (nframes_t outsample = 0; outsample < nframes; ++outsample) {
i = phase >> 24;
fr = (phase & 0xFFFFFF) / 16777216.0f;
- chan.speed_buffer[outsample] =
- chan.current_playback_buffer[i] * (1.0f - fr) +
- chan.current_playback_buffer[i+1] * fr;
+ chaninfo->speed_buffer[outsample] =
+ chaninfo->current_playback_buffer[i] * (1.0f - fr) +
+ chaninfo->current_playback_buffer[i+1] * fr;
phase += phi;
}
- chan.current_playback_buffer = chan.speed_buffer;
+ chaninfo->current_playback_buffer = chaninfo->speed_buffer;
}
playback_distance = i + 1;
@@ -813,12 +813,13 @@ AudioDiskstream::commit (nframes_t nframes)
playback_sample += playback_distance;
}
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- (*chan).playback_buf->increment_read_ptr (playback_distance);
+ (*chan)->playback_buf->increment_read_ptr (playback_distance);
if (adjust_capture_position) {
- (*chan).capture_buf->increment_write_ptr (adjust_capture_position);
+ (*chan)->capture_buf->increment_write_ptr (adjust_capture_position);
}
}
@@ -828,14 +829,13 @@ AudioDiskstream::commit (nframes_t nframes)
}
if (_slaved) {
- need_butler = channels[0].playback_buf->write_space() >= channels[0].playback_buf->bufsize() / 2;
+ need_butler = c->front()->playback_buf->write_space() >= c->front()->playback_buf->bufsize() / 2;
} else {
- need_butler = channels[0].playback_buf->write_space() >= disk_io_chunk_frames
- || channels[0].capture_buf->read_space() >= disk_io_chunk_frames;
+ need_butler = c->front()->playback_buf->write_space() >= disk_io_chunk_frames
+ || c->front()->capture_buf->read_space() >= disk_io_chunk_frames;
}
state_lock.unlock();
-
_processed = false;
return need_butler;
@@ -849,12 +849,13 @@ AudioDiskstream::set_pending_overwrite (bool yn)
pending_overwrite = yn;
overwrite_frame = playback_sample;
- overwrite_offset = channels.front().playback_buf->get_read_ptr();
+ overwrite_offset = channels.reader()->front()->playback_buf->get_read_ptr();
}
int
AudioDiskstream::overwrite_existing_buffers ()
{
+ boost::shared_ptr<ChannelList> c = channels.reader();
Sample* mixdown_buffer;
float* gain_buffer;
int ret = -1;
@@ -863,7 +864,7 @@ AudioDiskstream::overwrite_existing_buffers ()
overwrite_queued = false;
/* assume all are the same size */
- nframes_t size = channels[0].playback_buf->bufsize();
+ nframes_t size = c->front()->playback_buf->bufsize();
mixdown_buffer = new Sample[size];
gain_buffer = new float[size];
@@ -874,7 +875,7 @@ AudioDiskstream::overwrite_existing_buffers ()
uint32_t n=0;
nframes_t start;
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++n) {
start = overwrite_frame;
nframes_t cnt = size;
@@ -892,7 +893,7 @@ AudioDiskstream::overwrite_existing_buffers ()
nframes_t to_read = size - overwrite_offset;
- if (read ((*chan).playback_buf->buffer() + overwrite_offset, mixdown_buffer, gain_buffer, start, to_read, *chan, n, reversed)) {
+ if (read ((*chan)->playback_buf->buffer() + overwrite_offset, mixdown_buffer, gain_buffer, start, to_read, *chan, n, reversed)) {
error << string_compose(_("AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"),
_id, size, playback_sample) << endmsg;
goto out;
@@ -902,7 +903,7 @@ AudioDiskstream::overwrite_existing_buffers ()
cnt -= to_read;
- if (read ((*chan).playback_buf->buffer(), mixdown_buffer, gain_buffer,
+ if (read ((*chan)->playback_buf->buffer(), mixdown_buffer, gain_buffer,
start, cnt, *chan, n, reversed)) {
error << string_compose(_("AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"),
_id, size, playback_sample) << endmsg;
@@ -923,25 +924,27 @@ AudioDiskstream::overwrite_existing_buffers ()
int
AudioDiskstream::seek (nframes_t frame, bool complete_refill)
{
- Glib::Mutex::Lock lm (state_lock);
uint32_t n;
int ret = -1;
ChannelList::iterator chan;
+ boost::shared_ptr<ChannelList> c = channels.reader();
- for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
- (*chan).playback_buf->reset ();
- (*chan).capture_buf->reset ();
+ Glib::Mutex::Lock lm (state_lock);
+
+ for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
+ (*chan)->playback_buf->reset ();
+ (*chan)->capture_buf->reset ();
}
/* can't rec-enable in destructive mode if transport is before start */
-
+
if (destructive() && record_enabled() && frame < _session.current_start_frame()) {
disengage_record_enable ();
}
-
+
playback_sample = frame;
file_frame = frame;
-
+
if (complete_refill) {
while ((ret = do_refill_with_alloc ()) > 0) ;
} else {
@@ -955,9 +958,10 @@ int
AudioDiskstream::can_internal_playback_seek (nframes_t distance)
{
ChannelList::iterator chan;
+ boost::shared_ptr<ChannelList> c = channels.reader();
- for (chan = channels.begin(); chan != channels.end(); ++chan) {
- if ((*chan).playback_buf->read_space() < distance) {
+ for (chan = c->begin(); chan != c->end(); ++chan) {
+ if ((*chan)->playback_buf->read_space() < distance) {
return false;
}
}
@@ -968,9 +972,10 @@ int
AudioDiskstream::internal_playback_seek (nframes_t distance)
{
ChannelList::iterator chan;
+ boost::shared_ptr<ChannelList> c = channels.reader();
- for (chan = channels.begin(); chan != channels.end(); ++chan) {
- (*chan).playback_buf->increment_read_ptr (distance);
+ for (chan = c->begin(); chan != c->end(); ++chan) {
+ (*chan)->playback_buf->increment_read_ptr (distance);
}
first_recordable_frame += distance;
@@ -981,7 +986,7 @@ AudioDiskstream::internal_playback_seek (nframes_t distance)
int
AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, nframes_t& start, nframes_t cnt,
- ChannelInfo& channel_info, int channel, bool reversed)
+ ChannelInfo* channel_info, int channel, bool reversed)
{
nframes_t this_read = 0;
bool reloop = false;
@@ -991,7 +996,10 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
nframes_t offset = 0;
Location *loc = 0;
+ /* XXX we don't currently play loops in reverse. not sure why */
+
if (!reversed) {
+
/* Make the use of a Location atomic for this read operation.
Note: Locations don't get deleted, so all we care about
@@ -1015,11 +1023,16 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
start = loop_start + ((start - loop_start) % loop_length);
//cerr << "to " << start << endl;
}
+
//cerr << "start is " << start << " loopstart: " << loop_start << " loopend: " << loop_end << endl;
}
while (cnt) {
+ if (reversed) {
+ start -= cnt;
+ }
+
/* take any loop into account. we can't read past the end of the loop. */
if (loc && (loop_end - start < cnt)) {
@@ -1047,9 +1060,6 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
if (reversed) {
- /* don't adjust start, since caller has already done that
- */
-
swap_by_ptr (buf, buf + this_read - 1);
} else {
@@ -1071,7 +1081,7 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
}
int
-AudioDiskstream::do_refill_with_alloc()
+AudioDiskstream::do_refill_with_alloc ()
{
Sample* mix_buf = new Sample[disk_io_chunk_frames];
float* gain_buf = new float[disk_io_chunk_frames];
@@ -1095,17 +1105,27 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
nframes_t zero_fill;
uint32_t chan_n;
ChannelList::iterator i;
+ boost::shared_ptr<ChannelList> c = channels.reader();
nframes_t ts;
+ if (c->empty()) {
+ return 0;
+ }
+
assert(mixdown_buffer);
assert(gain_buffer);
- channels.front().playback_buf->get_write_vector (&vector);
+ vector.buf[0] = 0;
+ vector.len[0] = 0;
+ vector.buf[1] = 0;
+ vector.len[1] = 0;
+
+ c->front()->playback_buf->get_write_vector (&vector);
if ((total_space = vector.len[0] + vector.len[1]) == 0) {
return 0;
}
-
+
/* if there are 2+ chunks of disk i/o possible for
this track, let the caller know so that it can arrange
for us to be called again, ASAP.
@@ -1131,10 +1151,12 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
work with.
*/
- if (_slaved && total_space < (channels.front().playback_buf->bufsize() / 2)) {
+ if (_slaved && total_space < (c->front()->playback_buf->bufsize() / 2)) {
return 0;
}
+ /* never do more than disk_io_chunk_frames worth of disk input per call (limit doesn't apply for memset) */
+
total_space = min (disk_io_chunk_frames, total_space);
if (reversed) {
@@ -1143,15 +1165,15 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
/* at start: nothing to do but fill with silence */
- for (chan_n = 0, i = channels.begin(); i != channels.end(); ++i, ++chan_n) {
+ for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
- ChannelInfo& chan (*i);
- chan.playback_buf->get_write_vector (&vector);
+ ChannelInfo* chan (*i);
+ chan->playback_buf->get_write_vector (&vector);
memset (vector.buf[0], 0, sizeof(Sample) * vector.len[0]);
if (vector.len[1]) {
memset (vector.buf[1], 0, sizeof(Sample) * vector.len[1]);
}
- chan.playback_buf->increment_write_ptr (vector.len[0] + vector.len[1]);
+ chan->playback_buf->increment_write_ptr (vector.len[0] + vector.len[1]);
}
return 0;
}
@@ -1168,11 +1190,6 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
} else {
- /* move read position backwards because we are going
- to reverse the data.
- */
-
- file_frame -= total_space;
zero_fill = 0;
}
@@ -1182,15 +1199,15 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
/* at end: nothing to do but fill with silence */
- for (chan_n = 0, i = channels.begin(); i != channels.end(); ++i, ++chan_n) {
+ for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
- ChannelInfo& chan (*i);
- chan.playback_buf->get_write_vector (&vector);
+ ChannelInfo* chan (*i);
+ chan->playback_buf->get_write_vector (&vector);
memset (vector.buf[0], 0, sizeof(Sample) * vector.len[0]);
if (vector.len[1]) {
memset (vector.buf[1], 0, sizeof(Sample) * vector.len[1]);
}
- chan.playback_buf->increment_write_ptr (vector.len[0] + vector.len[1]);
+ chan->playback_buf->increment_write_ptr (vector.len[0] + vector.len[1]);
}
return 0;
}
@@ -1209,30 +1226,45 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
nframes_t file_frame_tmp = 0;
- for (chan_n = 0, i = channels.begin(); i != channels.end(); ++i, ++chan_n) {
+ for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
- ChannelInfo& chan (*i);
+ ChannelInfo* chan (*i);
Sample* buf1;
Sample* buf2;
nframes_t len1, len2;
- chan.playback_buf->get_write_vector (&vector);
+ chan->playback_buf->get_write_vector (&vector);
+
+ if (vector.len[0] > disk_io_chunk_frames) {
+
+ /* we're not going to fill the first chunk, so certainly do not bother with the
+ other part. it won't be connected with the part we do fill, as in:
+
+ .... => writable space
+ ++++ => readable space
+ ^^^^ => 1 x disk_io_chunk_frames that would be filled
+
+ |......|+++++++++++++|...............................|
+ buf1 buf0
+ ^^^^^^^^^^^^^^^
+
+
+ So, just pretend that the buf1 part isn't there.
+
+ */
+
+ vector.buf[1] = 0;
+ vector.len[1] = 0;
+
+ }
ts = total_space;
file_frame_tmp = file_frame;
- if (reversed) {
- buf1 = vector.buf[1];
- len1 = vector.len[1];
- buf2 = vector.buf[0];
- len2 = vector.len[0];
- } else {
- buf1 = vector.buf[0];
- len1 = vector.len[0];
- buf2 = vector.buf[1];
- len2 = vector.len[1];
- }
-
+ buf1 = vector.buf[0];
+ len1 = vector.len[0];
+ buf2 = vector.buf[1];
+ len2 = vector.len[1];
to_read = min (ts, len1);
to_read = min (to_read, disk_io_chunk_frames);
@@ -1243,8 +1275,8 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
ret = -1;
goto out;
}
-
- chan.playback_buf->increment_write_ptr (to_read);
+
+ chan->playback_buf->increment_write_ptr (to_read);
ts -= to_read;
}
@@ -1252,7 +1284,6 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
if (to_read) {
-
/* we read all of vector.len[0], but it wasn't an entire disk_io_chunk_frames of data,
so read some or all of vector.len[1] as well.
*/
@@ -1262,7 +1293,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
goto out;
}
- chan.playback_buf->increment_write_ptr (to_read);
+ chan->playback_buf->increment_write_ptr (to_read);
}
if (zero_fill) {
@@ -1299,13 +1330,18 @@ AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
_write_data_count = 0;
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+ transvec.buf[0] = 0;
+ transvec.buf[1] = 0;
+ vector.buf[0] = 0;
+ vector.buf[1] = 0;
+
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- (*chan).capture_buf->get_read_vector (&vector);
+ (*chan)->capture_buf->get_read_vector (&vector);
total = vector.len[0] + vector.len[1];
-
if (total == 0 || (total < disk_io_chunk_frames && !force_flush && was_recording)) {
goto out;
}
@@ -1331,7 +1367,7 @@ AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
// important that we get this after the capture buf
if (destructive()) {
- (*chan).capture_transition_buf->get_read_vector(&transvec);
+ (*chan)->capture_transition_buf->get_read_vector(&transvec);
size_t transcount = transvec.len[0] + transvec.len[1];
bool have_start = false;
size_t ti;
@@ -1342,8 +1378,8 @@ AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
if (captrans.type == CaptureStart) {
// by definition, the first data we got above represents the given capture pos
- (*chan).write_source->mark_capture_start (captrans.capture_val);
- (*chan).curr_capture_cnt = 0;
+ (*chan)->write_source->mark_capture_start (captrans.capture_val);
+ (*chan)->curr_capture_cnt = 0;
have_start = true;
}
@@ -1351,17 +1387,17 @@ AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
// capture end, the capture_val represents total frames in capture
- if (captrans.capture_val <= (*chan).curr_capture_cnt + to_write) {
+ if (captrans.capture_val <= (*chan)->curr_capture_cnt + to_write) {
// shorten to make the write a perfect fit
- uint32_t nto_write = (captrans.capture_val - (*chan).curr_capture_cnt);
+ uint32_t nto_write = (captrans.capture_val - (*chan)->curr_capture_cnt);
if (nto_write < to_write) {
ret = 1; // should we?
}
to_write = nto_write;
- (*chan).write_source->mark_capture_end ();
+ (*chan)->write_source->mark_capture_end ();
// increment past this transition, but go no further
++ti;
@@ -1376,17 +1412,17 @@ AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
}
if (ti > 0) {
- (*chan).capture_transition_buf->increment_read_ptr(ti);
+ (*chan)->capture_transition_buf->increment_read_ptr(ti);
}
}
- if ((!(*chan).write_source) || (*chan).write_source->write (vector.buf[0], to_write) != to_write) {
+ if ((!(*chan)->write_source) || (*chan)->write_source->write (vector.buf[0], to_write) != to_write) {
error << string_compose(_("AudioDiskstream %1: cannot write to disk"), _id) << endmsg;
return -1;
}
- (*chan).capture_buf->increment_read_ptr (to_write);
- (*chan).curr_capture_cnt += to_write;
+ (*chan)->capture_buf->increment_read_ptr (to_write);
+ (*chan)->curr_capture_cnt += to_write;
if ((to_write == vector.len[0]) && (total > to_write) && (to_write < disk_io_chunk_frames) && !destructive()) {
@@ -1394,18 +1430,18 @@ AudioDiskstream::do_flush (Session::RunContext context, bool force_flush)
disk_io_chunk_frames of data, so arrange for some part
of vector.len[1] to be flushed to disk as well.
*/
-
+
to_write = min ((nframes_t)(disk_io_chunk_frames - to_write), (nframes_t) vector.len[1]);
-
- if ((*chan).write_source->write (vector.buf[1], to_write) != to_write) {
+
+ if ((*chan)->write_source->write (vector.buf[1], to_write) != to_write) {
error << string_compose(_("AudioDiskstream %1: cannot write to disk"), _id) << endmsg;
return -1;
}
- _write_data_count += (*chan).write_source->write_data_count();
+ _write_data_count += (*chan)->write_source->write_data_count();
- (*chan).capture_buf->increment_read_ptr (to_write);
- (*chan).curr_capture_cnt += to_write;
+ (*chan)->capture_buf->increment_read_ptr (to_write);
+ (*chan)->curr_capture_cnt += to_write;
}
}
@@ -1425,10 +1461,11 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
SourceList::iterator src;
ChannelList::iterator chan;
vector<CaptureInfo*>::iterator ci;
+ boost::shared_ptr<ChannelList> c = channels.reader();
uint32_t n = 0;
bool mark_write_completed = false;
- finish_capture (true);
+ finish_capture (true, c);
/* butler is already stopped, but there may be work to do
to flush remaining data to disk.
@@ -1460,13 +1497,13 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
goto outout;
}
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- if ((*chan).write_source) {
+ if ((*chan)->write_source) {
- (*chan).write_source->mark_for_remove ();
- (*chan).write_source->drop_references ();
- (*chan).write_source.reset ();
+ (*chan)->write_source->mark_for_remove ();
+ (*chan)->write_source->drop_references ();
+ (*chan)->write_source.reset ();
}
/* new source set up in "out" below */
@@ -1481,15 +1518,15 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
/* figure out the name for this take */
- for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) {
+ for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
- boost::shared_ptr<AudioFileSource> s = (*chan).write_source;
+ boost::shared_ptr<AudioFileSource> s = (*chan)->write_source;
if (s) {
srcs.push_back (s);
s->update_header (capture_info.front()->start, when, twhen);
s->set_captured_for (_name);
-
+ s->mark_immutable ();
}
}
@@ -1508,7 +1545,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
} else {
string whole_file_region_name;
- whole_file_region_name = region_name_from_path (channels[0].write_source->name(), true);
+ whole_file_region_name = region_name_from_path (c->front()->write_source->name(), true);
/* Register a new region with the Session that
describes the entire source. Do this first
@@ -1517,7 +1554,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
*/
try {
- boost::shared_ptr<Region> rx (RegionFactory::create (srcs, channels[0].write_source->last_capture_start_frame(), total_capture,
+ boost::shared_ptr<Region> rx (RegionFactory::create (srcs, c->front()->write_source->last_capture_start_frame(), total_capture,
whole_file_region_name,
0, AudioRegion::Flag (AudioRegion::DefaultFlags|AudioRegion::Automatic|AudioRegion::WholeFile)));
@@ -1538,7 +1575,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
XMLNode &before = _playlist->get_state();
_playlist->freeze ();
- for (buffer_position = channels[0].write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
+ for (buffer_position = c->front()->write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
string region_name;
@@ -1588,7 +1625,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
}
void
-AudioDiskstream::finish_capture (bool rec_monitors_input)
+AudioDiskstream::finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList> c)
{
was_recording = false;
@@ -1597,16 +1634,16 @@ AudioDiskstream::finish_capture (bool rec_monitors_input)
}
if (recordable() && destructive()) {
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
RingBufferNPT<CaptureTransition>::rw_vector transvec;
- (*chan).capture_transition_buf->get_write_vector(&transvec);
+ (*chan)->capture_transition_buf->get_write_vector(&transvec);
if (transvec.len[0] > 0) {
transvec.buf[0]->type = CaptureEnd;
transvec.buf[0]->capture_val = capture_captured;
- (*chan).capture_transition_buf->increment_write_ptr(1);
+ (*chan)->capture_transition_buf->increment_write_ptr(1);
}
else {
// bad!
@@ -1649,7 +1686,7 @@ AudioDiskstream::set_record_enabled (bool yn)
return;
}
- if (yn && channels[0].source == 0) {
+ if (yn && channels.reader()->front()->source == 0) {
/* pick up connections not initiated *from* the IO object
we're associated with.
@@ -1674,20 +1711,24 @@ AudioDiskstream::set_record_enabled (bool yn)
void
AudioDiskstream::engage_record_enable ()
{
- bool rolling = _session.transport_speed() != 0.0f;
+ bool rolling = _session.transport_speed() != 0.0f;
+ boost::shared_ptr<ChannelList> c = channels.reader();
g_atomic_int_set (&_record_enabled, 1);
capturing_sources.clear ();
+
if (Config->get_monitoring_model() == HardwareMonitoring) {
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- if ((*chan).source) {
- (*chan).source->ensure_monitor_input (!(Config->get_auto_input() && rolling));
+
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+ if ((*chan)->source) {
+ (*chan)->source->ensure_monitor_input (!(Config->get_auto_input() && rolling));
}
- capturing_sources.push_back ((*chan).write_source);
+ capturing_sources.push_back ((*chan)->write_source);
}
+
} else {
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- capturing_sources.push_back ((*chan).write_source);
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+ capturing_sources.push_back ((*chan)->write_source);
}
}
@@ -1698,17 +1739,17 @@ void
AudioDiskstream::disengage_record_enable ()
{
g_atomic_int_set (&_record_enabled, 0);
- if (Config->get_monitoring_model() == HardwareMonitoring) {
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- if ((*chan).source) {
- (*chan).source->ensure_monitor_input (false);
+ boost::shared_ptr<ChannelList> c = channels.reader();
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+ if (Config->get_monitoring_model() == HardwareMonitoring) {
+ if ((*chan)->source) {
+ (*chan)->source->ensure_monitor_input (false);
}
}
}
capturing_sources.clear ();
RecordEnableChanged (); /* EMIT SIGNAL */
}
-
XMLNode&
AudioDiskstream::get_state ()
@@ -1716,10 +1757,11 @@ AudioDiskstream::get_state ()
XMLNode* node = new XMLNode ("AudioDiskstream");
char buf[64] = "";
LocaleGuard lg (X_("POSIX"));
+ boost::shared_ptr<ChannelList> c = channels.reader();
node->add_property ("flags", enum_2_string (_flags));
- snprintf (buf, sizeof(buf), "%zd", channels.size());
+ snprintf (buf, sizeof(buf), "%zd", c->size());
node->add_property ("channels", buf);
node->add_property ("playlist", _playlist->name());
@@ -1814,27 +1856,15 @@ AudioDiskstream::set_state (const XMLNode& node)
// create necessary extra channels
// we are always constructed with one and we always need one
+ _n_channels.set(DataType::AUDIO, channels.reader()->size());
+
if (nchans > _n_channels.get(DataType::AUDIO)) {
- // we need to add new channel infos
- //LockMonitor lm (state_lock, __LINE__, __FILE__);
-
- int diff = nchans - channels.size();
-
- for (int i=0; i < diff; ++i) {
- add_channel ();
- }
+ add_channel (nchans - _n_channels.get(DataType::AUDIO));
} else if (nchans < _n_channels.get(DataType::AUDIO)) {
- // we need to get rid of channels
- //LockMonitor lm (state_lock, __LINE__, __FILE__);
-
- int diff = channels.size() - nchans;
-
- for (int i = 0; i < diff; ++i) {
- remove_channel ();
- }
+ remove_channel (_n_channels.get(DataType::AUDIO) - nchans);
}
if ((prop = node.property ("playlist")) == 0) {
@@ -1870,8 +1900,6 @@ AudioDiskstream::set_state (const XMLNode& node)
}
}
- _n_channels.set(DataType::AUDIO, channels.size());
-
in_set_state = false;
/* make sure this is clear before we do anything else */
@@ -1890,37 +1918,40 @@ AudioDiskstream::set_state (const XMLNode& node)
int
AudioDiskstream::use_new_write_source (uint32_t n)
{
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
if (!recordable()) {
return 1;
}
- if (n >= channels.size()) {
+ if (n >= c->size()) {
error << string_compose (_("AudioDiskstream: channel %1 out of range"), n) << endmsg;
return -1;
}
- ChannelInfo &chan = channels[n];
+ ChannelInfo* chan = (*c)[n];
- if (chan.write_source) {
- chan.write_source->set_allow_remove_if_empty (true);
- chan.write_source.reset ();
+ if (chan->write_source) {
+ chan->write_source->done_with_peakfile_writes ();
+ chan->write_source->set_allow_remove_if_empty (true);
+ chan->write_source.reset ();
}
try {
- if ((chan.write_source = _session.create_audio_source_for_session (*this, n, destructive())) == 0) {
+ if ((chan->write_source = _session.create_audio_source_for_session (*this, n, destructive())) == 0) {
throw failed_constructor();
}
}
catch (failed_constructor &err) {
error << string_compose (_("%1:%2 new capture file not initialized correctly"), _name, n) << endmsg;
- chan.write_source.reset ();
+ chan->write_source.reset ();
return -1;
}
/* do not remove destructive files even if they are empty */
- chan.write_source->set_allow_remove_if_empty (!destructive());
+ chan->write_source->set_allow_remove_if_empty (!destructive());
return 0;
}
@@ -1929,6 +1960,7 @@ void
AudioDiskstream::reset_write_sources (bool mark_write_complete, bool force)
{
ChannelList::iterator chan;
+ boost::shared_ptr<ChannelList> c = channels.reader();
uint32_t n;
if (!recordable()) {
@@ -1937,20 +1969,20 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool force)
capturing_sources.clear ();
- for (chan = channels.begin(), n = 0; chan != channels.end(); ++chan, ++n) {
+ for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
if (!destructive()) {
- if ((*chan).write_source && mark_write_complete) {
- (*chan).write_source->mark_streaming_write_completed ();
+ if ((*chan)->write_source && mark_write_complete) {
+ (*chan)->write_source->mark_streaming_write_completed ();
}
use_new_write_source (n);
if (record_enabled()) {
- capturing_sources.push_back ((*chan).write_source);
+ capturing_sources.push_back ((*chan)->write_source);
}
} else {
- if ((*chan).write_source == 0) {
+ if ((*chan)->write_source == 0) {
use_new_write_source (n);
}
}
@@ -1972,11 +2004,12 @@ int
AudioDiskstream::rename_write_sources ()
{
ChannelList::iterator chan;
+ boost::shared_ptr<ChannelList> c = channels.reader();
uint32_t n;
- for (chan = channels.begin(), n = 0; chan != channels.end(); ++chan, ++n) {
- if ((*chan).write_source != 0) {
- (*chan).write_source->set_name (_name, destructive());
+ for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
+ if ((*chan)->write_source != 0) {
+ (*chan)->write_source->set_name (_name, destructive());
/* XXX what to do if one of them fails ? */
}
}
@@ -1989,10 +2022,11 @@ AudioDiskstream::set_block_size (nframes_t nframes)
{
if (_session.get_block_size() > speed_buffer_size) {
speed_buffer_size = _session.get_block_size();
+ boost::shared_ptr<ChannelList> c = channels.reader();
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- if ((*chan).speed_buffer) delete [] (*chan).speed_buffer;
- (*chan).speed_buffer = new Sample[speed_buffer_size];
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+ if ((*chan)->speed_buffer) delete [] (*chan)->speed_buffer;
+ (*chan)->speed_buffer = new Sample[speed_buffer_size];
}
}
allocate_temporary_buffers ();
@@ -2011,11 +2045,13 @@ AudioDiskstream::allocate_temporary_buffers ()
if (required_wrap_size > wrap_buffer_size) {
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- if ((*chan).playback_wrap_buffer) delete [] (*chan).playback_wrap_buffer;
- (*chan).playback_wrap_buffer = new Sample[required_wrap_size];
- if ((*chan).capture_wrap_buffer) delete [] (*chan).capture_wrap_buffer;
- (*chan).capture_wrap_buffer = new Sample[required_wrap_size];
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+ if ((*chan)->playback_wrap_buffer) delete [] (*chan)->playback_wrap_buffer;
+ (*chan)->playback_wrap_buffer = new Sample[required_wrap_size];
+ if ((*chan)->capture_wrap_buffer) delete [] (*chan)->capture_wrap_buffer;
+ (*chan)->capture_wrap_buffer = new Sample[required_wrap_size];
}
wrap_buffer_size = required_wrap_size;
@@ -2025,10 +2061,12 @@ AudioDiskstream::allocate_temporary_buffers ()
void
AudioDiskstream::monitor_input (bool yn)
{
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- if ((*chan).source) {
- (*chan).source->ensure_monitor_input (yn);
+ if ((*chan)->source) {
+ (*chan)->source->ensure_monitor_input (yn);
}
}
}
@@ -2044,8 +2082,10 @@ AudioDiskstream::set_align_style_from_io ()
get_input_sources ();
- for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) {
- if ((*chan).source && (*chan).source->flags() & JackPortIsPhysical) {
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
+ for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
+ if ((*chan)->source && (*chan)->source->flags() & JackPortIsPhysical) {
have_physical = true;
break;
}
@@ -2059,55 +2099,64 @@ AudioDiskstream::set_align_style_from_io ()
}
int
-AudioDiskstream::add_channel ()
+AudioDiskstream::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
{
- /* XXX need to take lock??? */
+ while (how_many--) {
+ c->push_back (new ChannelInfo(_session.diskstream_buffer_size(), speed_buffer_size, wrap_buffer_size));
+ }
- /* this copies the ChannelInfo, which currently has no buffers. kind
- of pointless really, but we want the channels list to contain
- actual objects, not pointers to objects. mostly for convenience,
- which isn't much in evidence.
- */
+ _n_channels.set(DataType::AUDIO, c->size());
+
+ return 0;
+}
- channels.push_back (ChannelInfo());
+int
+AudioDiskstream::add_channel (uint32_t how_many)
+{
+ RCUWriter<ChannelList> writer (channels);
+ boost::shared_ptr<ChannelList> c = writer.get_copy();
- /* now allocate the buffers */
+ return add_channel_to (c, how_many);
+}
- channels.back().init (_session.diskstream_buffer_size(),
- speed_buffer_size,
- wrap_buffer_size);
+int
+AudioDiskstream::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
+{
+ while (--how_many && !c->empty()) {
+ delete c->back();
+ c->pop_back();
+ }
- _n_channels.set(DataType::AUDIO, channels.size());
+ _n_channels.set(DataType::AUDIO, c->size());
return 0;
}
int
-AudioDiskstream::remove_channel ()
+AudioDiskstream::remove_channel (uint32_t how_many)
{
- if (channels.size() > 1) {
- /* XXX need to take lock??? */
- channels.back().release ();
- channels.pop_back();
- _n_channels.set(DataType::AUDIO, channels.size());
- return 0;
- }
-
- return -1;
+ RCUWriter<ChannelList> writer (channels);
+ boost::shared_ptr<ChannelList> c = writer.get_copy();
+
+ return remove_channel_from (c, how_many);
}
float
AudioDiskstream::playback_buffer_load () const
{
- return (float) ((double) channels.front().playback_buf->read_space()/
- (double) channels.front().playback_buf->bufsize());
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
+ return (float) ((double) c->front()->playback_buf->read_space()/
+ (double) c->front()->playback_buf->bufsize());
}
float
AudioDiskstream::capture_buffer_load () const
{
- return (float) ((double) channels.front().capture_buf->write_space()/
- (double) channels.front().capture_buf->bufsize());
+ boost::shared_ptr<ChannelList> c = channels.reader();
+
+ return (float) ((double) c->front()->capture_buf->write_space()/
+ (double) c->front()->capture_buf->bufsize());
}
int
@@ -2270,24 +2319,14 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const
return true;
}
-AudioDiskstream::ChannelInfo::ChannelInfo ()
+AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t bufsize, nframes_t speed_size, nframes_t wrap_size)
{
- playback_wrap_buffer = 0;
- capture_wrap_buffer = 0;
- speed_buffer = 0;
peak_power = 0.0f;
source = 0;
current_capture_buffer = 0;
current_playback_buffer = 0;
curr_capture_cnt = 0;
- playback_buf = 0;
- capture_buf = 0;
- capture_transition_buf = 0;
-}
-void
-AudioDiskstream::ChannelInfo::init (nframes_t bufsize, nframes_t speed_size, nframes_t wrap_size)
-{
speed_buffer = new Sample[speed_size];
playback_wrap_buffer = new Sample[wrap_size];
capture_wrap_buffer = new Sample[wrap_size];
@@ -2309,11 +2348,6 @@ AudioDiskstream::ChannelInfo::init (nframes_t bufsize, nframes_t speed_size, nfr
AudioDiskstream::ChannelInfo::~ChannelInfo ()
{
-}
-
-void
-AudioDiskstream::ChannelInfo::release ()
-{
if (write_source) {
write_source.reset ();
}
diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc
index a6d73e8544..9dd7064f69 100644
--- a/libs/ardour/audio_playlist.cc
+++ b/libs/ardour/audio_playlist.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -388,7 +387,7 @@ AudioPlaylist::check_dependents (boost::shared_ptr<Region> r, bool norefresh)
OverlapType c = top->coverage (bottom->position(), bottom->last_frame());
-
+
try {
switch (c) {
case OverlapNone:
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index b0ac7a4bd7..111bd9f4a9 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <sigc++/retype.h>
@@ -61,6 +60,7 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
}
boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name, dflags));
+
_session.add_diskstream (ds);
set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
@@ -276,14 +276,7 @@ AudioTrack::_set_state (const XMLNode& node, bool call_base)
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
child = *niter;
- if (child->name() == X_("remote_control")) {
- if ((prop = child->property (X_("id"))) != 0) {
- int32_t x;
- sscanf (prop->value().c_str(), "%d", &x);
- set_remote_control_id (x);
- }
-
- } else if (child->name() == X_("recenable")) {
+ if (child->name() == X_("recenable")) {
_rec_enable_control.set_state (*child);
_session.add_controllable (&_rec_enable_control);
}
@@ -329,11 +322,6 @@ AudioTrack::state(bool full_state)
align_node->add_property (X_("style"), enum_2_string (as));
root.add_child_nocopy (*align_node);
- XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
- snprintf (buf, sizeof (buf), "%d", _remote_control_id);
- remote_control_node->add_property (X_("id"), buf);
- root.add_child_nocopy (*remote_control_node);
-
root.add_property (X_("mode"), enum_2_string (_mode));
/* we don't return diskstream state because we don't
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 816e3bbf0c..6fc97703d6 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -15,16 +15,17 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <unistd.h>
#include <cerrno>
#include <vector>
#include <exception>
+#include <stdexcept>
#include <glibmm/timer.h>
#include <pbd/pthread_utils.h>
+#include <pbd/stacktrace.h>
#include <pbd/unknown_type.h>
#include <ardour/audioengine.h>
@@ -229,9 +230,9 @@ AudioEngine::jack_sync_callback (jack_transport_state_t state, jack_position_t*
{
if (_jack && session) {
return session->jack_sync_callback (state, pos);
- } else {
- return true;
}
+
+ return true;
}
int
@@ -296,6 +297,7 @@ AudioEngine::process_callback (nframes_t nframes)
if (_freewheeling) {
if (Freewheel (nframes)) {
+ cerr << "Freewheeling returned non-zero!\n";
_freewheeling = false;
jack_set_freewheel (_jack, false);
}
@@ -1187,8 +1189,13 @@ int
AudioEngine::request_buffer_size (nframes_t nframes)
{
if (_jack) {
- int ret = jack_set_buffer_size (_jack, nframes);
- return ret;
+
+ if (nframes == jack_get_buffer_size (_jack)) {
+ return 0;
+ }
+
+ return jack_set_buffer_size (_jack, nframes);
+
} else {
return -1;
}
@@ -1239,3 +1246,12 @@ AudioEngine::make_port_name_non_relative (string portname)
return str;
}
+bool
+AudioEngine::is_realtime () const
+{
+ if (_jack) {
+ return jack_is_realtime (_jack);
+ } else {
+ return false;
+ }
+}
diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc
index fa38cca0a0..1d10109aa1 100644
--- a/libs/ardour/audiofilesource.cc
+++ b/libs/ardour/audiofilesource.cc
@@ -53,9 +53,10 @@
using namespace ARDOUR;
using namespace PBD;
+using namespace Glib;
-string AudioFileSource::peak_dir = "";
-string AudioFileSource::search_path;
+ustring AudioFileSource::peak_dir = "";
+ustring AudioFileSource::search_path;
sigc::signal<void> AudioFileSource::HeaderPositionOffsetChanged;
uint64_t AudioFileSource::header_position_offset = 0;
@@ -63,9 +64,9 @@ uint64_t AudioFileSource::header_position_offset = 0;
/* XXX maybe this too */
char AudioFileSource::bwf_serial_number[13] = "000000000000";
-AudioFileSource::AudioFileSource (Session& s, string path, Flag flags)
+AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags)
: AudioSource (s, path), _flags (flags),
- channel (0)
+ _channel (0)
{
/* constructor used for existing external to session files. file must exist already */
_is_embedded = AudioFileSource::determine_embeddedness (path);
@@ -76,9 +77,9 @@ AudioFileSource::AudioFileSource (Session& s, string path, Flag flags)
}
-AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
+AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
: AudioSource (s, path), _flags (flags),
- channel (0)
+ _channel (0)
{
/* constructor used for new internal-to-session files. file cannot exist */
_is_embedded = false;
@@ -88,9 +89,9 @@ AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, Samp
}
}
-AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
+AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exist)
: AudioSource (s, node), _flags (Flag (Writable|CanRename))
- /* channel is set in set_state() */
+ /* _channel is set in set_state() */
{
/* constructor used for existing internal-to-session files. file must exist */
@@ -98,7 +99,7 @@ AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
throw failed_constructor ();
}
- if (init (_name, true)) {
+ if (init (_name, must_exist)) {
throw failed_constructor ();
}
}
@@ -112,7 +113,7 @@ AudioFileSource::~AudioFileSource ()
}
bool
-AudioFileSource::determine_embeddedness (std::string path)
+AudioFileSource::determine_embeddedness (ustring path)
{
return (path.find("/") == 0);
}
@@ -124,18 +125,17 @@ AudioFileSource::removable () const
}
int
-AudioFileSource::init (string pathstr, bool must_exist)
+AudioFileSource::init (ustring pathstr, bool must_exist)
{
bool is_new = false;
_length = 0;
timeline_position = 0;
- next_peak_clear_should_notify = false;
_peaks_built = false;
file_is_new = false;
if (!find (pathstr, must_exist, is_new)) {
- return -1;
+ throw non_existent_source ();
}
if (is_new && must_exist) {
@@ -146,40 +146,40 @@ AudioFileSource::init (string pathstr, bool must_exist)
}
-string
-AudioFileSource::peak_path (string audio_path)
+ustring
+AudioFileSource::peak_path (ustring audio_path)
{
return _session.peak_path_from_audio_path (audio_path);
}
-string
-AudioFileSource::old_peak_path (string audio_path)
+ustring
+AudioFileSource::old_peak_path (ustring audio_path)
{
/* XXX hardly bombproof! fix me */
struct stat stat_file;
struct stat stat_mount;
- string mp = mountpoint (audio_path);
+ ustring mp = mountpoint (audio_path);
stat (audio_path.c_str(), &stat_file);
stat (mp.c_str(), &stat_mount);
char buf[32];
#ifdef __APPLE__
- snprintf (buf, sizeof (buf), "%u-%u-%d.peak", stat_mount.st_ino, stat_file.st_ino, channel);
+ snprintf (buf, sizeof (buf), "%u-%u-%d.peak", stat_mount.st_ino, stat_file.st_ino, _channel);
#else
- snprintf (buf, sizeof (buf), "%ld-%ld-%d.peak", stat_mount.st_ino, stat_file.st_ino, channel);
+ snprintf (buf, sizeof (buf), "%ld-%ld-%d.peak", stat_mount.st_ino, stat_file.st_ino, _channel);
#endif
- string res = peak_dir;
+ ustring res = peak_dir;
res += buf;
return res;
}
bool
-AudioFileSource::get_soundfile_info (string path, SoundFileInfo& _info, string& error_msg)
+AudioFileSource::get_soundfile_info (ustring path, SoundFileInfo& _info, string& error_msg)
{
#ifdef HAVE_COREAUDIO
if (CoreAudioSource::get_soundfile_info (path, _info, error_msg) == 0) {
@@ -200,7 +200,7 @@ AudioFileSource::get_state ()
XMLNode& root (AudioSource::get_state());
char buf[32];
root.add_property (X_("flags"), enum_2_string (_flags));
- snprintf (buf, sizeof (buf), "%d", channel);
+ snprintf (buf, sizeof (buf), "%u", _channel);
root.add_property (X_("channel"), buf);
return root;
}
@@ -222,9 +222,9 @@ AudioFileSource::set_state (const XMLNode& node)
}
if ((prop = node.property (X_("channel"))) != 0) {
- channel = atoi (prop->value());
+ _channel = atoi (prop->value());
} else {
- channel = 0;
+ _channel = 0;
}
if ((prop = node.property (X_("name"))) != 0) {
@@ -260,16 +260,13 @@ AudioFileSource::mark_streaming_write_completed ()
Glib::Mutex::Lock lm (_lock);
- next_peak_clear_should_notify = true;
-
- if (_peaks_built || pending_peak_builds.empty()) {
- _peaks_built = true;
+ if (_peaks_built) {
PeaksReady (); /* EMIT SIGNAL */
}
}
void
-AudioFileSource::mark_take (string id)
+AudioFileSource::mark_take (ustring id)
{
if (writable()) {
_take_id = id;
@@ -277,14 +274,14 @@ AudioFileSource::mark_take (string id)
}
int
-AudioFileSource::move_to_trash (const string trash_dir_name)
+AudioFileSource::move_to_trash (const ustring& trash_dir_name)
{
if (is_embedded()) {
cerr << "tried to move an embedded region to trash" << endl;
return -1;
}
- string newpath;
+ ustring newpath;
if (!writable()) {
return -1;
@@ -311,7 +308,7 @@ AudioFileSource::move_to_trash (const string trash_dir_name)
char buf[PATH_MAX+1];
int version = 1;
- string newpath_v;
+ ustring newpath_v;
snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
newpath_v = buf;
@@ -362,18 +359,16 @@ AudioFileSource::move_to_trash (const string trash_dir_name)
}
bool
-AudioFileSource::find (string pathstr, bool must_exist, bool& isnew)
+AudioFileSource::find (ustring& pathstr, bool must_exist, bool& isnew)
{
- string::size_type pos;
+ ustring::size_type pos;
bool ret = false;
isnew = false;
/* clean up PATH:CHANNEL notation so that we are looking for the correct path */
- if ((pos = pathstr.find_last_of (':')) == string::npos) {
- pathstr = pathstr;
- } else {
+ if ((pos = pathstr.find_last_of (':')) != ustring::npos) {
pathstr = pathstr.substr (0, pos);
}
@@ -381,10 +376,10 @@ AudioFileSource::find (string pathstr, bool must_exist, bool& isnew)
/* non-absolute pathname: find pathstr in search path */
- vector<string> dirs;
+ vector<ustring> dirs;
int cnt;
- string fullpath;
- string keeppath;
+ ustring fullpath;
+ ustring keeppath;
if (search_path.length() == 0) {
error << _("FileSource: search path not set") << endmsg;
@@ -395,7 +390,7 @@ AudioFileSource::find (string pathstr, bool must_exist, bool& isnew)
cnt = 0;
- for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
+ for (vector<ustring>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
fullpath = *i;
if (fullpath[fullpath.length()-1] != '/') {
@@ -471,7 +466,7 @@ AudioFileSource::find (string pathstr, bool must_exist, bool& isnew)
}
void
-AudioFileSource::set_search_path (string p)
+AudioFileSource::set_search_path (ustring p)
{
search_path = p;
}
@@ -513,11 +508,11 @@ AudioFileSource::set_allow_remove_if_empty (bool yn)
}
int
-AudioFileSource::set_name (string newname, bool destructive)
+AudioFileSource::set_name (ustring newname, bool destructive)
{
Glib::Mutex::Lock lm (_lock);
- string oldpath = _path;
- string newpath = Session::change_audio_path_by_name (oldpath, _name, newname, destructive);
+ ustring oldpath = _path;
+ ustring newpath = Session::change_audio_path_by_name (oldpath, _name, newname, destructive);
if (newpath.empty()) {
error << string_compose (_("programming error: %1"), "cannot generate a changed audio path") << endmsg;
@@ -542,7 +537,7 @@ AudioFileSource::set_name (string newname, bool destructive)
}
bool
-AudioFileSource::is_empty (Session& s, string path)
+AudioFileSource::is_empty (Session& s, ustring path)
{
bool ret = false;
@@ -566,30 +561,36 @@ AudioFileSource::setup_peakfile ()
}
bool
-AudioFileSource::safe_file_extension(string file)
+AudioFileSource::safe_file_extension(ustring file)
{
- return !(file.rfind(".wav") == string::npos &&
- file.rfind(".aiff")== string::npos &&
- file.rfind(".aif") == string::npos &&
- file.rfind(".snd") == string::npos &&
- file.rfind(".au") == string::npos &&
- file.rfind(".raw") == string::npos &&
- file.rfind(".sf") == string::npos &&
- file.rfind(".cdr") == string::npos &&
- file.rfind(".smp") == string::npos &&
- file.rfind(".maud")== string::npos &&
- file.rfind(".vwe") == string::npos &&
- file.rfind(".paf") == string::npos &&
+ return !(file.rfind(".wav") == ustring::npos &&
+ file.rfind(".aiff")== ustring::npos &&
+ file.rfind(".aif") == ustring::npos &&
+ file.rfind(".snd") == ustring::npos &&
+ file.rfind(".au") == ustring::npos &&
+ file.rfind(".raw") == ustring::npos &&
+ file.rfind(".sf") == ustring::npos &&
+ file.rfind(".cdr") == ustring::npos &&
+ file.rfind(".smp") == ustring::npos &&
+ file.rfind(".maud")== ustring::npos &&
+ file.rfind(".vwe") == ustring::npos &&
+ file.rfind(".paf") == ustring::npos &&
#ifdef HAVE_COREAUDIO
- file.rfind(".mp3") == string::npos &&
- file.rfind(".aac") == string::npos &&
- file.rfind(".mp4") == string::npos &&
+ file.rfind(".mp3") == ustring::npos &&
+ file.rfind(".aac") == ustring::npos &&
+ file.rfind(".mp4") == ustring::npos &&
#endif // HAVE_COREAUDIO
- file.rfind(".voc") == string::npos);
+ file.rfind(".voc") == ustring::npos);
}
void
AudioFileSource::mark_immutable ()
{
- _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
+ /* destructive sources stay writable, and their other flags don't
+ change.
+ */
+
+ if (!(_flags & Destructive)) {
+ _flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
+ }
}
diff --git a/libs/ardour/audiofilter.cc b/libs/ardour/audiofilter.cc
index 4c38ecec20..d4d59d4a60 100644
--- a/libs/ardour/audiofilter.cc
+++ b/libs/ardour/audiofilter.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <time.h>
@@ -80,6 +79,7 @@ AudioFilter::finish (boost::shared_ptr<AudioRegion> region, SourceList& nsrcs)
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*si);
if (afs) {
afs->update_header (region->position(), *now, xnow);
+ afs->mark_immutable ();
}
}
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index 38f8ed3652..8bb40e9bcb 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -41,7 +40,6 @@
#include <ardour/playlist.h>
#include <ardour/audiofilter.h>
#include <ardour/audiofilesource.h>
-#include <ardour/destructive_filesource.h>
#include <ardour/region_factory.h>
#include "i18n.h"
@@ -932,10 +930,15 @@ AudioRegion::separate_by_channel (Session& session, vector<boost::shared_ptr<Aud
new_name += ('0' + n + 1);
}
- /* create a copy with just one source */
+ /* create a copy with just one source. prevent if from being thought of as "whole file" even if
+ it covers the entire source file(s).
+ */
+
+ Flag f = Flag (_flags & ~WholeFile);
- boost::shared_ptr<Region> r = RegionFactory::create (srcs, _start, _length, new_name, _layer, _flags);
+ boost::shared_ptr<Region> r = RegionFactory::create (srcs, _start, _length, new_name, _layer, f);
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
+ cerr << "new region name is " << ar->name() << endl;
v.push_back (ar);
@@ -1096,6 +1099,7 @@ AudioRegion::normalize_to (float target_dB)
boost::shared_ptr<Playlist> pl (playlist());
if (pl) {
+ cerr << "Send modified\n";
pl->Modified();
}
diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc
index 203590a4e1..6fe2f67e05 100644
--- a/libs/ardour/audiosource.cc
+++ b/libs/ardour/audiosource.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: source.cc 404 2006-03-17 17:39:21Z pauld $
*/
#include <sys/stat.h>
@@ -36,6 +35,7 @@
#include <ardour/audiosource.h>
#include <ardour/cycle_timer.h>
+#include <ardour/session.h>
#include "i18n.h"
@@ -43,41 +43,33 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-pthread_t AudioSource::peak_thread;
-bool AudioSource::have_peak_thread = false;
-vector<boost::shared_ptr<AudioSource> > AudioSource::pending_peak_sources;
-Glib::Mutex* AudioSource::pending_peak_sources_lock = 0;
-int AudioSource::peak_request_pipe[2];
-
bool AudioSource::_build_missing_peakfiles = false;
bool AudioSource::_build_peakfiles = false;
-AudioSource::AudioSource (Session& s, string name)
+AudioSource::AudioSource (Session& s, ustring name)
: Source (s, name, DataType::AUDIO)
{
- if (pending_peak_sources_lock == 0) {
- pending_peak_sources_lock = new Glib::Mutex;
- }
-
_peaks_built = false;
_peak_byte_max = 0;
- next_peak_clear_should_notify = true;
+ peakfile = -1;
_read_data_count = 0;
_write_data_count = 0;
+ peak_leftover_cnt = 0;
+ peak_leftover_size = 0;
+ peak_leftovers = 0;
}
AudioSource::AudioSource (Session& s, const XMLNode& node)
: Source (s, node)
{
- if (pending_peak_sources_lock == 0) {
- pending_peak_sources_lock = new Glib::Mutex;
- }
-
_peaks_built = false;
_peak_byte_max = 0;
- next_peak_clear_should_notify = true;
+ peakfile = -1;
_read_data_count = 0;
_write_data_count = 0;
+ peak_leftover_cnt = 0;
+ peak_leftover_size = 0;
+ peak_leftovers = 0;
if (set_state (node)) {
throw failed_constructor();
@@ -86,6 +78,19 @@ AudioSource::AudioSource (Session& s, const XMLNode& node)
AudioSource::~AudioSource ()
{
+ /* shouldn't happen but make sure we don't leak file descriptors anyway */
+
+ if (peak_leftover_cnt) {
+ cerr << "AudioSource destroyed with leftover peak data pending" << endl;
+ }
+
+ if (peakfile >= 0) {
+ ::close (peakfile);
+ }
+
+ if (peak_leftovers) {
+ delete [] peak_leftovers;
+ }
}
XMLNode&
@@ -118,171 +123,6 @@ AudioSource::set_state (const XMLNode& node)
PEAK FILE STUFF
***********************************************************************/
-void*
-AudioSource::peak_thread_work (void* arg)
-{
- PBD::ThreadCreated (pthread_self(), X_("Peak"));
- struct pollfd pfd[1];
-
- if (pending_peak_sources_lock == 0) {
- pending_peak_sources_lock = new Glib::Mutex;
- }
-
- Glib::Mutex::Lock lm (*pending_peak_sources_lock);
-
- while (true) {
-
- pfd[0].fd = peak_request_pipe[0];
- pfd[0].events = POLLIN|POLLERR|POLLHUP;
-
- pending_peak_sources_lock->unlock ();
-
- if (poll (pfd, 1, -1) < 0) {
-
- if (errno == EINTR) {
- pending_peak_sources_lock->lock ();
- continue;
- }
-
- error << string_compose (_("poll on peak request pipe failed (%1)"),
- strerror (errno))
- << endmsg;
- break;
- }
-
- if (pfd[0].revents & ~POLLIN) {
- error << _("Error on peak thread request pipe") << endmsg;
- break;
- }
-
- if (pfd[0].revents & POLLIN) {
-
- char req;
-
- /* empty the pipe of all current requests */
-
- while (1) {
- size_t nread = ::read (peak_request_pipe[0], &req, sizeof (req));
-
- if (nread == 1) {
- switch ((PeakRequest::Type) req) {
-
- case PeakRequest::Build:
- break;
-
- case PeakRequest::Quit:
- pthread_exit_pbd (0);
- /*NOTREACHED*/
- break;
-
- default:
- break;
- }
-
- } else if (nread == 0) {
- break;
- } else if (errno == EAGAIN) {
- break;
- } else {
- fatal << _("Error reading from peak request pipe") << endmsg;
- /*NOTREACHED*/
- }
- }
- }
-
- pending_peak_sources_lock->lock ();
-
- while (!pending_peak_sources.empty()) {
-
- boost::shared_ptr<AudioSource> s = pending_peak_sources.front();
- pending_peak_sources.erase (pending_peak_sources.begin());
-
- pending_peak_sources_lock->unlock ();
- s->build_peaks();
- pending_peak_sources_lock->lock ();
- }
- }
-
- pthread_exit_pbd (0);
- /*NOTREACHED*/
- return 0;
-}
-
-int
-AudioSource::start_peak_thread ()
-{
- if (!_build_peakfiles) {
- return 0;
- }
-
- if (pipe (peak_request_pipe)) {
- error << string_compose(_("Cannot create transport request signal pipe (%1)"), strerror (errno)) << endmsg;
- return -1;
- }
-
- if (fcntl (peak_request_pipe[0], F_SETFL, O_NONBLOCK)) {
- error << string_compose(_("UI: cannot set O_NONBLOCK on peak request pipe (%1)"), strerror (errno)) << endmsg;
- return -1;
- }
-
- if (fcntl (peak_request_pipe[1], F_SETFL, O_NONBLOCK)) {
- error << string_compose(_("UI: cannot set O_NONBLOCK on peak request pipe (%1)"), strerror (errno)) << endmsg;
- return -1;
- }
-
- if (pthread_create_and_store ("peak file builder", &peak_thread, 0, peak_thread_work, 0)) {
- error << _("AudioSource: could not create peak thread") << endmsg;
- return -1;
- }
-
- have_peak_thread = true;
- return 0;
-}
-
-void
-AudioSource::stop_peak_thread ()
-{
- if (!have_peak_thread) {
- return;
- }
-
- void* status;
-
- char c = (char) PeakRequest::Quit;
- ::write (peak_request_pipe[1], &c, 1);
- pthread_join (peak_thread, &status);
-}
-
-void
-AudioSource::queue_for_peaks (boost::shared_ptr<AudioSource> source, bool notify)
-{
- if (have_peak_thread) {
-
- Glib::Mutex::Lock lm (*pending_peak_sources_lock);
-
- source->next_peak_clear_should_notify = notify;
-
- if (find (pending_peak_sources.begin(),
- pending_peak_sources.end(),
- source) == pending_peak_sources.end()) {
- pending_peak_sources.push_back (source);
- }
-
- char c = (char) PeakRequest::Build;
- ::write (peak_request_pipe[1], &c, 1);
- }
-}
-
-void AudioSource::clear_queue_for_peaks ()
-{
- /* this is done to cancel a group of running peak builds */
- if (have_peak_thread) {
- Glib::Mutex::Lock lm (*pending_peak_sources_lock);
- pending_peak_sources.clear ();
- }
-}
-
-
bool
AudioSource::peaks_ready (sigc::slot<void> the_slot, sigc::connection& conn) const
{
@@ -318,11 +158,11 @@ AudioSource::touch_peakfile ()
}
int
-AudioSource::rename_peakfile (string newpath)
+AudioSource::rename_peakfile (ustring newpath)
{
/* caller must hold _lock */
- string oldpath = peakpath;
+ ustring oldpath = peakpath;
if (access (oldpath.c_str(), F_OK) == 0) {
if (rename (oldpath.c_str(), newpath.c_str()) != 0) {
@@ -337,7 +177,7 @@ AudioSource::rename_peakfile (string newpath)
}
int
-AudioSource::initialize_peakfile (bool newfile, string audio_path)
+AudioSource::initialize_peakfile (bool newfile, ustring audio_path)
{
struct stat statbuf;
@@ -348,7 +188,7 @@ AudioSource::initialize_peakfile (bool newfile, string audio_path)
*/
if (!newfile && access (peakpath.c_str(), R_OK) != 0) {
- string str = old_peak_path (audio_path);
+ ustring str = old_peak_path (audio_path);
if (access (str.c_str(), R_OK) == 0) {
peakpath = str;
}
@@ -431,7 +271,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
int ret = -1;
PeakData* staging = 0;
Sample* raw_staging = 0;
- int peakfile = -1;
+ int _peakfile = -1;
expected_peaks = (cnt / (double) frames_per_peak);
scale = npeaks/expected_peaks;
@@ -492,7 +332,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
/* open, read, close */
- if ((peakfile = ::open (peakpath.c_str(), O_RDONLY, 0664)) < 0) {
+ if ((_peakfile = ::open (peakpath.c_str(), O_RDONLY, 0664)) < 0) {
error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return -1;
}
@@ -501,8 +341,8 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
cerr << "DIRECT PEAKS\n";
#endif
- nread = ::pread (peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
- close (peakfile);
+ nread = ::pread (_peakfile, peaks, sizeof (PeakData)* npeaks, first_peak_byte);
+ close (_peakfile);
if (nread != sizeof (PeakData) * npeaks) {
cerr << "AudioSource["
@@ -566,7 +406,7 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
/* open ... close during out: handling */
- if ((peakfile = ::open (peakpath.c_str(), O_RDONLY, 0664)) < 0) {
+ if ((_peakfile = ::open (peakpath.c_str(), O_RDONLY, 0664)) < 0) {
error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
return 0;
}
@@ -583,10 +423,10 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
cerr << "read " << sizeof (PeakData) * to_read << " from peakfile @ " << start_byte << endl;
#endif
- if ((nread = ::pread (peakfile, staging, sizeof (PeakData) * to_read, start_byte))
+ if ((nread = ::pread (_peakfile, staging, sizeof (PeakData) * to_read, start_byte))
!= sizeof (PeakData) * to_read) {
- off_t fend = lseek (peakfile, 0, SEEK_END);
+ off_t fend = lseek (_peakfile, 0, SEEK_END);
cerr << "AudioSource["
<< _name
@@ -672,13 +512,21 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
to_read = min (chunksize, (_length - current_frame));
+ if (to_read == 0) {
+ /* XXX ARGH .. out by one error ... need to figure out why this happens
+ and fix it rather than do this band-aid move.
+ */
+ zero_fill = npeaks - nvisual_peaks;
+ break;
+ }
+
if ((frames_read = read_unlocked (raw_staging, current_frame, to_read)) == 0) {
- error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3")
- , _name, to_read, current_frame)
+ error << string_compose(_("AudioSource[%1]: peak read - cannot read %2 samples at offset %3 of %4 (%5)"),
+ _name, to_read, current_frame, _length, strerror (errno))
<< endmsg;
goto out;
}
-
+
i = 0;
}
@@ -708,8 +556,8 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
}
out:
- if (peakfile >= 0) {
- close (peakfile);
+ if (_peakfile >= 0) {
+ close (_peakfile);
}
if (staging) {
@@ -730,196 +578,277 @@ AudioSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nfr
#undef DEBUG_PEAK_BUILD
int
-AudioSource::build_peaks ()
+AudioSource::build_peaks_from_scratch ()
{
- vector<PeakBuildRecord*> built;
- int status = -1;
- bool pr_signal = false;
- list<PeakBuildRecord*> copy;
+ nframes_t current_frame;
+ nframes_t cnt;
+ Sample buf[frames_per_peak];
+ nframes_t frames_read;
+ nframes_t frames_to_read;
+ int ret = -1;
{
- Glib::Mutex::Lock lm (_lock);
- copy = pending_peak_builds;
- pending_peak_builds.clear ();
- }
-
-#ifdef DEBUG_PEAK_BUILD
- cerr << "build peaks with " << copy.size() << " requests pending\n";
-#endif
+ /* hold lock while building peaks */
- for (list<PeakBuildRecord *>::iterator i = copy.begin(); i != copy.end(); ++i) {
+ Glib::Mutex::Lock lp (_lock);
- if ((status = do_build_peak ((*i)->frame, (*i)->cnt)) != 0) {
- unlink (peakpath.c_str());
- break;
+ if (prepare_for_peakfile_writes ()) {
+ goto out;
}
- built.push_back (new PeakBuildRecord (*(*i)));
- delete *i;
- }
+
+ current_frame = 0;
+ cnt = _length;
+ _peaks_built = false;
+
+ while (cnt) {
+
+ frames_to_read = min (frames_per_peak, cnt);
- {
- Glib::Mutex::Lock lm (_lock);
+ if ((frames_read = read_unlocked (buf, current_frame, frames_to_read)) != frames_to_read) {
+ error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
+ done_with_peakfile_writes ();
+ goto out;
+ }
- if (status == 0) {
- _peaks_built = true;
-
- if (next_peak_clear_should_notify) {
- next_peak_clear_should_notify = false;
- pr_signal = true;
+ if (compute_and_write_peaks (buf, current_frame, frames_read, true)) {
+ break;
}
+
+ current_frame += frames_read;
+ cnt -= frames_read;
}
+
+ if (cnt == 0) {
+ /* success */
+ truncate_peakfile();
+ _peaks_built = true;
+ }
+
+ done_with_peakfile_writes ();
}
- if (status == 0) {
- for (vector<PeakBuildRecord *>::iterator i = built.begin(); i != built.end(); ++i) {
- PeakRangeReady ((*i)->frame, (*i)->cnt); /* EMIT SIGNAL */
- delete *i;
- }
+ /* lock no longer held, safe to signal */
- if (pr_signal) {
- truncate_peakfile();
- PeaksReady (); /* EMIT SIGNAL */
- }
+ if (_peaks_built) {
+ PeaksReady (); /* EMIT SIGNAL */
+ ret = 0;
+ }
+
+ out:
+ if (ret) {
+ unlink (peakpath.c_str());
}
- return status;
+ return ret;
}
int
-AudioSource::do_build_peak (nframes_t first_frame, nframes_t cnt)
+AudioSource::prepare_for_peakfile_writes ()
{
+ if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
+ error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
+ return -1;
+ }
+ return 0;
+}
+
+void
+AudioSource::done_with_peakfile_writes ()
+{
+ if (peak_leftover_cnt) {
+ compute_and_write_peaks (0, 0, 0, true);
+ }
+
+ if (peakfile >= 0) {
+ close (peakfile);
+ peakfile = -1;
+ }
+}
+
+int
+AudioSource::compute_and_write_peaks (Sample* buf, nframes_t first_frame, nframes_t cnt, bool force)
+{
+ Sample* buf2 = 0;
+ nframes_t to_do;
+ uint32_t peaks_computed;
+ PeakData* peakbuf = 0;
+ int ret = -1;
nframes_t current_frame;
- Sample buf[frames_per_peak];
- Sample xmin, xmax;
- uint32_t peaki;
- PeakData* peakbuf;
- nframes_t frames_read;
- nframes_t frames_to_read;
+ nframes_t frames_done;
+ const size_t blocksize = (128 * 1024);
off_t first_peak_byte;
- int peakfile = -1;
- int ret = -1;
- off_t target_length;
- off_t endpos;
-#ifdef DEBUG_PEAK_BUILD
- cerr << pthread_self() << ": " << _name << ": building peaks for " << first_frame << " to " << first_frame + cnt - 1 << endl;
-#endif
+ if (peakfile < 0) {
+ prepare_for_peakfile_writes ();
+ }
- first_peak_byte = (first_frame / frames_per_peak) * sizeof (PeakData);
+ restart:
+ if (peak_leftover_cnt) {
-#ifdef DEBUG_PEAK_BUILD
- cerr << "seeking to " << first_peak_byte << " before writing new peak data\n";
-#endif
+ if (first_frame != peak_leftover_frame + peak_leftover_cnt) {
- current_frame = first_frame;
- peakbuf = new PeakData[(cnt/frames_per_peak)+1];
- peaki = 0;
+ /* uh-oh, ::seek() since the last ::compute_and_write_peaks(),
+ and we have leftovers. flush a single peak (since the leftovers
+ never represent more than that, and restart.
+ */
+
+ PeakData x;
+
+ x.min = peak_leftovers[0];
+ x.max = peak_leftovers[0];
+ Session::find_peaks (peak_leftovers + 1, peak_leftover_cnt - 1, &x.min, &x.max);
- if ((peakfile = ::open (peakpath.c_str(), O_RDWR|O_CREAT, 0664)) < 0) {
- error << string_compose(_("AudioSource: cannot open peakpath \"%1\" (%2)"), peakpath, strerror (errno)) << endmsg;
- return -1;
- }
-
- while (cnt) {
+ off_t byte = (peak_leftover_frame / frames_per_peak) * sizeof (PeakData);
- frames_to_read = min (frames_per_peak, cnt);
+ if (::pwrite (peakfile, &x, sizeof (PeakData), byte) != sizeof (PeakData)) {
+ error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
+ goto out;
+ }
- /* lock for every read */
+ _peak_byte_max = max (_peak_byte_max, (off_t) (byte + sizeof(PeakData)));
- if ((frames_read = read (buf, current_frame, frames_to_read)) != frames_to_read) {
- error << string_compose(_("%1: could not write read raw data for peak computation (%2)"), _name, strerror (errno)) << endmsg;
- goto out;
+ PeakRangeReady (peak_leftover_frame, peak_leftover_cnt); /* EMIT SIGNAL */
+ PeaksReady (); /* EMIT SIGNAL */
+
+ /* left overs are done */
+
+ peak_leftover_cnt = 0;
+ goto restart;
}
- xmin = buf[0];
- xmax = buf[0];
+ /* else ... had leftovers, but they immediately preceed the new data, so just
+ merge them and compute.
+ */
+
+ /* make a new contiguous buffer containing leftovers and the new stuff */
- for (nframes_t n = 1; n < frames_read; ++n) {
- xmax = max (xmax, buf[n]);
- xmin = min (xmin, buf[n]);
+ to_do = cnt + peak_leftover_cnt;
+ buf2 = new Sample[to_do];
-// if (current_frame < frames_read) {
-// cerr << "sample = " << buf[n] << " max = " << xmax << " min = " << xmin << " max of 2 = " << max (xmax, buf[n]) << endl;
-// }
- }
+ /* the remnants */
+ memcpy (buf2, peak_leftovers, peak_leftover_cnt * sizeof (Sample));
+
+ /* the new stuff */
+ memcpy (buf2+peak_leftover_cnt, buf, cnt * sizeof (Sample));
+
+ /* no more leftovers */
+ peak_leftover_cnt = 0;
+
+ /* use the temporary buffer */
+ buf = buf2;
- peakbuf[peaki].max = xmax;
- peakbuf[peaki].min = xmin;
- peaki++;
+ /* make sure that when we write into the peakfile, we startup where we left off */
- current_frame += frames_read;
- cnt -= frames_read;
+ first_frame = peak_leftover_frame;
+
+ } else {
+ to_do = cnt;
}
-#define BLOCKSIZE (128 * 1024)
+ peakbuf = new PeakData[(to_do/frames_per_peak)+1];
+ peaks_computed = 0;
+ current_frame = first_frame;
+ frames_done = 0;
- /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
- the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
- it does not cause single-extent allocation even for peakfiles of
- less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
- */
- endpos = lseek (peakfile, 0, SEEK_END);
+ while (to_do) {
+
+ /* if some frames were passed in (i.e. we're not flushing leftovers)
+ and there are less than frames_per_peak to do, save them till
+ next time
+ */
+
+ if (force && (to_do < frames_per_peak)) {
+ /* keep the left overs around for next time */
+
+ if (peak_leftover_size < to_do) {
+ delete [] peak_leftovers;
+ peak_leftovers = new Sample[to_do];
+ peak_leftover_size = to_do;
+ }
+ memcpy (peak_leftovers, buf, to_do * sizeof (Sample));
+ peak_leftover_cnt = to_do;
+ peak_leftover_frame = current_frame;
+
+ /* done for now */
+
+ break;
+ }
+
+ nframes_t this_time = min (frames_per_peak, to_do);
+
+ peakbuf[peaks_computed].max = buf[0];
+ peakbuf[peaks_computed].min = buf[0];
+
+ Session::find_peaks (buf+1, this_time-1, &peakbuf[peaks_computed].min, &peakbuf[peaks_computed].max);
+
+ peaks_computed++;
+ buf += this_time;
+ to_do -= this_time;
+ frames_done += this_time;
+ current_frame += this_time;
+ }
- target_length = BLOCKSIZE * ((first_peak_byte + BLOCKSIZE + 1) / BLOCKSIZE);
+ first_peak_byte = (first_frame / frames_per_peak) * sizeof (PeakData);
- if (endpos < target_length) {
- // XXX - we really shouldn't be doing this for destructive source peaks
- ftruncate (peakfile, target_length);
- //cerr << "do build TRUNC: " << peakpath << " " << target_length << endl;
+ if (can_truncate_peaks()) {
- /* error doesn't actually matter though, so continue on without testing */
+ /* on some filesystems (ext3, at least) this helps to reduce fragmentation of
+ the peakfiles. its not guaranteed to do so, and even on ext3 (as of december 2006)
+ it does not cause single-extent allocation even for peakfiles of
+ less than BLOCKSIZE bytes. only call ftruncate if we'll make the file larger.
+ */
+
+ off_t endpos = lseek (peakfile, 0, SEEK_END);
+ off_t target_length = blocksize * ((first_peak_byte + blocksize + 1) / blocksize);
+
+ if (endpos < target_length) {
+ ftruncate (peakfile, target_length);
+ /* error doesn't actually matter though, so continue on without testing */
+ }
}
- if (::pwrite (peakfile, peakbuf, sizeof (PeakData) * peaki, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaki)) {
+ if (::pwrite (peakfile, peakbuf, sizeof (PeakData) * peaks_computed, first_peak_byte) != (ssize_t) (sizeof (PeakData) * peaks_computed)) {
error << string_compose(_("%1: could not write peak file data (%2)"), _name, strerror (errno)) << endmsg;
goto out;
}
- _peak_byte_max = max(_peak_byte_max, (off_t) (first_peak_byte + sizeof(PeakData)*peaki));
+ _peak_byte_max = max (_peak_byte_max, (off_t) (first_peak_byte + sizeof(PeakData)*peaks_computed));
+
+ if (frames_done) {
+ PeakRangeReady (first_frame, frames_done); /* EMIT SIGNAL */
+ PeaksReady (); /* EMIT SIGNAL */
+ }
ret = 0;
out:
delete [] peakbuf;
- if (peakfile >= 0) {
- close (peakfile);
+ if (buf2) {
+ delete [] buf2;
}
return ret;
}
void
-AudioSource::build_peaks_from_scratch ()
-{
- Glib::Mutex::Lock lp (_lock);
-
- next_peak_clear_should_notify = true;
- pending_peak_builds.push_back (new PeakBuildRecord (0, _length));
- queue_for_peaks (shared_from_this(), true);
-}
-
-void
AudioSource::truncate_peakfile ()
{
- int peakfile = -1;
+ if (peakfile < 0) {
+ error << string_compose (_("programming error: %1"), "AudioSource::truncate_peakfile() called without open peakfile descriptor")
+ << endmsg;
+ return;
+ }
/* truncate the peakfile down to its natural length if necessary */
- if ((peakfile = ::open (peakpath.c_str(), O_RDWR)) >= 0) {
- off_t end = lseek (peakfile, 0, SEEK_END);
-
- if (end > _peak_byte_max) {
- ftruncate(peakfile, _peak_byte_max);
- //cerr << "truncated " << peakpath << " to " << _peak_byte_max << " bytes" << endl;
- }
- else {
- //cerr << "NOT truncated " << peakpath << " to " << _peak_byte_max << " end " << end << endl;
- }
- close (peakfile);
+ off_t end = lseek (peakfile, 0, SEEK_END);
+
+ if (end > _peak_byte_max) {
+ ftruncate (peakfile, _peak_byte_max);
}
}
bool
-AudioSource::file_changed (string path)
+AudioSource::file_changed (ustring path)
{
struct stat stat_file;
struct stat stat_peak;
diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc
index 7bbc4cd0ba..0ba30b2b8b 100644
--- a/libs/ardour/auditioner.cc
+++ b/libs/ardour/auditioner.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <glibmm/thread.h>
@@ -65,7 +64,7 @@ Auditioner::Auditioner (Session& s)
}
if (right.length()) {
- audio_diskstream()->add_channel();
+ audio_diskstream()->add_channel (1);
add_output_port (right, this, DataType::AUDIO);
}
@@ -141,12 +140,10 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
_diskstream->playlist()->clear ();
_diskstream->playlist()->add_region (the_region, 0, 1);
- while (_diskstream->n_channels().get(DataType::AUDIO) < the_region->n_channels()) {
- audio_diskstream()->add_channel ();
- }
-
- while (_diskstream->n_channels().get(DataType::AUDIO) > the_region->n_channels()) {
- audio_diskstream()->remove_channel ();
+ if (_diskstream->n_channels().get(DataType::AUDIO) < the_region->n_channels()) {
+ audio_diskstream()->add_channel (the_region->n_channels() - _diskstream->n_channels().get(DataType::AUDIO));
+ } else if (_diskstream->n_channels().get(DataType::AUDIO) > the_region->n_channels()) {
+ audio_diskstream()->remove_channel (_diskstream->n_channels().get(DataType::AUDIO) - the_region->n_channels());
}
/* force a panner reset now that we have all channels */
diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc
index af6fffdeb9..341fa82091 100644
--- a/libs/ardour/automation_event.cc
+++ b/libs/ardour/automation_event.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <set>
diff --git a/libs/ardour/buffer.cc b/libs/ardour/buffer.cc
index d4a370685c..f13aa82207 100644
--- a/libs/ardour/buffer.cc
+++ b/libs/ardour/buffer.cc
@@ -22,6 +22,12 @@ using std::cerr; using std::endl;
#include <ardour/buffer.h>
+#ifdef __x86_64__
+static const int CPU_CACHE_ALIGN = 64;
+#else
+static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
+#endif
+
namespace ARDOUR {
@@ -47,7 +53,7 @@ AudioBuffer::AudioBuffer(size_t capacity)
#ifdef NO_POSIX_MEMALIGN
_data = (Sample *) malloc(sizeof(Sample) * capacity);
#else
- posix_memalign((void**)&_data, 16, sizeof(Sample) * capacity);
+ posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Sample) * capacity);
#endif
assert(_data);
_owns_data = true;
@@ -76,8 +82,8 @@ MidiBuffer::MidiBuffer(size_t capacity)
_events = (MidiEvent *) malloc(sizeof(MidiEvent) * capacity);
_data = (RawMidi *) malloc(sizeof(RawMidi) * capacity * MAX_EVENT_SIZE);
#else
- posix_memalign((void**)&_events, 16, sizeof(MidiEvent) * capacity);
- posix_memalign((void**)&_data, 16, sizeof(RawMidi) * capacity * MAX_EVENT_SIZE);
+ posix_memalign((void**)&_events, CPU_CACHE_ALIGN, sizeof(MidiEvent) * capacity);
+ posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(RawMidi) * capacity * MAX_EVENT_SIZE);
#endif
assert(_data);
assert(_events);
diff --git a/libs/ardour/configuration.cc b/libs/ardour/configuration.cc
index a0f2b5e036..c8d71c5155 100644
--- a/libs/ardour/configuration.cc
+++ b/libs/ardour/configuration.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <unistd.h>
@@ -27,7 +26,6 @@
#include <ardour/ardour.h>
#include <ardour/configuration.h>
#include <ardour/audio_diskstream.h>
-#include <ardour/destructive_filesource.h>
#include <ardour/control_protocol_manager.h>
#include "i18n.h"
@@ -318,6 +316,22 @@ Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
#undef CONFIG_VARIABLE_SPECIAL
}
+bool ConfigVariableBase::show_stores = false;
+
+void
+ConfigVariableBase::set_show_stored_values (bool yn)
+{
+ show_stores = yn;
+}
+
+void
+ConfigVariableBase::show_stored_value (const string& str)
+{
+ if (show_stores) {
+ cerr << "Config variable " << _name << " stored as " << str << endl;
+ }
+}
+
void
ConfigVariableBase::notify ()
{
@@ -330,3 +344,4 @@ ConfigVariableBase::miss ()
// placeholder for any debugging desired when a config variable
// is set but to the same value as it already has
}
+
diff --git a/libs/ardour/connection.cc b/libs/ardour/connection.cc
index fbfd02d509..13b7dc4ddb 100644
--- a/libs/ardour/connection.cc
+++ b/libs/ardour/connection.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc
index 72f56794d7..899790dddc 100644
--- a/libs/ardour/control_protocol_manager.cc
+++ b/libs/ardour/control_protocol_manager.cc
@@ -43,7 +43,6 @@ ControlProtocolManager::~ControlProtocolManager()
}
control_protocol_info.clear();
-
}
void
@@ -75,12 +74,11 @@ ControlProtocolManager::drop_session ()
delete *p;
}
control_protocols.clear ();
-
+
for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
- delete *p;
+ // otherwise the ControlProtocol instances are not recreated in set_session
+ (*p)->requested = true;
}
-
- control_protocol_info.clear();
}
}
@@ -106,10 +104,6 @@ ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
Glib::Mutex::Lock lm (protocols_lock);
control_protocols.push_back (cpi.protocol);
- if (cpi.state) {
- cpi.protocol->set_state (*cpi.state);
- }
-
return cpi.protocol;
}
@@ -297,7 +291,6 @@ ControlProtocolManager::set_state (const XMLNode& node)
if ((prop = (*citer)->property (X_("name"))) != 0) {
ControlProtocolInfo* cpi = cpi_by_name (prop->value());
if (cpi) {
-
if (!(*citer)->children().empty()) {
cpi->state = (*citer)->children().front ();
} else {
diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc
index 66d1e099da..d75758dfb0 100644
--- a/libs/ardour/crossfade.cc
+++ b/libs/ardour/crossfade.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <sigc++/bind.h>
diff --git a/libs/ardour/curve.cc b/libs/ardour/curve.cc
index 8465094775..5a1dc108f8 100644
--- a/libs/ardour/curve.cc
+++ b/libs/ardour/curve.cc
@@ -18,7 +18,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <iostream>
diff --git a/libs/ardour/cycle_timer.cc b/libs/ardour/cycle_timer.cc
index 3031d5a7ec..143cb841ec 100644
--- a/libs/ardour/cycle_timer.cc
+++ b/libs/ardour/cycle_timer.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdio>
diff --git a/libs/ardour/default_click.cc b/libs/ardour/default_click.cc
index b4067a2051..5bdbeb2ac5 100644
--- a/libs/ardour/default_click.cc
+++ b/libs/ardour/default_click.cc
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/ardour.h>
diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc
deleted file mode 100644
index 5eada195cd..0000000000
--- a/libs/ardour/destructive_filesource.cc
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- Copyright (C) 2006 Paul Davis
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
-
-/* This is is very hacky way to get pread and pwrite declarations.
- First, include <features.h> so that we can avoid its #undef __USE_UNIX98.
- Then define __USE_UNIX98, include <unistd.h>, and then undef it
- again. If #define _XOPEN_SOURCE actually worked, I'd use that, but
- despite claims in the header that it does, it doesn't.
-
- features.h isn't available on osx and it compiles fine without it.
-*/
-
-#ifdef HAVE_FEATURES_H
-#include <features.h>
-#endif
-
-#if __GNUC__ >= 3
-// #define _XOPEN_SOURCE 500
-#include <unistd.h>
-#else
-#define __USE_UNIX98
-#include <unistd.h>
-#undef __USE_UNIX98
-#endif
-
-// darwin supports 64 by default and doesn't provide wrapper functions.
-#if defined (__APPLE__)
-typedef off_t off64_t;
-#define open64 open
-#define close64 close
-#define lseek64 lseek
-#define pread64 pread
-#define pwrite64 pwrite
-#endif
-
-#include <errno.h>
-#include <cmath>
-#include <fcntl.h>
-
-#include <pbd/error.h>
-#include <pbd/stacktrace.h>
-#include <ardour/destructive_filesource.h>
-#include <ardour/utils.h>
-#include <ardour/session.h>
-
-#include "i18n.h"
-
-using namespace std;
-using namespace ARDOUR;
-using namespace PBD;
-
-gain_t* DestructiveFileSource::out_coefficient = 0;
-gain_t* DestructiveFileSource::in_coefficient = 0;
-nframes_t DestructiveFileSource::xfade_frames = 64;
-
-DestructiveFileSource::DestructiveFileSource (Session& s, string path, SampleFormat samp_format, HeaderFormat hdr_format, nframes_t rate, Flag flags)
- : SndFileSource (s, path, samp_format, hdr_format, rate, flags)
-{
- init ();
-}
-
-
-DestructiveFileSource::DestructiveFileSource (Session& s, string path, Flag flags)
- : SndFileSource (s, path, flags)
-{
- init ();
-}
-
-DestructiveFileSource::DestructiveFileSource (Session& s, const XMLNode& node)
- : SndFileSource (s, node)
-{
- init ();
-}
-
-void
-DestructiveFileSource::init ()
-{
- xfade_buf = new Sample[xfade_frames];
-
- _capture_start = false;
- _capture_end = false;
- file_pos = 0;
-
- timeline_position = header_position_offset;
- AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &DestructiveFileSource::handle_header_position_change));
-}
-
-DestructiveFileSource::~DestructiveFileSource()
-{
- delete xfade_buf;
-}
-
-void
-DestructiveFileSource::setup_standard_crossfades (nframes_t rate)
-{
- /* This static method is assumed to have been called by the Session
- before any DFS's are created.
- */
-
- xfade_frames = (nframes_t) floor ((Config->get_destructive_xfade_msecs () / 1000.0) * rate);
-
- if (out_coefficient) {
- delete [] out_coefficient;
- }
-
- if (in_coefficient) {
- delete [] in_coefficient;
- }
-
- out_coefficient = new gain_t[xfade_frames];
- in_coefficient = new gain_t[xfade_frames];
-
- compute_equal_power_fades (xfade_frames, in_coefficient, out_coefficient);
-}
-
-void
-DestructiveFileSource::mark_capture_start (nframes_t pos)
-{
- if (pos < timeline_position) {
- _capture_start = false;
- } else {
- _capture_start = true;
- capture_start_frame = pos;
- }
-}
-
-void
-DestructiveFileSource::mark_capture_end()
-{
- _capture_end = true;
-}
-
-void
-DestructiveFileSource::clear_capture_marks ()
-{
- _capture_start = false;
- _capture_end = false;
-}
-
-nframes_t
-DestructiveFileSource::crossfade (Sample* data, nframes_t cnt, int fade_in)
-{
- nframes_t xfade = min (xfade_frames, cnt);
- nframes_t nofade = cnt - xfade;
- Sample* fade_data = 0;
- nframes_t fade_position = 0; // in frames
- ssize_t retval;
- nframes_t file_cnt;
-
- if (fade_in) {
- fade_position = file_pos;
- fade_data = data;
- } else {
- fade_position = file_pos + nofade;
- fade_data = data + nofade;
- }
-
- if (fade_position > _length) {
-
- /* read starts beyond end of data, just memset to zero */
-
- file_cnt = 0;
-
- } else if (fade_position + xfade > _length) {
-
- /* read ends beyond end of data, read some, memset the rest */
-
- file_cnt = _length - fade_position;
-
- } else {
-
- /* read is entirely within data */
-
- file_cnt = xfade;
- }
-
- if (file_cnt) {
-
- if ((retval = read_unlocked (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
- if (retval >= 0 && errno == EAGAIN) {
- /* XXX - can we really trust that errno is meaningful here? yes POSIX, i'm talking to you.
- * short or no data there */
- memset (xfade_buf, 0, xfade * sizeof(Sample));
- } else {
- error << string_compose(_("DestructiveFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"), _path, retval, errno, strerror (errno), xfade) << endmsg;
- return 0;
- }
- }
- }
-
- if (file_cnt != xfade) {
- nframes_t delta = xfade - file_cnt;
- memset (xfade_buf+file_cnt, 0, sizeof (Sample) * delta);
- }
-
- if (nofade && !fade_in) {
- if (write_float (data, file_pos, nofade) != nofade) {
- error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
- return 0;
- }
- }
-
- if (xfade == xfade_frames) {
-
- nframes_t n;
-
- /* use the standard xfade curve */
-
- if (fade_in) {
-
- /* fade new material in */
-
- for (n = 0; n < xfade; ++n) {
- xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
- }
-
- } else {
-
-
- /* fade new material out */
-
- for (n = 0; n < xfade; ++n) {
- xfade_buf[n] = (xfade_buf[n] * in_coefficient[n]) + (fade_data[n] * out_coefficient[n]);
- }
- }
-
- } else if (xfade) {
-
- gain_t in[xfade];
- gain_t out[xfade];
-
- /* short xfade, compute custom curve */
-
- compute_equal_power_fades (xfade, in, out);
-
- for (nframes_t n = 0; n < xfade; ++n) {
- xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]);
- }
- }
-
- if (xfade) {
- if (write_float (xfade_buf, fade_position, xfade) != xfade) {
- error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
- return 0;
- }
- }
-
- if (fade_in && nofade) {
- if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
- error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
- return 0;
- }
- }
-
- return cnt;
-}
-
-nframes_t
-DestructiveFileSource::write_unlocked (Sample* data, nframes_t cnt)
-{
- nframes_t old_file_pos;
-
- if (!writable()) {
- return 0;
- }
-
- if (_capture_start && _capture_end) {
-
- /* start and end of capture both occur within the data we are writing,
- so do both crossfades.
- */
-
- _capture_start = false;
- _capture_end = false;
-
- /* move to the correct location place */
- file_pos = capture_start_frame - timeline_position;
-
- // split cnt in half
- nframes_t subcnt = cnt / 2;
- nframes_t ofilepos = file_pos;
-
- // fade in
- if (crossfade (data, subcnt, 1) != subcnt) {
- return 0;
- }
-
- file_pos += subcnt;
- Sample * tmpdata = data + subcnt;
-
- // fade out
- subcnt = cnt - subcnt;
- if (crossfade (tmpdata, subcnt, 0) != subcnt) {
- return 0;
- }
-
- file_pos = ofilepos; // adjusted below
-
- } else if (_capture_start) {
-
- /* start of capture both occur within the data we are writing,
- so do the fade in
- */
-
- _capture_start = false;
- _capture_end = false;
-
- /* move to the correct location place */
- file_pos = capture_start_frame - timeline_position;
-
- if (crossfade (data, cnt, 1) != cnt) {
- return 0;
- }
-
- } else if (_capture_end) {
-
- /* end of capture both occur within the data we are writing,
- so do the fade out
- */
-
- _capture_start = false;
- _capture_end = false;
-
- if (crossfade (data, cnt, 0) != cnt) {
- return 0;
- }
-
- } else {
-
- /* in the middle of recording */
-
- if (write_float (data, file_pos, cnt) != cnt) {
- return 0;
- }
- }
-
- old_file_pos = file_pos;
- update_length (file_pos, cnt);
- file_pos += cnt;
-
- if (_build_peakfiles) {
- PeakBuildRecord *pbr = 0;
-
- if (pending_peak_builds.size()) {
- pbr = pending_peak_builds.back();
- }
-
- if (pbr && pbr->frame + pbr->cnt == old_file_pos) {
-
- /* the last PBR extended to the start of the current write,
- so just extend it again.
- */
-
- pbr->cnt += cnt;
- } else {
- pending_peak_builds.push_back (new PeakBuildRecord (old_file_pos, cnt));
- }
-
- _peaks_built = false;
- }
-
- if (_build_peakfiles) {
- queue_for_peaks (shared_from_this ());
- }
-
- return cnt;
-}
-
-nframes_t
-DestructiveFileSource::last_capture_start_frame () const
-{
- return capture_start_frame;
-}
-
-XMLNode&
-DestructiveFileSource::get_state ()
-{
- XMLNode& node = AudioFileSource::get_state ();
- node.add_property (X_("destructive"), "true");
- return node;
-}
-
-void
-DestructiveFileSource::handle_header_position_change ()
-{
- if ( _length != 0 ) {
- error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
- //in the future, pop up a dialog here that allows user to regenerate file with new start offset
- } else if (writable()) {
- timeline_position = header_position_offset;
- set_header_timeline_position (); //this will get flushed if/when the file is recorded to
- }
-}
-
-void
-DestructiveFileSource::set_timeline_position (int64_t pos)
-{
- //destructive track timeline postion does not change except at instantion or when header_position_offset (session start) changes
-}
-
-int
-DestructiveFileSource::read_peaks (PeakData *peaks, nframes_t npeaks, nframes_t start, nframes_t cnt, double samples_per_unit) const
-{
- // cerr << _name << " read peaks at " << start << " for " << cnt << " tpos = " << timeline_position << endl;
- return AudioFileSource::read_peaks (peaks, npeaks, start, cnt, samples_per_unit);
-}
-
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
index 09c5b75b86..c8fd2e48bf 100644
--- a/libs/ardour/diskstream.cc
+++ b/libs/ardour/diskstream.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $
*/
#include <fstream>
@@ -45,7 +44,6 @@
#include <ardour/utils.h>
#include <ardour/configuration.h>
#include <ardour/audiofilesource.h>
-#include <ardour/destructive_filesource.h>
#include <ardour/send.h>
#include <ardour/playlist.h>
#include <ardour/cycle_timer.h>
@@ -125,9 +123,6 @@ Diskstream::init (Flag f)
Diskstream::~Diskstream ()
{
- // Taken by derived class destrctors.. should assure locked here somehow?
- //Glib::Mutex::Lock lm (state_lock);
-
if (_playlist)
_playlist->release ();
}
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 0460df43d8..4220adf7eb 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -31,6 +31,7 @@ setup_enum_writer ()
RegionPoint _RegionPoint;
Placement _Placement;
MonitorModel _MonitorModel;
+ RemoteModel _RemoteModel;
CrossfadeModel _CrossfadeModel;
LayerModel _LayerModel;
SoloModel _SoloModel;
@@ -142,6 +143,11 @@ setup_enum_writer ()
REGISTER_ENUM (ExternalMonitoring);
REGISTER (_MonitorModel);
+ REGISTER_ENUM (UserOrdered);
+ REGISTER_ENUM (MixerOrdered);
+ REGISTER_ENUM (EditorOrdered);
+ REGISTER (_RemoteModel);
+
REGISTER_ENUM (FullCrossfade);
REGISTER_ENUM (ShortCrossfade);
REGISTER (_CrossfadeModel);
diff --git a/libs/ardour/gain.cc b/libs/ardour/gain.cc
index 0b77bea279..369df7348c 100644
--- a/libs/ardour/gain.cc
+++ b/libs/ardour/gain.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/gain.h>
diff --git a/libs/ardour/gdither.cc b/libs/ardour/gdither.cc
index ec6bfaa2ea..7242f857c8 100644
--- a/libs/ardour/gdither.cc
+++ b/libs/ardour/gdither.cc
@@ -15,7 +15,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id$
*/
#include <ardour/gdither_types_internal.h>
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 549f4b7dbb..f5e841f00f 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -235,6 +235,7 @@ setup_hardware_optimization (bool try_optimization)
// SSE SET
Session::compute_peak = x86_sse_compute_peak;
+ Session::find_peaks = x86_sse_find_peaks;
Session::apply_gain_to_buffer = x86_sse_apply_gain_to_buffer;
Session::mix_buffers_with_gain = x86_sse_mix_buffers_with_gain;
Session::mix_buffers_no_gain = x86_sse_mix_buffers_no_gain;
@@ -251,6 +252,7 @@ setup_hardware_optimization (bool try_optimization)
if (sysVersion >= 0x00001040) { // Tiger at least
Session::compute_peak = veclib_compute_peak;
+ Session::find_peaks = veclib_find_peaks;
Session::apply_gain_to_buffer = veclib_apply_gain_to_buffer;
Session::mix_buffers_with_gain = veclib_mix_buffers_with_gain;
Session::mix_buffers_no_gain = veclib_mix_buffers_no_gain;
@@ -264,7 +266,8 @@ setup_hardware_optimization (bool try_optimization)
if (generic_mix_functions) {
- Session::compute_peak = compute_peak;
+ Session::compute_peak = compute_peak;
+ Session::find_peaks = find_peaks;
Session::apply_gain_to_buffer = apply_gain_to_buffer;
Session::mix_buffers_with_gain = mix_buffers_with_gain;
Session::mix_buffers_no_gain = mix_buffers_no_gain;
@@ -280,8 +283,6 @@ ARDOUR::init (ARDOUR::AudioEngine& engine, bool use_vst, bool try_optimization)
(void) bindtextdomain(PACKAGE, LOCALEDIR);
- PBD::ID::init ();
-
setup_enum_writer ();
lrdf_init();
@@ -617,6 +618,7 @@ std::istream& operator>>(std::istream& o, HeaderFormat& var) { return int_to_typ
std::istream& operator>>(std::istream& o, SampleFormat& var) { return int_to_type<SampleFormat> (o, var); }
std::istream& operator>>(std::istream& o, AutoConnectOption& var) { return int_to_type<AutoConnectOption> (o, var); }
std::istream& operator>>(std::istream& o, MonitorModel& var) { return int_to_type<MonitorModel> (o, var); }
+std::istream& operator>>(std::istream& o, RemoteModel& var) { return int_to_type<RemoteModel> (o, var); }
std::istream& operator>>(std::istream& o, EditMode& var) { return int_to_type<EditMode> (o, var); }
std::istream& operator>>(std::istream& o, SoloModel& var) { return int_to_type<SoloModel> (o, var); }
std::istream& operator>>(std::istream& o, LayerModel& var) { return int_to_type<LayerModel> (o, var); }
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index 4466c40a32..7c0deccca1 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cstdio>
@@ -52,6 +51,63 @@ using namespace PBD;
#define BLOCKSIZE 4096U
+class ImportableSource {
+ public:
+ ImportableSource (SNDFILE* sf, SF_INFO* info) : in (sf), sf_info (info) {}
+ virtual ~ImportableSource() {}
+
+ virtual nframes_t read (Sample* buffer, nframes_t nframes) {
+ nframes_t per_channel = nframes / sf_info->channels;
+ per_channel = sf_readf_float (in, buffer, per_channel);
+ return per_channel * sf_info->channels;
+ }
+
+ virtual float ratio() const { return 1.0f; }
+
+protected:
+ SNDFILE* in;
+ SF_INFO* sf_info;
+};
+
+class ResampledImportableSource : public ImportableSource {
+ public:
+ ResampledImportableSource (SNDFILE* sf, SF_INFO* info, nframes_t rate) : ImportableSource (sf, info) {
+ int err;
+
+ sf_seek (in, 0, SEEK_SET) ;
+
+ /* Initialize the sample rate converter. */
+
+ if ((src_state = src_new (SRC_SINC_BEST_QUALITY, sf_info->channels, &err)) == 0) {
+ error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ;
+ throw failed_constructor ();
+ }
+
+ src_data.end_of_input = 0 ; /* Set this later. */
+
+ /* Start with zero to force load in while loop. */
+
+ src_data.input_frames = 0 ;
+ src_data.data_in = input ;
+
+ src_data.src_ratio = ((float) rate) / sf_info->samplerate ;
+
+ }
+
+ ~ResampledImportableSource () {
+ src_state = src_delete (src_state) ;
+ }
+
+ nframes_t read (Sample* buffer, nframes_t nframes);
+
+ float ratio() const { return src_data.src_ratio; }
+
+ private:
+ float input[BLOCKSIZE];
+ SRC_STATE* src_state;
+ SRC_DATA src_data;
+};
+
int
Session::import_audiofile (import_status& status)
{
@@ -62,7 +118,6 @@ Session::import_audiofile (import_status& status)
float *data = 0;
Sample **channel_data = 0;
long nfiles = 0;
- long n;
string basepath;
string sounds_dir;
nframes_t so_far;
@@ -70,42 +125,32 @@ Session::import_audiofile (import_status& status)
int ret = -1;
vector<string> new_paths;
struct tm* now;
- string tmp_convert_file;
-
+ ImportableSource* importable = 0;
+ const nframes_t nframes = BLOCKSIZE;
+
status.new_regions.clear ();
if ((in = sf_open (status.paths.front().c_str(), SFM_READ, &info)) == 0) {
error << string_compose(_("Import: cannot open input sound file \"%1\""), status.paths.front()) << endmsg;
+ status.done = 1;
+ status.cancel = 1;
return -1;
+ }
+
+ if ((nframes_t) info.samplerate != frame_rate()) {
+ importable = new ResampledImportableSource (in, &info, frame_rate());
} else {
- if ((uint32_t) info.samplerate != frame_rate()) {
- sf_close(in);
- status.doing_what = _("resampling audio");
- // resample to session frame_rate
- if (sample_rate_convert(status, status.paths.front(), tmp_convert_file)) {
- if ((in = sf_open (tmp_convert_file.c_str(), SFM_READ, &info)) == 0) {
- error << string_compose(_("Import: cannot open converted sound file \"%1\""), tmp_convert_file) << endmsg;
- return -1;
- }
- } else if (!status.cancel){
- // error
- error << string_compose(_("Import: error while resampling sound file \"%1\""), status.paths.front()) << endmsg;
- return -1;
- } else {
- // canceled
- goto out;
- }
- }
+ importable = new ImportableSource (in, &info);
}
- for (n = 0; n < info.channels; ++n) {
+ for (int n = 0; n < info.channels; ++n) {
newfiles.push_back (boost::shared_ptr<AudioFileSource>());
}
sounds_dir = discover_best_sound_dir ();
basepath = PBD::basename_nosuffix (status.paths.front());
- for (n = 0; n < info.channels; ++n) {
+ for (int n = 0; n < info.channels; ++n) {
bool goodfile = false;
@@ -117,12 +162,12 @@ Session::import_audiofile (import_status& status)
snprintf (buf, sizeof(buf), "%s/%s-R.wav", sounds_dir.c_str(), basepath.c_str());
}
} else if (info.channels > 1) {
- snprintf (buf, sizeof(buf), "%s/%s-c%lu.wav", sounds_dir.c_str(), basepath.c_str(), n+1);
+ snprintf (buf, sizeof(buf), "%s/%s-c%d.wav", sounds_dir.c_str(), basepath.c_str(), n+1);
} else {
snprintf (buf, sizeof(buf), "%s/%s.wav", sounds_dir.c_str(), basepath.c_str());
}
- if (::access (buf, F_OK) == 0) {
+ if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
/* if the file already exists, we must come up with
* a new name for it. for now we just keep appending
@@ -152,12 +197,11 @@ Session::import_audiofile (import_status& status)
nfiles++;
}
-
- data = new float[BLOCKSIZE * info.channels];
+ data = new float[nframes * info.channels];
channel_data = new Sample * [ info.channels ];
- for (n = 0; n < info.channels; ++n) {
- channel_data[n] = new Sample[BLOCKSIZE];
+ for (int n = 0; n < info.channels; ++n) {
+ channel_data[n] = new Sample[nframes];
}
so_far = 0;
@@ -167,18 +211,21 @@ Session::import_audiofile (import_status& status)
while (!status.cancel) {
- long nread;
+ nframes_t nread, nfread;
long x;
long chn;
-
- if ((nread = sf_readf_float (in, data, BLOCKSIZE)) == 0) {
+
+ if ((nread = importable->read (data, nframes)) == 0) {
break;
}
+ nfread = nread / info.channels;
/* de-interleave */
for (chn = 0; chn < info.channels; ++chn) {
- for (x = chn, n = 0; n < nread; x += info.channels, ++n) {
+
+ nframes_t n;
+ for (x = chn, n = 0; n < nfread; x += info.channels, ++n) {
channel_data[chn][n] = (Sample) data[x];
}
}
@@ -186,11 +233,15 @@ Session::import_audiofile (import_status& status)
/* flush to disk */
for (chn = 0; chn < info.channels; ++chn) {
- newfiles[chn]->write (channel_data[chn], nread);
+ newfiles[chn]->write (channel_data[chn], nfread);
}
so_far += nread;
- status.progress = so_far / (float) (info.frames * info.channels);
+ status.progress = so_far / (importable->ratio () * info.frames * info.channels);
+ }
+
+ if (status.cancel) {
+ goto out;
}
if (status.multichan) {
@@ -205,13 +256,10 @@ Session::import_audiofile (import_status& status)
time (&xnow);
now = localtime (&xnow);
- if (status.cancel) {
- goto out;
- }
-
if (status.multichan) {
/* all sources are used in a single multichannel region */
- for (n = 0; n < nfiles && !status.cancel; ++n) {
+
+ for (int n = 0; n < nfiles && !status.cancel; ++n) {
/* flush the final length to the header */
newfiles[n]->update_header(0, *now, xnow);
sources.push_back(newfiles[n]);
@@ -228,7 +276,7 @@ Session::import_audiofile (import_status& status)
status.new_regions.push_back (r);
} else {
- for (n = 0; n < nfiles && !status.cancel; ++n) {
+ for (int n = 0; n < nfiles && !status.cancel; ++n) {
/* flush the final length to the header */
@@ -263,7 +311,7 @@ Session::import_audiofile (import_status& status)
}
if (channel_data) {
- for (n = 0; n < info.channels; ++n) {
+ for (int n = 0; n < info.channels; ++n) {
delete [] channel_data[n];
}
delete [] channel_data;
@@ -277,116 +325,59 @@ Session::import_audiofile (import_status& status)
}
}
- if (tmp_convert_file.length()) {
- unlink(tmp_convert_file.c_str());
+ if (importable) {
+ delete importable;
}
-
- sf_close (in);
+
+ sf_close (in);
status.done = true;
+
return ret;
}
-string
-Session::build_tmp_convert_name(string infile)
+nframes_t
+ResampledImportableSource::read (Sample* output, nframes_t nframes)
{
- string tmp_name(_path + "/." + Glib::path_get_basename (infile.c_str()) + "XXXXXX");
- char* tmp = new char[tmp_name.length() + 1];
- tmp_name.copy(tmp, string::npos);
- tmp[tmp_name.length()] = 0;
- mkstemp(tmp);
- string outfile = tmp;
- delete [] tmp;
-
- return outfile;
-}
+ int err;
-bool
-Session::sample_rate_convert (import_status& status, string infile, string& outfile)
-{
- float input [BLOCKSIZE] ;
- float output [BLOCKSIZE] ;
-
- SF_INFO sf_info;
- SRC_STATE* src_state ;
- SRC_DATA src_data ;
- int err ;
- sf_count_t output_count = 0 ;
- sf_count_t input_count = 0;
-
- SNDFILE* in = sf_open(infile.c_str(), SFM_READ, &sf_info);
- if (!in) {
- error << string_compose(_("Import/SRC: could not open input file: %1"), outfile) << endmsg;
- return false;
- }
- sf_count_t total_input_frames = sf_info.frames;
+ /* If the input buffer is empty, refill it. */
- outfile = build_tmp_convert_name(infile);
- SNDFILE* out = sf_open(outfile.c_str(), SFM_RDWR, &sf_info);
- if (!out) {
- error << string_compose(_("Import/SRC: could not open output file: %1"), outfile) << endmsg;
- return false;
- }
-
- sf_seek (in, 0, SEEK_SET) ;
- sf_seek (out, 0, SEEK_SET) ;
-
- /* Initialize the sample rate converter. */
- if ((src_state = src_new (SRC_SINC_BEST_QUALITY, sf_info.channels, &err)) == 0) {
- error << string_compose(_("Import: src_new() failed : %1"), src_strerror (err)) << endmsg ;
- return false ;
- }
+ if (src_data.input_frames == 0) {
- src_data.end_of_input = 0 ; /* Set this later. */
-
- /* Start with zero to force load in while loop. */
- src_data.input_frames = 0 ;
- src_data.data_in = input ;
-
- src_data.src_ratio = (1.0 * frame_rate()) / sf_info.samplerate ;
-
- src_data.data_out = output ;
- src_data.output_frames = BLOCKSIZE / sf_info.channels ;
-
- while (!status.cancel) {
- /* If the input buffer is empty, refill it. */
- if (src_data.input_frames == 0) {
- src_data.input_frames = sf_readf_float (in, input, BLOCKSIZE / sf_info.channels) ;
- src_data.data_in = input ;
-
- /* The last read will not be a full buffer, so snd_of_input. */
- if (src_data.input_frames < (int)BLOCKSIZE / sf_info.channels) {
- src_data.end_of_input = SF_TRUE ;
- }
- }
+ src_data.input_frames = ImportableSource::read (input, BLOCKSIZE);
- if ((err = src_process (src_state, &src_data))) {
- error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ;
- return false ;
- }
+ /* The last read will not be a full buffer, so set end_of_input. */
- /* Terminate if at end */
- if (src_data.end_of_input && src_data.output_frames_gen == 0) {
- break ;
- }
+ if ((nframes_t) src_data.input_frames < BLOCKSIZE) {
+ src_data.end_of_input = SF_TRUE ;
+ }
- /* Write output. */
- sf_writef_float (out, output, src_data.output_frames_gen) ;
- output_count += src_data.output_frames_gen ;
- input_count += src_data.input_frames_used;
+ src_data.input_frames /= sf_info->channels;
+ src_data.data_in = input ;
+ }
+
+ src_data.data_out = output;
- src_data.data_in += src_data.input_frames_used * sf_info.channels ;
- src_data.input_frames -= src_data.input_frames_used ;
-
- status.progress = (float) input_count / total_input_frames;
+ if (!src_data.end_of_input) {
+ src_data.output_frames = nframes / sf_info->channels ;
+ } else {
+ src_data.output_frames = src_data.input_frames;
}
- src_state = src_delete (src_state) ;
- sf_close(in);
- sf_close(out);
-
- if (status.cancel) {
- return false;
- } else {
- return true ;
+ if ((err = src_process (src_state, &src_data))) {
+ error << string_compose(_("Import: %1"), src_strerror (err)) << endmsg ;
+ return 0 ;
+ }
+
+ /* Terminate if at end */
+
+ if (src_data.end_of_input && src_data.output_frames_gen == 0) {
+ return 0;
}
+
+ src_data.data_in += src_data.input_frames_used * sf_info->channels ;
+ src_data.input_frames -= src_data.input_frames_used ;
+
+ return src_data.output_frames_gen * sf_info->channels;
}
+
diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc
index d109642fd4..e5d77c3951 100644
--- a/libs/ardour/insert.cc
+++ b/libs/ardour/insert.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <string>
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index b7472781a8..a9284d779c 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -27,6 +27,7 @@
#include <glibmm/thread.h>
#include <pbd/xml++.h>
+#include <pbd/replace_all.h>
#include <ardour/audioengine.h>
#include <ardour/io.h>
@@ -1817,6 +1818,12 @@ IO::set_name (string name, void* src)
return 0;
}
+ /* replace all colons in the name. i wish we didn't have to do this */
+
+ if (replace_all (name, ":", "-")) {
+ warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
+ }
+
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
string current_name = i->short_name();
current_name.replace (current_name.find (_name), _name.length(), name);
diff --git a/libs/ardour/jack_slave.cc b/libs/ardour/jack_slave.cc
index 2e03b2f45d..a06e295a09 100644
--- a/libs/ardour/jack_slave.cc
+++ b/libs/ardour/jack_slave.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <iostream>
diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc
index c21d09e01b..ba944f3c08 100644
--- a/libs/ardour/ladspa_plugin.cc
+++ b/libs/ardour/ladspa_plugin.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#define __STDC_FORMAT_MACROS 1
diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc
index bec87e5dd6..3d04c66824 100644
--- a/libs/ardour/location.cc
+++ b/libs/ardour/location.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -662,7 +661,7 @@ struct LocationStartLaterComparison
};
Location *
-Locations::first_location_before (nframes_t frame)
+Locations::first_location_before (nframes_t frame, bool include_special_ranges)
{
LocationList locs;
@@ -677,6 +676,9 @@ Locations::first_location_before (nframes_t frame)
/* locs is now sorted latest..earliest */
for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
+ if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
+ continue;
+ }
if (!(*i)->is_hidden() && (*i)->start() < frame) {
return (*i);
}
@@ -686,7 +688,7 @@ Locations::first_location_before (nframes_t frame)
}
Location *
-Locations::first_location_after (nframes_t frame)
+Locations::first_location_after (nframes_t frame, bool include_special_ranges)
{
LocationList locs;
@@ -701,6 +703,9 @@ Locations::first_location_after (nframes_t frame)
/* locs is now sorted earliest..latest */
for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
+ if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
+ continue;
+ }
if (!(*i)->is_hidden() && (*i)->start() > frame) {
return (*i);
}
@@ -710,7 +715,7 @@ Locations::first_location_after (nframes_t frame)
}
nframes_t
-Locations::first_mark_before (nframes_t frame)
+Locations::first_mark_before (nframes_t frame, bool include_special_ranges)
{
LocationList locs;
@@ -725,6 +730,9 @@ Locations::first_mark_before (nframes_t frame)
/* locs is now sorted latest..earliest */
for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
+ if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
+ continue;
+ }
if (!(*i)->is_hidden()) {
if ((*i)->is_mark()) {
/* MARK: start == end */
@@ -747,7 +755,7 @@ Locations::first_mark_before (nframes_t frame)
}
nframes_t
-Locations::first_mark_after (nframes_t frame)
+Locations::first_mark_after (nframes_t frame, bool include_special_ranges)
{
LocationList locs;
@@ -762,6 +770,9 @@ Locations::first_mark_after (nframes_t frame)
/* locs is now sorted earliest..latest */
for (LocationList::iterator i = locs.begin(); i != locs.end(); ++i) {
+ if (!include_special_ranges && ((*i)->is_auto_loop() || (*i)->is_auto_punch())) {
+ continue;
+ }
if (!(*i)->is_hidden()) {
if ((*i)->is_mark()) {
/* MARK, start == end so just compare start */
diff --git a/libs/ardour/macosx/English.lproj/InfoPlist.strings b/libs/ardour/macosx/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000000..0c0cacad8b
--- /dev/null
+++ b/libs/ardour/macosx/English.lproj/InfoPlist.strings
Binary files differ
diff --git a/libs/ardour/macosx/Info.plist b/libs/ardour/macosx/Info.plist
new file mode 100644
index 0000000000..931491039f
--- /dev/null
+++ b/libs/ardour/macosx/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>ardour</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.carbonframeworktemplate</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.01</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+</dict>
+</plist>
diff --git a/libs/ardour/macosx/ardour.xcodeproj/project.pbxproj b/libs/ardour/macosx/ardour.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..4026b65f59
--- /dev/null
+++ b/libs/ardour/macosx/ardour.xcodeproj/project.pbxproj
@@ -0,0 +1,1214 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 42;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 696149E90B97CEF500ECBDF0 /* glib in Frameworks */ = {isa = PBXBuildFile; fileRef = 696149E50B97CEF500ECBDF0 /* glib */; };
+ 696149EA0B97CEF500ECBDF0 /* gmodule in Frameworks */ = {isa = PBXBuildFile; fileRef = 696149E60B97CEF500ECBDF0 /* gmodule */; };
+ 696149EB0B97CEF500ECBDF0 /* gobject in Frameworks */ = {isa = PBXBuildFile; fileRef = 696149E70B97CEF500ECBDF0 /* gobject */; };
+ 696149EC0B97CEF500ECBDF0 /* gthread in Frameworks */ = {isa = PBXBuildFile; fileRef = 696149E80B97CEF500ECBDF0 /* gthread */; };
+ 6964FECA0B8E7A7900799BAE /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 6964FEC80B8E7A7900799BAE /* version.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6964FECB0B8E7A7900799BAE /* version.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6964FEC90B8E7A7900799BAE /* version.cc */; };
+ 696C90530B8D526000D66CAF /* ardour.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FAF0B8D526000D66CAF /* ardour.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90540B8D526000D66CAF /* audio_diskstream.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB00B8D526000D66CAF /* audio_diskstream.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90550B8D526000D66CAF /* audio_library.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB10B8D526000D66CAF /* audio_library.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90560B8D526000D66CAF /* audio_track.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB20B8D526000D66CAF /* audio_track.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90580B8D526000D66CAF /* audioengine.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB40B8D526000D66CAF /* audioengine.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90590B8D526000D66CAF /* audiofilesource.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB50B8D526000D66CAF /* audiofilesource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C905A0B8D526000D66CAF /* audiofilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB60B8D526000D66CAF /* audiofilter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C905B0B8D526000D66CAF /* audioplaylist.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB70B8D526000D66CAF /* audioplaylist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C905C0B8D526000D66CAF /* audioregion.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB80B8D526000D66CAF /* audioregion.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C905D0B8D526000D66CAF /* audiosource.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FB90B8D526000D66CAF /* audiosource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C905E0B8D526000D66CAF /* auditioner.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FBA0B8D526000D66CAF /* auditioner.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C905F0B8D526000D66CAF /* automation_event.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FBB0B8D526000D66CAF /* automation_event.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90600B8D526000D66CAF /* buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FBC0B8D526000D66CAF /* buffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90610B8D526000D66CAF /* click.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FBD0B8D526000D66CAF /* click.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90620B8D526000D66CAF /* configuration.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FBE0B8D526000D66CAF /* configuration.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90630B8D526000D66CAF /* configuration_variable.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FBF0B8D526000D66CAF /* configuration_variable.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90640B8D526000D66CAF /* configuration_vars.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC00B8D526000D66CAF /* configuration_vars.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90650B8D526000D66CAF /* connection.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC10B8D526000D66CAF /* connection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90660B8D526000D66CAF /* control_protocol_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC20B8D526000D66CAF /* control_protocol_manager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90680B8D526000D66CAF /* crossfade.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC40B8D526000D66CAF /* crossfade.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90690B8D526000D66CAF /* crossfade_compare.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC50B8D526000D66CAF /* crossfade_compare.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C906A0B8D526000D66CAF /* curve.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC60B8D526000D66CAF /* curve.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C906B0B8D526000D66CAF /* cycle_timer.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC70B8D526000D66CAF /* cycle_timer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C906C0B8D526000D66CAF /* cycles.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC80B8D526000D66CAF /* cycles.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C906D0B8D526000D66CAF /* data_type.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FC90B8D526000D66CAF /* data_type.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C906E0B8D526000D66CAF /* dB.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FCA0B8D526000D66CAF /* dB.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90700B8D526000D66CAF /* diskstream.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FCC0B8D526000D66CAF /* diskstream.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90710B8D526000D66CAF /* export.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FCD0B8D526000D66CAF /* export.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90720B8D526000D66CAF /* gain.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FCE0B8D526000D66CAF /* gain.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90730B8D526000D66CAF /* gdither.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FCF0B8D526000D66CAF /* gdither.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90740B8D526000D66CAF /* gdither_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD00B8D526000D66CAF /* gdither_types.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90750B8D526000D66CAF /* gdither_types_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD10B8D526000D66CAF /* gdither_types_internal.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90760B8D526000D66CAF /* insert.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD20B8D526000D66CAF /* insert.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90770B8D526000D66CAF /* io.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD30B8D526000D66CAF /* io.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90780B8D526000D66CAF /* ladspa.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD40B8D526000D66CAF /* ladspa.h */; settings = {ATTRIBUTES = (); }; };
+ 696C90790B8D526000D66CAF /* ladspa_plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD50B8D526000D66CAF /* ladspa_plugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C907A0B8D526000D66CAF /* location.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD60B8D526000D66CAF /* location.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C907B0B8D526000D66CAF /* logcurve.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD70B8D526000D66CAF /* logcurve.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C907C0B8D526000D66CAF /* mix.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD80B8D526000D66CAF /* mix.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C907D0B8D526000D66CAF /* named_selection.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FD90B8D526000D66CAF /* named_selection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C907E0B8D526000D66CAF /* noise.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FDA0B8D526000D66CAF /* noise.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C907F0B8D526000D66CAF /* osc.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FDB0B8D526000D66CAF /* osc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90800B8D526000D66CAF /* panner.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FDC0B8D526000D66CAF /* panner.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90810B8D526000D66CAF /* pcm_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FDD0B8D526000D66CAF /* pcm_utils.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90820B8D526000D66CAF /* peak.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FDE0B8D526000D66CAF /* peak.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90830B8D526000D66CAF /* playlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FDF0B8D526000D66CAF /* playlist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90840B8D526000D66CAF /* playlist_factory.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE00B8D526000D66CAF /* playlist_factory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90850B8D526000D66CAF /* playlist_templates.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE10B8D526000D66CAF /* playlist_templates.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90860B8D526000D66CAF /* plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE20B8D526000D66CAF /* plugin.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90870B8D526000D66CAF /* plugin_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE30B8D526000D66CAF /* plugin_manager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90880B8D526000D66CAF /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE40B8D526000D66CAF /* port.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90890B8D526000D66CAF /* recent_sessions.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE50B8D526000D66CAF /* recent_sessions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C908A0B8D526000D66CAF /* redirect.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE60B8D526000D66CAF /* redirect.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C908B0B8D526000D66CAF /* region.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE70B8D526000D66CAF /* region.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C908C0B8D526000D66CAF /* region_factory.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE80B8D526000D66CAF /* region_factory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C908D0B8D526000D66CAF /* reverse.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FE90B8D526000D66CAF /* reverse.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C908E0B8D526000D66CAF /* route.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FEA0B8D526000D66CAF /* route.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C908F0B8D526000D66CAF /* route_group.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FEB0B8D526000D66CAF /* route_group.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90900B8D526000D66CAF /* route_group_specialized.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FEC0B8D526000D66CAF /* route_group_specialized.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90910B8D526000D66CAF /* send.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FED0B8D526000D66CAF /* send.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90920B8D526000D66CAF /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FEE0B8D526000D66CAF /* session.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90930B8D526000D66CAF /* session_connection.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FEF0B8D526000D66CAF /* session_connection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90940B8D526000D66CAF /* session_playlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF00B8D526000D66CAF /* session_playlist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90950B8D526000D66CAF /* session_region.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF10B8D526000D66CAF /* session_region.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90960B8D526000D66CAF /* session_route.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF20B8D526000D66CAF /* session_route.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90970B8D526000D66CAF /* session_selection.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF30B8D526000D66CAF /* session_selection.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90980B8D526000D66CAF /* silentfilesource.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF40B8D526000D66CAF /* silentfilesource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90990B8D526000D66CAF /* slave.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF50B8D526000D66CAF /* slave.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C909A0B8D526000D66CAF /* sndfile_helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF60B8D526000D66CAF /* sndfile_helpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C909B0B8D526000D66CAF /* sndfilesource.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF70B8D526000D66CAF /* sndfilesource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C909C0B8D526000D66CAF /* soundseq.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF80B8D526000D66CAF /* soundseq.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C909D0B8D526000D66CAF /* source.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FF90B8D526000D66CAF /* source.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C909E0B8D526000D66CAF /* source_factory.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FFA0B8D526000D66CAF /* source_factory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C909F0B8D526000D66CAF /* spline.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FFB0B8D526000D66CAF /* spline.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90A00B8D526000D66CAF /* tempo.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FFC0B8D526000D66CAF /* tempo.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90A10B8D526000D66CAF /* timestamps.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FFD0B8D526000D66CAF /* timestamps.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90A20B8D526000D66CAF /* track.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FFE0B8D526000D66CAF /* track.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90A30B8D526000D66CAF /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C8FFF0B8D526000D66CAF /* types.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90A40B8D526000D66CAF /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C90000B8D526000D66CAF /* utils.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 696C90A60B8D526000D66CAF /* audio_diskstream.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90020B8D526000D66CAF /* audio_diskstream.cc */; };
+ 696C90A70B8D526000D66CAF /* audio_library.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90030B8D526000D66CAF /* audio_library.cc */; };
+ 696C90A80B8D526000D66CAF /* audio_playlist.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90040B8D526000D66CAF /* audio_playlist.cc */; };
+ 696C90A90B8D526000D66CAF /* audio_track.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90050B8D526000D66CAF /* audio_track.cc */; };
+ 696C90AB0B8D526000D66CAF /* audioengine.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90070B8D526000D66CAF /* audioengine.cc */; };
+ 696C90AC0B8D526000D66CAF /* audiofilesource.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90080B8D526000D66CAF /* audiofilesource.cc */; };
+ 696C90AD0B8D526000D66CAF /* audiofilter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90090B8D526000D66CAF /* audiofilter.cc */; };
+ 696C90AE0B8D526000D66CAF /* audioregion.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C900A0B8D526000D66CAF /* audioregion.cc */; };
+ 696C90AF0B8D526000D66CAF /* audiosource.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C900B0B8D526000D66CAF /* audiosource.cc */; };
+ 696C90B00B8D526000D66CAF /* auditioner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C900C0B8D526000D66CAF /* auditioner.cc */; };
+ 696C90B10B8D526000D66CAF /* automation.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C900D0B8D526000D66CAF /* automation.cc */; };
+ 696C90B20B8D526000D66CAF /* automation_event.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C900E0B8D526000D66CAF /* automation_event.cc */; };
+ 696C90B30B8D526000D66CAF /* configuration.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C900F0B8D526000D66CAF /* configuration.cc */; };
+ 696C90B40B8D526000D66CAF /* connection.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90100B8D526000D66CAF /* connection.cc */; };
+ 696C90B50B8D526000D66CAF /* control_protocol_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90110B8D526000D66CAF /* control_protocol_manager.cc */; };
+ 696C90B70B8D526000D66CAF /* crossfade.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90130B8D526000D66CAF /* crossfade.cc */; };
+ 696C90B80B8D526000D66CAF /* curve.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90140B8D526000D66CAF /* curve.cc */; };
+ 696C90B90B8D526000D66CAF /* cycle_timer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90150B8D526000D66CAF /* cycle_timer.cc */; };
+ 696C90BA0B8D526000D66CAF /* default_click.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90160B8D526000D66CAF /* default_click.cc */; };
+ 696C90BC0B8D526000D66CAF /* diskstream.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90180B8D526000D66CAF /* diskstream.cc */; };
+ 696C90BD0B8D526000D66CAF /* enums.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90190B8D526000D66CAF /* enums.cc */; };
+ 696C90BE0B8D526000D66CAF /* gain.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C901A0B8D526000D66CAF /* gain.cc */; };
+ 696C90BF0B8D526000D66CAF /* gdither.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C901B0B8D526000D66CAF /* gdither.cc */; };
+ 696C90C00B8D526000D66CAF /* gettext.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C901C0B8D526000D66CAF /* gettext.h */; settings = {ATTRIBUTES = (); }; };
+ 696C90C10B8D526000D66CAF /* globals.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C901D0B8D526000D66CAF /* globals.cc */; };
+ 696C90C20B8D526000D66CAF /* i18n.h in Headers */ = {isa = PBXBuildFile; fileRef = 696C901E0B8D526000D66CAF /* i18n.h */; settings = {ATTRIBUTES = (); }; };
+ 696C90C30B8D526000D66CAF /* import.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C901F0B8D526000D66CAF /* import.cc */; };
+ 696C90C40B8D526000D66CAF /* insert.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90200B8D526000D66CAF /* insert.cc */; };
+ 696C90C50B8D526000D66CAF /* io.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90210B8D526000D66CAF /* io.cc */; };
+ 696C90C60B8D526000D66CAF /* jack_slave.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90220B8D526000D66CAF /* jack_slave.cc */; };
+ 696C90C70B8D526000D66CAF /* ladspa_plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90230B8D526000D66CAF /* ladspa_plugin.cc */; };
+ 696C90C80B8D526000D66CAF /* location.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90240B8D526000D66CAF /* location.cc */; };
+ 696C90C90B8D526000D66CAF /* mix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90250B8D526000D66CAF /* mix.cc */; };
+ 696C90CA0B8D526000D66CAF /* mtc_slave.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90260B8D526000D66CAF /* mtc_slave.cc */; };
+ 696C90CB0B8D526000D66CAF /* named_selection.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90270B8D526000D66CAF /* named_selection.cc */; };
+ 696C90CC0B8D526000D66CAF /* osc.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90280B8D526000D66CAF /* osc.cc */; };
+ 696C90CD0B8D526000D66CAF /* panner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90290B8D526000D66CAF /* panner.cc */; };
+ 696C90CE0B8D526000D66CAF /* pcm_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C902A0B8D526000D66CAF /* pcm_utils.cc */; };
+ 696C90CF0B8D526000D66CAF /* playlist.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C902B0B8D526000D66CAF /* playlist.cc */; };
+ 696C90D00B8D526000D66CAF /* playlist_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C902C0B8D526000D66CAF /* playlist_factory.cc */; };
+ 696C90D10B8D526000D66CAF /* plugin.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C902D0B8D526000D66CAF /* plugin.cc */; };
+ 696C90D20B8D526000D66CAF /* plugin_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C902E0B8D526000D66CAF /* plugin_manager.cc */; };
+ 696C90D30B8D526000D66CAF /* port.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C902F0B8D526000D66CAF /* port.cc */; };
+ 696C90D40B8D526000D66CAF /* recent_sessions.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90300B8D526000D66CAF /* recent_sessions.cc */; };
+ 696C90D50B8D526000D66CAF /* redirect.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90310B8D526000D66CAF /* redirect.cc */; };
+ 696C90D60B8D526000D66CAF /* region.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90320B8D526000D66CAF /* region.cc */; };
+ 696C90D70B8D526000D66CAF /* region_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90330B8D526000D66CAF /* region_factory.cc */; };
+ 696C90D80B8D526000D66CAF /* reverse.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90340B8D526000D66CAF /* reverse.cc */; };
+ 696C90D90B8D526000D66CAF /* route.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90350B8D526000D66CAF /* route.cc */; };
+ 696C90DA0B8D526000D66CAF /* route_group.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90360B8D526000D66CAF /* route_group.cc */; };
+ 696C90DB0B8D526000D66CAF /* send.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90370B8D526000D66CAF /* send.cc */; };
+ 696C90DC0B8D526000D66CAF /* session.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90380B8D526000D66CAF /* session.cc */; };
+ 696C90DD0B8D526000D66CAF /* session_butler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90390B8D526000D66CAF /* session_butler.cc */; };
+ 696C90DE0B8D526000D66CAF /* session_click.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C903A0B8D526000D66CAF /* session_click.cc */; };
+ 696C90DF0B8D526000D66CAF /* session_command.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C903B0B8D526000D66CAF /* session_command.cc */; };
+ 696C90E10B8D526000D66CAF /* session_events.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C903D0B8D526000D66CAF /* session_events.cc */; };
+ 696C90E20B8D526000D66CAF /* session_export.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C903E0B8D526000D66CAF /* session_export.cc */; };
+ 696C90E30B8D526000D66CAF /* session_feedback.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C903F0B8D526000D66CAF /* session_feedback.cc */; };
+ 696C90E40B8D526000D66CAF /* session_midi.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90400B8D526000D66CAF /* session_midi.cc */; };
+ 696C90E50B8D526000D66CAF /* session_process.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90410B8D526000D66CAF /* session_process.cc */; };
+ 696C90E60B8D526000D66CAF /* session_state.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90420B8D526000D66CAF /* session_state.cc */; };
+ 696C90E70B8D526000D66CAF /* session_time.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90430B8D526000D66CAF /* session_time.cc */; };
+ 696C90E80B8D526000D66CAF /* session_timefx.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90440B8D526000D66CAF /* session_timefx.cc */; };
+ 696C90E90B8D526000D66CAF /* session_transport.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90450B8D526000D66CAF /* session_transport.cc */; };
+ 696C90EB0B8D526000D66CAF /* silentfilesource.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90470B8D526000D66CAF /* silentfilesource.cc */; };
+ 696C90EC0B8D526000D66CAF /* sndfile_helpers.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90480B8D526000D66CAF /* sndfile_helpers.cc */; };
+ 696C90ED0B8D526000D66CAF /* sndfilesource.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90490B8D526000D66CAF /* sndfilesource.cc */; };
+ 696C90EE0B8D526000D66CAF /* source.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C904A0B8D526000D66CAF /* source.cc */; };
+ 696C90EF0B8D526000D66CAF /* source_factory.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C904B0B8D526000D66CAF /* source_factory.cc */; };
+ 696C90F20B8D526000D66CAF /* tempo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C904E0B8D526000D66CAF /* tempo.cc */; };
+ 696C90F30B8D526000D66CAF /* track.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C904F0B8D526000D66CAF /* track.cc */; };
+ 696C90F40B8D526000D66CAF /* utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 696C90500B8D526000D66CAF /* utils.cc */; };
+ 696C91000B8D52F300D66CAF /* glibmm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90F70B8D52F300D66CAF /* glibmm.framework */; };
+ 696C91010B8D52F300D66CAF /* Jack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90F80B8D52F300D66CAF /* Jack.framework */; };
+ 696C91020B8D52F300D66CAF /* lo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90F90B8D52F300D66CAF /* lo.framework */; };
+ 696C91030B8D52F300D66CAF /* LRdf.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90FA0B8D52F300D66CAF /* LRdf.framework */; };
+ 696C91040B8D52F300D66CAF /* Raptor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90FB0B8D52F300D66CAF /* Raptor.framework */; };
+ 696C91050B8D52F300D66CAF /* SampleRate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90FC0B8D52F300D66CAF /* SampleRate.framework */; };
+ 696C91060B8D52F300D66CAF /* sigc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90FD0B8D52F300D66CAF /* sigc.framework */; };
+ 696C91070B8D52F300D66CAF /* Sndfile-ardour.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90FE0B8D52F300D66CAF /* Sndfile-ardour.framework */; };
+ 696C91080B8D52F300D66CAF /* soundtouch.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 696C90FF0B8D52F300D66CAF /* soundtouch.framework */; };
+ 697D98090B8DCD8C0006A892 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 697D98080B8DCD8C0006A892 /* libxml2.dylib */; };
+ 698D9AB60B969A6F00C53B63 /* midi++.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 698D9AB50B969A5B00C53B63 /* midi++.framework */; };
+ 69AD45850B97D10600806E7E /* FLAC in Frameworks */ = {isa = PBXBuildFile; fileRef = 69AD45840B97D10600806E7E /* FLAC */; };
+ 69B1B5210B8E7DFD007E41C1 /* pbd.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 691B3B7C0B8D5508009155B5 /* pbd.framework */; };
+ 69B1B5500B8E80AD007E41C1 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69B1B54F0B8E80AD007E41C1 /* CoreAudio.framework */; };
+ 69DBC41B0BA794A500C19E65 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DBC41A0BA794A500C19E65 /* Accelerate.framework */; };
+ 69DBC42B0BA7992800C19E65 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DBC42A0BA7992800C19E65 /* Carbon.framework */; };
+ 69F7CE5A0B8DCB3300D76871 /* basic_ui.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69F7CE520B8DCB3300D76871 /* basic_ui.cc */; };
+ 69F7CE5B0B8DCB3300D76871 /* basic_ui.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F7CE540B8DCB3300D76871 /* basic_ui.h */; };
+ 69F7CE5C0B8DCB3300D76871 /* control_protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F7CE550B8DCB3300D76871 /* control_protocol.h */; };
+ 69F7CE5D0B8DCB3300D76871 /* smpte.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F7CE560B8DCB3300D76871 /* smpte.h */; };
+ 69F7CE5E0B8DCB3300D76871 /* control_protocol.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69F7CE570B8DCB3300D76871 /* control_protocol.cc */; };
+ 69F7CE600B8DCB3300D76871 /* smpte.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69F7CE590B8DCB3300D76871 /* smpte.cc */; };
+ 8D07F2BE0486CC7A007CD1D0 /* ardour_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 32BAE0B70371A74B00C91783 /* ardour_Prefix.pch */; settings = {ATTRIBUTES = (); }; };
+ 8D07F2C00486CC7A007CD1D0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 691B3B7B0B8D5508009155B5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 691B3B770B8D5508009155B5 /* pbd.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 8D07F2C80486CC7A007CD1D0;
+ remoteInfo = pbd;
+ };
+ 698D9AB40B969A5B00C53B63 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 698D9AB00B969A5B00C53B63 /* midi++.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 8D07F2C80486CC7A007CD1D0;
+ remoteInfo = "midi++";
+ };
+ 698D9AB90B969ADC00C53B63 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 698D9AB00B969A5B00C53B63 /* midi++.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+ remoteInfo = "midi++";
+ };
+ 69D5F6250B8D58A500301E71 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 691B3B770B8D5508009155B5 /* pbd.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+ remoteInfo = pbd;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 32BAE0B70371A74B00C91783 /* ardour_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ardour_Prefix.pch; sourceTree = "<group>"; };
+ 691B3B770B8D5508009155B5 /* pbd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = pbd.xcodeproj; path = ../../pbd/macosx/pbd.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 696149E50B97CEF500ECBDF0 /* glib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = glib; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/glib; sourceTree = "<absolute>"; };
+ 696149E60B97CEF500ECBDF0 /* gmodule */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gmodule; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gmodule; sourceTree = "<absolute>"; };
+ 696149E70B97CEF500ECBDF0 /* gobject */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gobject; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gobject; sourceTree = "<absolute>"; };
+ 696149E80B97CEF500ECBDF0 /* gthread */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gthread; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gthread; sourceTree = "<absolute>"; };
+ 6964FEC80B8E7A7900799BAE /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
+ 6964FEC90B8E7A7900799BAE /* version.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = version.cc; sourceTree = "<group>"; };
+ 696C8FAF0B8D526000D66CAF /* ardour.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ardour.h; sourceTree = "<group>"; };
+ 696C8FB00B8D526000D66CAF /* audio_diskstream.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audio_diskstream.h; sourceTree = "<group>"; };
+ 696C8FB10B8D526000D66CAF /* audio_library.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audio_library.h; sourceTree = "<group>"; };
+ 696C8FB20B8D526000D66CAF /* audio_track.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audio_track.h; sourceTree = "<group>"; };
+ 696C8FB40B8D526000D66CAF /* audioengine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audioengine.h; sourceTree = "<group>"; };
+ 696C8FB50B8D526000D66CAF /* audiofilesource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audiofilesource.h; sourceTree = "<group>"; };
+ 696C8FB60B8D526000D66CAF /* audiofilter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audiofilter.h; sourceTree = "<group>"; };
+ 696C8FB70B8D526000D66CAF /* audioplaylist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audioplaylist.h; sourceTree = "<group>"; };
+ 696C8FB80B8D526000D66CAF /* audioregion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audioregion.h; sourceTree = "<group>"; };
+ 696C8FB90B8D526000D66CAF /* audiosource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = audiosource.h; sourceTree = "<group>"; };
+ 696C8FBA0B8D526000D66CAF /* auditioner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = auditioner.h; sourceTree = "<group>"; };
+ 696C8FBB0B8D526000D66CAF /* automation_event.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = automation_event.h; sourceTree = "<group>"; };
+ 696C8FBC0B8D526000D66CAF /* buffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = buffer.h; sourceTree = "<group>"; };
+ 696C8FBD0B8D526000D66CAF /* click.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = click.h; sourceTree = "<group>"; };
+ 696C8FBE0B8D526000D66CAF /* configuration.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = configuration.h; sourceTree = "<group>"; };
+ 696C8FBF0B8D526000D66CAF /* configuration_variable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = configuration_variable.h; sourceTree = "<group>"; };
+ 696C8FC00B8D526000D66CAF /* configuration_vars.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = configuration_vars.h; sourceTree = "<group>"; };
+ 696C8FC10B8D526000D66CAF /* connection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = connection.h; sourceTree = "<group>"; };
+ 696C8FC20B8D526000D66CAF /* control_protocol_manager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = control_protocol_manager.h; sourceTree = "<group>"; };
+ 696C8FC40B8D526000D66CAF /* crossfade.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = crossfade.h; sourceTree = "<group>"; };
+ 696C8FC50B8D526000D66CAF /* crossfade_compare.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = crossfade_compare.h; sourceTree = "<group>"; };
+ 696C8FC60B8D526000D66CAF /* curve.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = curve.h; sourceTree = "<group>"; };
+ 696C8FC70B8D526000D66CAF /* cycle_timer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cycle_timer.h; sourceTree = "<group>"; };
+ 696C8FC80B8D526000D66CAF /* cycles.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cycles.h; sourceTree = "<group>"; };
+ 696C8FC90B8D526000D66CAF /* data_type.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = data_type.h; sourceTree = "<group>"; };
+ 696C8FCA0B8D526000D66CAF /* dB.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dB.h; sourceTree = "<group>"; };
+ 696C8FCC0B8D526000D66CAF /* diskstream.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = diskstream.h; sourceTree = "<group>"; };
+ 696C8FCD0B8D526000D66CAF /* export.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = export.h; sourceTree = "<group>"; };
+ 696C8FCE0B8D526000D66CAF /* gain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gain.h; sourceTree = "<group>"; };
+ 696C8FCF0B8D526000D66CAF /* gdither.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gdither.h; sourceTree = "<group>"; };
+ 696C8FD00B8D526000D66CAF /* gdither_types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gdither_types.h; sourceTree = "<group>"; };
+ 696C8FD10B8D526000D66CAF /* gdither_types_internal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gdither_types_internal.h; sourceTree = "<group>"; };
+ 696C8FD20B8D526000D66CAF /* insert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = insert.h; sourceTree = "<group>"; };
+ 696C8FD30B8D526000D66CAF /* io.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = io.h; sourceTree = "<group>"; };
+ 696C8FD40B8D526000D66CAF /* ladspa.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ladspa.h; sourceTree = "<group>"; };
+ 696C8FD50B8D526000D66CAF /* ladspa_plugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ladspa_plugin.h; sourceTree = "<group>"; };
+ 696C8FD60B8D526000D66CAF /* location.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = location.h; sourceTree = "<group>"; };
+ 696C8FD70B8D526000D66CAF /* logcurve.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = logcurve.h; sourceTree = "<group>"; };
+ 696C8FD80B8D526000D66CAF /* mix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mix.h; sourceTree = "<group>"; };
+ 696C8FD90B8D526000D66CAF /* named_selection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = named_selection.h; sourceTree = "<group>"; };
+ 696C8FDA0B8D526000D66CAF /* noise.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = noise.h; sourceTree = "<group>"; };
+ 696C8FDB0B8D526000D66CAF /* osc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = osc.h; sourceTree = "<group>"; };
+ 696C8FDC0B8D526000D66CAF /* panner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = panner.h; sourceTree = "<group>"; };
+ 696C8FDD0B8D526000D66CAF /* pcm_utils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pcm_utils.h; sourceTree = "<group>"; };
+ 696C8FDE0B8D526000D66CAF /* peak.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = peak.h; sourceTree = "<group>"; };
+ 696C8FDF0B8D526000D66CAF /* playlist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = playlist.h; sourceTree = "<group>"; };
+ 696C8FE00B8D526000D66CAF /* playlist_factory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = playlist_factory.h; sourceTree = "<group>"; };
+ 696C8FE10B8D526000D66CAF /* playlist_templates.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = playlist_templates.h; sourceTree = "<group>"; };
+ 696C8FE20B8D526000D66CAF /* plugin.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plugin.h; sourceTree = "<group>"; };
+ 696C8FE30B8D526000D66CAF /* plugin_manager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = plugin_manager.h; sourceTree = "<group>"; };
+ 696C8FE40B8D526000D66CAF /* port.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = port.h; sourceTree = "<group>"; };
+ 696C8FE50B8D526000D66CAF /* recent_sessions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = recent_sessions.h; sourceTree = "<group>"; };
+ 696C8FE60B8D526000D66CAF /* redirect.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = redirect.h; sourceTree = "<group>"; };
+ 696C8FE70B8D526000D66CAF /* region.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = region.h; sourceTree = "<group>"; };
+ 696C8FE80B8D526000D66CAF /* region_factory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = region_factory.h; sourceTree = "<group>"; };
+ 696C8FE90B8D526000D66CAF /* reverse.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = reverse.h; sourceTree = "<group>"; };
+ 696C8FEA0B8D526000D66CAF /* route.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = route.h; sourceTree = "<group>"; };
+ 696C8FEB0B8D526000D66CAF /* route_group.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = route_group.h; sourceTree = "<group>"; };
+ 696C8FEC0B8D526000D66CAF /* route_group_specialized.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = route_group_specialized.h; sourceTree = "<group>"; };
+ 696C8FED0B8D526000D66CAF /* send.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = send.h; sourceTree = "<group>"; };
+ 696C8FEE0B8D526000D66CAF /* session.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session.h; sourceTree = "<group>"; };
+ 696C8FEF0B8D526000D66CAF /* session_connection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session_connection.h; sourceTree = "<group>"; };
+ 696C8FF00B8D526000D66CAF /* session_playlist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session_playlist.h; sourceTree = "<group>"; };
+ 696C8FF10B8D526000D66CAF /* session_region.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session_region.h; sourceTree = "<group>"; };
+ 696C8FF20B8D526000D66CAF /* session_route.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session_route.h; sourceTree = "<group>"; };
+ 696C8FF30B8D526000D66CAF /* session_selection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = session_selection.h; sourceTree = "<group>"; };
+ 696C8FF40B8D526000D66CAF /* silentfilesource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = silentfilesource.h; sourceTree = "<group>"; };
+ 696C8FF50B8D526000D66CAF /* slave.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = slave.h; sourceTree = "<group>"; };
+ 696C8FF60B8D526000D66CAF /* sndfile_helpers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndfile_helpers.h; sourceTree = "<group>"; };
+ 696C8FF70B8D526000D66CAF /* sndfilesource.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sndfilesource.h; sourceTree = "<group>"; };
+ 696C8FF80B8D526000D66CAF /* soundseq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = soundseq.h; sourceTree = "<group>"; };
+ 696C8FF90B8D526000D66CAF /* source.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = source.h; sourceTree = "<group>"; };
+ 696C8FFA0B8D526000D66CAF /* source_factory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = source_factory.h; sourceTree = "<group>"; };
+ 696C8FFB0B8D526000D66CAF /* spline.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = spline.h; sourceTree = "<group>"; };
+ 696C8FFC0B8D526000D66CAF /* tempo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tempo.h; sourceTree = "<group>"; };
+ 696C8FFD0B8D526000D66CAF /* timestamps.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = timestamps.h; sourceTree = "<group>"; };
+ 696C8FFE0B8D526000D66CAF /* track.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = track.h; sourceTree = "<group>"; };
+ 696C8FFF0B8D526000D66CAF /* types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; };
+ 696C90000B8D526000D66CAF /* utils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
+ 696C90020B8D526000D66CAF /* audio_diskstream.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audio_diskstream.cc; path = ../audio_diskstream.cc; sourceTree = SOURCE_ROOT; };
+ 696C90030B8D526000D66CAF /* audio_library.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audio_library.cc; path = ../audio_library.cc; sourceTree = SOURCE_ROOT; };
+ 696C90040B8D526000D66CAF /* audio_playlist.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audio_playlist.cc; path = ../audio_playlist.cc; sourceTree = SOURCE_ROOT; };
+ 696C90050B8D526000D66CAF /* audio_track.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audio_track.cc; path = ../audio_track.cc; sourceTree = SOURCE_ROOT; };
+ 696C90070B8D526000D66CAF /* audioengine.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audioengine.cc; path = ../audioengine.cc; sourceTree = SOURCE_ROOT; };
+ 696C90080B8D526000D66CAF /* audiofilesource.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audiofilesource.cc; path = ../audiofilesource.cc; sourceTree = SOURCE_ROOT; };
+ 696C90090B8D526000D66CAF /* audiofilter.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audiofilter.cc; path = ../audiofilter.cc; sourceTree = SOURCE_ROOT; };
+ 696C900A0B8D526000D66CAF /* audioregion.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audioregion.cc; path = ../audioregion.cc; sourceTree = SOURCE_ROOT; };
+ 696C900B0B8D526000D66CAF /* audiosource.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = audiosource.cc; path = ../audiosource.cc; sourceTree = SOURCE_ROOT; };
+ 696C900C0B8D526000D66CAF /* auditioner.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = auditioner.cc; path = ../auditioner.cc; sourceTree = SOURCE_ROOT; };
+ 696C900D0B8D526000D66CAF /* automation.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = automation.cc; path = ../automation.cc; sourceTree = SOURCE_ROOT; };
+ 696C900E0B8D526000D66CAF /* automation_event.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = automation_event.cc; path = ../automation_event.cc; sourceTree = SOURCE_ROOT; };
+ 696C900F0B8D526000D66CAF /* configuration.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = configuration.cc; path = ../configuration.cc; sourceTree = SOURCE_ROOT; };
+ 696C90100B8D526000D66CAF /* connection.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = connection.cc; path = ../connection.cc; sourceTree = SOURCE_ROOT; };
+ 696C90110B8D526000D66CAF /* control_protocol_manager.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = control_protocol_manager.cc; path = ../control_protocol_manager.cc; sourceTree = SOURCE_ROOT; };
+ 696C90130B8D526000D66CAF /* crossfade.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = crossfade.cc; path = ../crossfade.cc; sourceTree = SOURCE_ROOT; };
+ 696C90140B8D526000D66CAF /* curve.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = curve.cc; path = ../curve.cc; sourceTree = SOURCE_ROOT; };
+ 696C90150B8D526000D66CAF /* cycle_timer.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = cycle_timer.cc; path = ../cycle_timer.cc; sourceTree = SOURCE_ROOT; };
+ 696C90160B8D526000D66CAF /* default_click.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = default_click.cc; path = ../default_click.cc; sourceTree = SOURCE_ROOT; };
+ 696C90180B8D526000D66CAF /* diskstream.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = diskstream.cc; path = ../diskstream.cc; sourceTree = SOURCE_ROOT; };
+ 696C90190B8D526000D66CAF /* enums.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = enums.cc; path = ../enums.cc; sourceTree = SOURCE_ROOT; };
+ 696C901A0B8D526000D66CAF /* gain.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = gain.cc; path = ../gain.cc; sourceTree = SOURCE_ROOT; };
+ 696C901B0B8D526000D66CAF /* gdither.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = gdither.cc; path = ../gdither.cc; sourceTree = SOURCE_ROOT; };
+ 696C901C0B8D526000D66CAF /* gettext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = gettext.h; path = ../gettext.h; sourceTree = SOURCE_ROOT; };
+ 696C901D0B8D526000D66CAF /* globals.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = globals.cc; path = ../globals.cc; sourceTree = SOURCE_ROOT; };
+ 696C901E0B8D526000D66CAF /* i18n.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = i18n.h; path = ../i18n.h; sourceTree = SOURCE_ROOT; };
+ 696C901F0B8D526000D66CAF /* import.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = import.cc; path = ../import.cc; sourceTree = SOURCE_ROOT; };
+ 696C90200B8D526000D66CAF /* insert.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = insert.cc; path = ../insert.cc; sourceTree = SOURCE_ROOT; };
+ 696C90210B8D526000D66CAF /* io.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = io.cc; path = ../io.cc; sourceTree = SOURCE_ROOT; };
+ 696C90220B8D526000D66CAF /* jack_slave.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = jack_slave.cc; path = ../jack_slave.cc; sourceTree = SOURCE_ROOT; };
+ 696C90230B8D526000D66CAF /* ladspa_plugin.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ladspa_plugin.cc; path = ../ladspa_plugin.cc; sourceTree = SOURCE_ROOT; };
+ 696C90240B8D526000D66CAF /* location.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = location.cc; path = ../location.cc; sourceTree = SOURCE_ROOT; };
+ 696C90250B8D526000D66CAF /* mix.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = mix.cc; path = ../mix.cc; sourceTree = SOURCE_ROOT; };
+ 696C90260B8D526000D66CAF /* mtc_slave.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = mtc_slave.cc; path = ../mtc_slave.cc; sourceTree = SOURCE_ROOT; };
+ 696C90270B8D526000D66CAF /* named_selection.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = named_selection.cc; path = ../named_selection.cc; sourceTree = SOURCE_ROOT; };
+ 696C90280B8D526000D66CAF /* osc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = osc.cc; path = ../osc.cc; sourceTree = SOURCE_ROOT; };
+ 696C90290B8D526000D66CAF /* panner.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = panner.cc; path = ../panner.cc; sourceTree = SOURCE_ROOT; };
+ 696C902A0B8D526000D66CAF /* pcm_utils.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pcm_utils.cc; path = ../pcm_utils.cc; sourceTree = SOURCE_ROOT; };
+ 696C902B0B8D526000D66CAF /* playlist.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = playlist.cc; path = ../playlist.cc; sourceTree = SOURCE_ROOT; };
+ 696C902C0B8D526000D66CAF /* playlist_factory.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = playlist_factory.cc; path = ../playlist_factory.cc; sourceTree = SOURCE_ROOT; };
+ 696C902D0B8D526000D66CAF /* plugin.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = plugin.cc; path = ../plugin.cc; sourceTree = SOURCE_ROOT; };
+ 696C902E0B8D526000D66CAF /* plugin_manager.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = plugin_manager.cc; path = ../plugin_manager.cc; sourceTree = SOURCE_ROOT; };
+ 696C902F0B8D526000D66CAF /* port.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = port.cc; path = ../port.cc; sourceTree = SOURCE_ROOT; };
+ 696C90300B8D526000D66CAF /* recent_sessions.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = recent_sessions.cc; path = ../recent_sessions.cc; sourceTree = SOURCE_ROOT; };
+ 696C90310B8D526000D66CAF /* redirect.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = redirect.cc; path = ../redirect.cc; sourceTree = SOURCE_ROOT; };
+ 696C90320B8D526000D66CAF /* region.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = region.cc; path = ../region.cc; sourceTree = SOURCE_ROOT; };
+ 696C90330B8D526000D66CAF /* region_factory.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = region_factory.cc; path = ../region_factory.cc; sourceTree = SOURCE_ROOT; };
+ 696C90340B8D526000D66CAF /* reverse.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = reverse.cc; path = ../reverse.cc; sourceTree = SOURCE_ROOT; };
+ 696C90350B8D526000D66CAF /* route.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = route.cc; path = ../route.cc; sourceTree = SOURCE_ROOT; };
+ 696C90360B8D526000D66CAF /* route_group.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = route_group.cc; path = ../route_group.cc; sourceTree = SOURCE_ROOT; };
+ 696C90370B8D526000D66CAF /* send.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = send.cc; path = ../send.cc; sourceTree = SOURCE_ROOT; };
+ 696C90380B8D526000D66CAF /* session.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session.cc; path = ../session.cc; sourceTree = SOURCE_ROOT; };
+ 696C90390B8D526000D66CAF /* session_butler.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_butler.cc; path = ../session_butler.cc; sourceTree = SOURCE_ROOT; };
+ 696C903A0B8D526000D66CAF /* session_click.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_click.cc; path = ../session_click.cc; sourceTree = SOURCE_ROOT; };
+ 696C903B0B8D526000D66CAF /* session_command.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_command.cc; path = ../session_command.cc; sourceTree = SOURCE_ROOT; };
+ 696C903D0B8D526000D66CAF /* session_events.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_events.cc; path = ../session_events.cc; sourceTree = SOURCE_ROOT; };
+ 696C903E0B8D526000D66CAF /* session_export.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_export.cc; path = ../session_export.cc; sourceTree = SOURCE_ROOT; };
+ 696C903F0B8D526000D66CAF /* session_feedback.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_feedback.cc; path = ../session_feedback.cc; sourceTree = SOURCE_ROOT; };
+ 696C90400B8D526000D66CAF /* session_midi.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_midi.cc; path = ../session_midi.cc; sourceTree = SOURCE_ROOT; };
+ 696C90410B8D526000D66CAF /* session_process.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_process.cc; path = ../session_process.cc; sourceTree = SOURCE_ROOT; };
+ 696C90420B8D526000D66CAF /* session_state.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_state.cc; path = ../session_state.cc; sourceTree = SOURCE_ROOT; };
+ 696C90430B8D526000D66CAF /* session_time.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_time.cc; path = ../session_time.cc; sourceTree = SOURCE_ROOT; };
+ 696C90440B8D526000D66CAF /* session_timefx.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_timefx.cc; path = ../session_timefx.cc; sourceTree = SOURCE_ROOT; };
+ 696C90450B8D526000D66CAF /* session_transport.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = session_transport.cc; path = ../session_transport.cc; sourceTree = SOURCE_ROOT; };
+ 696C90470B8D526000D66CAF /* silentfilesource.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = silentfilesource.cc; path = ../silentfilesource.cc; sourceTree = SOURCE_ROOT; };
+ 696C90480B8D526000D66CAF /* sndfile_helpers.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sndfile_helpers.cc; path = ../sndfile_helpers.cc; sourceTree = SOURCE_ROOT; };
+ 696C90490B8D526000D66CAF /* sndfilesource.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = sndfilesource.cc; path = ../sndfilesource.cc; sourceTree = SOURCE_ROOT; };
+ 696C904A0B8D526000D66CAF /* source.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = source.cc; path = ../source.cc; sourceTree = SOURCE_ROOT; };
+ 696C904B0B8D526000D66CAF /* source_factory.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = source_factory.cc; path = ../source_factory.cc; sourceTree = SOURCE_ROOT; };
+ 696C904E0B8D526000D66CAF /* tempo.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = tempo.cc; path = ../tempo.cc; sourceTree = SOURCE_ROOT; };
+ 696C904F0B8D526000D66CAF /* track.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = track.cc; path = ../track.cc; sourceTree = SOURCE_ROOT; };
+ 696C90500B8D526000D66CAF /* utils.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = utils.cc; path = ../utils.cc; sourceTree = SOURCE_ROOT; };
+ 696C90F70B8D52F300D66CAF /* glibmm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = glibmm.framework; path = /Library/Frameworks/glibmm.framework; sourceTree = "<absolute>"; };
+ 696C90F80B8D52F300D66CAF /* Jack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Jack.framework; path = /Library/Frameworks/Jack.framework; sourceTree = "<absolute>"; };
+ 696C90F90B8D52F300D66CAF /* lo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = lo.framework; path = /Library/Frameworks/lo.framework; sourceTree = "<absolute>"; };
+ 696C90FA0B8D52F300D66CAF /* LRdf.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LRdf.framework; path = /Library/Frameworks/LRdf.framework; sourceTree = "<absolute>"; };
+ 696C90FB0B8D52F300D66CAF /* Raptor.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Raptor.framework; path = /Library/Frameworks/Raptor.framework; sourceTree = "<absolute>"; };
+ 696C90FC0B8D52F300D66CAF /* SampleRate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SampleRate.framework; path = /Library/Frameworks/SampleRate.framework; sourceTree = "<absolute>"; };
+ 696C90FD0B8D52F300D66CAF /* sigc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = sigc.framework; path = /Library/Frameworks/sigc.framework; sourceTree = "<absolute>"; };
+ 696C90FE0B8D52F300D66CAF /* Sndfile-ardour.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "Sndfile-ardour.framework"; path = "/Library/Frameworks/Sndfile-ardour.framework"; sourceTree = "<absolute>"; };
+ 696C90FF0B8D52F300D66CAF /* soundtouch.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = soundtouch.framework; path = /Library/Frameworks/soundtouch.framework; sourceTree = "<absolute>"; };
+ 697D98080B8DCD8C0006A892 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = "<absolute>"; };
+ 698D9AB00B969A5B00C53B63 /* midi++.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "midi++.xcodeproj"; path = "../../midi++2/macosx/midi++.xcodeproj"; sourceTree = SOURCE_ROOT; };
+ 69AD45840B97D10600806E7E /* FLAC */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = FLAC; path = "/Library/Frameworks/Sndfile-ardour.framework/Versions/A/Libraries/FLAC"; sourceTree = "<absolute>"; };
+ 69B1B54F0B8E80AD007E41C1 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; };
+ 69DBC41A0BA794A500C19E65 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = "<absolute>"; };
+ 69DBC42A0BA7992800C19E65 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
+ 69F7CE520B8DCB3300D76871 /* basic_ui.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = basic_ui.cc; sourceTree = "<group>"; };
+ 69F7CE540B8DCB3300D76871 /* basic_ui.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = basic_ui.h; sourceTree = "<group>"; };
+ 69F7CE550B8DCB3300D76871 /* control_protocol.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = control_protocol.h; sourceTree = "<group>"; };
+ 69F7CE560B8DCB3300D76871 /* smpte.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = smpte.h; sourceTree = "<group>"; };
+ 69F7CE570B8DCB3300D76871 /* control_protocol.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = control_protocol.cc; sourceTree = "<group>"; };
+ 69F7CE590B8DCB3300D76871 /* smpte.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = smpte.cc; sourceTree = "<group>"; };
+ 8D07F2C70486CC7A007CD1D0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+ 8D07F2C80486CC7A007CD1D0 /* ardour.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ardour.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D07F2C30486CC7A007CD1D0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 698D9AB60B969A6F00C53B63 /* midi++.framework in Frameworks */,
+ 69B1B5500B8E80AD007E41C1 /* CoreAudio.framework in Frameworks */,
+ 696C91000B8D52F300D66CAF /* glibmm.framework in Frameworks */,
+ 696C91010B8D52F300D66CAF /* Jack.framework in Frameworks */,
+ 696C91020B8D52F300D66CAF /* lo.framework in Frameworks */,
+ 696C91030B8D52F300D66CAF /* LRdf.framework in Frameworks */,
+ 696C91040B8D52F300D66CAF /* Raptor.framework in Frameworks */,
+ 696C91050B8D52F300D66CAF /* SampleRate.framework in Frameworks */,
+ 696C91060B8D52F300D66CAF /* sigc.framework in Frameworks */,
+ 696C91070B8D52F300D66CAF /* Sndfile-ardour.framework in Frameworks */,
+ 696C91080B8D52F300D66CAF /* soundtouch.framework in Frameworks */,
+ 697D98090B8DCD8C0006A892 /* libxml2.dylib in Frameworks */,
+ 69B1B5210B8E7DFD007E41C1 /* pbd.framework in Frameworks */,
+ 696149E90B97CEF500ECBDF0 /* glib in Frameworks */,
+ 696149EA0B97CEF500ECBDF0 /* gmodule in Frameworks */,
+ 696149EB0B97CEF500ECBDF0 /* gobject in Frameworks */,
+ 696149EC0B97CEF500ECBDF0 /* gthread in Frameworks */,
+ 69AD45850B97D10600806E7E /* FLAC in Frameworks */,
+ 69DBC41B0BA794A500C19E65 /* Accelerate.framework in Frameworks */,
+ 69DBC42B0BA7992800C19E65 /* Carbon.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DDFF38A45A11DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D07F2C80486CC7A007CD1D0 /* ardour.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* ardour */ = {
+ isa = PBXGroup;
+ children = (
+ 6964FEC80B8E7A7900799BAE /* version.h */,
+ 6964FEC90B8E7A7900799BAE /* version.cc */,
+ 08FB77ACFE841707C02AAC07 /* Source */,
+ 089C1665FE841158C02AAC07 /* Resources */,
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+ 034768DDFF38A45A11DB9C8B /* Products */,
+ );
+ name = ardour;
+ sourceTree = "<group>";
+ };
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 69DBC42A0BA7992800C19E65 /* Carbon.framework */,
+ 69DBC41A0BA794A500C19E65 /* Accelerate.framework */,
+ 69AD45840B97D10600806E7E /* FLAC */,
+ 696149E50B97CEF500ECBDF0 /* glib */,
+ 696149E60B97CEF500ECBDF0 /* gmodule */,
+ 696149E70B97CEF500ECBDF0 /* gobject */,
+ 696149E80B97CEF500ECBDF0 /* gthread */,
+ 698D9AB00B969A5B00C53B63 /* midi++.xcodeproj */,
+ 69B1B54F0B8E80AD007E41C1 /* CoreAudio.framework */,
+ 697D98080B8DCD8C0006A892 /* libxml2.dylib */,
+ 691B3B770B8D5508009155B5 /* pbd.xcodeproj */,
+ 696C90F70B8D52F300D66CAF /* glibmm.framework */,
+ 696C90F80B8D52F300D66CAF /* Jack.framework */,
+ 696C90F90B8D52F300D66CAF /* lo.framework */,
+ 696C90FA0B8D52F300D66CAF /* LRdf.framework */,
+ 696C90FB0B8D52F300D66CAF /* Raptor.framework */,
+ 696C90FC0B8D52F300D66CAF /* SampleRate.framework */,
+ 696C90FD0B8D52F300D66CAF /* sigc.framework */,
+ 696C90FE0B8D52F300D66CAF /* Sndfile-ardour.framework */,
+ 696C90FF0B8D52F300D66CAF /* soundtouch.framework */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 089C1665FE841158C02AAC07 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 8D07F2C70486CC7A007CD1D0 /* Info.plist */,
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 08FB77ACFE841707C02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 69F7CE510B8DCB3300D76871 /* control_protocol */,
+ 696C8FAD0B8D526000D66CAF /* ardour */,
+ 696C90020B8D526000D66CAF /* audio_diskstream.cc */,
+ 696C90030B8D526000D66CAF /* audio_library.cc */,
+ 696C90040B8D526000D66CAF /* audio_playlist.cc */,
+ 696C90050B8D526000D66CAF /* audio_track.cc */,
+ 696C90070B8D526000D66CAF /* audioengine.cc */,
+ 696C90080B8D526000D66CAF /* audiofilesource.cc */,
+ 696C90090B8D526000D66CAF /* audiofilter.cc */,
+ 696C900A0B8D526000D66CAF /* audioregion.cc */,
+ 696C900B0B8D526000D66CAF /* audiosource.cc */,
+ 696C900C0B8D526000D66CAF /* auditioner.cc */,
+ 696C900D0B8D526000D66CAF /* automation.cc */,
+ 696C900E0B8D526000D66CAF /* automation_event.cc */,
+ 696C900F0B8D526000D66CAF /* configuration.cc */,
+ 696C90100B8D526000D66CAF /* connection.cc */,
+ 696C90110B8D526000D66CAF /* control_protocol_manager.cc */,
+ 696C90130B8D526000D66CAF /* crossfade.cc */,
+ 696C90140B8D526000D66CAF /* curve.cc */,
+ 696C90150B8D526000D66CAF /* cycle_timer.cc */,
+ 696C90160B8D526000D66CAF /* default_click.cc */,
+ 696C90180B8D526000D66CAF /* diskstream.cc */,
+ 696C90190B8D526000D66CAF /* enums.cc */,
+ 696C901A0B8D526000D66CAF /* gain.cc */,
+ 696C901B0B8D526000D66CAF /* gdither.cc */,
+ 696C901C0B8D526000D66CAF /* gettext.h */,
+ 696C901D0B8D526000D66CAF /* globals.cc */,
+ 696C901E0B8D526000D66CAF /* i18n.h */,
+ 696C901F0B8D526000D66CAF /* import.cc */,
+ 696C90200B8D526000D66CAF /* insert.cc */,
+ 696C90210B8D526000D66CAF /* io.cc */,
+ 696C90220B8D526000D66CAF /* jack_slave.cc */,
+ 696C90230B8D526000D66CAF /* ladspa_plugin.cc */,
+ 696C90240B8D526000D66CAF /* location.cc */,
+ 696C90250B8D526000D66CAF /* mix.cc */,
+ 696C90260B8D526000D66CAF /* mtc_slave.cc */,
+ 696C90270B8D526000D66CAF /* named_selection.cc */,
+ 696C90280B8D526000D66CAF /* osc.cc */,
+ 696C90290B8D526000D66CAF /* panner.cc */,
+ 696C902A0B8D526000D66CAF /* pcm_utils.cc */,
+ 696C902B0B8D526000D66CAF /* playlist.cc */,
+ 696C902C0B8D526000D66CAF /* playlist_factory.cc */,
+ 696C902D0B8D526000D66CAF /* plugin.cc */,
+ 696C902E0B8D526000D66CAF /* plugin_manager.cc */,
+ 696C902F0B8D526000D66CAF /* port.cc */,
+ 696C90300B8D526000D66CAF /* recent_sessions.cc */,
+ 696C90310B8D526000D66CAF /* redirect.cc */,
+ 696C90320B8D526000D66CAF /* region.cc */,
+ 696C90330B8D526000D66CAF /* region_factory.cc */,
+ 696C90340B8D526000D66CAF /* reverse.cc */,
+ 696C90350B8D526000D66CAF /* route.cc */,
+ 696C90360B8D526000D66CAF /* route_group.cc */,
+ 696C90370B8D526000D66CAF /* send.cc */,
+ 696C90380B8D526000D66CAF /* session.cc */,
+ 696C90390B8D526000D66CAF /* session_butler.cc */,
+ 696C903A0B8D526000D66CAF /* session_click.cc */,
+ 696C903B0B8D526000D66CAF /* session_command.cc */,
+ 696C903D0B8D526000D66CAF /* session_events.cc */,
+ 696C903E0B8D526000D66CAF /* session_export.cc */,
+ 696C903F0B8D526000D66CAF /* session_feedback.cc */,
+ 696C90400B8D526000D66CAF /* session_midi.cc */,
+ 696C90410B8D526000D66CAF /* session_process.cc */,
+ 696C90420B8D526000D66CAF /* session_state.cc */,
+ 696C90430B8D526000D66CAF /* session_time.cc */,
+ 696C90440B8D526000D66CAF /* session_timefx.cc */,
+ 696C90450B8D526000D66CAF /* session_transport.cc */,
+ 696C90470B8D526000D66CAF /* silentfilesource.cc */,
+ 696C90480B8D526000D66CAF /* sndfile_helpers.cc */,
+ 696C90490B8D526000D66CAF /* sndfilesource.cc */,
+ 696C904A0B8D526000D66CAF /* source.cc */,
+ 696C904B0B8D526000D66CAF /* source_factory.cc */,
+ 696C904E0B8D526000D66CAF /* tempo.cc */,
+ 696C904F0B8D526000D66CAF /* track.cc */,
+ 696C90500B8D526000D66CAF /* utils.cc */,
+ 32BAE0B70371A74B00C91783 /* ardour_Prefix.pch */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 691B3B780B8D5508009155B5 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 691B3B7C0B8D5508009155B5 /* pbd.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 696C8FAD0B8D526000D66CAF /* ardour */ = {
+ isa = PBXGroup;
+ children = (
+ 696C8FAF0B8D526000D66CAF /* ardour.h */,
+ 696C8FB00B8D526000D66CAF /* audio_diskstream.h */,
+ 696C8FB10B8D526000D66CAF /* audio_library.h */,
+ 696C8FB20B8D526000D66CAF /* audio_track.h */,
+ 696C8FB40B8D526000D66CAF /* audioengine.h */,
+ 696C8FB50B8D526000D66CAF /* audiofilesource.h */,
+ 696C8FB60B8D526000D66CAF /* audiofilter.h */,
+ 696C8FB70B8D526000D66CAF /* audioplaylist.h */,
+ 696C8FB80B8D526000D66CAF /* audioregion.h */,
+ 696C8FB90B8D526000D66CAF /* audiosource.h */,
+ 696C8FBA0B8D526000D66CAF /* auditioner.h */,
+ 696C8FBB0B8D526000D66CAF /* automation_event.h */,
+ 696C8FBC0B8D526000D66CAF /* buffer.h */,
+ 696C8FBD0B8D526000D66CAF /* click.h */,
+ 696C8FBE0B8D526000D66CAF /* configuration.h */,
+ 696C8FBF0B8D526000D66CAF /* configuration_variable.h */,
+ 696C8FC00B8D526000D66CAF /* configuration_vars.h */,
+ 696C8FC10B8D526000D66CAF /* connection.h */,
+ 696C8FC20B8D526000D66CAF /* control_protocol_manager.h */,
+ 696C8FC40B8D526000D66CAF /* crossfade.h */,
+ 696C8FC50B8D526000D66CAF /* crossfade_compare.h */,
+ 696C8FC60B8D526000D66CAF /* curve.h */,
+ 696C8FC70B8D526000D66CAF /* cycle_timer.h */,
+ 696C8FC80B8D526000D66CAF /* cycles.h */,
+ 696C8FC90B8D526000D66CAF /* data_type.h */,
+ 696C8FCA0B8D526000D66CAF /* dB.h */,
+ 696C8FCC0B8D526000D66CAF /* diskstream.h */,
+ 696C8FCD0B8D526000D66CAF /* export.h */,
+ 696C8FCE0B8D526000D66CAF /* gain.h */,
+ 696C8FCF0B8D526000D66CAF /* gdither.h */,
+ 696C8FD00B8D526000D66CAF /* gdither_types.h */,
+ 696C8FD10B8D526000D66CAF /* gdither_types_internal.h */,
+ 696C8FD20B8D526000D66CAF /* insert.h */,
+ 696C8FD30B8D526000D66CAF /* io.h */,
+ 696C8FD40B8D526000D66CAF /* ladspa.h */,
+ 696C8FD50B8D526000D66CAF /* ladspa_plugin.h */,
+ 696C8FD60B8D526000D66CAF /* location.h */,
+ 696C8FD70B8D526000D66CAF /* logcurve.h */,
+ 696C8FD80B8D526000D66CAF /* mix.h */,
+ 696C8FD90B8D526000D66CAF /* named_selection.h */,
+ 696C8FDA0B8D526000D66CAF /* noise.h */,
+ 696C8FDB0B8D526000D66CAF /* osc.h */,
+ 696C8FDC0B8D526000D66CAF /* panner.h */,
+ 696C8FDD0B8D526000D66CAF /* pcm_utils.h */,
+ 696C8FDE0B8D526000D66CAF /* peak.h */,
+ 696C8FDF0B8D526000D66CAF /* playlist.h */,
+ 696C8FE00B8D526000D66CAF /* playlist_factory.h */,
+ 696C8FE10B8D526000D66CAF /* playlist_templates.h */,
+ 696C8FE20B8D526000D66CAF /* plugin.h */,
+ 696C8FE30B8D526000D66CAF /* plugin_manager.h */,
+ 696C8FE40B8D526000D66CAF /* port.h */,
+ 696C8FE50B8D526000D66CAF /* recent_sessions.h */,
+ 696C8FE60B8D526000D66CAF /* redirect.h */,
+ 696C8FE70B8D526000D66CAF /* region.h */,
+ 696C8FE80B8D526000D66CAF /* region_factory.h */,
+ 696C8FE90B8D526000D66CAF /* reverse.h */,
+ 696C8FEA0B8D526000D66CAF /* route.h */,
+ 696C8FEB0B8D526000D66CAF /* route_group.h */,
+ 696C8FEC0B8D526000D66CAF /* route_group_specialized.h */,
+ 696C8FED0B8D526000D66CAF /* send.h */,
+ 696C8FEE0B8D526000D66CAF /* session.h */,
+ 696C8FEF0B8D526000D66CAF /* session_connection.h */,
+ 696C8FF00B8D526000D66CAF /* session_playlist.h */,
+ 696C8FF10B8D526000D66CAF /* session_region.h */,
+ 696C8FF20B8D526000D66CAF /* session_route.h */,
+ 696C8FF30B8D526000D66CAF /* session_selection.h */,
+ 696C8FF40B8D526000D66CAF /* silentfilesource.h */,
+ 696C8FF50B8D526000D66CAF /* slave.h */,
+ 696C8FF60B8D526000D66CAF /* sndfile_helpers.h */,
+ 696C8FF70B8D526000D66CAF /* sndfilesource.h */,
+ 696C8FF80B8D526000D66CAF /* soundseq.h */,
+ 696C8FF90B8D526000D66CAF /* source.h */,
+ 696C8FFA0B8D526000D66CAF /* source_factory.h */,
+ 696C8FFB0B8D526000D66CAF /* spline.h */,
+ 696C8FFC0B8D526000D66CAF /* tempo.h */,
+ 696C8FFD0B8D526000D66CAF /* timestamps.h */,
+ 696C8FFE0B8D526000D66CAF /* track.h */,
+ 696C8FFF0B8D526000D66CAF /* types.h */,
+ 696C90000B8D526000D66CAF /* utils.h */,
+ );
+ name = ardour;
+ path = ../ardour;
+ sourceTree = SOURCE_ROOT;
+ };
+ 698D9AB10B969A5B00C53B63 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 698D9AB50B969A5B00C53B63 /* midi++.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 69F7CE510B8DCB3300D76871 /* control_protocol */ = {
+ isa = PBXGroup;
+ children = (
+ 69F7CE520B8DCB3300D76871 /* basic_ui.cc */,
+ 69F7CE530B8DCB3300D76871 /* control_protocol */,
+ 69F7CE570B8DCB3300D76871 /* control_protocol.cc */,
+ 69F7CE590B8DCB3300D76871 /* smpte.cc */,
+ );
+ name = control_protocol;
+ path = ../../surfaces/control_protocol;
+ sourceTree = SOURCE_ROOT;
+ };
+ 69F7CE530B8DCB3300D76871 /* control_protocol */ = {
+ isa = PBXGroup;
+ children = (
+ 69F7CE540B8DCB3300D76871 /* basic_ui.h */,
+ 69F7CE550B8DCB3300D76871 /* control_protocol.h */,
+ 69F7CE560B8DCB3300D76871 /* smpte.h */,
+ );
+ path = control_protocol;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 8D07F2BD0486CC7A007CD1D0 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D07F2BE0486CC7A007CD1D0 /* ardour_Prefix.pch in Headers */,
+ 696C90530B8D526000D66CAF /* ardour.h in Headers */,
+ 696C90540B8D526000D66CAF /* audio_diskstream.h in Headers */,
+ 696C90550B8D526000D66CAF /* audio_library.h in Headers */,
+ 696C90560B8D526000D66CAF /* audio_track.h in Headers */,
+ 696C90580B8D526000D66CAF /* audioengine.h in Headers */,
+ 696C90590B8D526000D66CAF /* audiofilesource.h in Headers */,
+ 696C905A0B8D526000D66CAF /* audiofilter.h in Headers */,
+ 696C905B0B8D526000D66CAF /* audioplaylist.h in Headers */,
+ 696C905C0B8D526000D66CAF /* audioregion.h in Headers */,
+ 696C905D0B8D526000D66CAF /* audiosource.h in Headers */,
+ 696C905E0B8D526000D66CAF /* auditioner.h in Headers */,
+ 696C905F0B8D526000D66CAF /* automation_event.h in Headers */,
+ 696C90600B8D526000D66CAF /* buffer.h in Headers */,
+ 696C90610B8D526000D66CAF /* click.h in Headers */,
+ 696C90620B8D526000D66CAF /* configuration.h in Headers */,
+ 696C90630B8D526000D66CAF /* configuration_variable.h in Headers */,
+ 696C90640B8D526000D66CAF /* configuration_vars.h in Headers */,
+ 696C90650B8D526000D66CAF /* connection.h in Headers */,
+ 696C90660B8D526000D66CAF /* control_protocol_manager.h in Headers */,
+ 696C90680B8D526000D66CAF /* crossfade.h in Headers */,
+ 696C90690B8D526000D66CAF /* crossfade_compare.h in Headers */,
+ 696C906A0B8D526000D66CAF /* curve.h in Headers */,
+ 696C906B0B8D526000D66CAF /* cycle_timer.h in Headers */,
+ 696C906C0B8D526000D66CAF /* cycles.h in Headers */,
+ 696C906D0B8D526000D66CAF /* data_type.h in Headers */,
+ 696C906E0B8D526000D66CAF /* dB.h in Headers */,
+ 696C90700B8D526000D66CAF /* diskstream.h in Headers */,
+ 696C90710B8D526000D66CAF /* export.h in Headers */,
+ 696C90720B8D526000D66CAF /* gain.h in Headers */,
+ 696C90730B8D526000D66CAF /* gdither.h in Headers */,
+ 696C90740B8D526000D66CAF /* gdither_types.h in Headers */,
+ 696C90750B8D526000D66CAF /* gdither_types_internal.h in Headers */,
+ 696C90760B8D526000D66CAF /* insert.h in Headers */,
+ 696C90770B8D526000D66CAF /* io.h in Headers */,
+ 696C90780B8D526000D66CAF /* ladspa.h in Headers */,
+ 696C90790B8D526000D66CAF /* ladspa_plugin.h in Headers */,
+ 696C907A0B8D526000D66CAF /* location.h in Headers */,
+ 696C907B0B8D526000D66CAF /* logcurve.h in Headers */,
+ 696C907C0B8D526000D66CAF /* mix.h in Headers */,
+ 696C907D0B8D526000D66CAF /* named_selection.h in Headers */,
+ 696C907E0B8D526000D66CAF /* noise.h in Headers */,
+ 696C907F0B8D526000D66CAF /* osc.h in Headers */,
+ 696C90800B8D526000D66CAF /* panner.h in Headers */,
+ 696C90810B8D526000D66CAF /* pcm_utils.h in Headers */,
+ 696C90820B8D526000D66CAF /* peak.h in Headers */,
+ 696C90830B8D526000D66CAF /* playlist.h in Headers */,
+ 696C90840B8D526000D66CAF /* playlist_factory.h in Headers */,
+ 696C90850B8D526000D66CAF /* playlist_templates.h in Headers */,
+ 696C90860B8D526000D66CAF /* plugin.h in Headers */,
+ 696C90870B8D526000D66CAF /* plugin_manager.h in Headers */,
+ 696C90880B8D526000D66CAF /* port.h in Headers */,
+ 696C90890B8D526000D66CAF /* recent_sessions.h in Headers */,
+ 696C908A0B8D526000D66CAF /* redirect.h in Headers */,
+ 696C908B0B8D526000D66CAF /* region.h in Headers */,
+ 696C908C0B8D526000D66CAF /* region_factory.h in Headers */,
+ 696C908D0B8D526000D66CAF /* reverse.h in Headers */,
+ 696C908E0B8D526000D66CAF /* route.h in Headers */,
+ 696C908F0B8D526000D66CAF /* route_group.h in Headers */,
+ 696C90900B8D526000D66CAF /* route_group_specialized.h in Headers */,
+ 696C90910B8D526000D66CAF /* send.h in Headers */,
+ 696C90920B8D526000D66CAF /* session.h in Headers */,
+ 696C90930B8D526000D66CAF /* session_connection.h in Headers */,
+ 696C90940B8D526000D66CAF /* session_playlist.h in Headers */,
+ 696C90950B8D526000D66CAF /* session_region.h in Headers */,
+ 696C90960B8D526000D66CAF /* session_route.h in Headers */,
+ 696C90970B8D526000D66CAF /* session_selection.h in Headers */,
+ 696C90980B8D526000D66CAF /* silentfilesource.h in Headers */,
+ 696C90990B8D526000D66CAF /* slave.h in Headers */,
+ 696C909A0B8D526000D66CAF /* sndfile_helpers.h in Headers */,
+ 696C909B0B8D526000D66CAF /* sndfilesource.h in Headers */,
+ 696C909C0B8D526000D66CAF /* soundseq.h in Headers */,
+ 696C909D0B8D526000D66CAF /* source.h in Headers */,
+ 696C909E0B8D526000D66CAF /* source_factory.h in Headers */,
+ 696C909F0B8D526000D66CAF /* spline.h in Headers */,
+ 696C90A00B8D526000D66CAF /* tempo.h in Headers */,
+ 696C90A10B8D526000D66CAF /* timestamps.h in Headers */,
+ 696C90A20B8D526000D66CAF /* track.h in Headers */,
+ 696C90A30B8D526000D66CAF /* types.h in Headers */,
+ 696C90A40B8D526000D66CAF /* utils.h in Headers */,
+ 696C90C00B8D526000D66CAF /* gettext.h in Headers */,
+ 696C90C20B8D526000D66CAF /* i18n.h in Headers */,
+ 69F7CE5B0B8DCB3300D76871 /* basic_ui.h in Headers */,
+ 69F7CE5C0B8DCB3300D76871 /* control_protocol.h in Headers */,
+ 69F7CE5D0B8DCB3300D76871 /* smpte.h in Headers */,
+ 6964FECA0B8E7A7900799BAE /* version.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 8D07F2BC0486CC7A007CD1D0 /* ardour */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "ardour" */;
+ buildPhases = (
+ 8D07F2BD0486CC7A007CD1D0 /* Headers */,
+ 8D07F2BF0486CC7A007CD1D0 /* Resources */,
+ 8D07F2C10486CC7A007CD1D0 /* Sources */,
+ 8D07F2C30486CC7A007CD1D0 /* Frameworks */,
+ 8D07F2C50486CC7A007CD1D0 /* Rez */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 69D5F6260B8D58A500301E71 /* PBXTargetDependency */,
+ 698D9ABA0B969ADC00C53B63 /* PBXTargetDependency */,
+ );
+ name = ardour;
+ productInstallPath = "$(HOME)/Library/Frameworks";
+ productName = ardour;
+ productReference = 8D07F2C80486CC7A007CD1D0 /* ardour.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "ardour" */;
+ hasScannedForEncodings = 1;
+ mainGroup = 0867D691FE84028FC02AAC07 /* ardour */;
+ productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 698D9AB10B969A5B00C53B63 /* Products */;
+ ProjectRef = 698D9AB00B969A5B00C53B63 /* midi++.xcodeproj */;
+ },
+ {
+ ProductGroup = 691B3B780B8D5508009155B5 /* Products */;
+ ProjectRef = 691B3B770B8D5508009155B5 /* pbd.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ 8D07F2BC0486CC7A007CD1D0 /* ardour */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 691B3B7C0B8D5508009155B5 /* pbd.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = pbd.framework;
+ remoteRef = 691B3B7B0B8D5508009155B5 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 698D9AB50B969A5B00C53B63 /* midi++.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = "midi++.framework";
+ remoteRef = 698D9AB40B969A5B00C53B63 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D07F2BF0486CC7A007CD1D0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D07F2C00486CC7A007CD1D0 /* InfoPlist.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+ 8D07F2C50486CC7A007CD1D0 /* Rez */ = {
+ isa = PBXRezBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D07F2C10486CC7A007CD1D0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 696C90A60B8D526000D66CAF /* audio_diskstream.cc in Sources */,
+ 696C90A70B8D526000D66CAF /* audio_library.cc in Sources */,
+ 696C90A80B8D526000D66CAF /* audio_playlist.cc in Sources */,
+ 696C90A90B8D526000D66CAF /* audio_track.cc in Sources */,
+ 696C90AB0B8D526000D66CAF /* audioengine.cc in Sources */,
+ 696C90AC0B8D526000D66CAF /* audiofilesource.cc in Sources */,
+ 696C90AD0B8D526000D66CAF /* audiofilter.cc in Sources */,
+ 696C90AE0B8D526000D66CAF /* audioregion.cc in Sources */,
+ 696C90AF0B8D526000D66CAF /* audiosource.cc in Sources */,
+ 696C90B00B8D526000D66CAF /* auditioner.cc in Sources */,
+ 696C90B10B8D526000D66CAF /* automation.cc in Sources */,
+ 696C90B20B8D526000D66CAF /* automation_event.cc in Sources */,
+ 696C90B30B8D526000D66CAF /* configuration.cc in Sources */,
+ 696C90B40B8D526000D66CAF /* connection.cc in Sources */,
+ 696C90B50B8D526000D66CAF /* control_protocol_manager.cc in Sources */,
+ 696C90B70B8D526000D66CAF /* crossfade.cc in Sources */,
+ 696C90B80B8D526000D66CAF /* curve.cc in Sources */,
+ 696C90B90B8D526000D66CAF /* cycle_timer.cc in Sources */,
+ 696C90BA0B8D526000D66CAF /* default_click.cc in Sources */,
+ 696C90BC0B8D526000D66CAF /* diskstream.cc in Sources */,
+ 696C90BD0B8D526000D66CAF /* enums.cc in Sources */,
+ 696C90BE0B8D526000D66CAF /* gain.cc in Sources */,
+ 696C90BF0B8D526000D66CAF /* gdither.cc in Sources */,
+ 696C90C10B8D526000D66CAF /* globals.cc in Sources */,
+ 696C90C30B8D526000D66CAF /* import.cc in Sources */,
+ 696C90C40B8D526000D66CAF /* insert.cc in Sources */,
+ 696C90C50B8D526000D66CAF /* io.cc in Sources */,
+ 696C90C60B8D526000D66CAF /* jack_slave.cc in Sources */,
+ 696C90C70B8D526000D66CAF /* ladspa_plugin.cc in Sources */,
+ 696C90C80B8D526000D66CAF /* location.cc in Sources */,
+ 696C90C90B8D526000D66CAF /* mix.cc in Sources */,
+ 696C90CA0B8D526000D66CAF /* mtc_slave.cc in Sources */,
+ 696C90CB0B8D526000D66CAF /* named_selection.cc in Sources */,
+ 696C90CC0B8D526000D66CAF /* osc.cc in Sources */,
+ 696C90CD0B8D526000D66CAF /* panner.cc in Sources */,
+ 696C90CE0B8D526000D66CAF /* pcm_utils.cc in Sources */,
+ 696C90CF0B8D526000D66CAF /* playlist.cc in Sources */,
+ 696C90D00B8D526000D66CAF /* playlist_factory.cc in Sources */,
+ 696C90D10B8D526000D66CAF /* plugin.cc in Sources */,
+ 696C90D20B8D526000D66CAF /* plugin_manager.cc in Sources */,
+ 696C90D30B8D526000D66CAF /* port.cc in Sources */,
+ 696C90D40B8D526000D66CAF /* recent_sessions.cc in Sources */,
+ 696C90D50B8D526000D66CAF /* redirect.cc in Sources */,
+ 696C90D60B8D526000D66CAF /* region.cc in Sources */,
+ 696C90D70B8D526000D66CAF /* region_factory.cc in Sources */,
+ 696C90D80B8D526000D66CAF /* reverse.cc in Sources */,
+ 696C90D90B8D526000D66CAF /* route.cc in Sources */,
+ 696C90DA0B8D526000D66CAF /* route_group.cc in Sources */,
+ 696C90DB0B8D526000D66CAF /* send.cc in Sources */,
+ 696C90DC0B8D526000D66CAF /* session.cc in Sources */,
+ 696C90DD0B8D526000D66CAF /* session_butler.cc in Sources */,
+ 696C90DE0B8D526000D66CAF /* session_click.cc in Sources */,
+ 696C90DF0B8D526000D66CAF /* session_command.cc in Sources */,
+ 696C90E10B8D526000D66CAF /* session_events.cc in Sources */,
+ 696C90E20B8D526000D66CAF /* session_export.cc in Sources */,
+ 696C90E30B8D526000D66CAF /* session_feedback.cc in Sources */,
+ 696C90E40B8D526000D66CAF /* session_midi.cc in Sources */,
+ 696C90E50B8D526000D66CAF /* session_process.cc in Sources */,
+ 696C90E60B8D526000D66CAF /* session_state.cc in Sources */,
+ 696C90E70B8D526000D66CAF /* session_time.cc in Sources */,
+ 696C90E80B8D526000D66CAF /* session_timefx.cc in Sources */,
+ 696C90E90B8D526000D66CAF /* session_transport.cc in Sources */,
+ 696C90EB0B8D526000D66CAF /* silentfilesource.cc in Sources */,
+ 696C90EC0B8D526000D66CAF /* sndfile_helpers.cc in Sources */,
+ 696C90ED0B8D526000D66CAF /* sndfilesource.cc in Sources */,
+ 696C90EE0B8D526000D66CAF /* source.cc in Sources */,
+ 696C90EF0B8D526000D66CAF /* source_factory.cc in Sources */,
+ 696C90F20B8D526000D66CAF /* tempo.cc in Sources */,
+ 696C90F30B8D526000D66CAF /* track.cc in Sources */,
+ 696C90F40B8D526000D66CAF /* utils.cc in Sources */,
+ 69F7CE5A0B8DCB3300D76871 /* basic_ui.cc in Sources */,
+ 69F7CE5E0B8DCB3300D76871 /* control_protocol.cc in Sources */,
+ 69F7CE600B8DCB3300D76871 /* smpte.cc in Sources */,
+ 6964FECB0B8E7A7900799BAE /* version.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 698D9ABA0B969ADC00C53B63 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = "midi++";
+ targetProxy = 698D9AB90B969ADC00C53B63 /* PBXContainerItemProxy */;
+ };
+ 69D5F6260B8D58A500301E71 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = pbd;
+ targetProxy = 69D5F6250B8D58A500301E71 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C1667FE841158C02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 4FADC24408B4156D00ABE55E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = (
+ ppc,
+ i386,
+ );
+ DEBUG_INFORMATION_FORMAT = stabs;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks\"";
+ FRAMEWORK_VERSION = A;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ardour_Prefix.pch;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_2)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/Sndfile-ardour.framework/Versions/A/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/Sndfile-ardour.framework/Versions/A/Libraries\"";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ PRODUCT_NAME = ardour;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Release;
+ };
+ 4FADC24808B4156D00ABE55E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = (
+ "$(NATIVE_ARCH)",
+ ppc,
+ );
+ FRAMEWORK_SEARCH_PATHS = /opt/ardour/build;
+ GCC_FAST_OBJC_DISPATCH = NO;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = G4;
+ GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ BUILD_VECLIB_OPTIMIZATIONS,
+ HAVE_WORDEXP,
+ HAVE_WEAK_COREAUDIO,
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_2)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_3)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_4)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_5)",
+ NO_POSIX_MEMALIGN,
+ );
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "PACKAGE=\"\\\"libardour\\\"\"";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_2 = "CONFIG_DIR=\"\\\"/Library/Application\\ Support/Ardour/config\\\"\"";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_3 = "MODULE_DIR=\"\\\"/Library/Application\\ Support/Ardour/modules\\\"\"";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_4 = "DATA_DIR=\"\\\"/Library/Application\\ Support/Ardour/data\\\"\"";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_5 = "LOCALEDIR=\"\\\"/Library/Application\\ Support/Ardour/locales\\\"\"";
+ GCC_STRICT_ALIASING = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ /usr/include/libxml2,
+ /Library/Frameworks/sigc.framework/Headers,
+ /Library/Frameworks/GLib.framework/Headers,
+ /Library/Frameworks/glibmm.framework/Headers,
+ "/Library/Frameworks/Sndfile-ardour.framework/Headers",
+ /Library/Frameworks/SampleRate.framework/Headers,
+ /Library/Frameworks/Raptor.framework/Headers,
+ /Library/Frameworks/LRdf.framework/Headers,
+ /opt/ardour/src/ardour2/libs/surfaces/control_protocol,
+ );
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = "";
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ };
+ name = Release;
+ };
+ 694E7C8A0B97B0FE0018D03D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(NATIVE_ARCH)";
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = /opt/ardour/build;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = NO;
+ GCC_FAST_OBJC_DISPATCH = NO;
+ GCC_MODEL_TUNING = G4;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ BUILD_VECLIB_OPTIMIZATIONS,
+ HAVE_WORDEXP,
+ HAVE_WEAK_COREAUDIO,
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_2)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_3)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_4)",
+ "$(GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_5)",
+ NO_POSIX_MEMALIGN,
+ );
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_1 = "PACKAGE=\"\\\"libardour\\\"\"";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_2 = "CONFIG_DIR=\"\\\"/Library/Application\\ Support/Ardour/config\\\"\"";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_3 = "MODULE_DIR=\"\\\"/Library/Application\\ Support/Ardour/modules\\\"\"";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_4 = "DATA_DIR=\"\\\"/Library/Application\\ Support/Ardour/data\\\"\"";
+ GCC_PREPROCESSOR_DEFINITIONS_QUOTED_FOR_PROJECT_5 = "LOCALEDIR=\"\\\"/Library/Application\\ Support/Ardour/locales\\\"\"";
+ GCC_STRICT_ALIASING = YES;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO;
+ GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
+ GCC_WARN_EFFECTIVE_CPLUSPLUS_VIOLATIONS = NO;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = NO;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ /usr/include/libxml2,
+ /Library/Frameworks/sigc.framework/Headers,
+ /Library/Frameworks/GLib.framework/Headers,
+ /Library/Frameworks/glibmm.framework/Headers,
+ "/Library/Frameworks/Sndfile-ardour.framework/Headers",
+ /Library/Frameworks/SampleRate.framework/Headers,
+ /Library/Frameworks/Raptor.framework/Headers,
+ /Library/Frameworks/LRdf.framework/Headers,
+ /opt/ardour/src/ardour2/libs/surfaces/control_protocol,
+ );
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ MACOSX_DEPLOYMENT_TARGET = "";
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Debug;
+ };
+ 694E7C8B0B97B0FE0018D03D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = i386;
+ DEBUG_INFORMATION_FORMAT = stabs;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)",
+ );
+ FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks\"";
+ FRAMEWORK_VERSION = A;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = ardour_Prefix.pch;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/Sndfile-ardour.framework/Versions/A/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_4 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/Sndfile-ardour.framework/Versions/A/Libraries\"";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ PRODUCT_NAME = ardour;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "ardour" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4FADC24408B4156D00ABE55E /* Release */,
+ 694E7C8B0B97B0FE0018D03D /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "ardour" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4FADC24808B4156D00ABE55E /* Release */,
+ 694E7C8A0B97B0FE0018D03D /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/libs/ardour/macosx/ardour_Prefix.pch b/libs/ardour/macosx/ardour_Prefix.pch
new file mode 100644
index 0000000000..b03e5d3d98
--- /dev/null
+++ b/libs/ardour/macosx/ardour_Prefix.pch
@@ -0,0 +1,4 @@
+//
+// Prefix header for all source files of the 'ardour' target in the 'ardour' project.
+//
+
diff --git a/libs/ardour/macosx/version.cc b/libs/ardour/macosx/version.cc
new file mode 100644
index 0000000000..9da3d2c359
--- /dev/null
+++ b/libs/ardour/macosx/version.cc
@@ -0,0 +1,3 @@
+int libardour_major_version = 2;
+int libardour_minor_version = 0;
+int libardour_micro_version = 0;
diff --git a/libs/ardour/macosx/version.h b/libs/ardour/macosx/version.h
new file mode 100644
index 0000000000..9c575ee077
--- /dev/null
+++ b/libs/ardour/macosx/version.h
@@ -0,0 +1,17 @@
+/*
+ * version.h
+ * ardour
+ *
+ * Created by Taybin Rutkin on 2/22/07.
+ * Copyright 2007 Paul Davis. All rights reserved.
+ *
+ */
+
+#ifndef __libardour_version_h__
+#define __libardour_version_h__
+
+extern int libardour_major_version;
+extern int libardour_minor_version;
+extern int libardour_micro_version;
+
+#endif /* __libardour_version_h__ */
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index b11e3f3062..06b75211f7 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -42,7 +42,6 @@
#include <ardour/utils.h>
#include <ardour/configuration.h>
#include <ardour/smf_source.h>
-#include <ardour/destructive_filesource.h>
#include <ardour/send.h>
#include <ardour/region_factory.h>
#include <ardour/midi_playlist.h>
diff --git a/libs/ardour/mix.cc b/libs/ardour/mix.cc
index 6b7755e498..2d31c8ccc8 100644
--- a/libs/ardour/mix.cc
+++ b/libs/ardour/mix.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -25,7 +24,6 @@
#include <stdint.h>
#if defined (ARCH_X86) && defined (BUILD_SSE_OPTIMIZATIONS)
-
// Debug wrappers
float
@@ -92,6 +90,25 @@ compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current)
}
void
+find_peaks (ARDOUR::Sample *buf, nframes_t nframes, float *min, float *max)
+{
+ nframes_t i;
+ float a, b;
+
+ a = *max;
+ b = *min;
+
+ for (i = 0; i < nframes; i++)
+ {
+ a = fmax (buf[i], a);
+ b = fmin (buf[i], b);
+ }
+
+ *max = a;
+ *min = b;
+}
+
+void
apply_gain_to_buffer (ARDOUR::Sample *buf, nframes_t nframes, float gain)
{
for (nframes_t i=0; i<nframes; i++)
@@ -126,6 +143,13 @@ veclib_compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current)
}
void
+veclib_find_peaks (ARDOUR::Sample *buf, nframes_t nframes, float *min, float *max)
+{
+ vDSP_maxv (buf, 1, max, nframes);
+ vDSP_minv (buf, 1, min, nframes);
+}
+
+void
veclib_apply_gain_to_buffer (ARDOUR::Sample *buf, nframes_t nframes, float gain)
{
vDSP_vsmul(buf, 1, &gain, buf, 1, nframes);
diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc
index 2b4b2ae5bf..3447a92ce4 100644
--- a/libs/ardour/mtc_slave.cc
+++ b/libs/ardour/mtc_slave.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <errno.h>
@@ -42,6 +41,8 @@ using namespace PBD;
MTC_Slave::MTC_Slave (Session& s, MIDI::Port& p)
: session (s)
{
+ can_notify_on_unknown_rate = true;
+
rebind (p);
reset ();
}
@@ -94,8 +95,39 @@ MTC_Slave::update_mtc_time (const byte *msg, bool was_full)
smpte.minutes = msg[2];
smpte.seconds = msg[1];
smpte.frames = msg[0];
-
- session.smpte_to_sample( smpte, mtc_frame, true, false );
+
+ switch (msg[4]) {
+ case MTC_24_FPS:
+ smpte.rate = 24;
+ smpte.drop = false;
+ can_notify_on_unknown_rate = true;
+ break;
+ case MTC_25_FPS:
+ smpte.rate = 25;
+ smpte.drop = false;
+ can_notify_on_unknown_rate = true;
+ break;
+ case MTC_30_FPS_DROP:
+ smpte.rate = 30;
+ smpte.drop = true;
+ can_notify_on_unknown_rate = true;
+ break;
+ case MTC_30_FPS:
+ smpte.rate = 30;
+ smpte.drop = false;
+ can_notify_on_unknown_rate = true;
+ break;
+ default:
+ /* throttle error messages about unknown MTC rates */
+ if (can_notify_on_unknown_rate) {
+ error << _("Unknown rate/drop value in incoming MTC stream, session values used instead") << endmsg;
+ can_notify_on_unknown_rate = false;
+ }
+ smpte.rate = session.smpte_frames_per_second();
+ smpte.drop = session.smpte_drop_frames();
+ }
+
+ session.smpte_to_sample (smpte, mtc_frame, true, false);
if (was_full) {
diff --git a/libs/ardour/named_selection.cc b/libs/ardour/named_selection.cc
index b5a71f6403..fbb4b748df 100644
--- a/libs/ardour/named_selection.cc
+++ b/libs/ardour/named_selection.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <pbd/failed_constructor.h>
diff --git a/libs/ardour/osc.cc b/libs/ardour/osc.cc
index 933fba8740..d999386005 100644
--- a/libs/ardour/osc.cc
+++ b/libs/ardour/osc.cc
@@ -15,7 +15,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * $Id$
*/
#include <iostream>
@@ -59,6 +58,11 @@ int
OSC::start ()
{
char tmpstr[255];
+
+ if (_osc_server) {
+ /* already started */
+ return 0;
+ }
for (int j=0; j < 20; ++j) {
snprintf(tmpstr, sizeof(tmpstr), "%d", _port);
@@ -109,16 +113,22 @@ OSC::start ()
int
OSC::stop ()
{
+ if (_osc_server == 0) {
+ /* already stopped */
+ return 0;
+ }
+
+ // stop server thread
+ terminate_osc_thread();
+
lo_server_free (_osc_server);
+ _osc_server = 0;
if (!_osc_unix_socket_path.empty()) {
// unlink it
unlink(_osc_unix_socket_path.c_str());
}
- // stop server thread
- terminate_osc_thread();
-
return 0;
}
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index 8ba662aaf4..8e41e70687 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#define __STDC_FORMAT_MACROS 1
diff --git a/libs/ardour/pcm_utils.cc b/libs/ardour/pcm_utils.cc
index dd18fe8690..08d8a63d6e 100644
--- a/libs/ardour/pcm_utils.cc
+++ b/libs/ardour/pcm_utils.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/pcm_utils.h>
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index db84b015bb..325ef27a18 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <set>
@@ -1517,17 +1516,33 @@ Playlist::bump_name_once (string name)
string newname;
if ((period = name.find_last_of ('.')) == string::npos) {
- newname = name;
+ newname = name;
newname += ".1";
} else {
- char buf[32];
- int version;
-
- sscanf (name.substr (period+1).c_str(), "%d", &version);
- snprintf (buf, sizeof(buf), "%d", version+1);
+ int isnumber = 1;
+ const char *last_element = name.c_str() + period + 1;
+ for (size_t i = 0; i < strlen(last_element); i++) {
+ if (!isdigit(last_element[i])) {
+ isnumber = 0;
+ break;
+ }
+ }
+
+ errno = 0;
+ long int version = strtol (name.c_str()+period+1, (char **)NULL, 10);
+
+ if (isnumber == 0 || errno != 0) {
+ // last_element is not a number, or is too large
+ newname = name;
+ newname += ".1";
+ } else {
+ char buf[32];
+
+ snprintf (buf, sizeof(buf), "%ld", version+1);
- newname = name.substr (0, period+1);
- newname += buf;
+ newname = name.substr (0, period+1);
+ newname += buf;
+ }
}
return newname;
diff --git a/libs/ardour/playlist_factory.cc b/libs/ardour/playlist_factory.cc
index 862f85a402..a801bae76c 100644
--- a/libs/ardour/playlist_factory.cc
+++ b/libs/ardour/playlist_factory.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <pbd/error.h>
diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc
index 3b471014eb..b1fb43fc8f 100644
--- a/libs/ardour/plugin.cc
+++ b/libs/ardour/plugin.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <vector>
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index 09da4c9ca7..9af7ad0451 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#define __STDC_FORMAT_MACROS 1
diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc
index 9e77128e4c..d9c93c250b 100644
--- a/libs/ardour/port.cc
+++ b/libs/ardour/port.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/port.h>
diff --git a/libs/ardour/redirect.cc b/libs/ardour/redirect.cc
index dbdd3d1ddd..ba895f6447 100644
--- a/libs/ardour/redirect.cc
+++ b/libs/ardour/redirect.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <fstream>
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 973e14fd31..15609706b2 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <iostream>
@@ -888,7 +887,7 @@ Region::state (bool full_state)
{
XMLNode *node = new XMLNode ("Region");
char buf[64];
- char* fe;
+ char* fe = NULL;
_id.print (buf, sizeof (buf));
node->add_property ("id", buf);
@@ -911,6 +910,10 @@ Region::state (bool full_state)
case EditChangesID:
fe = X_("id");
break;
+ default: /* should be unreachable but makes g++ happy */
+ cerr << "Odd region property found\n";
+ fe = X_("nothing");
+ break;
}
node->add_property ("first_edit", fe);
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index 4041852f4e..a0aa3be759 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: playlist_factory.cc 629 2006-06-21 23:01:03Z paul $
*/
#include <pbd/error.h>
diff --git a/libs/ardour/reverse.cc b/libs/ardour/reverse.cc
index 2279331701..c7ebecea31 100644
--- a/libs/ardour/reverse.cc
+++ b/libs/ardour/reverse.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -47,10 +46,9 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
{
SourceList nsrcs;
SourceList::iterator si;
- const nframes_t blocksize = 256 * 1048;
- Sample buf[blocksize];
+ nframes_t blocksize = 256 * 1024;
+ Sample* buf = 0;
nframes_t fpos;
- nframes_t fend;
nframes_t fstart;
nframes_t to_read;
int ret = -1;
@@ -61,20 +59,19 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
goto out;
}
- fend = region->start() + region->length();
fstart = region->start();
- if (blocksize < fend) {
- fpos =max(fstart, fend - blocksize);
- } else {
- fpos = fstart;
+ if (blocksize > region->length()) {
+ blocksize = region->length();
}
- to_read = min (region->length(), blocksize);
+ fpos = max (fstart, (fstart + region->length() - blocksize));
+ buf = new Sample[blocksize];
+ to_read = blocksize;
/* now read it backwards */
- while (1) {
+ while (to_read) {
uint32_t n;
@@ -85,7 +82,7 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
if (region->audio_source (n)->read (buf, fpos, to_read) != to_read) {
goto out;
}
-
+
/* swap memory order */
for (nframes_t i = 0; i < to_read/2; ++i) {
@@ -101,13 +98,11 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
}
}
- if (fpos == fstart) {
- break;
- } else if (fpos > fstart + to_read) {
+ if (fpos > fstart + blocksize) {
fpos -= to_read;
- to_read = min (fstart - fpos, blocksize);
+ to_read = blocksize;
} else {
- to_read = fpos-fstart;
+ to_read = fpos - fstart;
fpos = fstart;
}
};
@@ -116,6 +111,10 @@ Reverse::run (boost::shared_ptr<AudioRegion> region)
out:
+ if (buf) {
+ delete [] buf;
+ }
+
if (ret) {
for (si = nsrcs.begin(); si != nsrcs.end(); ++si) {
boost::shared_ptr<AudioSource> asrc(boost::dynamic_pointer_cast<AudioSource>(*si));
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index d415741831..43c233e4d7 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -81,7 +80,7 @@ Route::init ()
_soloed = false;
_solo_safe = false;
_phase_invert = false;
- order_keys[N_("signal")] = order_key_cnt++;
+ order_keys[strdup (N_("signal"))] = order_key_cnt++;
_active = true;
_silent = false;
_meter_point = MeterPostFader;
@@ -116,6 +115,10 @@ Route::~Route ()
{
clear_redirects (this);
+ for (OrderKeys::iterator i = order_keys.begin(); i != order_keys.end(); ++i) {
+ free ((void*)(i->first));
+ }
+
if (_control_outs) {
delete _control_outs;
}
@@ -137,21 +140,23 @@ Route::remote_control_id() const
}
long
-Route::order_key (string name) const
+Route::order_key (const char* name) const
{
OrderKeys::const_iterator i;
- if ((i = order_keys.find (name)) == order_keys.end()) {
- return -1;
+ for (i = order_keys.begin(); i != order_keys.end(); ++i) {
+ if (!strcmp (name, i->first)) {
+ return i->second;
+ }
}
- return (*i).second;
+ return -1;
}
void
-Route::set_order_key (string name, long n)
+Route::set_order_key (const char* name, long n)
{
- order_keys[name] = n;
+ order_keys[strdup(name)] = n;
_session.set_dirty ();
}
@@ -1107,9 +1112,16 @@ Route::_reset_plugin_counts (uint32_t* err_streams)
} else {
s->expect_inputs ((*prev)->output_streams());
}
- }
- redirect_max_outs = max ((*r)->output_streams(), redirect_max_outs);
+ } else {
+
+ /* don't pay any attention to send output configuration, since it doesn't
+ affect the route.
+ */
+
+ redirect_max_outs = max ((*r)->output_streams (), redirect_max_outs);
+
+ }
}
/* we're done */
@@ -1349,7 +1361,7 @@ Route::state(bool full_state)
OrderKeys::iterator x = order_keys.begin();
while (x != order_keys.end()) {
- order_string += (*x).first;
+ order_string += string ((*x).first);
order_string += '=';
snprintf (buf, sizeof(buf), "%ld", (*x).second);
order_string += buf;
@@ -1368,6 +1380,11 @@ Route::state(bool full_state)
node->add_child_nocopy (_solo_control.get_state ());
node->add_child_nocopy (_mute_control.get_state ());
+ XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
+ snprintf (buf, sizeof (buf), "%d", _remote_control_id);
+ remote_control_node->add_property (X_("id"), buf);
+ node->add_child_nocopy (*remote_control_node);
+
if (_control_outs) {
XMLNode* cnode = new XMLNode (X_("ControlOuts"));
cnode->add_child_nocopy (_control_outs->state (full_state));
@@ -1564,7 +1581,7 @@ Route::_set_state (const XMLNode& node, bool call_base)
error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
<< endmsg;
} else {
- set_order_key (remaining.substr (0, equal), n);
+ set_order_key (remaining.substr (0, equal).c_str(), n);
}
}
@@ -1661,6 +1678,13 @@ Route::_set_state (const XMLNode& node, bool call_base)
_session.add_controllable (&_mute_control);
}
}
+ else if (child->name() == X_("remote_control")) {
+ if ((prop = child->property (X_("id"))) != 0) {
+ int32_t x;
+ sscanf (prop->value().c_str(), "%d", &x);
+ set_remote_control_id (x);
+ }
+ }
}
if ((prop = node.property (X_("mix-group"))) != 0) {
diff --git a/libs/ardour/route_group.cc b/libs/ardour/route_group.cc
index c2aa59ed8b..13b90474cc 100644
--- a/libs/ardour/route_group.cc
+++ b/libs/ardour/route_group.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#define __STDC_FORMAT_MACROS
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index 0141007803..39c917571a 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 764b25dc9b..9d0b13fccd 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -54,7 +53,6 @@
#include <ardour/midi_playlist.h>
#include <ardour/midi_region.h>
#include <ardour/smf_source.h>
-#include <ardour/destructive_filesource.h>
#include <ardour/auditioner.h>
#include <ardour/recent_sessions.h>
#include <ardour/redirect.h>
@@ -86,6 +84,12 @@ using namespace ARDOUR;
using namespace PBD;
using boost::shared_ptr;
+#ifdef __x86_64__
+static const int CPU_CACHE_ALIGN = 64;
+#else
+static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
+#endif
+
const char* Session::_template_suffix = X_(".template");
const char* Session::_statefile_suffix = X_(".ardour");
const char* Session::_pending_suffix = X_(".pending");
@@ -94,8 +98,10 @@ const char* Session::sound_dir_name = X_("audiofiles");
const char* Session::peak_dir_name = X_("peaks");
const char* Session::dead_sound_dir_name = X_("dead_sounds");
const char* Session::interchange_dir_name = X_("interchange");
+const char* Session::export_dir_name = X_("export");
-Session::compute_peak_t Session::compute_peak = 0;
+Session::compute_peak_t Session::compute_peak = 0;
+Session::find_peaks_t Session::find_peaks = 0;
Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 0;
Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0;
Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0;
@@ -280,6 +286,10 @@ Session::Session (AudioEngine &eng,
{
bool new_session;
+ if (!eng.connected()) {
+ throw failed_constructor();
+ }
+
cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl;
n_physical_outputs = _engine.n_physical_outputs();
@@ -342,6 +352,10 @@ Session::Session (AudioEngine &eng,
{
bool new_session;
+ if (!eng.connected()) {
+ throw failed_constructor();
+ }
+
cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl;
n_physical_outputs = _engine.n_physical_outputs();
@@ -1396,7 +1410,7 @@ Session::set_block_size (nframes_t nframes)
{
current_block_size = nframes;
-
+
ensure_buffers(_scratch_buffers->available());
if (_gain_automation_buffer) {
@@ -1740,16 +1754,19 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
} else {
nphysical_out = 0;
}
+
+ shared_ptr<AudioTrack> track;
try {
- shared_ptr<AudioTrack> track (new AudioTrack (*this, track_name, Route::Flag (0), mode));
+ track = boost::shared_ptr<AudioTrack>((new AudioTrack (*this, track_name, Route::Flag (0), mode)));
if (track->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
+ goto failed;
}
-
+
if (nphysical_in) {
for (uint32_t x = 0; x < track->n_inputs().get(DataType::AUDIO) && x < nphysical_in; ++x) {
@@ -1809,14 +1826,43 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
catch (failed_constructor &err) {
error << _("Session: could not create new audio track.") << endmsg;
- // XXX should we delete the tracks already created?
- ret.clear ();
- return ret;
+
+ if (track) {
+ /* we need to get rid of this, since the track failed to be created */
+ /* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
+
+ {
+ RCUWriter<DiskstreamList> writer (diskstreams);
+ boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
+ ds->remove (track->audio_diskstream());
+ }
+ }
+
+ goto failed;
}
-
+
+ catch (AudioEngine::PortRegistrationFailure& pfe) {
+
+ error << _("No more JACK ports are available. You will need to stop Ardour and restart JACK with ports if you need this many tracks.") << endmsg;
+
+ if (track) {
+ /* we need to get rid of this, since the track failed to be created */
+ /* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
+
+ {
+ RCUWriter<DiskstreamList> writer (diskstreams);
+ boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
+ ds->remove (track->audio_diskstream());
+ }
+ }
+
+ goto failed;
+ }
+
--how_many;
}
+ failed:
if (!new_routes.empty()) {
add_routes (new_routes, false);
save_state (_current_snapshot_name);
@@ -1825,6 +1871,27 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
return ret;
}
+void
+Session::set_remote_control_ids ()
+{
+ RemoteModel m = Config->get_remote_model();
+
+ shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ( MixerOrdered == m) {
+ long order = (*i)->order_key(N_("signal"));
+ (*i)->set_remote_control_id( order+1 );
+ } else if ( EditorOrdered == m) {
+ long order = (*i)->order_key(N_("editor"));
+ (*i)->set_remote_control_id( order+1 );
+ } else if ( UserOrdered == m) {
+ //do nothing ... only changes to remote id's are initiated by user
+ }
+ }
+}
+
+
Session::RouteList
Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
{
@@ -1876,6 +1943,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
+ goto failure;
}
for (uint32_t x = 0; n_physical_inputs && x < bus->n_inputs().get(DataType::AUDIO); ++x) {
@@ -1927,13 +1995,19 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
catch (failed_constructor &err) {
error << _("Session: could not create new audio route.") << endmsg;
- ret.clear ();
- return ret;
+ goto failure;
+ }
+
+ catch (AudioEngine::PortRegistrationFailure& pfe) {
+ error << _("No more JACK ports are available. You will need to stop Ardour and restart JACK with ports if you need this many tracks.") << endmsg;
+ goto failure;
}
+
--how_many;
}
+ failure:
if (!ret.empty()) {
add_routes (ret, false);
save_state (_current_snapshot_name);
@@ -1984,21 +2058,23 @@ void
Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
{
/* need to do this in case we're rolling at the time, to prevent false underruns */
- dstream->do_refill_with_alloc();
+ dstream->do_refill_with_alloc ();
- {
+ dstream->set_block_size (current_block_size);
+
+ {
RCUWriter<DiskstreamList> writer (diskstreams);
boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
ds->push_back (dstream);
- }
-
- dstream->set_block_size (current_block_size);
+ /* writer goes out of scope, copies ds back to main */
+ }
dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream));
/* this will connect to future changes, and check the current length */
diskstream_playlist_changed (dstream);
dstream->prepare ();
+
}
void
@@ -2180,9 +2256,11 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
modify_solo_mute (is_track, same_thing_soloed);
if (signal) {
- SoloActive (currently_soloing);
+ SoloActive (currently_soloing); /* EMIT SIGNAL */
}
+ SoloChanged (); /* EMIT SIGNAL */
+
set_dirty();
}
@@ -2797,6 +2875,24 @@ Session::source_by_id (const PBD::ID& id)
return source;
}
+
+boost::shared_ptr<Source>
+Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
+{
+ Glib::Mutex::Lock lm (source_lock);
+
+ for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
+ cerr << "comparing " << path << " with " << i->second->name() << endl;
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(i->second);
+
+ if (afs && afs->path() == path && chn == afs->channel()) {
+ return afs;
+ }
+
+ }
+ return boost::shared_ptr<Source>();
+}
+
string
Session::peak_path_from_audio_path (string audio_path) const
{
@@ -3503,7 +3599,7 @@ void
Session::graph_reordered ()
{
/* don't do this stuff if we are setting up connections
- from a set_state() call.
+ from a set_state() call or creating new tracks.
*/
if (_state_of_the_state & InitialConnecting) {
@@ -3630,11 +3726,11 @@ Session::available_capture_duration ()
switch (Config->get_native_file_data_format()) {
case FormatFloat:
- sample_bytes_on_disk = 4;
+ sample_bytes_on_disk = 4.0;
break;
case FormatInt24:
- sample_bytes_on_disk = 3;
+ sample_bytes_on_disk = 3.0;
break;
default:
@@ -3733,7 +3829,6 @@ Session::next_insert_id ()
for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < insert_bitset.size(); ++n) {
if (!insert_bitset[n]) {
insert_bitset[n] = true;
- cerr << "Returning " << n << " as insert ID\n";
return n;
}
@@ -3754,7 +3849,6 @@ Session::next_send_id ()
for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < send_bitset.size(); ++n) {
if (!send_bitset[n]) {
send_bitset[n] = true;
- cerr << "Returning " << n << " as send ID\n";
return n;
}
@@ -3991,6 +4085,12 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
buffers.ensure_buffers(nchans, chunk_size);
buffers.set_count(nchans);
+ for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
+ if (afs)
+ afs->prepare_for_peakfile_writes ();
+ }
+
while (to_do && !itt.cancel) {
this_chunk = min (to_do, chunk_size);
@@ -4029,18 +4129,10 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
if (afs) {
afs->update_header (position, *xnow, now);
+ afs->flush_header ();
}
}
- /* build peakfile for new source */
-
- for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
- boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
- if (afs) {
- afs->build_peaks ();
- }
- }
-
/* construct a region to represent the bounced material */
boost::shared_ptr<Region> aregion = RegionFactory::create (srcs, 0, srcs.front()->length(),
@@ -4060,6 +4152,14 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le
(*src)->drop_references ();
}
+
+ } else {
+ for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
+ boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
+
+ if (afs)
+ afs->done_with_peakfile_writes ();
+ }
}
g_atomic_int_set (&processing_prohibited, 0);
diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc
index bb02eede91..16c8d9cffa 100644
--- a/libs/ardour/session_butler.cc
+++ b/libs/ardour/session_butler.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
@@ -104,10 +103,12 @@ Session::start_butler_thread ()
void
Session::terminate_butler_thread ()
{
- void* status;
- char c = ButlerRequest::Quit;
- ::write (butler_request_pipe[1], &c, 1);
- pthread_join (butler_thread, &status);
+ if (butler_thread) {
+ void* status;
+ char c = ButlerRequest::Quit;
+ ::write (butler_request_pipe[1], &c, 1);
+ pthread_join (butler_thread, &status);
+ }
}
void
diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc
index f09c7232d7..9dccce04f2 100644
--- a/libs/ardour/session_click.cc
+++ b/libs/ardour/session_click.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <list>
diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc
index 7cf52b741f..62067bfb46 100644
--- a/libs/ardour/session_command.cc
+++ b/libs/ardour/session_command.cc
@@ -394,7 +394,7 @@ Session::GlobalMeteringStateCommand::get_state()
if (r) {
child->add_property (X_("id"), r->id().to_s());
- const char* meterstr;
+ const char* meterstr = 0;
switch (x->second) {
case MeterInput:
@@ -406,6 +406,8 @@ Session::GlobalMeteringStateCommand::get_state()
case MeterPostFader:
meterstr = X_("post");
break;
+ default:
+ fatal << string_compose (_("programming error: %1") , "no meter state in Session::GlobalMeteringStateCommand::get_state") << endmsg;
}
child->add_property (X_("meter"), meterstr);
@@ -432,6 +434,7 @@ Session::GlobalMeteringStateCommand::get_state()
case MeterPostFader:
meterstr = X_("post");
break;
+ default: meterstr = "";
}
child->add_property (X_("meter"), meterstr);
diff --git a/libs/ardour/session_control.cc b/libs/ardour/session_control.cc
deleted file mode 100644
index afecc146b7..0000000000
--- a/libs/ardour/session_control.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-
-#include <ardour/session.h>
-#include <control_protocol/control_protocol.h>
-#include <generic_midi/generic_midi_control_protocol.h>
-#include <transport/tranzport_control_protocol.h>
-
-using namespace ARDOUR;
-
-void
-Session::initialize_control ()
-{
- GenericMidiControlProtocol* midi_protocol = new GenericMidiControlProtocol (*this);
-
- if (midi_protocol->init() == 0) {
- control_protocols.push_back (midi_protocol);
- }
-
- if (Config->get_use_tranzport()) {
- cerr << "Creating new tranzport control" << endl;
-
- TranzportControlProtocol* tranzport_protocol = new TranzportControlProtocol (*this);
-
- cerr << "Initializing new tranzport control" << endl;
-
- if (tranzport_protocol->init() == 0) {
- control_protocols.push_back (tranzport_protocol);
- }
- }
-}
-
diff --git a/libs/ardour/session_events.cc b/libs/ardour/session_events.cc
index 981f9505d9..35c1019c0e 100644
--- a/libs/ardour/session_events.cc
+++ b/libs/ardour/session_events.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index 6902a426c3..e2d79b86d3 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
/* see gdither.cc for why we have to do this */
@@ -269,7 +268,7 @@ AudioExportSpecification::process (nframes_t nframes)
char errbuf[256];
nframes_t to_write = 0;
int cnt = 0;
-
+
do {
/* now do sample rate conversion */
@@ -429,8 +428,6 @@ AudioExportSpecification::process (nframes_t nframes)
int
Session::start_audio_export (AudioExportSpecification& spec)
{
- int ret;
-
if (spec.prepare (current_block_size, frame_rate())) {
return -1;
}
@@ -438,40 +435,21 @@ Session::start_audio_export (AudioExportSpecification& spec)
spec.pos = spec.start_frame;
spec.end_frame = spec.end_frame;
spec.total_frames = spec.end_frame - spec.start_frame;
+ spec.running = true;
+ spec.do_freewheel = false; /* force a call to ::prepare_to_export() before proceeding to normal operation */
spec.freewheel_connection = _engine.Freewheel.connect (sigc::bind (mem_fun (*this, &Session::process_export), &spec));
- if ((ret = _engine.freewheel (true)) == 0) {
- spec.running = true;
- spec.do_freewheel = false;
- }
-
- return ret;
+ return _engine.freewheel (true);
}
int
Session::stop_audio_export (AudioExportSpecification& spec)
{
- /* can't use stop_transport() here because we need
- an immediate halt and don't require all the declick
- stuff that stop_transport() implements.
- */
-
- realtime_stop (true);
- schedule_butler_transport_work ();
-
- /* restart slaving */
+ /* don't stop freewheeling but do stop paying attention to it for now */
- if (post_export_slave != None) {
- Config->set_slave_source (post_export_slave);
- } else {
- locate (post_export_position, false, false, false);
- }
-
- spec.clear ();
- _exporting = false;
-
- spec.running = false;
+ spec.freewheel_connection.disconnect ();
+ spec.clear (); /* resets running/stop etc */
return 0;
}
@@ -645,3 +623,25 @@ Session::process_export (nframes_t nframes, AudioExportSpecification* spec)
return ret;
}
+void
+Session::finalize_audio_export ()
+{
+ _engine.freewheel (false);
+ _exporting = false;
+
+ /* can't use stop_transport() here because we need
+ an immediate halt and don't require all the declick
+ stuff that stop_transport() implements.
+ */
+
+ realtime_stop (true);
+ schedule_butler_transport_work ();
+
+ /* restart slaving */
+
+ if (post_export_slave != None) {
+ Config->set_slave_source (post_export_slave);
+ } else {
+ locate (post_export_position, false, false, false);
+ }
+}
diff --git a/libs/ardour/session_feedback.cc b/libs/ardour/session_feedback.cc
index 1fd8389e11..2bb9886f50 100644
--- a/libs/ardour/session_feedback.cc
+++ b/libs/ardour/session_feedback.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <string>
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index 18bf9b83e1..2a078565b5 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <string>
@@ -90,50 +89,98 @@ int
Session::set_mtc_port (string port_tag)
{
#if 0
- MTC_Slave *ms;
+ MIDI::byte old_device_id = 0;
+ bool reset_id = false;
if (port_tag.length() == 0) {
-
- if (_slave && ((ms = dynamic_cast<MTC_Slave*> (_slave)) != 0)) {
- error << _("Ardour is slaved to MTC - port cannot be reset") << endmsg;
- return -1;
- }
-
- if (_mtc_port == 0) {
+ if (_mmc_port == 0) {
return 0;
}
-
- _mtc_port = 0;
+ _mmc_port = 0;
goto out;
}
MIDI::Port* port;
if ((port = MIDI::Manager::instance()->port (port_tag)) == 0) {
- error << string_compose (_("unknown port %1 requested for MTC"), port_tag) << endl;
return -1;
}
- _mtc_port = port;
+ _mmc_port = port;
- if (_slave && ((ms = dynamic_cast<MTC_Slave*> (_slave)) != 0)) {
- ms->rebind (*port);
+ if (mmc) {
+ old_device_id = mmc->device_id();
+ reset_id = true;
+ delete mmc;
}
- Config->set_mtc_port_name (port_tag);
+ mmc = new MIDI::MachineControl (*_mmc_port, 1.0,
+ MMC_CommandSignature,
+ MMC_ResponseSignature);
+
+ if (reset_id) {
+ mmc->set_device_id (old_device_id);
+ }
+
+ mmc->Play.connect
+ (mem_fun (*this, &Session::mmc_deferred_play));
+ mmc->DeferredPlay.connect
+ (mem_fun (*this, &Session::mmc_deferred_play));
+ mmc->Stop.connect
+ (mem_fun (*this, &Session::mmc_stop));
+ mmc->FastForward.connect
+ (mem_fun (*this, &Session::mmc_fast_forward));
+ mmc->Rewind.connect
+ (mem_fun (*this, &Session::mmc_rewind));
+ mmc->Pause.connect
+ (mem_fun (*this, &Session::mmc_pause));
+ mmc->RecordPause.connect
+ (mem_fun (*this, &Session::mmc_record_pause));
+ mmc->RecordStrobe.connect
+ (mem_fun (*this, &Session::mmc_record_strobe));
+ mmc->RecordExit.connect
+ (mem_fun (*this, &Session::mmc_record_exit));
+ mmc->Locate.connect
+ (mem_fun (*this, &Session::mmc_locate));
+ mmc->Step.connect
+ (mem_fun (*this, &Session::mmc_step));
+ mmc->Shuttle.connect
+ (mem_fun (*this, &Session::mmc_shuttle));
+ mmc->TrackRecordStatusChange.connect
+ (mem_fun (*this, &Session::mmc_record_enable));
+
+
+ /* also handle MIDI SPP because its so common */
+
+ _mmc_port->input()->start.connect (mem_fun (*this, &Session::spp_start));
+ _mmc_port->input()->contineu.connect (mem_fun (*this, &Session::spp_continue));
+ _mmc_port->input()->stop.connect (mem_fun (*this, &Session::spp_stop));
+
+ Config->set_mmc_port_name (port_tag);
out:
- #endif
- MTC_PortChanged(); /* EMIT SIGNAL */
+ MMC_PortChanged(); /* EMIT SIGNAL */
change_midi_ports ();
set_dirty();
+#endif
return 0;
}
+void
+Session::set_mmc_device_id (uint32_t device_id)
+{
+ if (mmc) {
+ mmc->set_device_id (device_id);
+ }
+}
+
int
Session::set_mmc_port (string port_tag)
{
#if 0
+ MIDI::byte old_device_id = 0;
+ bool reset_id = false;
+
if (port_tag.length() == 0) {
if (_mmc_port == 0) {
return 0;
@@ -151,6 +198,8 @@ Session::set_mmc_port (string port_tag)
_mmc_port = port;
if (mmc) {
+ old_device_id = mmc->device_id();
+ reset_id = true;
delete mmc;
}
@@ -158,6 +207,9 @@ Session::set_mmc_port (string port_tag)
MMC_CommandSignature,
MMC_ResponseSignature);
+ if (reset_id) {
+ mmc->set_device_id (old_device_id);
+ }
mmc->Play.connect
(mem_fun (*this, &Session::mmc_deferred_play));
@@ -186,6 +238,7 @@ Session::set_mmc_port (string port_tag)
mmc->TrackRecordStatusChange.connect
(mem_fun (*this, &Session::mmc_record_enable));
+
/* also handle MIDI SPP because its so common */
_mmc_port->input()->start.connect (mem_fun (*this, &Session::spp_start));
@@ -193,6 +246,7 @@ Session::set_mmc_port (string port_tag)
_mmc_port->input()->stop.connect (mem_fun (*this, &Session::spp_stop));
Config->set_mmc_port_name (port_tag);
+
out:
#endif
MMC_PortChanged(); /* EMIT SIGNAL */
@@ -1127,15 +1181,17 @@ Session::start_midi_thread ()
void
Session::terminate_midi_thread ()
{
- MIDIRequest* request = new MIDIRequest;
- void* status;
-
- request->type = MIDIRequest::Quit;
-
- midi_requests.write (&request, 1);
- poke_midi_thread ();
-
- pthread_join (midi_thread, &status);
+ if (midi_thread) {
+ MIDIRequest* request = new MIDIRequest;
+ void* status;
+
+ request->type = MIDIRequest::Quit;
+
+ midi_requests.write (&request, 1);
+ poke_midi_thread ();
+
+ pthread_join (midi_thread, &status);
+ }
}
void
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 2de3448cd1..9b8b7f1d24 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -306,7 +305,7 @@ Session::process_with_events (nframes_t nframes)
return;
}
- end_frame = _transport_frame + nframes;
+ end_frame = _transport_frame + (nframes_t)abs(floor(nframes * _transport_speed));
{
Event* this_event;
@@ -354,20 +353,15 @@ Session::process_with_events (nframes_t nframes)
while (nframes) {
- if (this_event == 0 || this_event->action_frame > end_frame || this_event->action_frame < _transport_frame) {
+ this_nframes = nframes; /* real (jack) time relative */
+ frames_moved = (long) floor (_transport_speed * nframes); /* transport relative */
- this_nframes = nframes;
-
- } else {
-
- /* compute nframes to next event */
-
- if (this_event->action_frame < end_frame) {
- this_nframes = nframes - (end_frame - this_event->action_frame);
- } else {
- this_nframes = nframes;
- }
- }
+ /* running an event, position transport precisely to its time */
+ if (this_event && this_event->action_frame <= end_frame && this_event->action_frame >= _transport_frame) {
+ /* this isn't quite right for reverse play */
+ frames_moved = (long) (this_event->action_frame - _transport_frame);
+ this_nframes = (nframes_t) abs( floor(frames_moved / _transport_speed) );
+ }
if (this_nframes) {
@@ -386,8 +380,6 @@ Session::process_with_events (nframes_t nframes)
nframes -= this_nframes;
offset += this_nframes;
- frames_moved = (nframes_t) floor (_transport_speed * this_nframes);
-
if (frames_moved < 0) {
decrement_transport_position (-frames_moved);
} else {
@@ -419,8 +411,7 @@ Session::process_with_events (nframes_t nframes)
}
/* this is necessary to handle the case of seamless looping */
- /* not sure if it will work in conjuction with varispeed */
- end_frame = _transport_frame + nframes;
+ end_frame = _transport_frame + (nframes_t) floor (nframes * _transport_speed);
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index c8a81be4d4..aae5830b34 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#define __STDC_FORMAT_MACROS 1
@@ -71,7 +70,8 @@
#include <ardour/midi_playlist.h>
#include <ardour/smf_source.h>
#include <ardour/audiofilesource.h>
-#include <ardour/destructive_filesource.h>
+#include <ardour/silentfilesource.h>
+#include <ardour/sndfilesource.h>
#include <ardour/midi_source.h>
#include <ardour/sndfile_helpers.h>
#include <ardour/auditioner.h>
@@ -193,6 +193,8 @@ Session::first_stage_init (string fullpath, string snapshot_name)
current_trans = 0;
first_file_data_format_reset = true;
first_file_header_format_reset = true;
+ butler_thread = (pthread_t) 0;
+ //midi_thread = (pthread_t) 0;
AudioDiskstream::allocate_working_buffers();
@@ -477,11 +479,16 @@ Session::create (bool& new_session, string* mix_template, nframes_t initial_leng
return -1;
}
- dir = sound_dir ();
+ /* if this is is an existing session with an old "sounds" directory, just use it. see Session::sound_dir() for more details */
- if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
- error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
- return -1;
+ if (!Glib::file_test (old_sound_dir(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
+
+ dir = sound_dir ();
+
+ if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+ return -1;
+ }
}
dir = dead_sound_dir ();
@@ -498,6 +505,13 @@ Session::create (bool& new_session, string* mix_template, nframes_t initial_leng
return -1;
}
+ dir = export_dir ();
+
+ if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session export dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+ return -1;
+ }
+
/* check new_session so we don't overwrite an existing one */
@@ -608,6 +622,12 @@ Session::save_state (string snapshot_name, bool pending)
return 1;
}
+ if (!_engine.connected ()) {
+ error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
+ << endmsg;
+ return 1;
+ }
+
tree.set_root (&get_state());
if (snapshot_name.empty()) {
@@ -1442,6 +1462,19 @@ Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
try {
boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
+
+ /* a final detail: this is the one and only place that we know how long missing files are */
+
+ if (region->whole_file()) {
+ for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
+ boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
+ if (sfp) {
+ sfp->set_length (region->length());
+ }
+ }
+ }
+
+
return region;
}
@@ -1533,11 +1566,16 @@ Session::path_from_region_name (string name, string identifier)
} else {
snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
}
- if (access (buf, F_OK) != 0) {
+
+ if (!g_file_test (buf, G_FILE_TEST_EXISTS)) {
return buf;
}
}
+ error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
+ name, identifier)
+ << endmsg;
+
return "";
}
@@ -1555,10 +1593,16 @@ Session::load_sources (const XMLNode& node)
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- if ((source = XMLSourceFactory (**niter)) == 0) {
- error << _("Session: cannot create Source from XML description.") << endmsg;
+ try {
+ if ((source = XMLSourceFactory (**niter)) == 0) {
+ error << _("Session: cannot create Source from XML description.") << endmsg;
+ }
}
+ catch (non_existent_source& err) {
+ warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
+ source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
+ }
}
return 0;
@@ -1574,7 +1618,7 @@ Session::XMLSourceFactory (const XMLNode& node)
try {
return SourceFactory::create (*this, node);
}
-
+
catch (failed_constructor& err) {
error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
return boost::shared_ptr<Source>();
@@ -1922,36 +1966,34 @@ Session::dead_sound_dir () const
{
string res = _path;
res += dead_sound_dir_name;
- res += '/';
+
return res;
}
string
-Session::sound_dir (bool with_path) const
+Session::old_sound_dir (bool with_path) const
{
- /* support old session structure */
+ string res;
- struct stat statbuf;
- string old_nopath;
- string old_withpath;
+ if (with_path) {
+ res = _path;
+ }
- old_nopath += old_sound_dir_name;
- old_nopath += '/';
-
- old_withpath = _path;
- old_withpath += old_sound_dir_name;
+ res += old_sound_dir_name;
- if (stat (old_withpath.c_str(), &statbuf) == 0) {
- if (with_path)
- return old_withpath;
-
- return old_nopath;
- }
+ return res;
+}
+string
+Session::sound_dir (bool with_path) const
+{
string res;
+ string full;
if (with_path) {
res = _path;
+ } else {
+ full = _path;
}
res += interchange_dir_name;
@@ -1960,6 +2002,38 @@ Session::sound_dir (bool with_path) const
res += '/';
res += sound_dir_name;
+ if (with_path) {
+ full = res;
+ } else {
+ full += res;
+ }
+
+ /* if this already exists, don't check for the old session sound directory */
+
+ if (Glib::file_test (full, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
+ return res;
+ }
+
+ /* possibly support old session structure */
+
+ string old_nopath;
+ string old_withpath;
+
+ old_nopath += old_sound_dir_name;
+ old_nopath += '/';
+
+ old_withpath = _path;
+ old_withpath += old_sound_dir_name;
+
+ if (Glib::file_test (old_withpath.c_str(), Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
+ if (with_path)
+ return old_withpath;
+
+ return old_nopath;
+ }
+
+ /* ok, old "sounds" directory isn't there, return the new path */
+
return res;
}
@@ -1990,6 +2064,15 @@ Session::template_dir ()
}
string
+Session::export_dir () const
+{
+ string res = _path;
+ res += export_dir_name;
+ res += '/';
+ return res;
+}
+
+string
Session::suffixed_search_path (string suffix, bool data)
{
string path;
@@ -2703,7 +2786,7 @@ Session::cleanup_sources (Session::cleanup_report& rep)
on whichever filesystem it was already on.
*/
- if (_path.find ("/sounds/")) {
+ if ((*x).find ("/sounds/") != string::npos) {
/* old school, go up 1 level */
@@ -2898,6 +2981,12 @@ Session::set_deletion_in_progress ()
void
Session::add_controllable (Controllable* c)
{
+ /* this adds a controllable to the list managed by the Session.
+ this is a subset of those managed by the Controllable class
+ itself, and represents the only ones whose state will be saved
+ as part of the session.
+ */
+
Glib::Mutex::Lock lm (controllables_lock);
controllables.insert (c);
}
@@ -3131,6 +3220,12 @@ Session::config_changed (const char* parameter_name)
//poke_midi_thread ();
+ } else if (PARAM_IS ("mmc-device-id")) {
+
+ if (mmc) {
+ mmc->set_device_id (Config->get_mmc_device_id());
+ }
+
} else if (PARAM_IS ("midi-control")) {
//poke_midi_thread ();
@@ -3233,6 +3328,8 @@ Session::config_changed (const char* parameter_name)
} else if (PARAM_IS ("slave-source")) {
set_slave_source (Config->get_slave_source());
+ } else if (PARAM_IS ("remote-model")) {
+ set_remote_control_ids ();
}
set_dirty ();
diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc
index 585dad6b1a..836958f667 100644
--- a/libs/ardour/session_time.cc
+++ b/libs/ardour/session_time.cc
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <iostream>
diff --git a/libs/ardour/session_timefx.cc b/libs/ardour/session_timefx.cc
index 69a42ec8b8..4061b2ccd0 100644
--- a/libs/ardour/session_timefx.cc
+++ b/libs/ardour/session_timefx.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cerrno>
@@ -50,6 +49,9 @@ Session::tempoize_region (TimeStretchRequest& tsr)
float percentage;
nframes_t total_frames;
nframes_t done;
+ int c;
+ char buf[64];
+ string::size_type len;
/* the soundtouch code wants a *tempo* change percentage, which is
of opposite sign to the length change.
@@ -73,8 +75,18 @@ Session::tempoize_region (TimeStretchRequest& tsr)
done = 0;
for (uint32_t i = 0; i < tsr.region->n_channels(); ++i) {
- string path = path_from_region_name (PBD::basename_nosuffix (names[i]), ident);
+ string rstr;
+ string::size_type existing_ident;
+
+ if ((existing_ident = names[i].find (ident)) != string::npos) {
+ rstr = names[i].substr (0, existing_ident);
+ } else {
+ rstr = names[i];
+ }
+
+ string path = path_from_region_name (PBD::basename_nosuffix (rstr), ident);
+
if (path.length() == 0) {
error << string_compose (_("tempoize: error creating name for new audio file based on %1"), tsr.region->name())
<< endmsg;
@@ -88,6 +100,7 @@ Session::tempoize_region (TimeStretchRequest& tsr)
error << string_compose (_("tempoize: error creating new audio file %1 (%2)"), path, strerror (errno)) << endmsg;
goto out;
}
+
}
try {
@@ -164,7 +177,34 @@ Session::tempoize_region (TimeStretchRequest& tsr)
}
}
- region_name = tsr.region->name() + X_(".t");
+ len = tsr.region->name().length();
+
+ while (--len) {
+ if (!isdigit (tsr.region->name()[len])) {
+ break;
+ }
+ }
+
+ if (len == 0) {
+
+ region_name = tsr.region->name() + ".t000";
+
+ } else {
+
+ if (tsr.region->name()[len] == 't') {
+ c = atoi (tsr.region->name().substr(len+1));
+
+ snprintf (buf, sizeof (buf), "t%03d", ++c);
+ region_name = tsr.region->name().substr (0, len) + buf;
+
+ } else {
+
+ /* not sure what this is, just tack the suffix on to it */
+
+ region_name = tsr.region->name() + ".t000";
+ }
+
+ }
r = (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, 0, sources.front()->length(), region_name,
0, AudioRegion::Flag (AudioRegion::DefaultFlags | AudioRegion::WholeFile))));
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index ad3573a72e..3ee74231e0 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cmath>
@@ -181,7 +180,7 @@ Session::realtime_stop (bool abort)
waiting_for_sync_offset = true;
}
- transport_sub_state = (Config->get_auto_return() ? AutoReturning : 0);
+ transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0);
}
void
@@ -377,13 +376,13 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
update_latency_compensation (true, abort);
}
- if (Config->get_auto_return() || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
+ if ((Config->get_slave_source() == None && Config->get_auto_return()) || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
if (pending_locate_flush) {
flush_all_redirects ();
}
-
- if ((Config->get_auto_return() || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
+
+ if (((Config->get_slave_source() == None && Config->get_auto_return()) || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
_transport_frame = last_stop_frame;
@@ -663,8 +662,6 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
} else {
- cerr << "butler not requested\n";
-
/* this is functionally what clear_clicks() does but with a tentative lock */
Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
@@ -808,7 +805,7 @@ Session::set_transport_speed (float speed, bool abort)
before the last stop, then we have to do extra work.
*/
- if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f)) {
+ if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse);
}
@@ -939,7 +936,7 @@ Session::post_transport ()
if (post_transport_work & PostTransportLocate) {
- if ((Config->get_auto_play() && !_exporting) || (post_transport_work & PostTransportRoll)) {
+ if (((Config->get_slave_source() == None && Config->get_auto_play()) && !_exporting) || (post_transport_work & PostTransportRoll)) {
start_transport ();
} else {
diff --git a/libs/ardour/session_vst.cc b/libs/ardour/session_vst.cc
index 70bf1a8042..16233feba2 100644
--- a/libs/ardour/session_vst.cc
+++ b/libs/ardour/session_vst.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <stdbool.h>
diff --git a/gtk2_ardour/ardour_message.h b/libs/ardour/silentfilesource.cc
index a9ac02a5bc..b34944e342 100644
--- a/gtk2_ardour/ardour_message.h
+++ b/libs/ardour/silentfilesource.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2004 Paul Davis
+ Copyright (C) 2007 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -15,33 +15,25 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
-
*/
-#ifndef __ardour_message_h__
-#define __ardour_message_h__
+#include <ardour/silentfilesource.h>
-#include <string>
+using namespace ARDOUR;
-#include <gtkmm/box.h>
-#include <gtkmm/button.h>
-#include <gtkmm/label.h>
+SilentFileSource::SilentFileSource (Session& s, const XMLNode& node, nframes_t len, float sr)
+ : AudioFileSource (s, node, false)
+{
+ _length = len;
+ _sample_rate = sr;
+}
-#include "ardour_dialog.h"
+SilentFileSource::~SilentFileSource ()
+{
+}
-class ArdourMessage : public ArdourDialog
+void
+SilentFileSource::set_length (nframes_t len)
{
- public:
- ArdourMessage (Gtk::Window* parent,
- std::string name, std::string msg,
- bool grabfocus = true,
- bool autorun = true);
- ~ArdourMessage();
-
- private:
- Gtk::Label label;
-
-};
-
-#endif // __ardour_message_h__
+ _length = len;
+}
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index 2885240a51..d11afa736b 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <cerrno>
@@ -36,6 +35,7 @@
using namespace std;
using namespace ARDOUR;
using namespace PBD;
+using Glib::ustring;
gain_t* SndFileSource::out_coefficient = 0;
gain_t* SndFileSource::in_coefficient = 0;
@@ -50,18 +50,16 @@ SndFileSource::SndFileSource (Session& s, const XMLNode& node)
{
init ();
- cerr << "SndFileSource @ " << _path << " channel = " << channel << endl;
-
if (open()) {
throw failed_constructor ();
}
}
-SndFileSource::SndFileSource (Session& s, string path, int chn, Flag flags)
+SndFileSource::SndFileSource (Session& s, ustring path, int chn, Flag flags)
/* files created this way are never writable or removable */
: AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
{
- channel = chn;
+ _channel = chn;
init ();
@@ -70,7 +68,7 @@ SndFileSource::SndFileSource (Session& s, string path, int chn, Flag flags)
}
}
-SndFileSource::SndFileSource (Session& s, string path, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
+SndFileSource::SndFileSource (Session& s, ustring path, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
: AudioFileSource (s, path, flags, sfmt, hf)
{
int fmt = 0;
@@ -180,7 +178,7 @@ SndFileSource::SndFileSource (Session& s, string path, SampleFormat sfmt, Header
void
SndFileSource::init ()
{
- string file;
+ ustring file;
// lets try to keep the object initalizations here at the top
xfade_buf = 0;
@@ -224,8 +222,8 @@ SndFileSource::open ()
return -1;
}
- if (channel >= _info.channels) {
- error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, channel) << endmsg;
+ if (_channel >= _info.channels) {
+ error << string_compose(_("SndFileSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, _channel) << endmsg;
sf_close (sf);
sf = 0;
return -1;
@@ -349,7 +347,7 @@ SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
}
nread = sf_read_float (sf, interleave_buf, real_cnt);
- ptr = interleave_buf + channel;
+ ptr = interleave_buf + _channel;
nread /= _info.channels;
/* stride through the interleaved data */
@@ -390,7 +388,7 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
nframes_t oldlen;
int32_t frame_pos = _length;
-
+
if (write_float (data, frame_pos, cnt) != cnt) {
return 0;
}
@@ -399,28 +397,7 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
update_length (oldlen, cnt);
if (_build_peakfiles) {
- PeakBuildRecord *pbr = 0;
-
- if (pending_peak_builds.size()) {
- pbr = pending_peak_builds.back();
- }
-
- if (pbr && pbr->frame + pbr->cnt == oldlen) {
-
- /* the last PBR extended to the start of the current write,
- so just extend it again.
- */
- pbr->cnt += cnt;
- } else {
- pending_peak_builds.push_back (new PeakBuildRecord (oldlen, cnt));
- }
-
- _peaks_built = false;
- }
-
-
- if (_build_peakfiles) {
- queue_for_peaks (shared_from_this (), false);
+ compute_and_write_peaks (data, frame_pos, cnt, false);
}
_write_data_count = cnt;
@@ -510,32 +487,12 @@ SndFileSource::destructive_write_unlocked (Sample* data, nframes_t cnt)
old_file_pos = file_pos;
update_length (file_pos, cnt);
- file_pos += cnt;
if (_build_peakfiles) {
- PeakBuildRecord *pbr = 0;
-
- if (pending_peak_builds.size()) {
- pbr = pending_peak_builds.back();
- }
-
- if (pbr && pbr->frame + pbr->cnt == old_file_pos) {
-
- /* the last PBR extended to the start of the current write,
- so just extend it again.
- */
-
- pbr->cnt += cnt;
- } else {
- pending_peak_builds.push_back (new PeakBuildRecord (old_file_pos, cnt));
- }
-
- _peaks_built = false;
+ compute_and_write_peaks (data, file_pos, cnt, false);
}
- if (_build_peakfiles) {
- queue_for_peaks (shared_from_this (), true);
- }
+ file_pos += cnt;
return cnt;
}
@@ -630,9 +587,6 @@ SndFileSource::set_header_timeline_position ()
delete _broadcast_info;
_broadcast_info = 0;
}
-
-
-
}
nframes_t
@@ -888,7 +842,7 @@ SndFileSource::set_timeline_position (int64_t pos)
}
int
-SndFileSource::get_soundfile_info (string path, SoundFileInfo& info, string& error_msg)
+SndFileSource::get_soundfile_info (const ustring& path, SoundFileInfo& info, string& error_msg)
{
SNDFILE *sf;
SF_INFO sf_info;
diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc
index db2147493a..c4cf1156cd 100644
--- a/libs/ardour/source.cc
+++ b/libs/ardour/source.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <sys/stat.h>
diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc
index 560bf03e7f..143d564809 100644
--- a/libs/ardour/source_factory.cc
+++ b/libs/ardour/source_factory.cc
@@ -22,9 +22,9 @@
#include <ardour/source_factory.h>
#include <ardour/sndfilesource.h>
-#include <ardour/smf_source.h>
-#include <ardour/destructive_filesource.h>
+#include <ardour/silentfilesource.h>
#include <ardour/configuration.h>
+#include <ardour/smf_source.h>
#ifdef HAVE_COREAUDIO
#include <ardour/coreaudiosource.h>
@@ -52,6 +52,14 @@ SourceFactory::setup_peakfile (boost::shared_ptr<Source> s)
return 0;
}
+boost::shared_ptr<Source>
+SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes, float sr)
+{
+ boost::shared_ptr<Source> ret (new SilentFileSource (s, node, nframes, sr));
+ SourceCreated (ret);
+ return ret;
+}
+
#ifdef HAVE_COREAUDIO
boost::shared_ptr<Source>
SourceFactory::create (Session& s, const XMLNode& node)
@@ -74,6 +82,9 @@ SourceFactory::create (Session& s, const XMLNode& node)
}
catch (failed_constructor& err) {
+
+ /* this is allowed to throw */
+
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
@@ -87,7 +98,6 @@ SourceFactory::create (Session& s, const XMLNode& node)
boost::shared_ptr<Source> ret (new SMFSource (node));
SourceCreated (ret);
return ret;
-
}
return boost::shared_ptr<Source>();
@@ -98,12 +108,14 @@ SourceFactory::create (Session& s, const XMLNode& node)
boost::shared_ptr<Source>
SourceFactory::create (Session& s, const XMLNode& node)
{
+ /* this is allowed to throw */
+
DataType type = DataType::AUDIO;
const XMLProperty* prop = node.property("type");
if (prop) {
type = DataType(prop->value());
}
-
+
if (type == DataType::AUDIO) {
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
@@ -123,7 +135,7 @@ SourceFactory::create (Session& s, const XMLNode& node)
return ret;
}
-
+
return boost::shared_ptr<Source> ();
}
@@ -160,6 +172,9 @@ SourceFactory::createReadable (DataType type, Session& s, string path, int chn,
} else {
+
+ /* this is allowed to throw */
+
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
diff --git a/libs/ardour/sse_functions_xmm.cc b/libs/ardour/sse_functions_xmm.cc
new file mode 100644
index 0000000000..5554462132
--- /dev/null
+++ b/libs/ardour/sse_functions_xmm.cc
@@ -0,0 +1,116 @@
+/*
+ Copyright (C) 2007 Paul sDavis
+ Written by Sampo Savolainen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <xmmintrin.h>
+#include <ardour/types.h>
+
+void
+x86_sse_find_peaks(float *buf, nframes_t nframes, float *min, float *max)
+{
+ __m128 current_max, current_min, work;
+
+ // Load max and min values into all four slots of the XMM registers
+ current_min = _mm_set1_ps(*min);
+ current_max = _mm_set1_ps(*max);
+
+ // Work input until "buf" reaches 16 byte alignment
+ while ( ((unsigned long)buf) % 16 != 0 && nframes > 0) {
+
+ // Load the next float into the work buffer
+ work = _mm_set1_ps(*buf);
+
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+
+ buf++;
+ nframes--;
+ }
+
+ // use 64 byte prefetch for quadruple quads
+ while (nframes >= 16) {
+ __builtin_prefetch(buf+64,0,0);
+
+ work = _mm_load_ps(buf);
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+ buf+=4;
+ work = _mm_load_ps(buf);
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+ buf+=4;
+ work = _mm_load_ps(buf);
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+ buf+=4;
+ work = _mm_load_ps(buf);
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+ buf+=4;
+ nframes-=16;
+ }
+
+ // work through aligned buffers
+ while (nframes >= 4) {
+
+ work = _mm_load_ps(buf);
+
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+
+ buf+=4;
+ nframes-=4;
+ }
+
+ // work through the rest < 4 samples
+ while ( nframes > 0) {
+
+ // Load the next float into the work buffer
+ work = _mm_set1_ps(*buf);
+
+ current_min = _mm_min_ps(current_min, work);
+ current_max = _mm_max_ps(current_max, work);
+
+ buf++;
+ nframes--;
+ }
+
+ // Find min & max value in current_max through shuffle tricks
+
+ work = current_min;
+ work = _mm_shuffle_ps(work, work, _MM_SHUFFLE(2, 3, 0, 1));
+ work = _mm_min_ps (work, current_min);
+ current_min = work;
+ work = _mm_shuffle_ps(work, work, _MM_SHUFFLE(1, 0, 3, 2));
+ work = _mm_min_ps (work, current_min);
+
+ _mm_store_ss(min, work);
+
+ work = current_max;
+ work = _mm_shuffle_ps(work, work, _MM_SHUFFLE(2, 3, 0, 1));
+ work = _mm_max_ps (work, current_max);
+ current_max = work;
+ work = _mm_shuffle_ps(work, work, _MM_SHUFFLE(1, 0, 3, 2));
+ work = _mm_max_ps (work, current_max);
+
+ _mm_store_ss(max, work);
+}
+
+
+
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index e86c30dd4d..cd59e93054 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc
index e0ef8fd0b3..51a0414d0c 100644
--- a/libs/ardour/utils.cc
+++ b/libs/ardour/utils.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#define __STDC_FORMAT_MACROS 1
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index 5d7a303fc6..ed78b0942d 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <algorithm>
diff --git a/libs/clearlooks/clearlooks_theme_main.c b/libs/clearlooks/clearlooks_theme_main.c
index d30d4dd0b7..5356f915dd 100644
--- a/libs/clearlooks/clearlooks_theme_main.c
+++ b/libs/clearlooks/clearlooks_theme_main.c
@@ -9,7 +9,7 @@ theme_init (GTypeModule *module)
{
clearlooks_rc_style_register_type (module);
clearlooks_style_register_type (module);
- printf("theme_init() called from internal clearlooks engine!\n");
+ printf("theme_init() called from internal clearlooks engine\n");
}
G_MODULE_EXPORT void
diff --git a/libs/fst/fst.h b/libs/fst/fst.h
index 9055eac620..493cb2e572 100644
--- a/libs/fst/fst.h
+++ b/libs/fst/fst.h
@@ -82,6 +82,7 @@ extern "C" {
#endif
extern int fst_init ();
+extern void fst_finish ();
extern FSTHandle* fst_load (const char*);
extern int fst_unload (FSTHandle*);
diff --git a/libs/fst/vstwin.c b/libs/fst/vstwin.c
index 8911ff4a01..55061c2b72 100644
--- a/libs/fst/vstwin.c
+++ b/libs/fst/vstwin.c
@@ -326,9 +326,17 @@ DWORD WINAPI gui_event_loop (LPVOID param)
fst_error ("cannot set timer on dummy window");
}
- while (GetMessageA (&msg, NULL, 0,0)) {
+ while (1) {
+
+ GetMessageA (&msg, NULL, 0,0);
+
+ if (msg.message == WM_SYSTEMERROR) {
+ /* sent when this thread is supposed to exist */
+ break;
+ }
- if( msg.message == WM_KEYDOWN ) debreak();
+ if (msg.message == WM_KEYDOWN) debreak();
+
TranslateMessage( &msg );
DispatchMessageA (&msg);
@@ -336,7 +344,6 @@ DWORD WINAPI gui_event_loop (LPVOID param)
and run idle callbacks
*/
-
if( msg.message == WM_TIMER ) {
pthread_mutex_lock (&plugin_mutex);
again:
@@ -411,6 +418,12 @@ fst_init ()
return 0;
}
+void
+fst_finish ()
+{
+ PostThreadMessageA (gui_thread_id, WM_SYSTEMERROR, 0, 0);
+}
+
int
fst_run_editor (FST* fst)
{
@@ -501,7 +514,9 @@ fst_load (const char *path)
return NULL;
}
- if ((fhandle->main_entry = GetProcAddress (fhandle->dll, "main")) == NULL) {
+ typedef AEffect* (*entryFunctionType)(audioMasterCallback);
+
+ if ((fhandle->main_entry = (entryFunctionType) GetProcAddress (fhandle->dll, "main")) == NULL) {
fst_unload (fhandle);
return NULL;
}
diff --git a/libs/glibmm2/autogen.sh b/libs/glibmm2/autogen.sh
index c58ddd27a2..f2f287d325 100755
--- a/libs/glibmm2/autogen.sh
+++ b/libs/glibmm2/autogen.sh
@@ -1,5 +1,27 @@
#! /bin/sh
+# check all tools first
+
+if /usr/bin/which libtoolize >/dev/null 2>&1 ; then
+ :
+else
+ echo "You do not have libtool installed, which is very sadly required to build part of Ardour"
+ exit 1
+fi
+if /usr/bin/which automake >/dev/null 2>&1 ; then
+ :
+else
+ echo "You do not have automake installed, which is very sadly required to build part of Ardour"
+ exit 1
+fi
+if /usr/bin/which autoconf >/dev/null 2>&1 ; then
+ :
+else
+ echo "You do not have autoconf installed, which is very sadly required to build part of Ardour"
+ exit 1
+fi
+
+
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
diff --git a/libs/gtkmm2ext/SConscript b/libs/gtkmm2ext/SConscript
index 9c7511c85d..579ba5dd8e 100644
--- a/libs/gtkmm2ext/SConscript
+++ b/libs/gtkmm2ext/SConscript
@@ -40,6 +40,7 @@ click_box.cc
dndtreeview.cc
fastmeter.cc
focus_entry.cc
+grouped_buttons.cc
gtk_ui.cc
hexentry.cc
idle_adjustment.cc
diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc
index f59d192ff1..c3c15b4281 100644
--- a/libs/gtkmm2ext/barcontroller.cc
+++ b/libs/gtkmm2ext/barcontroller.cc
@@ -267,14 +267,12 @@ BarController::expose (GdkEventExpose* event)
gint w, h;
double fract;
- w = darea.get_width() - 2;
- h = darea.get_height() - 2;
-
fract = ((adjustment.get_value() - adjustment.get_lower()) /
(adjustment.get_upper() - adjustment.get_lower()));
switch (_style) {
case Line:
+ w = darea.get_width() - 1;
h = darea.get_height();
x1 = (gint) floor (w * fract);
x2 = x1;
@@ -304,6 +302,10 @@ BarController::expose (GdkEventExpose* event)
break;
case LeftToRight:
+
+ w = darea.get_width() - 2;
+ h = darea.get_height() - 2;
+
x1 = 0;
x2 = (gint) floor (w * fract);
y1 = 0;
diff --git a/libs/gtkmm2ext/bindable_button.cc b/libs/gtkmm2ext/bindable_button.cc
index 76b89deb02..3c3cad6e46 100644
--- a/libs/gtkmm2ext/bindable_button.cc
+++ b/libs/gtkmm2ext/bindable_button.cc
@@ -42,7 +42,7 @@ BindableToggleButton::BindableToggleButton (MIDI::Controllable *mc)
}
BindableToggleButton::BindableToggleButton(MIDI::Controllable *mc, const string &label)
- : ToggleButton (label),
+ : StatefulButton (label),
prompter (Gtk::WIN_POS_MOUSE, 30000, false),
midi_control (mc),
bind_button (2),
@@ -90,17 +90,6 @@ BindableToggleButton::midi_learn()
}
bool
-BindableToggleButton::on_button_press_event (GdkEventButton *ev)
-{
- if ((ev->state & bind_statemask) && ev->button == bind_button) {
- midi_learn ();
- return true;
- }
-
- return false;
-}
-
-bool
BindableToggleButton::prompter_hiding (GdkEventAny *ev)
{
if (unprompting) {
diff --git a/libs/gtkmm2ext/fastmeter.cc b/libs/gtkmm2ext/fastmeter.cc
index 3c489e08ff..253dad80a2 100644
--- a/libs/gtkmm2ext/fastmeter.cc
+++ b/libs/gtkmm2ext/fastmeter.cc
@@ -57,11 +57,10 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o)
pixrect.x = 0;
pixrect.y = 0;
-
if (orientation == Vertical) {
- pixbuf = request_vertical_meter(250);
+ pixbuf = request_vertical_meter(dimen, 250);
} else {
- pixbuf = request_horizontal_meter(186);
+ pixbuf = request_horizontal_meter(186, dimen);
}
pixheight = pixbuf->get_height();
@@ -79,14 +78,14 @@ FastMeter::FastMeter (long hold, unsigned long dimen, Orientation o)
request_height= pixrect.height;
}
-Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_vertical_meter(int length)
+Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_vertical_meter(int width, int height)
{
- if (length < min_v_pixbuf_size)
- length = min_v_pixbuf_size;
- if (length > max_v_pixbuf_size)
- length = max_v_pixbuf_size;
+ if (height < min_v_pixbuf_size)
+ height = min_v_pixbuf_size;
+ if (height > max_v_pixbuf_size)
+ height = max_v_pixbuf_size;
- int index = length - 1;
+ int index = height - 1;
if (v_pixbuf_cache == 0) {
v_pixbuf_cache = (Glib::RefPtr<Gdk::Pixbuf>*) malloc(sizeof(Glib::RefPtr<Gdk::Pixbuf>) * max_v_pixbuf_size);
@@ -97,8 +96,6 @@ Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_vertical_meter(int length)
return ret;
guint8* data;
- int width = 5;
- int height = length;
data = (guint8*) malloc(width*height * 3);
@@ -155,15 +152,15 @@ Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_vertical_meter(int length)
return ret;
}
-Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_horizontal_meter(int length)
+Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_horizontal_meter(int width, int height)
{
- if (length < min_h_pixbuf_size)
- length = min_h_pixbuf_size;
- if (length > max_h_pixbuf_size)
- length = max_h_pixbuf_size;
+ if (width < min_h_pixbuf_size)
+ width = min_h_pixbuf_size;
+ if (width > max_h_pixbuf_size)
+ width = max_h_pixbuf_size;
+
+ int index = width - 1;
- int index = length - 1;
-
if (h_pixbuf_cache == 0) {
h_pixbuf_cache = (Glib::RefPtr<Gdk::Pixbuf>*) malloc(sizeof(Glib::RefPtr<Gdk::Pixbuf>) * max_h_pixbuf_size);
memset(h_pixbuf_cache,0,sizeof(Glib::RefPtr<Gdk::Pixbuf>) * max_h_pixbuf_size);
@@ -173,8 +170,6 @@ Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_horizontal_meter(int length)
return ret;
guint8* data;
- int width = length;
- int height = 5;
data = (guint8*) malloc(width*height * 3);
@@ -253,19 +248,20 @@ void
FastMeter::on_size_request (GtkRequisition* req)
{
if (orientation == Vertical) {
+
req->height = request_height;
-
req->height = max(req->height, min_v_pixbuf_size);
req->height = min(req->height, max_v_pixbuf_size);
- req->width = 5;
- } else {
req->width = request_width;
+ } else {
+
+ req->width = request_width;
req->width = max(req->width, min_h_pixbuf_size);
req->width = min(req->width, max_h_pixbuf_size);
- req->height = 5;
+ req->height = request_height;
}
}
@@ -274,8 +270,9 @@ void
FastMeter::on_size_allocate (Gtk::Allocation &alloc)
{
if (orientation == Vertical) {
- if (alloc.get_width() != 5) {
- alloc.set_width(5);
+
+ if (alloc.get_width() != request_width) {
+ alloc.set_width (request_width);
}
int h = alloc.get_height();
@@ -286,11 +283,13 @@ FastMeter::on_size_allocate (Gtk::Allocation &alloc)
alloc.set_height(h);
if (pixheight != h) {
- pixbuf = request_vertical_meter(h);
+ pixbuf = request_vertical_meter(request_width, h);
}
+
} else {
- if (alloc.get_height() != 5) {
- alloc.set_height(5);
+
+ if (alloc.get_height() != request_height) {
+ alloc.set_height(request_height);
}
int w = alloc.get_width();
@@ -301,7 +300,7 @@ FastMeter::on_size_allocate (Gtk::Allocation &alloc)
alloc.set_width(w);
if (pixwidth != w) {
- pixbuf = request_horizontal_meter(w);
+ pixbuf = request_horizontal_meter(w, request_height);
}
}
diff --git a/gtk2_ardour/grouped_buttons.cc b/libs/gtkmm2ext/grouped_buttons.cc
index 64c58d8197..b16b983d02 100644
--- a/gtk2_ardour/grouped_buttons.cc
+++ b/libs/gtkmm2ext/grouped_buttons.cc
@@ -20,7 +20,7 @@
#include <gtkmm.h>
-#include "grouped_buttons.h"
+#include <gtkmm2ext/grouped_buttons.h>
using namespace std;
diff --git a/libs/gtkmm2ext/gtkmm2ext/auto_spin.h b/libs/gtkmm2ext/gtkmm2ext/auto_spin.h
index 68da2249a0..b692a7ccdc 100644
--- a/libs/gtkmm2ext/gtkmm2ext/auto_spin.h
+++ b/libs/gtkmm2ext/gtkmm2ext/auto_spin.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_auto_spin_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
index e5b8e31b58..c91f4c8a06 100644
--- a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
+++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_bar_controller_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/bindable_button.h b/libs/gtkmm2ext/gtkmm2ext/bindable_button.h
index 1936125405..2ddd3628fc 100644
--- a/libs/gtkmm2ext/gtkmm2ext/bindable_button.h
+++ b/libs/gtkmm2ext/gtkmm2ext/bindable_button.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __bindable_button_h__
@@ -30,15 +29,46 @@ namespace PBD {
class Controllable;
}
-class BindableToggleButton : public Gtk::ToggleButton
+class BindableToggleButton : public Gtkmm2ext::StatefulToggleButton
{
public:
BindableToggleButton (PBD::Controllable& c) : binding_proxy (c) {}
- explicit BindableToggleButton (PBD::Controllable& c, const std::string &label) : Gtk::ToggleButton (label), binding_proxy (c) {}
+
+ explicit BindableToggleButton (PBD::Controllable& c, const std::string &label)
+ : Gtkmm2ext::StatefulToggleButton (label), binding_proxy (c) {}
+
virtual ~BindableToggleButton() {}
bool on_button_press_event (GdkEventButton *ev) {
- return binding_proxy.button_press_handler (ev);
+ if (!binding_proxy.button_press_handler (ev)) {
+ StatefulToggleButton::on_button_press_event (ev);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private:
+ BindingProxy binding_proxy;
+};
+
+class BindableButton : public Gtkmm2ext::StatefulButton
+{
+ public:
+ BindableButton (PBD::Controllable& c) : binding_proxy (c) {}
+
+ explicit BindableButton (PBD::Controllable& c, const std::string &label)
+ : Gtkmm2ext::StatefulButton (label), binding_proxy (c) {}
+
+ ~BindableButton() {}
+
+ bool on_button_press_event (GdkEventButton *ev) {
+ if (!binding_proxy.button_press_handler (ev)) {
+ StatefulButton::on_button_press_event (ev);
+ return false;
+ } else {
+ return true;
+ }
}
private:
diff --git a/libs/gtkmm2ext/gtkmm2ext/click_box.h b/libs/gtkmm2ext/gtkmm2ext/click_box.h
index e4aee36ebe..8f9fb55717 100644
--- a/libs/gtkmm2ext/gtkmm2ext/click_box.h
+++ b/libs/gtkmm2ext/gtkmm2ext/click_box.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_click_box_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/doi.h b/libs/gtkmm2ext/gtkmm2ext/doi.h
index 16a9a6549c..6ad1f7dd94 100644
--- a/libs/gtkmm2ext/gtkmm2ext/doi.h
+++ b/libs/gtkmm2ext/gtkmm2ext/doi.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_gtk_doi_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/fastmeter.h b/libs/gtkmm2ext/gtkmm2ext/fastmeter.h
index d624f29afb..775cb201cd 100644
--- a/libs/gtkmm2ext/gtkmm2ext/fastmeter.h
+++ b/libs/gtkmm2ext/gtkmm2ext/fastmeter.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_fastmeter_h__
@@ -70,13 +69,13 @@ class FastMeter : public Gtk::DrawingArea {
bool vertical_expose (GdkEventExpose*);
bool horizontal_expose (GdkEventExpose*);
- static Glib::RefPtr<Gdk::Pixbuf> request_vertical_meter(int);
+ static Glib::RefPtr<Gdk::Pixbuf> request_vertical_meter(int w, int h);
static Glib::RefPtr<Gdk::Pixbuf> *v_pixbuf_cache;
static int min_v_pixbuf_size;
static int max_v_pixbuf_size;
- static Glib::RefPtr<Gdk::Pixbuf> request_horizontal_meter(int);
+ static Glib::RefPtr<Gdk::Pixbuf> request_horizontal_meter(int w, int h);
static Glib::RefPtr<Gdk::Pixbuf> *h_pixbuf_cache;
static int min_h_pixbuf_size;
diff --git a/gtk2_ardour/grouped_buttons.h b/libs/gtkmm2ext/gtkmm2ext/grouped_buttons.h
index 2bb067fcd0..99d9f8ffc4 100644
--- a/gtk2_ardour/grouped_buttons.h
+++ b/libs/gtkmm2ext/gtkmm2ext/grouped_buttons.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_grouped_buttons_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
index a692e64c9c..b6a52c6c0c 100644
--- a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
+++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __pbd_gtk_ui_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/gtkutils.h b/libs/gtkmm2ext/gtkmm2ext/gtkutils.h
index 1841040560..832423f31d 100644
--- a/libs/gtkmm2ext/gtkmm2ext/gtkutils.h
+++ b/libs/gtkmm2ext/gtkmm2ext/gtkutils.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkutils_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/hexentry.h b/libs/gtkmm2ext/gtkmm2ext/hexentry.h
index 785d6eef36..410f54274e 100644
--- a/libs/gtkmm2ext/gtkmm2ext/hexentry.h
+++ b/libs/gtkmm2ext/gtkmm2ext/hexentry.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_hexentry_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/pixfader.h b/libs/gtkmm2ext/gtkmm2ext/pixfader.h
index bb4176240a..d974f5d5bc 100644
--- a/libs/gtkmm2ext/gtkmm2ext/pixfader.h
+++ b/libs/gtkmm2ext/gtkmm2ext/pixfader.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: fastmeter.h 570 2006-06-07 21:21:21Z sampo $
*/
#ifndef __gtkmm2ext_pixfader_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/popup.h b/libs/gtkmm2ext/gtkmm2ext/popup.h
index 89f14b4c50..1db357341d 100644
--- a/libs/gtkmm2ext/gtkmm2ext/popup.h
+++ b/libs/gtkmm2ext/gtkmm2ext/popup.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __qui_popup_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/prompter.h b/libs/gtkmm2ext/gtkmm2ext/prompter.h
index 9847e73661..10870ee752 100644
--- a/libs/gtkmm2ext/gtkmm2ext/prompter.h
+++ b/libs/gtkmm2ext/gtkmm2ext/prompter.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_prompter_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/selector.h b/libs/gtkmm2ext/gtkmm2ext/selector.h
index 9eb07cfbfe..841742db03 100644
--- a/libs/gtkmm2ext/gtkmm2ext/selector.h
+++ b/libs/gtkmm2ext/gtkmm2ext/selector.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkselector_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/slider_controller.h b/libs/gtkmm2ext/gtkmm2ext/slider_controller.h
index c137dbabf5..74ff36816b 100644
--- a/libs/gtkmm2ext/gtkmm2ext/slider_controller.h
+++ b/libs/gtkmm2ext/gtkmm2ext/slider_controller.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_slider_controller_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/stateful_button.h b/libs/gtkmm2ext/gtkmm2ext/stateful_button.h
index f684903836..c86402e54e 100644
--- a/libs/gtkmm2ext/gtkmm2ext/stateful_button.h
+++ b/libs/gtkmm2ext/gtkmm2ext/stateful_button.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __pbd_gtkmm_abutton_h__
@@ -27,28 +26,56 @@
namespace Gtkmm2ext {
-class StatefulButton : public Gtk::Button
+class StateButton
{
public:
- StatefulButton();
- explicit StatefulButton(const std::string &label);
- virtual ~StatefulButton() {}
+ StateButton();
+ virtual ~StateButton() {}
+
+ void set_visual_state (int);
+ int get_visual_state () { return visual_state; }
+ void set_self_managed (bool yn) { _self_managed = yn; }
- void set_colors (const std::vector<Gdk::Color>& colors);
- void set_state (int);
- int get_state () { return current_state; }
- void set_active (bool yn) {
- set_state (yn ? 1 : 0);
- }
-
+ protected:
+ int visual_state;
+ bool _self_managed;
+ bool _is_realized;
+
+ virtual std::string get_widget_name() const = 0;
+ virtual void set_widget_name (std::string) = 0;
+ virtual int get_widget_state() = 0;
+};
+
+
+class StatefulToggleButton : public StateButton, public Gtk::ToggleButton
+{
+ public:
+ StatefulToggleButton() {}
+ explicit StatefulToggleButton(const std::string &label) : Gtk::ToggleButton (label) {}
+ ~StatefulToggleButton() {}
protected:
- std::vector<Gdk::Color> colors;
- int current_state;
- Gdk::Color saved_bg;
- bool have_saved_bg;
+ void on_realize ();
+ void on_toggled ();
+
+ std::string get_widget_name() const { return get_name(); }
+ void set_widget_name (std::string name) { set_name (name); get_child()->set_name (name); }
+ int get_widget_state() { return get_state(); }
+};
+class StatefulButton : public StateButton, public Gtk::Button
+{
+ public:
+ StatefulButton() {}
+ explicit StatefulButton(const std::string &label) : Gtk::Button (label) {}
+ virtual ~StatefulButton() {}
+
+ protected:
void on_realize ();
+
+ std::string get_widget_name() const { return get_name(); }
+ void set_widget_name (std::string name) { set_name (name); get_child()->set_name (name); }
+ int get_widget_state() { return get_state(); }
};
};
diff --git a/libs/gtkmm2ext/gtkmm2ext/tearoff.h b/libs/gtkmm2ext/gtkmm2ext/tearoff.h
index fd36cb6416..5e80892b98 100644
--- a/libs/gtkmm2ext/gtkmm2ext/tearoff.h
+++ b/libs/gtkmm2ext/gtkmm2ext/tearoff.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_tearoff_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/textviewer.h b/libs/gtkmm2ext/gtkmm2ext/textviewer.h
index 280eb4437d..9cc639cd75 100644
--- a/libs/gtkmm2ext/gtkmm2ext/textviewer.h
+++ b/libs/gtkmm2ext/gtkmm2ext/textviewer.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __pbd_gtkmm_textviewer_h__
diff --git a/libs/gtkmm2ext/gtkmm2ext/utils.h b/libs/gtkmm2ext/gtkmm2ext/utils.h
index 97dab523aa..ca1b88abba 100644
--- a/libs/gtkmm2ext/gtkmm2ext/utils.h
+++ b/libs/gtkmm2ext/gtkmm2ext/utils.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __gtkmm2ext_utils_h__
diff --git a/libs/gtkmm2ext/stateful_button.cc b/libs/gtkmm2ext/stateful_button.cc
index 074d086651..ffcafab123 100644
--- a/libs/gtkmm2ext/stateful_button.cc
+++ b/libs/gtkmm2ext/stateful_button.cc
@@ -1,31 +1,63 @@
#include <string>
#include <iostream>
-#include "gtkmm2ext/stateful_button.h"
+
+#include <gtkmm/main.h>
+
+#include <gtkmm2ext/stateful_button.h>
using namespace Gtk;
using namespace Glib;
using namespace Gtkmm2ext;
using namespace std;
-StatefulButton::StatefulButton ()
+StateButton::StateButton ()
{
- current_state = 0;
- have_saved_bg = false;
+ _is_realized = false;
+ visual_state = 0;
}
-StatefulButton::StatefulButton (const string& label)
- : Button (label)
+void
+StateButton::set_visual_state (int n)
{
- current_state = 0;
- have_saved_bg = false;
+ if (!_is_realized) {
+ /* not yet realized */
+ visual_state = n;
+ return;
+ }
+
+ if (n == visual_state) {
+ return;
+ }
+
+ string name = get_widget_name ();
+ name = name.substr (0, name.find_last_of ('-'));
+
+ switch (n) {
+ case 0:
+ /* relax */
+ break;
+ case 1:
+ name += "-active";
+ break;
+ case 2:
+ name += "-alternate";
+ break;
+ }
+
+ set_widget_name (name);
+ visual_state = n;
}
+/* ----------------------------------------------------------------- */
+
void
-StatefulButton::set_colors (const vector<Gdk::Color>& c)
+StatefulToggleButton::on_realize ()
{
- colors = c;
- current_state++; // to force transition
- set_state (current_state - 1);
+ ToggleButton::on_realize ();
+
+ _is_realized = true;
+ visual_state++; // to force transition
+ set_visual_state (visual_state - 1);
}
void
@@ -33,48 +65,19 @@ StatefulButton::on_realize ()
{
Button::on_realize ();
- if (!have_saved_bg) {
- saved_bg = get_style()->get_bg (STATE_NORMAL);
- have_saved_bg = true;
- }
-
- current_state++; // to force transition
- set_state (current_state - 1);
+ _is_realized = true;
+ visual_state++; // to force transition
+ set_visual_state (visual_state - 1);
}
void
-StatefulButton::set_state (int n)
+StatefulToggleButton::on_toggled ()
{
- if (is_realized()) {
-
- if (n == current_state) {
- return;
- }
-
- if (n == 0) {
-
- /* back to the default color */
-
- if (have_saved_bg) {
- modify_bg (STATE_NORMAL, saved_bg);
- modify_bg (STATE_ACTIVE, saved_bg);
- modify_bg (STATE_SELECTED, saved_bg);
- modify_bg (STATE_PRELIGHT, saved_bg);
- }
-
-
+ if (!_self_managed) {
+ if (get_active()) {
+ set_visual_state (1);
} else {
-
- int index = (n-1) % colors.size ();
-
- modify_bg (STATE_NORMAL, colors[index]);
- modify_bg (STATE_ACTIVE, colors[index]);
- modify_bg (STATE_SELECTED, colors[index]);
- modify_bg (STATE_PRELIGHT, colors[index]);
+ set_visual_state (0);
}
-
- /* leave insensitive alone */
}
-
- current_state = n;
}
diff --git a/libs/midi++2/macosx/English.lproj/InfoPlist.strings b/libs/midi++2/macosx/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000000..a7b6345cb0
--- /dev/null
+++ b/libs/midi++2/macosx/English.lproj/InfoPlist.strings
Binary files differ
diff --git a/libs/midi++2/macosx/Info.plist b/libs/midi++2/macosx/Info.plist
new file mode 100644
index 0000000000..8eebfc968f
--- /dev/null
+++ b/libs/midi++2/macosx/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>midi++</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.carbonframeworktemplate</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.01</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+</dict>
+</plist>
diff --git a/libs/midi++2/macosx/midi++.xcodeproj/project.pbxproj b/libs/midi++2/macosx/midi++.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..49896b11a3
--- /dev/null
+++ b/libs/midi++2/macosx/midi++.xcodeproj/project.pbxproj
@@ -0,0 +1,498 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 42;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 696149880B97CED200ECBDF0 /* glib in Frameworks */ = {isa = PBXBuildFile; fileRef = 696149840B97CED200ECBDF0 /* glib */; };
+ 696149890B97CED200ECBDF0 /* gmodule in Frameworks */ = {isa = PBXBuildFile; fileRef = 696149850B97CED200ECBDF0 /* gmodule */; };
+ 6961498A0B97CED200ECBDF0 /* gobject in Frameworks */ = {isa = PBXBuildFile; fileRef = 696149860B97CED200ECBDF0 /* gobject */; };
+ 6961498B0B97CED200ECBDF0 /* gthread in Frameworks */ = {isa = PBXBuildFile; fileRef = 696149870B97CED200ECBDF0 /* gthread */; };
+ 69A0E07A0B8A3B1200A24967 /* coremidi_midiport.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E05C0B8A3B1200A24967 /* coremidi_midiport.cc */; };
+ 69A0E07B0B8A3B1200A24967 /* fd_midiport.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E05D0B8A3B1200A24967 /* fd_midiport.cc */; };
+ 69A0E07C0B8A3B1200A24967 /* fifomidi.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E05E0B8A3B1200A24967 /* fifomidi.cc */; };
+ 69A0E0800B8A3B1200A24967 /* channel.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E0630B8A3B1200A24967 /* channel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0810B8A3B1200A24967 /* coremidi_midiport.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E0640B8A3B1200A24967 /* coremidi_midiport.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0820B8A3B1200A24967 /* factory.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E0650B8A3B1200A24967 /* factory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0830B8A3B1200A24967 /* fd_midiport.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E0660B8A3B1200A24967 /* fd_midiport.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0840B8A3B1200A24967 /* fifomidi.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E0670B8A3B1200A24967 /* fifomidi.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0850B8A3B1200A24967 /* manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E0680B8A3B1200A24967 /* manager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0860B8A3B1200A24967 /* mmc.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E0690B8A3B1200A24967 /* mmc.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0870B8A3B1200A24967 /* nullmidi.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E06A0B8A3B1200A24967 /* nullmidi.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0880B8A3B1200A24967 /* parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E06B0B8A3B1200A24967 /* parser.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E0890B8A3B1200A24967 /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E06C0B8A3B1200A24967 /* port.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E08A0B8A3B1200A24967 /* port_request.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E06D0B8A3B1200A24967 /* port_request.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E08B0B8A3B1200A24967 /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A0E06E0B8A3B1200A24967 /* types.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69A0E08C0B8A3B1200A24967 /* midi.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E06F0B8A3B1200A24967 /* midi.cc */; };
+ 69A0E08D0B8A3B1200A24967 /* midichannel.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E0700B8A3B1200A24967 /* midichannel.cc */; };
+ 69A0E08E0B8A3B1200A24967 /* midifactory.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E0710B8A3B1200A24967 /* midifactory.cc */; };
+ 69A0E08F0B8A3B1200A24967 /* midimanager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E0720B8A3B1200A24967 /* midimanager.cc */; };
+ 69A0E0900B8A3B1200A24967 /* midiparser.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E0730B8A3B1200A24967 /* midiparser.cc */; };
+ 69A0E0910B8A3B1200A24967 /* midiport.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E0740B8A3B1200A24967 /* midiport.cc */; };
+ 69A0E0930B8A3B1200A24967 /* mmc.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E0760B8A3B1200A24967 /* mmc.cc */; };
+ 69A0E0950B8A3B1200A24967 /* mtc.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E0780B8A3B1200A24967 /* mtc.cc */; };
+ 69A0E0960B8A3B1200A24967 /* port_request.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A0E0790B8A3B1200A24967 /* port_request.cc */; };
+ 69A0E09E0B8A3B6300A24967 /* sigc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69A0E09C0B8A3B6300A24967 /* sigc.framework */; };
+ 69A0E0B00B8A3BEF00A24967 /* CoreMIDI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69A0E0AF0B8A3BEF00A24967 /* CoreMIDI.framework */; };
+ 69A0E0B50B8A3C0B00A24967 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69A0E0B40B8A3C0B00A24967 /* CoreFoundation.framework */; };
+ 69A0E0BA0B8A3C2000A24967 /* glibmm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69A0E0B90B8A3C2000A24967 /* glibmm.framework */; };
+ 69C63C4C0B936ACF00BC0BCA /* version.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69C63C4A0B936ACF00BC0BCA /* version.cc */; };
+ 69C63C4D0B936ACF00BC0BCA /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 69C63C4B0B936ACF00BC0BCA /* version.h */; };
+ 69D5F6010B8D55B100301E71 /* pbd.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 69D5F6000B8D55A000301E71 /* pbd.framework */; };
+ 8D07F2BE0486CC7A007CD1D0 /* midi++_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 32BAE0B70371A74B00C91783 /* midi++_Prefix.pch */; settings = {ATTRIBUTES = (Public, ); }; };
+ 8D07F2C00486CC7A007CD1D0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 69D5F5FF0B8D55A000301E71 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 69D5F5FB0B8D55A000301E71 /* pbd.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 8D07F2C80486CC7A007CD1D0;
+ remoteInfo = pbd;
+ };
+ 69D5F6060B8D570800301E71 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 69D5F5FB0B8D55A000301E71 /* pbd.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D07F2BC0486CC7A007CD1D0;
+ remoteInfo = pbd;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 32BAE0B70371A74B00C91783 /* midi++_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "midi++_Prefix.pch"; sourceTree = "<group>"; };
+ 696149840B97CED200ECBDF0 /* glib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = glib; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/glib; sourceTree = "<absolute>"; };
+ 696149850B97CED200ECBDF0 /* gmodule */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gmodule; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gmodule; sourceTree = "<absolute>"; };
+ 696149860B97CED200ECBDF0 /* gobject */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gobject; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gobject; sourceTree = "<absolute>"; };
+ 696149870B97CED200ECBDF0 /* gthread */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gthread; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gthread; sourceTree = "<absolute>"; };
+ 69A0E05C0B8A3B1200A24967 /* coremidi_midiport.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = coremidi_midiport.cc; path = ../coremidi_midiport.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E05D0B8A3B1200A24967 /* fd_midiport.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = fd_midiport.cc; path = ../fd_midiport.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E05E0B8A3B1200A24967 /* fifomidi.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = fifomidi.cc; path = ../fifomidi.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0630B8A3B1200A24967 /* channel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = channel.h; sourceTree = "<group>"; };
+ 69A0E0640B8A3B1200A24967 /* coremidi_midiport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = coremidi_midiport.h; sourceTree = "<group>"; };
+ 69A0E0650B8A3B1200A24967 /* factory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = factory.h; sourceTree = "<group>"; };
+ 69A0E0660B8A3B1200A24967 /* fd_midiport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fd_midiport.h; sourceTree = "<group>"; };
+ 69A0E0670B8A3B1200A24967 /* fifomidi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fifomidi.h; sourceTree = "<group>"; };
+ 69A0E0680B8A3B1200A24967 /* manager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = manager.h; sourceTree = "<group>"; };
+ 69A0E0690B8A3B1200A24967 /* mmc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mmc.h; sourceTree = "<group>"; };
+ 69A0E06A0B8A3B1200A24967 /* nullmidi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nullmidi.h; sourceTree = "<group>"; };
+ 69A0E06B0B8A3B1200A24967 /* parser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = "<group>"; };
+ 69A0E06C0B8A3B1200A24967 /* port.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = port.h; sourceTree = "<group>"; };
+ 69A0E06D0B8A3B1200A24967 /* port_request.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = port_request.h; sourceTree = "<group>"; };
+ 69A0E06E0B8A3B1200A24967 /* types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; };
+ 69A0E06F0B8A3B1200A24967 /* midi.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = midi.cc; path = ../midi.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0700B8A3B1200A24967 /* midichannel.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = midichannel.cc; path = ../midichannel.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0710B8A3B1200A24967 /* midifactory.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = midifactory.cc; path = ../midifactory.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0720B8A3B1200A24967 /* midimanager.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = midimanager.cc; path = ../midimanager.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0730B8A3B1200A24967 /* midiparser.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = midiparser.cc; path = ../midiparser.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0740B8A3B1200A24967 /* midiport.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = midiport.cc; path = ../midiport.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0760B8A3B1200A24967 /* mmc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = mmc.cc; path = ../mmc.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0780B8A3B1200A24967 /* mtc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = mtc.cc; path = ../mtc.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E0790B8A3B1200A24967 /* port_request.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = port_request.cc; path = ../port_request.cc; sourceTree = SOURCE_ROOT; };
+ 69A0E09C0B8A3B6300A24967 /* sigc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = sigc.framework; path = /Library/Frameworks/sigc.framework; sourceTree = "<absolute>"; };
+ 69A0E0AF0B8A3BEF00A24967 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = /System/Library/Frameworks/CoreMIDI.framework; sourceTree = "<absolute>"; };
+ 69A0E0B40B8A3C0B00A24967 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+ 69A0E0B90B8A3C2000A24967 /* glibmm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = glibmm.framework; path = /Library/Frameworks/glibmm.framework; sourceTree = "<absolute>"; };
+ 69C63C4A0B936ACF00BC0BCA /* version.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = version.cc; sourceTree = "<group>"; };
+ 69C63C4B0B936ACF00BC0BCA /* version.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
+ 69D5F5FB0B8D55A000301E71 /* pbd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = pbd.xcodeproj; path = ../../pbd/macosx/pbd.xcodeproj; sourceTree = SOURCE_ROOT; };
+ 8D07F2C70486CC7A007CD1D0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+ 8D07F2C80486CC7A007CD1D0 /* midi++.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = "midi++.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D07F2C30486CC7A007CD1D0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 69D5F6010B8D55B100301E71 /* pbd.framework in Frameworks */,
+ 69A0E09E0B8A3B6300A24967 /* sigc.framework in Frameworks */,
+ 69A0E0B00B8A3BEF00A24967 /* CoreMIDI.framework in Frameworks */,
+ 69A0E0B50B8A3C0B00A24967 /* CoreFoundation.framework in Frameworks */,
+ 69A0E0BA0B8A3C2000A24967 /* glibmm.framework in Frameworks */,
+ 696149880B97CED200ECBDF0 /* glib in Frameworks */,
+ 696149890B97CED200ECBDF0 /* gmodule in Frameworks */,
+ 6961498A0B97CED200ECBDF0 /* gobject in Frameworks */,
+ 6961498B0B97CED200ECBDF0 /* gthread in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DDFF38A45A11DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D07F2C80486CC7A007CD1D0 /* midi++.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* midi++ */ = {
+ isa = PBXGroup;
+ children = (
+ 69C63C4A0B936ACF00BC0BCA /* version.cc */,
+ 69C63C4B0B936ACF00BC0BCA /* version.h */,
+ 08FB77ACFE841707C02AAC07 /* Source */,
+ 089C1665FE841158C02AAC07 /* Resources */,
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+ 034768DDFF38A45A11DB9C8B /* Products */,
+ );
+ name = "midi++";
+ sourceTree = "<group>";
+ };
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 696149840B97CED200ECBDF0 /* glib */,
+ 696149850B97CED200ECBDF0 /* gmodule */,
+ 696149860B97CED200ECBDF0 /* gobject */,
+ 696149870B97CED200ECBDF0 /* gthread */,
+ 69D5F5FB0B8D55A000301E71 /* pbd.xcodeproj */,
+ 69A0E0B90B8A3C2000A24967 /* glibmm.framework */,
+ 69A0E0B40B8A3C0B00A24967 /* CoreFoundation.framework */,
+ 69A0E0AF0B8A3BEF00A24967 /* CoreMIDI.framework */,
+ 69A0E09C0B8A3B6300A24967 /* sigc.framework */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 089C1665FE841158C02AAC07 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 8D07F2C70486CC7A007CD1D0 /* Info.plist */,
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 08FB77ACFE841707C02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 69A0E05C0B8A3B1200A24967 /* coremidi_midiport.cc */,
+ 69A0E05D0B8A3B1200A24967 /* fd_midiport.cc */,
+ 69A0E05E0B8A3B1200A24967 /* fifomidi.cc */,
+ 69A0E05F0B8A3B1200A24967 /* midi++ */,
+ 69A0E06F0B8A3B1200A24967 /* midi.cc */,
+ 69A0E0700B8A3B1200A24967 /* midichannel.cc */,
+ 69A0E0710B8A3B1200A24967 /* midifactory.cc */,
+ 69A0E0720B8A3B1200A24967 /* midimanager.cc */,
+ 69A0E0730B8A3B1200A24967 /* midiparser.cc */,
+ 69A0E0740B8A3B1200A24967 /* midiport.cc */,
+ 69A0E0760B8A3B1200A24967 /* mmc.cc */,
+ 69A0E0780B8A3B1200A24967 /* mtc.cc */,
+ 69A0E0790B8A3B1200A24967 /* port_request.cc */,
+ 32BAE0B70371A74B00C91783 /* midi++_Prefix.pch */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 69A0E05F0B8A3B1200A24967 /* midi++ */ = {
+ isa = PBXGroup;
+ children = (
+ 69A0E0630B8A3B1200A24967 /* channel.h */,
+ 69A0E0640B8A3B1200A24967 /* coremidi_midiport.h */,
+ 69A0E0650B8A3B1200A24967 /* factory.h */,
+ 69A0E0660B8A3B1200A24967 /* fd_midiport.h */,
+ 69A0E0670B8A3B1200A24967 /* fifomidi.h */,
+ 69A0E0680B8A3B1200A24967 /* manager.h */,
+ 69A0E0690B8A3B1200A24967 /* mmc.h */,
+ 69A0E06A0B8A3B1200A24967 /* nullmidi.h */,
+ 69A0E06B0B8A3B1200A24967 /* parser.h */,
+ 69A0E06C0B8A3B1200A24967 /* port.h */,
+ 69A0E06D0B8A3B1200A24967 /* port_request.h */,
+ 69A0E06E0B8A3B1200A24967 /* types.h */,
+ );
+ name = "midi++";
+ path = "../midi++";
+ sourceTree = SOURCE_ROOT;
+ };
+ 69D5F5FC0B8D55A000301E71 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 69D5F6000B8D55A000301E71 /* pbd.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 8D07F2BD0486CC7A007CD1D0 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 69C63C4D0B936ACF00BC0BCA /* version.h in Headers */,
+ 8D07F2BE0486CC7A007CD1D0 /* midi++_Prefix.pch in Headers */,
+ 69A0E0800B8A3B1200A24967 /* channel.h in Headers */,
+ 69A0E0810B8A3B1200A24967 /* coremidi_midiport.h in Headers */,
+ 69A0E0820B8A3B1200A24967 /* factory.h in Headers */,
+ 69A0E0830B8A3B1200A24967 /* fd_midiport.h in Headers */,
+ 69A0E0840B8A3B1200A24967 /* fifomidi.h in Headers */,
+ 69A0E0850B8A3B1200A24967 /* manager.h in Headers */,
+ 69A0E0860B8A3B1200A24967 /* mmc.h in Headers */,
+ 69A0E0870B8A3B1200A24967 /* nullmidi.h in Headers */,
+ 69A0E0880B8A3B1200A24967 /* parser.h in Headers */,
+ 69A0E0890B8A3B1200A24967 /* port.h in Headers */,
+ 69A0E08A0B8A3B1200A24967 /* port_request.h in Headers */,
+ 69A0E08B0B8A3B1200A24967 /* types.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 8D07F2BC0486CC7A007CD1D0 /* midi++ */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "midi++" */;
+ buildPhases = (
+ 8D07F2BD0486CC7A007CD1D0 /* Headers */,
+ 8D07F2BF0486CC7A007CD1D0 /* Resources */,
+ 8D07F2C10486CC7A007CD1D0 /* Sources */,
+ 8D07F2C30486CC7A007CD1D0 /* Frameworks */,
+ 8D07F2C50486CC7A007CD1D0 /* Rez */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 69D5F6070B8D570800301E71 /* PBXTargetDependency */,
+ );
+ name = "midi++";
+ productInstallPath = "$(HOME)/Library/Frameworks";
+ productName = "midi++";
+ productReference = 8D07F2C80486CC7A007CD1D0 /* midi++.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "midi++" */;
+ hasScannedForEncodings = 1;
+ mainGroup = 0867D691FE84028FC02AAC07 /* midi++ */;
+ productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = 69D5F5FC0B8D55A000301E71 /* Products */;
+ ProjectRef = 69D5F5FB0B8D55A000301E71 /* pbd.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ 8D07F2BC0486CC7A007CD1D0 /* midi++ */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ 69D5F6000B8D55A000301E71 /* pbd.framework */ = {
+ isa = PBXReferenceProxy;
+ fileType = wrapper.framework;
+ path = pbd.framework;
+ remoteRef = 69D5F5FF0B8D55A000301E71 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D07F2BF0486CC7A007CD1D0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D07F2C00486CC7A007CD1D0 /* InfoPlist.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+ 8D07F2C50486CC7A007CD1D0 /* Rez */ = {
+ isa = PBXRezBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D07F2C10486CC7A007CD1D0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 69C63C4C0B936ACF00BC0BCA /* version.cc in Sources */,
+ 69A0E07A0B8A3B1200A24967 /* coremidi_midiport.cc in Sources */,
+ 69A0E07B0B8A3B1200A24967 /* fd_midiport.cc in Sources */,
+ 69A0E07C0B8A3B1200A24967 /* fifomidi.cc in Sources */,
+ 69A0E08C0B8A3B1200A24967 /* midi.cc in Sources */,
+ 69A0E08D0B8A3B1200A24967 /* midichannel.cc in Sources */,
+ 69A0E08E0B8A3B1200A24967 /* midifactory.cc in Sources */,
+ 69A0E08F0B8A3B1200A24967 /* midimanager.cc in Sources */,
+ 69A0E0900B8A3B1200A24967 /* midiparser.cc in Sources */,
+ 69A0E0910B8A3B1200A24967 /* midiport.cc in Sources */,
+ 69A0E0930B8A3B1200A24967 /* mmc.cc in Sources */,
+ 69A0E0950B8A3B1200A24967 /* mtc.cc in Sources */,
+ 69A0E0960B8A3B1200A24967 /* port_request.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 69D5F6070B8D570800301E71 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = pbd;
+ targetProxy = 69D5F6060B8D570800301E71 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C1667FE841158C02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 4FADC24408B4156D00ABE55E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = (
+ ppc,
+ i386,
+ );
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "midi++_Prefix.pch";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ PRODUCT_NAME = "midi++";
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Release;
+ };
+ 4FADC24808B4156D00ABE55E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = (
+ "$(NATIVE_ARCH)",
+ ppc,
+ );
+ DEAD_CODE_STRIPPING = YES;
+ FRAMEWORK_SEARCH_PATHS = /opt/ardour/build;
+ GCC_FAST_OBJC_DISPATCH = NO;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = G4;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ /Library/Frameworks/GLib.framework/Headers,
+ /Library/Frameworks/sigc.framework/Headers,
+ );
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ };
+ name = Release;
+ };
+ 694E7C660B97AD230018D03D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ FRAMEWORK_SEARCH_PATHS = /opt/ardour/build;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_FAST_OBJC_DISPATCH = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ /Library/Frameworks/GLib.framework/Headers,
+ /Library/Frameworks/sigc.framework/Headers,
+ );
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Debug;
+ };
+ 694E7C670B97AD230018D03D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = i386;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "midi++_Prefix.pch";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ PRODUCT_NAME = "midi++";
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "midi++" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4FADC24408B4156D00ABE55E /* Release */,
+ 694E7C670B97AD230018D03D /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "midi++" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4FADC24808B4156D00ABE55E /* Release */,
+ 694E7C660B97AD230018D03D /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/libs/midi++2/macosx/midi++_Prefix.pch b/libs/midi++2/macosx/midi++_Prefix.pch
new file mode 100644
index 0000000000..8f1f98260c
--- /dev/null
+++ b/libs/midi++2/macosx/midi++_Prefix.pch
@@ -0,0 +1,3 @@
+//
+// Prefix header for all source files of the 'midi++' target in the 'midi++' project.
+//
diff --git a/libs/midi++2/macosx/version.cc b/libs/midi++2/macosx/version.cc
new file mode 100644
index 0000000000..72e767bca5
--- /dev/null
+++ b/libs/midi++2/macosx/version.cc
@@ -0,0 +1,3 @@
+int midipp_major_version = 2;
+int midipp_minor_version = 1;
+int midipp_micro_version = 1;
diff --git a/libs/midi++2/macosx/version.h b/libs/midi++2/macosx/version.h
new file mode 100644
index 0000000000..7ff7d8ce10
--- /dev/null
+++ b/libs/midi++2/macosx/version.h
@@ -0,0 +1,7 @@
+#ifndef __midipp_version_h__
+#define __midipp_version_h__
+extern const char* midipp_revision;
+extern int midipp_major_version;
+extern int midipp_minor_version;
+extern int midipp_micro_version;
+#endif /* __midipp_version_h__ */
diff --git a/libs/midi++2/midi++/alsa_rawmidi.h b/libs/midi++2/midi++/alsa_rawmidi.h
index f6c17541c2..8e50609fbe 100644
--- a/libs/midi++2/midi++/alsa_rawmidi.h
+++ b/libs/midi++2/midi++/alsa_rawmidi.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __alsa_rawmidi_h__
diff --git a/libs/midi++2/midi++/alsa_sequencer.h b/libs/midi++2/midi++/alsa_sequencer.h
index a4b4ba856f..7fe880fe63 100644
--- a/libs/midi++2/midi++/alsa_sequencer.h
+++ b/libs/midi++2/midi++/alsa_sequencer.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __alsa_sequencer_midiport_h__
diff --git a/libs/midi++2/midi++/channel.h b/libs/midi++2/midi++/channel.h
index e1ffb954a5..5a4a397b9d 100644
--- a/libs/midi++2/midi++/channel.h
+++ b/libs/midi++2/midi++/channel.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __midichannel_h__
diff --git a/libs/midi++2/midi++/factory.h b/libs/midi++2/midi++/factory.h
index 1d5c7e0b30..df7f35e073 100644
--- a/libs/midi++2/midi++/factory.h
+++ b/libs/midi++2/midi++/factory.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __midi_factory_h__
diff --git a/libs/midi++2/midi++/fd_midiport.h b/libs/midi++2/midi++/fd_midiport.h
index 3ff05b21c8..8a1af55967 100644
--- a/libs/midi++2/midi++/fd_midiport.h
+++ b/libs/midi++2/midi++/fd_midiport.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __fd_midiport_h__
diff --git a/libs/midi++2/midi++/fifomidi.h b/libs/midi++2/midi++/fifomidi.h
index 200d90eda8..57d1502c45 100644
--- a/libs/midi++2/midi++/fifomidi.h
+++ b/libs/midi++2/midi++/fifomidi.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __fifomidi_h__
diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h
index d5a49eb0a3..80de408ee1 100644
--- a/libs/midi++2/midi++/manager.h
+++ b/libs/midi++2/midi++/manager.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __midi_manager_h__
diff --git a/libs/midi++2/midi++/mmc.h b/libs/midi++2/midi++/mmc.h
index 2d569f122c..bc23beb0a1 100644
--- a/libs/midi++2/midi++/mmc.h
+++ b/libs/midi++2/midi++/mmc.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __midipp_mmc_h_h__
@@ -93,6 +92,8 @@ class MachineControl : public sigc::trackable
Port &port() { return _port; }
void set_device_id (byte id);
+ byte device_id () const { return _device_id; }
+
static bool is_mmc (byte *sysex_buf, size_t len);
/* Signals to connect to if you want to run "callbacks"
diff --git a/libs/midi++2/midi++/nullmidi.h b/libs/midi++2/midi++/nullmidi.h
index 75445facb7..1474da77ed 100644
--- a/libs/midi++2/midi++/nullmidi.h
+++ b/libs/midi++2/midi++/nullmidi.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __nullmidi_h__
diff --git a/libs/midi++2/midi++/parser.h b/libs/midi++2/midi++/parser.h
index 36d19f3da9..73c7c75f61 100644
--- a/libs/midi++2/midi++/parser.h
+++ b/libs/midi++2/midi++/parser.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __midi_parse_h__
@@ -162,8 +161,8 @@ class Parser : public sigc::trackable {
bool _mmc_forward;
bool _mtc_forward;
int expected_mtc_quarter_frame_code;
- byte _mtc_time[4];
- byte _qtr_mtc_time[4];
+ byte _mtc_time[5];
+ byte _qtr_mtc_time[5];
unsigned long consecutive_qtr_frame_cnt;
MTC_FPS _mtc_fps;
MTC_Status _mtc_running;
diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h
index a706127eff..e4338cf952 100644
--- a/libs/midi++2/midi++/port.h
+++ b/libs/midi++2/midi++/port.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __libmidi_port_h__
diff --git a/libs/midi++2/midi++/port_request.h b/libs/midi++2/midi++/port_request.h
index 86838dd04d..0cb4ffded6 100644
--- a/libs/midi++2/midi++/port_request.h
+++ b/libs/midi++2/midi++/port_request.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __midi_port_request_h__
diff --git a/libs/midi++2/midiparser.cc b/libs/midi++2/midiparser.cc
index 7c29478413..a1f6ce39b4 100644
--- a/libs/midi++2/midiparser.cc
+++ b/libs/midi++2/midiparser.cc
@@ -25,6 +25,7 @@
#include <unistd.h>
#include <string>
#include <iostream>
+#include <iterator>
#include <midi++/types.h>
#include <midi++/parser.h>
@@ -138,7 +139,6 @@ Parser::~Parser ()
void
Parser::trace_event (Parser &p, byte *msg, size_t len)
-
{
eventType type;
ostream *o;
@@ -309,15 +309,13 @@ Parser::trace_event (Parser &p, byte *msg, size_t len)
void
Parser::trace (bool onoff, ostream *o, const string &prefix)
-
{
trace_connection.disconnect ();
if (onoff) {
trace_stream = o;
trace_prefix = prefix;
- trace_connection = any.connect
- (mem_fun (*this, &Parser::trace_event));
+ trace_connection = any.connect (mem_fun (*this, &Parser::trace_event));
} else {
trace_prefix = "";
trace_stream = 0;
diff --git a/libs/midi++2/mmc.cc b/libs/midi++2/mmc.cc
index 61c47e856f..28d6393fb4 100644
--- a/libs/midi++2/mmc.cc
+++ b/libs/midi++2/mmc.cc
@@ -202,7 +202,7 @@ MachineControl::MachineControl (Port &p, float version,
build_mmc_cmd_map ();
- _device_id = 1;
+ _device_id = 0;
if ((parser = _port.input()) != 0) {
parser->mmc.connect
@@ -258,7 +258,7 @@ MachineControl::process_mmc_message (Parser &p, byte *msg, size_t len)
*/
#if 0
- cerr << "*** MMC message: len = " << len << "\n\t";
+ cerr << "*** me = " << (int) _device_id << " MMC message: len = " << len << "\n\t";
for (size_t i = 0; i < len; i++) {
cerr << hex << (int) msg[i] << dec << ' ';
}
diff --git a/libs/midi++2/mtc.cc b/libs/midi++2/mtc.cc
index 19fdb1fabd..7fd86eff35 100644
--- a/libs/midi++2/mtc.cc
+++ b/libs/midi++2/mtc.cc
@@ -36,7 +36,7 @@ using namespace MIDI;
bool
Parser::possible_mtc (byte *sysex_buf, size_t msglen)
{
- byte fake_mtc_time[4];
+ byte fake_mtc_time[5];
if (msglen != 10 || sysex_buf[0] != 0xf0 || sysex_buf[1] != 0x7f || sysex_buf[3] != 0x01 || sysex_buf[4] != 0x01) {
return false;
@@ -50,7 +50,9 @@ Parser::possible_mtc (byte *sysex_buf, size_t msglen)
fake_mtc_time[3] = (sysex_buf[5] & 0x1f); // hours
_mtc_fps = MTC_FPS ((sysex_buf[5] & 0x60) >> 5); // fps
-
+
+ fake_mtc_time[4] = (byte) _mtc_fps;
+
/* wait for first quarter frame, which could indicate forwards
or backwards ...
*/
@@ -262,6 +264,7 @@ Parser::process_mtc_quarter_frame (byte *msg)
_qtr_mtc_time[3] |= ((msg[1] & 0x1) << 4);
_mtc_fps = MTC_FPS ((msg[1] & 0x6) >> 1);
+ _qtr_mtc_time[4] = _mtc_fps;
break;
default:
diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript
index afb24a4311..12664a1fca 100644
--- a/libs/pbd/SConscript
+++ b/libs/pbd/SConscript
@@ -36,6 +36,7 @@ pthread_utils.cc
receiver.cc
stacktrace.cc
stateful.cc
+strreplace.cc
strsplit.cc
textreceiver.cc
transmitter.cc
diff --git a/libs/pbd/controllable.cc b/libs/pbd/controllable.cc
index 049ad0aa21..00638e6c06 100644
--- a/libs/pbd/controllable.cc
+++ b/libs/pbd/controllable.cc
@@ -10,9 +10,64 @@ sigc::signal<void,Controllable*> Controllable::Destroyed;
sigc::signal<bool,Controllable*> Controllable::StartLearning;
sigc::signal<void,Controllable*> Controllable::StopLearning;
+Glib::Mutex* Controllable::registry_lock = 0;
+Controllable::Controllables Controllable::registry;
+
Controllable::Controllable (std::string name)
: _name (name)
{
+ if (registry_lock == 0) {
+ registry_lock = new Glib::Mutex;
+ }
+
+ add ();
+}
+
+void
+Controllable::add ()
+{
+ Glib::Mutex::Lock lm (*registry_lock);
+ registry.insert (this);
+ this->GoingAway.connect (mem_fun (this, &Controllable::remove));
+}
+
+void
+Controllable::remove ()
+{
+ Glib::Mutex::Lock lm (*registry_lock);
+ for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
+ if ((*i) == this) {
+ registry.erase (i);
+ break;
+ }
+ }
+}
+
+Controllable*
+Controllable::by_id (const ID& id)
+{
+ Glib::Mutex::Lock lm (*registry_lock);
+
+ for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
+ if ((*i)->id() == id) {
+ return (*i);
+ }
+ }
+ return 0;
+}
+
+
+Controllable*
+Controllable::by_name (const std::string& str)
+{
+ Glib::Mutex::Lock lm (*registry_lock);
+
+ for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
+ if ((*i)->_name == str) {
+ return (*i);
+ }
+ }
+ return 0;
}
XMLNode&
diff --git a/libs/pbd/macosx/English.lproj/InfoPlist.strings b/libs/pbd/macosx/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000000..d8479018a9
--- /dev/null
+++ b/libs/pbd/macosx/English.lproj/InfoPlist.strings
Binary files differ
diff --git a/libs/pbd/macosx/Info.plist b/libs/pbd/macosx/Info.plist
new file mode 100644
index 0000000000..0c31617fd2
--- /dev/null
+++ b/libs/pbd/macosx/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>pbd</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.carbonframeworktemplate</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.01</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+</dict>
+</plist>
diff --git a/libs/pbd/macosx/pbd.xcodeproj/project.pbxproj b/libs/pbd/macosx/pbd.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..535d16b8a2
--- /dev/null
+++ b/libs/pbd/macosx/pbd.xcodeproj/project.pbxproj
@@ -0,0 +1,634 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 42;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 6941206F0B8A34AB00AF661E /* base_ui.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120270B8A34AB00AF661E /* base_ui.cc */; };
+ 694120700B8A34AB00AF661E /* basename.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120280B8A34AB00AF661E /* basename.cc */; };
+ 694120710B8A34AB00AF661E /* command.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120290B8A34AB00AF661E /* command.cc */; };
+ 694120720B8A34AB00AF661E /* controllable.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941202A0B8A34AB00AF661E /* controllable.cc */; };
+ 694120730B8A34AB00AF661E /* convert.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941202B0B8A34AB00AF661E /* convert.cc */; };
+ 694120740B8A34AB00AF661E /* copyfile.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941202C0B8A34AB00AF661E /* copyfile.cc */; };
+ 694120750B8A34AB00AF661E /* dmalloc.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941202D0B8A34AB00AF661E /* dmalloc.cc */; };
+ 694120760B8A34AB00AF661E /* enumwriter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941202E0B8A34AB00AF661E /* enumwriter.cc */; };
+ 694120770B8A34AB00AF661E /* error.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941202F0B8A34AB00AF661E /* error.cc */; };
+ 694120780B8A34AB00AF661E /* gettext.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120300B8A34AB00AF661E /* gettext.h */; settings = {ATTRIBUTES = (); }; };
+ 694120790B8A34AB00AF661E /* i18n.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120310B8A34AB00AF661E /* i18n.h */; settings = {ATTRIBUTES = (); }; };
+ 6941207A0B8A34AB00AF661E /* id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120320B8A34AB00AF661E /* id.cc */; };
+ 6941207B0B8A34AB00AF661E /* mountpoint.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120330B8A34AB00AF661E /* mountpoint.cc */; };
+ 6941207C0B8A34AB00AF661E /* path.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120340B8A34AB00AF661E /* path.cc */; };
+ 6941207D0B8A34AB00AF661E /* pathscanner.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120350B8A34AB00AF661E /* pathscanner.cc */; };
+ 6941207F0B8A34AB00AF661E /* abstract_ui.cc in Headers */ = {isa = PBXBuildFile; fileRef = 694120380B8A34AB00AF661E /* abstract_ui.cc */; };
+ 694120800B8A34AB00AF661E /* abstract_ui.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120390B8A34AB00AF661E /* abstract_ui.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120810B8A34AB00AF661E /* base_ui.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941203A0B8A34AB00AF661E /* base_ui.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120820B8A34AB00AF661E /* basename.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941203B0B8A34AB00AF661E /* basename.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120830B8A34AB00AF661E /* command.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941203C0B8A34AB00AF661E /* command.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120840B8A34AB00AF661E /* compose.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941203D0B8A34AB00AF661E /* compose.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120850B8A34AB00AF661E /* controllable.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941203E0B8A34AB00AF661E /* controllable.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120860B8A34AB00AF661E /* convert.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941203F0B8A34AB00AF661E /* convert.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120870B8A34AB00AF661E /* copyfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120400B8A34AB00AF661E /* copyfile.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120880B8A34AB00AF661E /* crossthread.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120410B8A34AB00AF661E /* crossthread.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120890B8A34AB00AF661E /* destructible.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120420B8A34AB00AF661E /* destructible.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941208A0B8A34AB00AF661E /* enumwriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120430B8A34AB00AF661E /* enumwriter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941208B0B8A34AB00AF661E /* error.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120440B8A34AB00AF661E /* error.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941208C0B8A34AB00AF661E /* failed_constructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120450B8A34AB00AF661E /* failed_constructor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941208D0B8A34AB00AF661E /* fastlog.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120460B8A34AB00AF661E /* fastlog.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941208E0B8A34AB00AF661E /* forkexec.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120470B8A34AB00AF661E /* forkexec.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941208F0B8A34AB00AF661E /* id.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120480B8A34AB00AF661E /* id.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120900B8A34AB00AF661E /* mathfix.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120490B8A34AB00AF661E /* mathfix.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120910B8A34AB00AF661E /* memento_command.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941204A0B8A34AB00AF661E /* memento_command.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120920B8A34AB00AF661E /* mountpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941204B0B8A34AB00AF661E /* mountpoint.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120930B8A34AB00AF661E /* path.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941204C0B8A34AB00AF661E /* path.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120940B8A34AB00AF661E /* pathscanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941204D0B8A34AB00AF661E /* pathscanner.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120950B8A34AB00AF661E /* pool.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941204E0B8A34AB00AF661E /* pool.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120960B8A34AB00AF661E /* pthread_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941204F0B8A34AB00AF661E /* pthread_utils.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120970B8A34AB00AF661E /* rcu.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120500B8A34AB00AF661E /* rcu.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120980B8A34AB00AF661E /* receiver.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120510B8A34AB00AF661E /* receiver.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120990B8A34AB00AF661E /* ringbuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120520B8A34AB00AF661E /* ringbuffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941209A0B8A34AB00AF661E /* ringbufferNPT.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120530B8A34AB00AF661E /* ringbufferNPT.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941209B0B8A34AB00AF661E /* selectable.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120540B8A34AB00AF661E /* selectable.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941209C0B8A34AB00AF661E /* shiva.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120550B8A34AB00AF661E /* shiva.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941209D0B8A34AB00AF661E /* stacktrace.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120560B8A34AB00AF661E /* stacktrace.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941209E0B8A34AB00AF661E /* stateful.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120570B8A34AB00AF661E /* stateful.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 6941209F0B8A34AB00AF661E /* statefuldestructible.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120580B8A34AB00AF661E /* statefuldestructible.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A00B8A34AB00AF661E /* stl_delete.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120590B8A34AB00AF661E /* stl_delete.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A10B8A34AB00AF661E /* stl_functors.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941205A0B8A34AB00AF661E /* stl_functors.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A20B8A34AB00AF661E /* strsplit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941205B0B8A34AB00AF661E /* strsplit.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A30B8A34AB00AF661E /* textreceiver.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941205C0B8A34AB00AF661E /* textreceiver.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A40B8A34AB00AF661E /* thrown_error.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941205D0B8A34AB00AF661E /* thrown_error.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A50B8A34AB00AF661E /* tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941205E0B8A34AB00AF661E /* tokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A60B8A34AB00AF661E /* touchable.h in Headers */ = {isa = PBXBuildFile; fileRef = 6941205F0B8A34AB00AF661E /* touchable.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A70B8A34AB00AF661E /* transmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120600B8A34AB00AF661E /* transmitter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A80B8A34AB00AF661E /* undo.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120610B8A34AB00AF661E /* undo.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120A90B8A34AB00AF661E /* whitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120620B8A34AB00AF661E /* whitespace.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120AA0B8A34AB00AF661E /* xml++.h in Headers */ = {isa = PBXBuildFile; fileRef = 694120630B8A34AB00AF661E /* xml++.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 694120AB0B8A34AB00AF661E /* pool.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120640B8A34AB00AF661E /* pool.cc */; };
+ 694120AC0B8A34AB00AF661E /* pthread_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120650B8A34AB00AF661E /* pthread_utils.cc */; };
+ 694120AD0B8A34AB00AF661E /* receiver.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120660B8A34AB00AF661E /* receiver.cc */; };
+ 694120AE0B8A34AB00AF661E /* stacktrace.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120670B8A34AB00AF661E /* stacktrace.cc */; };
+ 694120AF0B8A34AB00AF661E /* stateful.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120680B8A34AB00AF661E /* stateful.cc */; };
+ 694120B00B8A34AB00AF661E /* strsplit.cc in Sources */ = {isa = PBXBuildFile; fileRef = 694120690B8A34AB00AF661E /* strsplit.cc */; };
+ 694120B10B8A34AB00AF661E /* textreceiver.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941206A0B8A34AB00AF661E /* textreceiver.cc */; };
+ 694120B20B8A34AB00AF661E /* transmitter.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941206B0B8A34AB00AF661E /* transmitter.cc */; };
+ 694120B30B8A34AB00AF661E /* undo.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941206C0B8A34AB00AF661E /* undo.cc */; };
+ 694120B40B8A34AB00AF661E /* whitespace.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941206D0B8A34AB00AF661E /* whitespace.cc */; };
+ 694120B50B8A34AB00AF661E /* xml++.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6941206E0B8A34AB00AF661E /* xml++.cc */; };
+ 694120D40B8A36A200AF661E /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 694120D30B8A36A200AF661E /* libxml2.dylib */; };
+ 694191980B97CD950083505E /* glibmm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 694191950B97CD950083505E /* glibmm.framework */; };
+ 694191990B97CD950083505E /* sigc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 694191960B97CD950083505E /* sigc.framework */; };
+ 69C63C150B9369CB00BC0BCA /* strreplace.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69C63C140B9369CB00BC0BCA /* strreplace.cc */; };
+ 69C63C190B9369DE00BC0BCA /* replace_all.h in Headers */ = {isa = PBXBuildFile; fileRef = 69C63C180B9369DE00BC0BCA /* replace_all.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69C63C2B0B936A6E00BC0BCA /* version.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69C63C290B936A6E00BC0BCA /* version.cc */; };
+ 69C63C2C0B936A6E00BC0BCA /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 69C63C2A0B936A6E00BC0BCA /* version.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 69CD7FED0B97CDD50049ED98 /* glib in Frameworks */ = {isa = PBXBuildFile; fileRef = 69CD7FE90B97CDD50049ED98 /* glib */; };
+ 69CD7FEE0B97CDD50049ED98 /* gmodule in Frameworks */ = {isa = PBXBuildFile; fileRef = 69CD7FEA0B97CDD50049ED98 /* gmodule */; };
+ 69CD7FEF0B97CDD50049ED98 /* gobject in Frameworks */ = {isa = PBXBuildFile; fileRef = 69CD7FEB0B97CDD50049ED98 /* gobject */; };
+ 69CD7FF00B97CDD50049ED98 /* gthread in Frameworks */ = {isa = PBXBuildFile; fileRef = 69CD7FEC0B97CDD50049ED98 /* gthread */; };
+ 8D07F2BE0486CC7A007CD1D0 /* pbd_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 32BAE0B70371A74B00C91783 /* pbd_Prefix.pch */; settings = {ATTRIBUTES = (); }; };
+ 8D07F2C00486CC7A007CD1D0 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 089C1667FE841158C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+ 32BAE0B70371A74B00C91783 /* pbd_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pbd_Prefix.pch; sourceTree = "<group>"; };
+ 694120270B8A34AB00AF661E /* base_ui.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = base_ui.cc; path = ../base_ui.cc; sourceTree = SOURCE_ROOT; };
+ 694120280B8A34AB00AF661E /* basename.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = basename.cc; path = ../basename.cc; sourceTree = SOURCE_ROOT; };
+ 694120290B8A34AB00AF661E /* command.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = command.cc; path = ../command.cc; sourceTree = SOURCE_ROOT; };
+ 6941202A0B8A34AB00AF661E /* controllable.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = controllable.cc; path = ../controllable.cc; sourceTree = SOURCE_ROOT; };
+ 6941202B0B8A34AB00AF661E /* convert.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = convert.cc; path = ../convert.cc; sourceTree = SOURCE_ROOT; };
+ 6941202C0B8A34AB00AF661E /* copyfile.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = copyfile.cc; path = ../copyfile.cc; sourceTree = SOURCE_ROOT; };
+ 6941202D0B8A34AB00AF661E /* dmalloc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = dmalloc.cc; path = ../dmalloc.cc; sourceTree = SOURCE_ROOT; };
+ 6941202E0B8A34AB00AF661E /* enumwriter.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = enumwriter.cc; path = ../enumwriter.cc; sourceTree = SOURCE_ROOT; };
+ 6941202F0B8A34AB00AF661E /* error.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = error.cc; path = ../error.cc; sourceTree = SOURCE_ROOT; };
+ 694120300B8A34AB00AF661E /* gettext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = gettext.h; path = ../gettext.h; sourceTree = SOURCE_ROOT; };
+ 694120310B8A34AB00AF661E /* i18n.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = i18n.h; path = ../i18n.h; sourceTree = SOURCE_ROOT; };
+ 694120320B8A34AB00AF661E /* id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = id.cc; path = ../id.cc; sourceTree = SOURCE_ROOT; };
+ 694120330B8A34AB00AF661E /* mountpoint.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = mountpoint.cc; path = ../mountpoint.cc; sourceTree = SOURCE_ROOT; };
+ 694120340B8A34AB00AF661E /* path.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = path.cc; path = ../path.cc; sourceTree = SOURCE_ROOT; };
+ 694120350B8A34AB00AF661E /* pathscanner.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pathscanner.cc; path = ../pathscanner.cc; sourceTree = SOURCE_ROOT; };
+ 694120380B8A34AB00AF661E /* abstract_ui.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = abstract_ui.cc; sourceTree = "<group>"; };
+ 694120390B8A34AB00AF661E /* abstract_ui.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = abstract_ui.h; sourceTree = "<group>"; };
+ 6941203A0B8A34AB00AF661E /* base_ui.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = base_ui.h; sourceTree = "<group>"; };
+ 6941203B0B8A34AB00AF661E /* basename.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = basename.h; sourceTree = "<group>"; };
+ 6941203C0B8A34AB00AF661E /* command.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = command.h; sourceTree = "<group>"; };
+ 6941203D0B8A34AB00AF661E /* compose.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = compose.h; sourceTree = "<group>"; };
+ 6941203E0B8A34AB00AF661E /* controllable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = controllable.h; sourceTree = "<group>"; };
+ 6941203F0B8A34AB00AF661E /* convert.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = convert.h; sourceTree = "<group>"; };
+ 694120400B8A34AB00AF661E /* copyfile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = copyfile.h; sourceTree = "<group>"; };
+ 694120410B8A34AB00AF661E /* crossthread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = crossthread.h; sourceTree = "<group>"; };
+ 694120420B8A34AB00AF661E /* destructible.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = destructible.h; sourceTree = "<group>"; };
+ 694120430B8A34AB00AF661E /* enumwriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = enumwriter.h; sourceTree = "<group>"; };
+ 694120440B8A34AB00AF661E /* error.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = "<group>"; };
+ 694120450B8A34AB00AF661E /* failed_constructor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = failed_constructor.h; sourceTree = "<group>"; };
+ 694120460B8A34AB00AF661E /* fastlog.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fastlog.h; sourceTree = "<group>"; };
+ 694120470B8A34AB00AF661E /* forkexec.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = forkexec.h; sourceTree = "<group>"; };
+ 694120480B8A34AB00AF661E /* id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = id.h; sourceTree = "<group>"; };
+ 694120490B8A34AB00AF661E /* mathfix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mathfix.h; sourceTree = "<group>"; };
+ 6941204A0B8A34AB00AF661E /* memento_command.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = memento_command.h; sourceTree = "<group>"; };
+ 6941204B0B8A34AB00AF661E /* mountpoint.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mountpoint.h; sourceTree = "<group>"; };
+ 6941204C0B8A34AB00AF661E /* path.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = path.h; sourceTree = "<group>"; };
+ 6941204D0B8A34AB00AF661E /* pathscanner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pathscanner.h; sourceTree = "<group>"; };
+ 6941204E0B8A34AB00AF661E /* pool.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pool.h; sourceTree = "<group>"; };
+ 6941204F0B8A34AB00AF661E /* pthread_utils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pthread_utils.h; sourceTree = "<group>"; };
+ 694120500B8A34AB00AF661E /* rcu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rcu.h; sourceTree = "<group>"; };
+ 694120510B8A34AB00AF661E /* receiver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = receiver.h; sourceTree = "<group>"; };
+ 694120520B8A34AB00AF661E /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ringbuffer.h; sourceTree = "<group>"; };
+ 694120530B8A34AB00AF661E /* ringbufferNPT.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ringbufferNPT.h; sourceTree = "<group>"; };
+ 694120540B8A34AB00AF661E /* selectable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = selectable.h; sourceTree = "<group>"; };
+ 694120550B8A34AB00AF661E /* shiva.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = shiva.h; sourceTree = "<group>"; };
+ 694120560B8A34AB00AF661E /* stacktrace.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stacktrace.h; sourceTree = "<group>"; };
+ 694120570B8A34AB00AF661E /* stateful.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stateful.h; sourceTree = "<group>"; };
+ 694120580B8A34AB00AF661E /* statefuldestructible.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = statefuldestructible.h; sourceTree = "<group>"; };
+ 694120590B8A34AB00AF661E /* stl_delete.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stl_delete.h; sourceTree = "<group>"; };
+ 6941205A0B8A34AB00AF661E /* stl_functors.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stl_functors.h; sourceTree = "<group>"; };
+ 6941205B0B8A34AB00AF661E /* strsplit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = strsplit.h; sourceTree = "<group>"; };
+ 6941205C0B8A34AB00AF661E /* textreceiver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = textreceiver.h; sourceTree = "<group>"; };
+ 6941205D0B8A34AB00AF661E /* thrown_error.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = thrown_error.h; sourceTree = "<group>"; };
+ 6941205E0B8A34AB00AF661E /* tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = tokenizer.h; sourceTree = "<group>"; };
+ 6941205F0B8A34AB00AF661E /* touchable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = touchable.h; sourceTree = "<group>"; };
+ 694120600B8A34AB00AF661E /* transmitter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = transmitter.h; sourceTree = "<group>"; };
+ 694120610B8A34AB00AF661E /* undo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = undo.h; sourceTree = "<group>"; };
+ 694120620B8A34AB00AF661E /* whitespace.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = whitespace.h; sourceTree = "<group>"; };
+ 694120630B8A34AB00AF661E /* xml++.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = "xml++.h"; sourceTree = "<group>"; };
+ 694120640B8A34AB00AF661E /* pool.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pool.cc; path = ../pool.cc; sourceTree = SOURCE_ROOT; };
+ 694120650B8A34AB00AF661E /* pthread_utils.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pthread_utils.cc; path = ../pthread_utils.cc; sourceTree = SOURCE_ROOT; };
+ 694120660B8A34AB00AF661E /* receiver.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = receiver.cc; path = ../receiver.cc; sourceTree = SOURCE_ROOT; };
+ 694120670B8A34AB00AF661E /* stacktrace.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stacktrace.cc; path = ../stacktrace.cc; sourceTree = SOURCE_ROOT; };
+ 694120680B8A34AB00AF661E /* stateful.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stateful.cc; path = ../stateful.cc; sourceTree = SOURCE_ROOT; };
+ 694120690B8A34AB00AF661E /* strsplit.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = strsplit.cc; path = ../strsplit.cc; sourceTree = SOURCE_ROOT; };
+ 6941206A0B8A34AB00AF661E /* textreceiver.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = textreceiver.cc; path = ../textreceiver.cc; sourceTree = SOURCE_ROOT; };
+ 6941206B0B8A34AB00AF661E /* transmitter.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = transmitter.cc; path = ../transmitter.cc; sourceTree = SOURCE_ROOT; };
+ 6941206C0B8A34AB00AF661E /* undo.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = undo.cc; path = ../undo.cc; sourceTree = SOURCE_ROOT; };
+ 6941206D0B8A34AB00AF661E /* whitespace.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = whitespace.cc; path = ../whitespace.cc; sourceTree = SOURCE_ROOT; };
+ 6941206E0B8A34AB00AF661E /* xml++.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "xml++.cc"; path = "../xml++.cc"; sourceTree = SOURCE_ROOT; };
+ 694120D30B8A36A200AF661E /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = "<absolute>"; };
+ 694191950B97CD950083505E /* glibmm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = glibmm.framework; path = /Library/Frameworks/glibmm.framework; sourceTree = "<absolute>"; };
+ 694191960B97CD950083505E /* sigc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = sigc.framework; path = /Library/Frameworks/sigc.framework; sourceTree = "<absolute>"; };
+ 69C63C140B9369CB00BC0BCA /* strreplace.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = strreplace.cc; path = ../strreplace.cc; sourceTree = SOURCE_ROOT; };
+ 69C63C180B9369DE00BC0BCA /* replace_all.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = replace_all.h; sourceTree = "<group>"; };
+ 69C63C290B936A6E00BC0BCA /* version.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = version.cc; sourceTree = "<group>"; };
+ 69C63C2A0B936A6E00BC0BCA /* version.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
+ 69CD7FE90B97CDD50049ED98 /* glib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = glib; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/glib; sourceTree = "<absolute>"; };
+ 69CD7FEA0B97CDD50049ED98 /* gmodule */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gmodule; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gmodule; sourceTree = "<absolute>"; };
+ 69CD7FEB0B97CDD50049ED98 /* gobject */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gobject; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gobject; sourceTree = "<absolute>"; };
+ 69CD7FEC0B97CDD50049ED98 /* gthread */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = gthread; path = /Library/Frameworks/GLib.framework/Versions/2.12.3/Libraries/gthread; sourceTree = "<absolute>"; };
+ 8D07F2C70486CC7A007CD1D0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
+ 8D07F2C80486CC7A007CD1D0 /* pbd.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = pbd.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D07F2C30486CC7A007CD1D0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 694120D40B8A36A200AF661E /* libxml2.dylib in Frameworks */,
+ 694191980B97CD950083505E /* glibmm.framework in Frameworks */,
+ 694191990B97CD950083505E /* sigc.framework in Frameworks */,
+ 69CD7FED0B97CDD50049ED98 /* glib in Frameworks */,
+ 69CD7FEE0B97CDD50049ED98 /* gmodule in Frameworks */,
+ 69CD7FEF0B97CDD50049ED98 /* gobject in Frameworks */,
+ 69CD7FF00B97CDD50049ED98 /* gthread in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 034768DDFF38A45A11DB9C8B /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D07F2C80486CC7A007CD1D0 /* pbd.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 0867D691FE84028FC02AAC07 /* pbd */ = {
+ isa = PBXGroup;
+ children = (
+ 69C63C290B936A6E00BC0BCA /* version.cc */,
+ 69C63C2A0B936A6E00BC0BCA /* version.h */,
+ 08FB77ACFE841707C02AAC07 /* Source */,
+ 089C1665FE841158C02AAC07 /* Resources */,
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */,
+ 034768DDFF38A45A11DB9C8B /* Products */,
+ );
+ name = pbd;
+ sourceTree = "<group>";
+ };
+ 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 69CD7FE90B97CDD50049ED98 /* glib */,
+ 69CD7FEA0B97CDD50049ED98 /* gmodule */,
+ 69CD7FEB0B97CDD50049ED98 /* gobject */,
+ 69CD7FEC0B97CDD50049ED98 /* gthread */,
+ 694191950B97CD950083505E /* glibmm.framework */,
+ 694191960B97CD950083505E /* sigc.framework */,
+ 694120D30B8A36A200AF661E /* libxml2.dylib */,
+ );
+ name = "External Frameworks and Libraries";
+ sourceTree = "<group>";
+ };
+ 089C1665FE841158C02AAC07 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 8D07F2C70486CC7A007CD1D0 /* Info.plist */,
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 08FB77ACFE841707C02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ 69C63C140B9369CB00BC0BCA /* strreplace.cc */,
+ 694120270B8A34AB00AF661E /* base_ui.cc */,
+ 694120280B8A34AB00AF661E /* basename.cc */,
+ 694120290B8A34AB00AF661E /* command.cc */,
+ 6941202A0B8A34AB00AF661E /* controllable.cc */,
+ 6941202B0B8A34AB00AF661E /* convert.cc */,
+ 6941202C0B8A34AB00AF661E /* copyfile.cc */,
+ 6941202D0B8A34AB00AF661E /* dmalloc.cc */,
+ 6941202E0B8A34AB00AF661E /* enumwriter.cc */,
+ 6941202F0B8A34AB00AF661E /* error.cc */,
+ 694120300B8A34AB00AF661E /* gettext.h */,
+ 694120310B8A34AB00AF661E /* i18n.h */,
+ 694120320B8A34AB00AF661E /* id.cc */,
+ 694120330B8A34AB00AF661E /* mountpoint.cc */,
+ 694120340B8A34AB00AF661E /* path.cc */,
+ 694120350B8A34AB00AF661E /* pathscanner.cc */,
+ 694120360B8A34AB00AF661E /* pbd */,
+ 694120640B8A34AB00AF661E /* pool.cc */,
+ 694120650B8A34AB00AF661E /* pthread_utils.cc */,
+ 694120660B8A34AB00AF661E /* receiver.cc */,
+ 694120670B8A34AB00AF661E /* stacktrace.cc */,
+ 694120680B8A34AB00AF661E /* stateful.cc */,
+ 694120690B8A34AB00AF661E /* strsplit.cc */,
+ 6941206A0B8A34AB00AF661E /* textreceiver.cc */,
+ 6941206B0B8A34AB00AF661E /* transmitter.cc */,
+ 6941206C0B8A34AB00AF661E /* undo.cc */,
+ 6941206D0B8A34AB00AF661E /* whitespace.cc */,
+ 6941206E0B8A34AB00AF661E /* xml++.cc */,
+ 32BAE0B70371A74B00C91783 /* pbd_Prefix.pch */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 694120360B8A34AB00AF661E /* pbd */ = {
+ isa = PBXGroup;
+ children = (
+ 69C63C180B9369DE00BC0BCA /* replace_all.h */,
+ 694120380B8A34AB00AF661E /* abstract_ui.cc */,
+ 694120390B8A34AB00AF661E /* abstract_ui.h */,
+ 6941203A0B8A34AB00AF661E /* base_ui.h */,
+ 6941203B0B8A34AB00AF661E /* basename.h */,
+ 6941203C0B8A34AB00AF661E /* command.h */,
+ 6941203D0B8A34AB00AF661E /* compose.h */,
+ 6941203E0B8A34AB00AF661E /* controllable.h */,
+ 6941203F0B8A34AB00AF661E /* convert.h */,
+ 694120400B8A34AB00AF661E /* copyfile.h */,
+ 694120410B8A34AB00AF661E /* crossthread.h */,
+ 694120420B8A34AB00AF661E /* destructible.h */,
+ 694120430B8A34AB00AF661E /* enumwriter.h */,
+ 694120440B8A34AB00AF661E /* error.h */,
+ 694120450B8A34AB00AF661E /* failed_constructor.h */,
+ 694120460B8A34AB00AF661E /* fastlog.h */,
+ 694120470B8A34AB00AF661E /* forkexec.h */,
+ 694120480B8A34AB00AF661E /* id.h */,
+ 694120490B8A34AB00AF661E /* mathfix.h */,
+ 6941204A0B8A34AB00AF661E /* memento_command.h */,
+ 6941204B0B8A34AB00AF661E /* mountpoint.h */,
+ 6941204C0B8A34AB00AF661E /* path.h */,
+ 6941204D0B8A34AB00AF661E /* pathscanner.h */,
+ 6941204E0B8A34AB00AF661E /* pool.h */,
+ 6941204F0B8A34AB00AF661E /* pthread_utils.h */,
+ 694120500B8A34AB00AF661E /* rcu.h */,
+ 694120510B8A34AB00AF661E /* receiver.h */,
+ 694120520B8A34AB00AF661E /* ringbuffer.h */,
+ 694120530B8A34AB00AF661E /* ringbufferNPT.h */,
+ 694120540B8A34AB00AF661E /* selectable.h */,
+ 694120550B8A34AB00AF661E /* shiva.h */,
+ 694120560B8A34AB00AF661E /* stacktrace.h */,
+ 694120570B8A34AB00AF661E /* stateful.h */,
+ 694120580B8A34AB00AF661E /* statefuldestructible.h */,
+ 694120590B8A34AB00AF661E /* stl_delete.h */,
+ 6941205A0B8A34AB00AF661E /* stl_functors.h */,
+ 6941205B0B8A34AB00AF661E /* strsplit.h */,
+ 6941205C0B8A34AB00AF661E /* textreceiver.h */,
+ 6941205D0B8A34AB00AF661E /* thrown_error.h */,
+ 6941205E0B8A34AB00AF661E /* tokenizer.h */,
+ 6941205F0B8A34AB00AF661E /* touchable.h */,
+ 694120600B8A34AB00AF661E /* transmitter.h */,
+ 694120610B8A34AB00AF661E /* undo.h */,
+ 694120620B8A34AB00AF661E /* whitespace.h */,
+ 694120630B8A34AB00AF661E /* xml++.h */,
+ );
+ name = pbd;
+ path = ../pbd;
+ sourceTree = SOURCE_ROOT;
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 8D07F2BD0486CC7A007CD1D0 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 69C63C2C0B936A6E00BC0BCA /* version.h in Headers */,
+ 69C63C190B9369DE00BC0BCA /* replace_all.h in Headers */,
+ 8D07F2BE0486CC7A007CD1D0 /* pbd_Prefix.pch in Headers */,
+ 6941207F0B8A34AB00AF661E /* abstract_ui.cc in Headers */,
+ 694120780B8A34AB00AF661E /* gettext.h in Headers */,
+ 694120790B8A34AB00AF661E /* i18n.h in Headers */,
+ 694120800B8A34AB00AF661E /* abstract_ui.h in Headers */,
+ 694120810B8A34AB00AF661E /* base_ui.h in Headers */,
+ 694120820B8A34AB00AF661E /* basename.h in Headers */,
+ 694120830B8A34AB00AF661E /* command.h in Headers */,
+ 694120840B8A34AB00AF661E /* compose.h in Headers */,
+ 694120850B8A34AB00AF661E /* controllable.h in Headers */,
+ 694120860B8A34AB00AF661E /* convert.h in Headers */,
+ 694120870B8A34AB00AF661E /* copyfile.h in Headers */,
+ 694120880B8A34AB00AF661E /* crossthread.h in Headers */,
+ 694120890B8A34AB00AF661E /* destructible.h in Headers */,
+ 6941208A0B8A34AB00AF661E /* enumwriter.h in Headers */,
+ 6941208B0B8A34AB00AF661E /* error.h in Headers */,
+ 6941208C0B8A34AB00AF661E /* failed_constructor.h in Headers */,
+ 6941208D0B8A34AB00AF661E /* fastlog.h in Headers */,
+ 6941208E0B8A34AB00AF661E /* forkexec.h in Headers */,
+ 6941208F0B8A34AB00AF661E /* id.h in Headers */,
+ 694120900B8A34AB00AF661E /* mathfix.h in Headers */,
+ 694120910B8A34AB00AF661E /* memento_command.h in Headers */,
+ 694120920B8A34AB00AF661E /* mountpoint.h in Headers */,
+ 694120930B8A34AB00AF661E /* path.h in Headers */,
+ 694120940B8A34AB00AF661E /* pathscanner.h in Headers */,
+ 694120950B8A34AB00AF661E /* pool.h in Headers */,
+ 694120960B8A34AB00AF661E /* pthread_utils.h in Headers */,
+ 694120970B8A34AB00AF661E /* rcu.h in Headers */,
+ 694120980B8A34AB00AF661E /* receiver.h in Headers */,
+ 694120990B8A34AB00AF661E /* ringbuffer.h in Headers */,
+ 6941209A0B8A34AB00AF661E /* ringbufferNPT.h in Headers */,
+ 6941209B0B8A34AB00AF661E /* selectable.h in Headers */,
+ 6941209C0B8A34AB00AF661E /* shiva.h in Headers */,
+ 6941209D0B8A34AB00AF661E /* stacktrace.h in Headers */,
+ 6941209E0B8A34AB00AF661E /* stateful.h in Headers */,
+ 6941209F0B8A34AB00AF661E /* statefuldestructible.h in Headers */,
+ 694120A00B8A34AB00AF661E /* stl_delete.h in Headers */,
+ 694120A10B8A34AB00AF661E /* stl_functors.h in Headers */,
+ 694120A20B8A34AB00AF661E /* strsplit.h in Headers */,
+ 694120A30B8A34AB00AF661E /* textreceiver.h in Headers */,
+ 694120A40B8A34AB00AF661E /* thrown_error.h in Headers */,
+ 694120A50B8A34AB00AF661E /* tokenizer.h in Headers */,
+ 694120A60B8A34AB00AF661E /* touchable.h in Headers */,
+ 694120A70B8A34AB00AF661E /* transmitter.h in Headers */,
+ 694120A80B8A34AB00AF661E /* undo.h in Headers */,
+ 694120A90B8A34AB00AF661E /* whitespace.h in Headers */,
+ 694120AA0B8A34AB00AF661E /* xml++.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 8D07F2BC0486CC7A007CD1D0 /* pbd */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "pbd" */;
+ buildPhases = (
+ 8D07F2BD0486CC7A007CD1D0 /* Headers */,
+ 8D07F2BF0486CC7A007CD1D0 /* Resources */,
+ 8D07F2C10486CC7A007CD1D0 /* Sources */,
+ 8D07F2C30486CC7A007CD1D0 /* Frameworks */,
+ 8D07F2C50486CC7A007CD1D0 /* Rez */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = pbd;
+ productInstallPath = "$(HOME)/Library/Frameworks";
+ productName = pbd;
+ productReference = 8D07F2C80486CC7A007CD1D0 /* pbd.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 0867D690FE84028FC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "pbd" */;
+ hasScannedForEncodings = 1;
+ mainGroup = 0867D691FE84028FC02AAC07 /* pbd */;
+ productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8D07F2BC0486CC7A007CD1D0 /* pbd */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D07F2BF0486CC7A007CD1D0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D07F2C00486CC7A007CD1D0 /* InfoPlist.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXRezBuildPhase section */
+ 8D07F2C50486CC7A007CD1D0 /* Rez */ = {
+ isa = PBXRezBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXRezBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D07F2C10486CC7A007CD1D0 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 69C63C2B0B936A6E00BC0BCA /* version.cc in Sources */,
+ 6941206F0B8A34AB00AF661E /* base_ui.cc in Sources */,
+ 69C63C150B9369CB00BC0BCA /* strreplace.cc in Sources */,
+ 694120700B8A34AB00AF661E /* basename.cc in Sources */,
+ 694120710B8A34AB00AF661E /* command.cc in Sources */,
+ 694120720B8A34AB00AF661E /* controllable.cc in Sources */,
+ 694120730B8A34AB00AF661E /* convert.cc in Sources */,
+ 694120740B8A34AB00AF661E /* copyfile.cc in Sources */,
+ 694120750B8A34AB00AF661E /* dmalloc.cc in Sources */,
+ 694120760B8A34AB00AF661E /* enumwriter.cc in Sources */,
+ 694120770B8A34AB00AF661E /* error.cc in Sources */,
+ 6941207A0B8A34AB00AF661E /* id.cc in Sources */,
+ 6941207B0B8A34AB00AF661E /* mountpoint.cc in Sources */,
+ 6941207C0B8A34AB00AF661E /* path.cc in Sources */,
+ 6941207D0B8A34AB00AF661E /* pathscanner.cc in Sources */,
+ 694120AB0B8A34AB00AF661E /* pool.cc in Sources */,
+ 694120AC0B8A34AB00AF661E /* pthread_utils.cc in Sources */,
+ 694120AD0B8A34AB00AF661E /* receiver.cc in Sources */,
+ 694120AE0B8A34AB00AF661E /* stacktrace.cc in Sources */,
+ 694120AF0B8A34AB00AF661E /* stateful.cc in Sources */,
+ 694120B00B8A34AB00AF661E /* strsplit.cc in Sources */,
+ 694120B10B8A34AB00AF661E /* textreceiver.cc in Sources */,
+ 694120B20B8A34AB00AF661E /* transmitter.cc in Sources */,
+ 694120B30B8A34AB00AF661E /* undo.cc in Sources */,
+ 694120B40B8A34AB00AF661E /* whitespace.cc in Sources */,
+ 694120B50B8A34AB00AF661E /* xml++.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 089C1666FE841158C02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C1667FE841158C02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 4FADC24408B4156D00ABE55E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = (
+ ppc,
+ i386,
+ );
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = pbd_Prefix.pch;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ PRODUCT_NAME = pbd;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Release;
+ };
+ 4FADC24808B4156D00ABE55E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = (
+ "$(NATIVE_ARCH)",
+ ppc,
+ );
+ GCC_FAST_OBJC_DISPATCH = NO;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_STRICT_ALIASING = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ /usr/include/libxml2,
+ /Library/Frameworks/GLib.framework/Headers,
+ /Library/Frameworks/glibmm.framework/Headers,
+ /Library/Frameworks/sigc.framework/Headers,
+ );
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ };
+ name = Release;
+ };
+ 69C9AF150B97A83A0097DE90 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = "$(NATIVE_ARCH)";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = stabs;
+ GCC_FAST_OBJC_DISPATCH = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ /usr/include/libxml2,
+ /Library/Frameworks/GLib.framework/Headers,
+ /Library/Frameworks/glibmm.framework/Headers,
+ /Library/Frameworks/sigc.framework/Headers,
+ );
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ PREBINDING = NO;
+ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
+ STRIP_INSTALLED_PRODUCT = NO;
+ };
+ name = Debug;
+ };
+ 69C9AF160B97A83A0097DE90 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = i386;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ FRAMEWORK_VERSION = A;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_MODEL_TUNING = G5;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = pbd_Prefix.pch;
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "@executable_path/../Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(LOCAL_LIBRARY_DIR)/Frameworks/GLib.framework/Versions/2.12.3/Libraries\"";
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ PRODUCT_NAME = pbd;
+ WRAPPER_EXTENSION = framework;
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 4FADC24208B4156D00ABE55E /* Build configuration list for PBXNativeTarget "pbd" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4FADC24408B4156D00ABE55E /* Release */,
+ 69C9AF160B97A83A0097DE90 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 4FADC24608B4156D00ABE55E /* Build configuration list for PBXProject "pbd" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 4FADC24808B4156D00ABE55E /* Release */,
+ 69C9AF150B97A83A0097DE90 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 0867D690FE84028FC02AAC07 /* Project object */;
+}
diff --git a/libs/pbd/macosx/pbd_Prefix.pch b/libs/pbd/macosx/pbd_Prefix.pch
new file mode 100644
index 0000000000..a774fac593
--- /dev/null
+++ b/libs/pbd/macosx/pbd_Prefix.pch
@@ -0,0 +1,4 @@
+//
+// Prefix header for all source files of the 'pbd' target in the 'pbd' project.
+//
+
diff --git a/libs/pbd/macosx/version.cc b/libs/pbd/macosx/version.cc
new file mode 100644
index 0000000000..61a94f6fc9
--- /dev/null
+++ b/libs/pbd/macosx/version.cc
@@ -0,0 +1,3 @@
+int libpbd_major_version = 4;
+int libpbd_minor_version = 1;
+int libpbd_micro_version = 0;
diff --git a/libs/pbd/macosx/version.h b/libs/pbd/macosx/version.h
new file mode 100644
index 0000000000..ec6c854141
--- /dev/null
+++ b/libs/pbd/macosx/version.h
@@ -0,0 +1,7 @@
+#ifndef __libpbd_version_h__
+#define __libpbd_version_h__
+extern const char* libpbd_revision;
+extern int libpbd_major_version;
+extern int libpbd_minor_version;
+extern int libpbd_micro_version;
+#endif /* __libpbd_version_h__ */
diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc
index eca53916af..97f19e1fe5 100644
--- a/libs/pbd/pbd/abstract_ui.cc
+++ b/libs/pbd/pbd/abstract_ui.cc
@@ -54,6 +54,8 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
}
RequestBufferVector vec;
+ vec.buf[0] = 0;
+ vec.buf[1] = 0;
rbuf->get_write_vector (&vec);
@@ -100,16 +102,10 @@ AbstractUI<RequestObject>::handle_ui_requests ()
if (vec.len[0] == 0) {
break;
} else {
- /* request_factory/copy constructor does a deep
- copy of the Request object,
- unlike Ringbuffer::read()
- */
-
- RequestObject req (*vec.buf[0]);
- i->second->increment_read_ptr (1);
request_buffer_map_lock.unlock ();
- do_request (&req);
+ do_request (vec.buf[0]);
request_buffer_map_lock.lock ();
+ i->second->increment_read_ptr (1);
}
}
}
diff --git a/libs/pbd/pbd/abstract_ui.h b/libs/pbd/pbd/abstract_ui.h
index f80db7bf1a..88c27aa0bc 100644
--- a/libs/pbd/pbd/abstract_ui.h
+++ b/libs/pbd/pbd/abstract_ui.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __pbd_abstract_ui_h__
diff --git a/libs/pbd/pbd/command.h b/libs/pbd/pbd/command.h
index 8044b51a83..23bcf85b91 100644
--- a/libs/pbd/pbd/command.h
+++ b/libs/pbd/pbd/command.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: /local/undo/libs/pbd3/pbd/undo.h 80 2006-06-22T22:37:01.079855Z fugalh $
*/
#ifndef __lib_pbd_command_h__
diff --git a/libs/pbd/pbd/controllable.h b/libs/pbd/pbd/controllable.h
index c88eb298bc..c152013c66 100644
--- a/libs/pbd/pbd/controllable.h
+++ b/libs/pbd/pbd/controllable.h
@@ -2,6 +2,7 @@
#define __pbd_controllable_h__
#include <string>
+#include <set>
#include <sigc++/trackable.h>
#include <sigc++/signal.h>
@@ -36,8 +37,18 @@ class Controllable : public PBD::StatefulDestructible {
std::string name() const { return _name; }
+ static Controllable* by_id (const PBD::ID&);
+ static Controllable* by_name (const std::string&);
+
private:
std::string _name;
+
+ void add ();
+ void remove ();
+
+ typedef std::set<PBD::Controllable*> Controllables;
+ static Glib::Mutex* registry_lock;
+ static Controllables registry;
};
}
diff --git a/libs/pbd/pbd/error.h b/libs/pbd/pbd/error.h
index 4136f02ee2..58842d68eb 100644
--- a/libs/pbd/pbd/error.h
+++ b/libs/pbd/pbd/error.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __libpbd_error_h__
#define __libpbd_error_h__
diff --git a/libs/pbd/pbd/mathfix.h b/libs/pbd/pbd/mathfix.h
index f0dc7e491e..fd0468905f 100644
--- a/libs/pbd/pbd/mathfix.h
+++ b/libs/pbd/pbd/mathfix.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __pbd_mathfix_h__
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h
index fe1aa8e7d0..d913b2c0fe 100644
--- a/libs/pbd/pbd/memento_command.h
+++ b/libs/pbd/pbd/memento_command.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: /local/undo/libs/pbd3/pbd/undo.h 132 2006-06-29T18:45:16.609763Z fugalh $
*/
#ifndef __lib_pbd_memento_command_h__
diff --git a/libs/pbd/pbd/mountpoint.h b/libs/pbd/pbd/mountpoint.h
index 86ccc58190..e0ec1be7f9 100644
--- a/libs/pbd/pbd/mountpoint.h
+++ b/libs/pbd/pbd/mountpoint.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __pbd_mountpoint_h__
diff --git a/libs/pbd/pbd/pool.h b/libs/pbd/pbd/pool.h
index f8e19e72fb..d604680ae2 100644
--- a/libs/pbd/pbd/pool.h
+++ b/libs/pbd/pbd/pool.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __qm_pool_h__
diff --git a/libs/pbd/pbd/rcu.h b/libs/pbd/pbd/rcu.h
index a8f3cdd5bc..8b0b8b3548 100644
--- a/libs/pbd/pbd/rcu.h
+++ b/libs/pbd/pbd/rcu.h
@@ -12,22 +12,21 @@ class RCUManager
public:
RCUManager (T* new_rcu_value) {
- m_rcu_value = new boost::shared_ptr<T> (new_rcu_value);
+ x.m_rcu_value = new boost::shared_ptr<T> (new_rcu_value);
}
- virtual ~RCUManager() { delete m_rcu_value; }
+ virtual ~RCUManager() { delete x.m_rcu_value; }
- boost::shared_ptr<T> reader () const { return *((boost::shared_ptr<T> *) g_atomic_pointer_get (the_pointer())); }
+ boost::shared_ptr<T> reader () const { return *((boost::shared_ptr<T> *) g_atomic_pointer_get (&x.gptr)); }
virtual boost::shared_ptr<T> write_copy () = 0;
virtual bool update (boost::shared_ptr<T> new_value) = 0;
protected:
- boost::shared_ptr<T>* m_rcu_value;
-
- // this monstrosity is needed because of some wierd behavior by g++
-
- gpointer * the_pointer() const { return (gpointer *) &m_rcu_value; }
+ union {
+ boost::shared_ptr<T>* m_rcu_value;
+ mutable volatile gpointer gptr;
+ } x;
};
@@ -60,7 +59,7 @@ public:
// store the current
- current_write_old = RCUManager<T>::m_rcu_value;
+ current_write_old = RCUManager<T>::x.m_rcu_value;
boost::shared_ptr<T> new_copy (new T(**current_write_old));
@@ -76,7 +75,7 @@ public:
// update, checking that nobody beat us to it
- bool ret = g_atomic_pointer_compare_and_exchange (RCUManager<T>::the_pointer(),
+ bool ret = g_atomic_pointer_compare_and_exchange (&RCUManager<T>::x.gptr,
(gpointer) current_write_old,
(gpointer) new_spp);
diff --git a/libs/pbd/pbd/receiver.h b/libs/pbd/pbd/receiver.h
index 5ce238df63..93192ce787 100644
--- a/libs/pbd/pbd/receiver.h
+++ b/libs/pbd/pbd/receiver.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __libmisc_receiver_h__
diff --git a/libs/pbd/pbd/replace_all.h b/libs/pbd/pbd/replace_all.h
new file mode 100644
index 0000000000..4434637283
--- /dev/null
+++ b/libs/pbd/pbd/replace_all.h
@@ -0,0 +1,8 @@
+#ifndef __pbd_replace_all_h__
+#define __pbd_replace_all_h__
+
+#include <string>
+
+int replace_all (std::string& str, const std::string& target, const std::string& replacement);
+
+#endif // __pbd_replace_all_h__
diff --git a/libs/pbd/pbd/ringbuffer.h b/libs/pbd/pbd/ringbuffer.h
index 1d9c9b04e3..d98601461e 100644
--- a/libs/pbd/pbd/ringbuffer.h
+++ b/libs/pbd/pbd/ringbuffer.h
@@ -15,25 +15,21 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef ringbuffer_h
#define ringbuffer_h
-//#include <sys/mman.h>
-
#include <glib.h>
template<class T>
class RingBuffer
{
public:
- RingBuffer (size_t sz) {
- size_t power_of_two;
-
- for (power_of_two = 1; 1U<<power_of_two < sz; power_of_two++);
-
+ RingBuffer (guint sz) {
+// size = ffs(sz); /* find first [bit] set is a single inlined assembly instruction. But it looks like the API rounds up so... */
+ guint power_of_two;
+ for (power_of_two = 1; 1U<<power_of_two < sz; power_of_two++);
size = 1<<power_of_two;
size_mask = size;
size_mask -= 1;
@@ -48,44 +44,44 @@ class RingBuffer
void reset () {
/* !!! NOT THREAD SAFE !!! */
- g_atomic_int_set (&write_ptr, 0);
- g_atomic_int_set (&read_ptr, 0);
+ g_atomic_int_set (&write_idx, 0);
+ g_atomic_int_set (&read_idx, 0);
}
- void set (size_t r, size_t w) {
+ void set (guint r, guint w) {
/* !!! NOT THREAD SAFE !!! */
- g_atomic_int_set (&write_ptr, w);
- g_atomic_int_set (&read_ptr, r);
+ g_atomic_int_set (&write_idx, w);
+ g_atomic_int_set (&read_idx, r);
}
- size_t read (T *dest, size_t cnt);
- size_t write (T *src, size_t cnt);
+ guint read (T *dest, guint cnt);
+ guint write (T *src, guint cnt);
struct rw_vector {
T *buf[2];
- size_t len[2];
+ guint len[2];
};
void get_read_vector (rw_vector *);
void get_write_vector (rw_vector *);
- void decrement_read_ptr (size_t cnt) {
- g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) - cnt) & size_mask);
+ void decrement_read_idx (guint cnt) {
+ g_atomic_int_set (&read_idx, (g_atomic_int_get(&read_idx) - cnt) & size_mask);
}
- void increment_read_ptr (size_t cnt) {
- g_atomic_int_set (&read_ptr, (g_atomic_int_get(&read_ptr) + cnt) & size_mask);
+ void increment_read_idx (guint cnt) {
+ g_atomic_int_set (&read_idx, (g_atomic_int_get(&read_idx) + cnt) & size_mask);
}
- void increment_write_ptr (size_t cnt) {
- g_atomic_int_set (&write_ptr, (g_atomic_int_get(&write_ptr) + cnt) & size_mask);
+ void increment_write_idx (guint cnt) {
+ g_atomic_int_set (&write_idx, (g_atomic_int_get(&write_idx) + cnt) & size_mask);
}
- size_t write_space () {
- size_t w, r;
+ guint write_space () {
+ guint w, r;
- w = g_atomic_int_get (&write_ptr);
- r = g_atomic_int_get (&read_ptr);
+ w = g_atomic_int_get (&write_idx);
+ r = g_atomic_int_get (&read_idx);
if (w > r) {
return ((r - w + size) & size_mask) - 1;
@@ -96,11 +92,11 @@ class RingBuffer
}
}
- size_t read_space () {
- size_t w, r;
+ guint read_space () {
+ guint w, r;
- w = g_atomic_int_get (&write_ptr);
- r = g_atomic_int_get (&read_ptr);
+ w = g_atomic_int_get (&write_idx);
+ r = g_atomic_int_get (&read_idx);
if (w > r) {
return w - r;
@@ -110,28 +106,28 @@ class RingBuffer
}
T *buffer () { return buf; }
- size_t get_write_ptr () const { return g_atomic_int_get (&write_ptr); }
- size_t get_read_ptr () const { return g_atomic_int_get (&read_ptr); }
- size_t bufsize () const { return size; }
+ guint get_write_idx () const { return g_atomic_int_get (&write_idx); }
+ guint get_read_idx () const { return g_atomic_int_get (&read_idx); }
+ guint bufsize () const { return size; }
protected:
T *buf;
- size_t size;
- mutable gint write_ptr;
- mutable gint read_ptr;
- size_t size_mask;
+ guint size;
+ mutable gint write_idx;
+ mutable gint read_idx;
+ guint size_mask;
};
-template<class T> size_t
-RingBuffer<T>::read (T *dest, size_t cnt)
+template<class T> guint
+RingBuffer<T>::read (T *dest, guint cnt)
{
- size_t free_cnt;
- size_t cnt2;
- size_t to_read;
- size_t n1, n2;
- size_t priv_read_ptr;
+ guint free_cnt;
+ guint cnt2;
+ guint to_read;
+ guint n1, n2;
+ guint priv_read_idx;
- priv_read_ptr=g_atomic_int_get(&read_ptr);
+ priv_read_idx=g_atomic_int_get(&read_idx);
if ((free_cnt = read_space ()) == 0) {
return 0;
@@ -139,39 +135,39 @@ RingBuffer<T>::read (T *dest, size_t cnt)
to_read = cnt > free_cnt ? free_cnt : cnt;
- cnt2 = priv_read_ptr + to_read;
+ cnt2 = priv_read_idx + to_read;
if (cnt2 > size) {
- n1 = size - priv_read_ptr;
+ n1 = size - priv_read_idx;
n2 = cnt2 & size_mask;
} else {
n1 = to_read;
n2 = 0;
}
- memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
- priv_read_ptr = (priv_read_ptr + n1) & size_mask;
+ memcpy (dest, &buf[priv_read_idx], n1 * sizeof (T));
+ priv_read_idx = (priv_read_idx + n1) & size_mask;
if (n2) {
memcpy (dest+n1, buf, n2 * sizeof (T));
- priv_read_ptr = n2;
+ priv_read_idx = n2;
}
- g_atomic_int_set(&read_ptr, priv_read_ptr);
+ g_atomic_int_set(&read_idx, priv_read_idx);
return to_read;
}
-template<class T> size_t
-RingBuffer<T>::write (T *src, size_t cnt)
+template<class T> guint
+RingBuffer<T>::write (T *src, guint cnt)
{
- size_t free_cnt;
- size_t cnt2;
- size_t to_write;
- size_t n1, n2;
- size_t priv_write_ptr;
+ guint free_cnt;
+ guint cnt2;
+ guint to_write;
+ guint n1, n2;
+ guint priv_write_idx;
- priv_write_ptr=g_atomic_int_get(&write_ptr);
+ priv_write_idx=g_atomic_int_get(&write_idx);
if ((free_cnt = write_space ()) == 0) {
return 0;
@@ -179,25 +175,25 @@ RingBuffer<T>::write (T *src, size_t cnt)
to_write = cnt > free_cnt ? free_cnt : cnt;
- cnt2 = priv_write_ptr + to_write;
+ cnt2 = priv_write_idx + to_write;
if (cnt2 > size) {
- n1 = size - priv_write_ptr;
+ n1 = size - priv_write_idx;
n2 = cnt2 & size_mask;
} else {
n1 = to_write;
n2 = 0;
}
- memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
- priv_write_ptr = (priv_write_ptr + n1) & size_mask;
+ memcpy (&buf[priv_write_idx], src, n1 * sizeof (T));
+ priv_write_idx = (priv_write_idx + n1) & size_mask;
if (n2) {
memcpy (buf, src+n1, n2 * sizeof (T));
- priv_write_ptr = n2;
+ priv_write_idx = n2;
}
- g_atomic_int_set(&write_ptr, priv_write_ptr);
+ g_atomic_int_set(&write_idx, priv_write_idx);
return to_write;
}
@@ -205,12 +201,12 @@ template<class T> void
RingBuffer<T>::get_read_vector (RingBuffer<T>::rw_vector *vec)
{
- size_t free_cnt;
- size_t cnt2;
- size_t w, r;
+ guint free_cnt;
+ guint cnt2;
+ guint w, r;
- w = g_atomic_int_get (&write_ptr);
- r = g_atomic_int_get (&read_ptr);
+ w = g_atomic_int_get (&write_idx);
+ r = g_atomic_int_get (&read_idx);
if (w > r) {
free_cnt = w - r;
@@ -245,12 +241,12 @@ template<class T> void
RingBuffer<T>::get_write_vector (RingBuffer<T>::rw_vector *vec)
{
- size_t free_cnt;
- size_t cnt2;
- size_t w, r;
+ guint free_cnt;
+ guint cnt2;
+ guint w, r;
- w = g_atomic_int_get (&write_ptr);
- r = g_atomic_int_get (&read_ptr);
+ w = g_atomic_int_get (&write_idx);
+ r = g_atomic_int_get (&read_idx);
if (w > r) {
free_cnt = ((r - w + size) & size_mask) - 1;
diff --git a/libs/pbd/pbd/ringbufferNPT.h b/libs/pbd/pbd/ringbufferNPT.h
index fee2efce3d..9db09098d6 100644
--- a/libs/pbd/pbd/ringbufferNPT.h
+++ b/libs/pbd/pbd/ringbufferNPT.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef ringbuffer_npt_h
diff --git a/libs/pbd/pbd/selectable.h b/libs/pbd/pbd/selectable.h
index 470bc3cfcc..85f3e79ab0 100644
--- a/libs/pbd/pbd/selectable.h
+++ b/libs/pbd/pbd/selectable.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __selectable_h__
diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h
index 5fbac11e5c..550db5a24e 100644
--- a/libs/pbd/pbd/stateful.h
+++ b/libs/pbd/pbd/stateful.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: stateful.h 17 2005-09-24 19:13:41Z taybin $
*/
#ifndef __pbd_stateful_h__
diff --git a/libs/pbd/pbd/stl_delete.h b/libs/pbd/pbd/stl_delete.h
index 6e5bfa0734..66fb027387 100644
--- a/libs/pbd/pbd/stl_delete.h
+++ b/libs/pbd/pbd/stl_delete.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __libmisc_stl_delete_h__
diff --git a/libs/pbd/pbd/stl_functors.h b/libs/pbd/pbd/stl_functors.h
index 4a96e91a28..3c83a1ae2f 100644
--- a/libs/pbd/pbd/stl_functors.h
+++ b/libs/pbd/pbd/stl_functors.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __stl_functors_h__
diff --git a/libs/pbd/pbd/strsplit.h b/libs/pbd/pbd/strsplit.h
index e55ad1c825..f36a3ae5f0 100644
--- a/libs/pbd/pbd/strsplit.h
+++ b/libs/pbd/pbd/strsplit.h
@@ -3,7 +3,9 @@
#include <string>
#include <vector>
+#include <glibmm/ustring.h>
extern void split (std::string, std::vector<std::string>&, char);
+extern void split (Glib::ustring, std::vector<Glib::ustring>&, char);
#endif // __pbd_strplit_h__
diff --git a/libs/pbd/pbd/textreceiver.h b/libs/pbd/pbd/textreceiver.h
index b8bfe5bc78..e5900fc652 100644
--- a/libs/pbd/pbd/textreceiver.h
+++ b/libs/pbd/pbd/textreceiver.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __libmisc_textreceiver_h__
diff --git a/libs/pbd/pbd/thrown_error.h b/libs/pbd/pbd/thrown_error.h
index 83cf8acfac..0a63085f11 100644
--- a/libs/pbd/pbd/thrown_error.h
+++ b/libs/pbd/pbd/thrown_error.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __qm_thrown_error_h__
#define __qm_thrown_error_h__
diff --git a/libs/pbd/pbd/touchable.h b/libs/pbd/pbd/touchable.h
index 0298574dfa..12f1c443fd 100644
--- a/libs/pbd/pbd/touchable.h
+++ b/libs/pbd/pbd/touchable.h
@@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __pbd_touchable_h__
diff --git a/libs/pbd/pbd/transmitter.h b/libs/pbd/pbd/transmitter.h
index 357cb9965f..61ac9bd8d8 100644
--- a/libs/pbd/pbd/transmitter.h
+++ b/libs/pbd/pbd/transmitter.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __libmisc_transmitter_h__
diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h
index 4dfab5178f..9539d8b41d 100644
--- a/libs/pbd/pbd/undo.h
+++ b/libs/pbd/pbd/undo.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __lib_pbd_undo_h__
diff --git a/libs/pbd/stacktrace.cc b/libs/pbd/stacktrace.cc
index a653fe3033..8a6eb606b2 100644
--- a/libs/pbd/stacktrace.cc
+++ b/libs/pbd/stacktrace.cc
@@ -23,7 +23,7 @@ PBD::stacktrace (std::ostream& out, int levels)
printf ("Obtained %zd stack frames.\n", size);
- for (i = 0; i < size && (levels == 0 || i < levels); i++) {
+ for (i = 0; i < size && (levels == 0 || i < size_t(levels)); i++) {
out << strings[i] << std::endl;
}
@@ -39,4 +39,10 @@ PBD::stacktrace (std::ostream& out, int levels)
out << "stack tracing is not enabled on this platform" << std::endl;
}
+void
+c_stacktrace ()
+{
+ PBD::stacktrace (std::cout);
+}
+
#endif /* HAVE_EXECINFO */
diff --git a/libs/pbd/strreplace.cc b/libs/pbd/strreplace.cc
new file mode 100644
index 0000000000..dd90baf324
--- /dev/null
+++ b/libs/pbd/strreplace.cc
@@ -0,0 +1,19 @@
+#include <pbd/replace_all.h>
+
+int
+replace_all (std::string& str,
+ std::string const& target,
+ std::string const& replacement)
+{
+ std::string::size_type start = str.find (target, 0);
+ int cnt = 0;
+
+ while (start != std::string::npos) {
+ str.replace (start, target.size(), replacement);
+ start = str.find (target, start+replacement.size());
+ ++cnt;
+ }
+
+ return cnt;
+}
+
diff --git a/libs/pbd/strsplit.cc b/libs/pbd/strsplit.cc
index 7f29a77887..1fb6112150 100644
--- a/libs/pbd/strsplit.cc
+++ b/libs/pbd/strsplit.cc
@@ -1,6 +1,7 @@
#include <pbd/strsplit.h>
using namespace std;
+using namespace Glib;
void
split (string str, vector<string>& result, char splitchar)
@@ -39,3 +40,41 @@ split (string str, vector<string>& result, char splitchar)
result.push_back (remaining);
}
}
+
+void
+split (ustring str, vector<ustring>& result, char splitchar)
+{
+ ustring::size_type pos;
+ ustring remaining;
+ ustring::size_type len = str.length();
+ int cnt;
+
+ cnt = 0;
+
+ if (str.empty()) {
+ return;
+ }
+
+ for (ustring::size_type n = 0; n < len; ++n) {
+ if (str[n] == gunichar(splitchar)) {
+ cnt++;
+ }
+ }
+
+ if (cnt == 0) {
+ result.push_back (str);
+ return;
+ }
+
+ remaining = str;
+
+ while ((pos = remaining.find_first_of (':')) != ustring::npos) {
+ result.push_back (remaining.substr (0, pos));
+ remaining = remaining.substr (pos+1);
+ }
+
+ if (remaining.length()) {
+
+ result.push_back (remaining);
+ }
+}
diff --git a/libs/sigc++2/autogen.sh b/libs/sigc++2/autogen.sh
index ebb519d373..09597765c6 100755
--- a/libs/sigc++2/autogen.sh
+++ b/libs/sigc++2/autogen.sh
@@ -1,5 +1,26 @@
#! /bin/sh
+# check all tools first
+
+if /usr/bin/which libtoolize >/dev/null 2>&1 ; then
+ :
+else
+ echo "You do not have libtool installed, which is very sadly required to build part of Ardour"
+ exit 1
+fi
+if /usr/bin/which automake >/dev/null 2>&1 ; then
+ :
+else
+ echo "You do not have automake installed, which is very sadly required to build part of Ardour"
+ exit 1
+fi
+if /usr/bin/which autoconf >/dev/null 2>&1 ; then
+ :
+else
+ echo "You do not have autoconf installed, which is very sadly required to build part of Ardour"
+ exit 1
+fi
+
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
diff --git a/libs/soundtouch/RateTransposer.cpp b/libs/soundtouch/RateTransposer.cpp
index 740d099239..493d5326f2 100644
--- a/libs/soundtouch/RateTransposer.cpp
+++ b/libs/soundtouch/RateTransposer.cpp
@@ -339,7 +339,7 @@ void RateTransposer::clear()
// Returns nonzero if there aren't any samples available for outputting.
-uint RateTransposer::isEmpty()
+int RateTransposer::isEmpty() const
{
int res;
diff --git a/libs/soundtouch/RateTransposer.h b/libs/soundtouch/RateTransposer.h
index f7c03f759e..5315d6fec3 100644
--- a/libs/soundtouch/RateTransposer.h
+++ b/libs/soundtouch/RateTransposer.h
@@ -150,7 +150,7 @@ public:
void clear();
/// Returns nonzero if there aren't any samples available for outputting.
- uint isEmpty();
+ int isEmpty() const;
};
}
diff --git a/libs/soundtouch/TDStretch.cpp b/libs/soundtouch/TDStretch.cpp
index f1b85b5f17..c71c65967f 100644
--- a/libs/soundtouch/TDStretch.cpp
+++ b/libs/soundtouch/TDStretch.cpp
@@ -114,13 +114,6 @@ TDStretch::~TDStretch()
-// Calculates the x having the closest 2^x value for the given value
-static int _getClosest2Power(double value)
-{
- return (int)(log(value) / log(2.0) + 0.5);
-}
-
-
// Sets routine control parameters. These control are certain time constants
// defining how the sound is stretched to the desired duration.
diff --git a/libs/soundtouch/cpu_detect_x86_gcc.cpp b/libs/soundtouch/cpu_detect_x86_gcc.cpp
index b4ccdc2834..b58b80fa06 100644
--- a/libs/soundtouch/cpu_detect_x86_gcc.cpp
+++ b/libs/soundtouch/cpu_detect_x86_gcc.cpp
@@ -80,6 +80,7 @@ uint detectCPUextensions(void)
if (_dwDisabledISA == 0xffffffff) return 0;
asm volatile(
+ "\n\tpushl %%ebx" // store ebx
"\n\txor %%esi, %%esi" // clear %%esi = result register
// check if 'cpuid' instructions is available by toggling eflags bit 21
@@ -128,6 +129,7 @@ uint detectCPUextensions(void)
"\n\tend:"
"\n\tmov %%esi, %0"
+ "\n\tpopl %%ebx"
: "=r" (res)
: /* no inputs */
diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc
index e6642d3394..44445192be 100644
--- a/libs/surfaces/control_protocol/basic_ui.cc
+++ b/libs/surfaces/control_protocol/basic_ui.cc
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <pbd/pthread_utils.h>
diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc
index d660c10800..1ef7a2c1b4 100644
--- a/libs/surfaces/control_protocol/control_protocol.cc
+++ b/libs/surfaces/control_protocol/control_protocol.cc
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#include <ardour/session.h>
diff --git a/libs/surfaces/control_protocol/control_protocol/basic_ui.h b/libs/surfaces/control_protocol/control_protocol/basic_ui.h
index 23b274ca01..7bc6b25c32 100644
--- a/libs/surfaces/control_protocol/control_protocol/basic_ui.h
+++ b/libs/surfaces/control_protocol/control_protocol/basic_ui.h
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __ardour_basic_ui_h__
diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
index a689d49431..c0961645ab 100644
--- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h
+++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
@@ -16,7 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef ardour_control_protocols_h
diff --git a/libs/surfaces/frontier/kernel_drivers/BUILD b/libs/surfaces/frontier/kernel_drivers/BUILD
new file mode 100644
index 0000000000..dc612e20bf
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/BUILD
@@ -0,0 +1,10 @@
+To build, type make
+
+# make install and run
+ir: install
+ rmmod tranzport
+ modprobe tranzport
+
+# make install, run, and run tests
+irt: ir
+
diff --git a/libs/surfaces/frontier/kernel_drivers/Makefile b/libs/surfaces/frontier/kernel_drivers/Makefile
new file mode 100644
index 0000000000..223fcdb6fc
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/Makefile
@@ -0,0 +1,35 @@
+ifneq ($(KERNELRELEASE),)
+
+obj-m := tranzport.o
+tranzport-objs :=
+
+else
+
+KDIR := /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+MODDIR := $(DESTDIR)/lib/modules/$(shell uname -r)/kernel/sound/usb/misc
+BINDIR := $(DESTDIR)/usr/local/bin
+
+default::
+ $(MAKE) -Wall -C $(KDIR) SUBDIRS=$(PWD) modules
+ $(MAKE) -C tests
+
+install-only:: default
+ mkdir -p $(MODDIR) $(BINDIR)
+ cp tranzport.ko $(MODDIR)
+ $(MAKE) -C tests install
+
+install:: install-only
+ /sbin/depmod -a
+ +/sbin/rmmod tranzport
+ /sbin/modprobe tranzport
+
+irt:: install
+ tranzport_tests.sh
+
+clean::
+ rm -f core .*.cmd *.o *.ko *.mod.c Module.symvers *.bak .\#* *~
+ rm -rf .tmp_versions
+ $(MAKE) -C tests clean
+
+endif
diff --git a/libs/surfaces/frontier/kernel_drivers/README b/libs/surfaces/frontier/kernel_drivers/README
new file mode 100644
index 0000000000..51b4af0f2e
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/README
@@ -0,0 +1,16 @@
+This directory contains the USB Tranzport Kernel driver for Linux.
+
+At present it accepts reads/writes of 8 byte cmds to /dev/tranzport0 to control
+the lights and screen.
+
+Reads are possible. Wheel Compression does not currently account for button changes
+
+It also has some sysfs hooks that are non-functional at the moment.
+
+The API is closely tied to the ardour revision and WILL change.
+
+A sysfs interface is PERFECT for simple userspace apps to do fun things with the
+lights and screen. It's fairly lousy for handling input events and very lousy
+for watching the state of the shuttle wheel.
+
+In the end this is going to be driven by a midi layer
diff --git a/libs/surfaces/frontier/kernel_drivers/doc/keycodes.html b/libs/surfaces/frontier/kernel_drivers/doc/keycodes.html
new file mode 100644
index 0000000000..651517a7f2
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/doc/keycodes.html
@@ -0,0 +1,35 @@
+<HTML>
+<HEAD>
+<TITLE> TRANZPORT KEYCODES REFERENCE </TITLE>
+</HEAD>
+<BODY>
+<H2> TRANZPORT KEYCODES REFERENCE </H2>
+
+<H3>Footswitch</H3>
+
+At least on every footswitch I've tried, the polarity appears to be wrong, in that the footswitch "up" position results
+in 0100 being OR'd into the result. Pressing it down results in a 0, if no other keys are pressed. Releasing it results in 0100.
+
+Every other key when up results in 0. This odd behavior would hopefully be controllable via a command to the tranzport,
+but I don't have that, so dealing with footswitch events is weird.
+
+So, seeing this bit enabled would be something like "HAVE_FOOTSWITCH INSTALLED", BE SMART ABOUT IT.
+
+
+<H3>Special Key Combinations</H3>
+<p>
+In addition to the normal keycodes generated by the tranzport, it is possible to hit several combinations of keys and get a unique
+result. Some are really weird. Perhaps the following assignments make sense:
+</p><p>
+<table><tr><th>PRESSING</th><th>RESULT</th><th>ASSIGNED TO</th></tr>
+<tr><td>TRACKLEFT+TRACKRIGHT</td><td>TRACKLEFT+TRACKRIGHT</td><td>Master</td></tr>
+<tr><td>SHIFT+TRACKLEFT+TRACKRIGHT</td><td>SHIFT+TRACKLEFT+TRACKRIGHT+UNDO</td><td>Show Bus Only Toggle</td></tr>
+<tr><td>IN+OUT</td><td>IN+OUT</td><td>Zoom 100%</td></tr>
+<tr><td>SHIFT+IN+OUT</td><td>SHIFT+IN+OUT+UNDO</td><td>Max Zoom</td></tr>
+<tr><td>SHIFT+REW+FFW</td><td>SHIFT+REW+FFW+UNDO</td><td></td></tr>
+<tr><td>RECORD+TRACKSOLO+FOOTSWITCHNOTDEPRESSED</td><td>RECORD+TRACKSOLO+BATTERY</td><td></td></tr>
+<tr><td>PLAY+MUTE</td><td>PLAY+MUTE</td><td></td></tr>
+</table>
+</p>
+</body>
+</html>
diff --git a/libs/surfaces/frontier/kernel_drivers/tests/Makefile b/libs/surfaces/frontier/kernel_drivers/tests/Makefile
new file mode 100644
index 0000000000..534bc7da4b
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/tests/Makefile
@@ -0,0 +1,23 @@
+# Some basic utilities for testing the tranzport's I/O
+# eventually "tranzport" will become a flexible command
+#
+#
+
+FILES:=tranzport tranzport_lights tranzport_tests.sh
+BINDIR ?= $(DESTDIR)/usr/local/bin
+
+all: tranzport tranzport_lights
+
+tranzport: tranzport.c
+ gcc -g -Wall -o tranzport tranzport.c
+
+tranzport_lights: tranzport_lights.c
+ gcc -g -Wall -o tranzport_lights tranzport_lights.c
+
+clean::
+ rm -f core .*.cmd *.o *.ko *.mod.c Module.symvers *.bak .\#* *~
+ rm -rf .tmp_versions tranzport tranzport_lights
+
+install::
+ cp $(FILES) $(BINDIR)
+
diff --git a/libs/surfaces/frontier/kernel_drivers/tests/README b/libs/surfaces/frontier/kernel_drivers/tests/README
new file mode 100644
index 0000000000..f9efd18f69
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/tests/README
@@ -0,0 +1,104 @@
+tranzport 0.1 <tranzport.sf.net>
+oct 18, 2005
+arthur@artcmusic.com
+---
+
+The Frontier Design Tranzport(tm) (www.frontierdesign.com) is a simple
+wireless USB device. It is not a MIDI device. The document on their web
+site "Tranzport(tm) Native Mode Interface Description" describes the
+Tranzport(tm) as if it were a MIDI device, but this is implemented by their
+Windows and Macintosh software drivers.
+
+This code will allow you to use your Tranzport(tm) at a lower level of
+abstraction. This code relies on libusb, which can be obtained from
+libusb.sourceforge.net.
+
+To compile the program, type "make". You should end up with a executable
+called "tranzport". You'll probably have to run this program as root.
+
+Using the program is straightforward. It will simply tell you which
+buttons are being pressed and what not. If you press one of the buttons
+with a light, the light will turn on. If you hold shift and press one of
+the buttons with a light, the light will turn off. If you take out the
+batteries to the device (or go out of range), it will tell you that the
+device is offline. When you replace the batteries (or come back in
+range), it should tell you it is back online.
+
+Once you understand how everything works, you should be able to
+incorporate it into your own setup however you wish.
+
+This code was developed on a Linux machine, but (theoretically) it
+should work on any system that is supported by libusb, since that is how
+it communicates with the device.
+
+Here are a few more details about the device:
+
+There are two endpoints for communication with the device. All data
+reads and writes are done in 8-byte segments.
+
+One endpoint is for interrupt reads. This is used to read button data
+from the device. It also supplies status information for when the device
+goes out of range and comes back in range, loses power and regains
+power, etc. The format of the data is:
+
+ 00 ss bb bb bb bb dd 00 (hexadecimal)
+
+where:
+
+ ss - status code, 01=online ff=offline
+ bb - button bits
+ dd - data wheel, 01-3f=forward 41-7f=backward
+
+Please refer to the source code for a list of the button bits.
+
+The other endpoint is for interrupt writes. This is used to toggle the
+lights on the device, and to write data to the LCD.
+
+There are 7 lights on the device. To turn a light on, send the following
+sequence of bytes:
+
+ 00 00 nn 01 00 00 00 00 (hexadecimal)
+
+where nn is the light number.
+
+To turn a light off:
+
+ 00 00 nn 00 00 00 00 00 (hexadecimal)
+
+Here is the list of lights:
+
+ 00 Record
+ 01 Track Rec
+ 02 Track Mute
+ 03 Track Solo
+ 04 Any Solo
+ 05 Loop
+ 06 Punch
+
+The size of the LCD is 20x2, and it is split into 10 cells, each cell
+being 4 characters wide. The cells progress across, then down. To write
+to the LCD, send the following sequence of bytes:
+
+ 00 01 cc aa aa aa aa 00 (hexadecimal)
+
+where:
+
+ cc - cell number
+ aa - ASCII code
+
+Here is a list of the cells to clarify:
+
+ 00 row 0, column 0-3
+ 01 row 0, column 4-7
+ 02 row 0, column 8-11
+ 03 row 0, column 12-15
+ 04 row 0, column 16-19
+ 05 row 1, column 0-3
+ 06 row 1, column 4-7
+ 07 row 1, column 8-11
+ 08 row 1, column 12-15
+ 09 row 1, column 16-19
+
+You should refer to the "Tranzport(tm) Native Mode Interface
+Description" document for a listing of the ASCII codes the LCD uses.
+
diff --git a/libs/surfaces/frontier/kernel_drivers/tests/tranzport.c b/libs/surfaces/frontier/kernel_drivers/tests/tranzport.c
new file mode 100644
index 0000000000..2ef5b6c910
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/tests/tranzport.c
@@ -0,0 +1,375 @@
+/*
+ * tranzport 0.1 <tranzport.sf.net>
+ * oct 18, 2005
+ * arthur@artcmusic.com
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <malloc.h>
+
+#define VENDORID 0x165b
+#define PRODUCTID 0x8101
+
+#define READ_ENDPOINT 0x81
+#define WRITE_ENDPOINT 0x02
+
+enum {
+ LIGHT_RECORD = 0,
+ LIGHT_TRACKREC,
+ LIGHT_TRACKMUTE,
+ LIGHT_TRACKSOLO,
+ LIGHT_ANYSOLO,
+ LIGHT_LOOP,
+ LIGHT_PUNCH
+};
+
+#define BUTTONMASK_BATTERY 0x00004000
+#define BUTTONMASK_BACKLIGHT 0x00008000
+#define BUTTONMASK_TRACKLEFT 0x04000000
+#define BUTTONMASK_TRACKRIGHT 0x40000000
+#define BUTTONMASK_TRACKREC 0x00040000
+#define BUTTONMASK_TRACKMUTE 0x00400000
+#define BUTTONMASK_TRACKSOLO 0x00000400
+#define BUTTONMASK_UNDO 0x80000000
+#define BUTTONMASK_IN 0x02000000
+#define BUTTONMASK_OUT 0x20000000
+#define BUTTONMASK_PUNCH 0x00800000
+#define BUTTONMASK_LOOP 0x00080000
+#define BUTTONMASK_PREV 0x00020000
+#define BUTTONMASK_ADD 0x00200000
+#define BUTTONMASK_NEXT 0x00000200
+#define BUTTONMASK_REWIND 0x01000000
+#define BUTTONMASK_FASTFORWARD 0x10000000
+#define BUTTONMASK_STOP 0x00010000
+#define BUTTONMASK_PLAY 0x00100000
+#define BUTTONMASK_RECORD 0x00000100
+#define BUTTONMASK_SHIFT 0x08000000
+
+#define STATUS_OFFLINE 0xff
+#define STATUS_ONLINE 0x01
+#define STATUS_OK 0x00
+
+struct tranzport_s {
+ int *dev;
+ int udev;
+};
+
+typedef struct tranzport_s tranzport_t;
+
+void log_entry(FILE *fp, char *format, va_list ap)
+{
+ vfprintf(fp, format, ap);
+ fputc('\n', fp);
+}
+
+void log_error(char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ log_entry(stderr, format, ap);
+ va_end(ap);
+}
+
+void vlog_error(char *format, va_list ap)
+{
+ log_entry(stderr, format, ap);
+}
+
+void die(char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlog_error(format, ap);
+ va_end(ap);
+ exit(1);
+}
+
+tranzport_t *open_tranzport_core()
+{
+ tranzport_t *z;
+ int val;
+
+ z = malloc(sizeof(tranzport_t));
+ if (!z)
+ die("not enough memory");
+ memset(z, 0, sizeof(tranzport_t));
+
+ z->udev = open("/dev/tranzport0",O_RDWR);
+ if (z->udev < 1)
+ die("unable to open tranzport");
+
+ return z;
+}
+
+tranzport_t *open_tranzport()
+{
+return open_tranzport_core();
+}
+
+void close_tranzport(tranzport_t *z)
+{
+ int val;
+
+ val = close(z->udev);
+ if (val < 0)
+ log_error("unable to release tranzport");
+
+ free(z);
+}
+
+int tranzport_write_core(tranzport_t *z, uint8_t *cmd, int timeout)
+{
+ int val;
+ val = write(z->udev, cmd, 8);
+ if (val < 0)
+ return val;
+ if (val != 8)
+ return -1;
+ return 0;
+}
+
+int tranzport_lcdwrite(tranzport_t *z, uint8_t cell, char *text, int timeout)
+{
+ uint8_t cmd[8];
+
+ if (cell > 9) {
+ return -1;
+ }
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x01;
+ cmd[2] = cell;
+ cmd[3] = text[0];
+ cmd[4] = text[1];
+ cmd[5] = text[2];
+ cmd[6] = text[3];
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, cmd, timeout);
+}
+
+int tranzport_lighton(tranzport_t *z, uint8_t light, int timeout)
+{
+ uint8_t cmd[8];
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ cmd[2] = light;
+ cmd[3] = 0x01;
+ cmd[4] = 0x00;
+ cmd[5] = 0x00;
+ cmd[6] = 0x00;
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, &cmd[0], timeout);
+}
+
+int tranzport_lightoff(tranzport_t *z, uint8_t light, int timeout)
+{
+ uint8_t cmd[8];
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ cmd[2] = light;
+ cmd[3] = 0x00;
+ cmd[4] = 0x00;
+ cmd[5] = 0x00;
+ cmd[6] = 0x00;
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, &cmd[0], timeout);
+}
+
+int tranzport_read(tranzport_t *z, uint8_t *status, uint32_t *buttons, uint8_t *datawheel, int timeout)
+{
+ uint8_t buf[8];
+ int val;
+
+ memset(buf, 0xff, 8);
+ val = read(z->udev, buf, 8);
+ if (val < 0) {
+ printf("errno: %d\n",errno);
+ switch(errno) {
+ case ENOENT: ;
+ case ECONNRESET: ;
+ case ESHUTDOWN: printf("dying\n"); exit(1); break;
+ }
+ return val;
+ }
+ if (val != 8)
+ return -1;
+
+ /*printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/
+
+ *status = buf[1];
+
+ *buttons = 0;
+ *buttons |= buf[2] << 24;
+ *buttons |= buf[3] << 16;
+ *buttons |= buf[4] << 8;
+ *buttons |= buf[5];
+
+ *datawheel = buf[6];
+
+ return 0;
+}
+
+void lights_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, uint8_t light)
+{
+ if (buttons & buttonmask) {
+ if (buttons & BUTTONMASK_SHIFT) {
+ tranzport_lightoff(z, light, 10);
+ } else {
+ tranzport_lighton(z, light, 10);
+ }
+ }
+}
+
+void do_lights(tranzport_t *z, uint32_t buttons)
+{
+ lights_core(z, buttons, BUTTONMASK_RECORD, LIGHT_RECORD);
+ lights_core(z, buttons, BUTTONMASK_TRACKREC, LIGHT_TRACKREC);
+ lights_core(z, buttons, BUTTONMASK_TRACKMUTE, LIGHT_TRACKMUTE);
+ lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_TRACKSOLO);
+ lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_ANYSOLO);
+ lights_core(z, buttons, BUTTONMASK_PUNCH, LIGHT_PUNCH);
+ lights_core(z, buttons, BUTTONMASK_LOOP, LIGHT_LOOP);
+}
+
+void buttons_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, char *str)
+{
+ if (buttons & buttonmask)
+ printf(" %s", str);
+}
+
+void do_buttons(tranzport_t *z, uint32_t buttons, uint8_t datawheel)
+{
+ printf("buttons: %x ", buttons);
+ buttons_core(z, buttons, BUTTONMASK_BATTERY, "battery");
+ buttons_core(z, buttons, BUTTONMASK_BACKLIGHT, "backlight");
+ buttons_core(z, buttons, BUTTONMASK_TRACKLEFT, "trackleft");
+ buttons_core(z, buttons, BUTTONMASK_TRACKRIGHT, "trackright");
+ buttons_core(z, buttons, BUTTONMASK_TRACKREC, "trackrec");
+ buttons_core(z, buttons, BUTTONMASK_TRACKMUTE, "trackmute");
+ buttons_core(z, buttons, BUTTONMASK_TRACKSOLO, "tracksolo");
+ buttons_core(z, buttons, BUTTONMASK_UNDO, "undo");
+ buttons_core(z, buttons, BUTTONMASK_IN, "in");
+ buttons_core(z, buttons, BUTTONMASK_OUT, "out");
+ buttons_core(z, buttons, BUTTONMASK_PUNCH, "punch");
+ buttons_core(z, buttons, BUTTONMASK_LOOP, "loop");
+ buttons_core(z, buttons, BUTTONMASK_PREV, "prev");
+ buttons_core(z, buttons, BUTTONMASK_ADD, "add");
+ buttons_core(z, buttons, BUTTONMASK_NEXT, "next");
+ buttons_core(z, buttons, BUTTONMASK_REWIND, "rewind");
+ buttons_core(z, buttons, BUTTONMASK_FASTFORWARD, "fastforward");
+ buttons_core(z, buttons, BUTTONMASK_STOP, "stop");
+ buttons_core(z, buttons, BUTTONMASK_PLAY, "play");
+ buttons_core(z, buttons, BUTTONMASK_RECORD, "record");
+ buttons_core(z, buttons, BUTTONMASK_SHIFT, "shift");
+ if (datawheel)
+ printf(" datawheel=%02x", datawheel);
+ printf("\n");
+}
+
+void do_lcd(tranzport_t *z)
+{
+ tranzport_lcdwrite(z, 0, " ", 10);
+ tranzport_lcdwrite(z, 1, "DISL", 10);
+ tranzport_lcdwrite(z, 2, "EXIA", 10);
+ tranzport_lcdwrite(z, 3, " FOR", 10);
+ tranzport_lcdwrite(z, 4, " ", 10);
+
+ tranzport_lcdwrite(z, 5, " ", 10);
+ tranzport_lcdwrite(z, 6, " CUR", 10);
+ tranzport_lcdwrite(z, 7, "E FO", 10);
+ tranzport_lcdwrite(z, 8, "UND ", 10);
+ tranzport_lcdwrite(z, 9, " ", 10);
+}
+
+void do_lcd2(tranzport_t *z)
+{
+ tranzport_lcdwrite(z, 0, "THE ", 10);
+ tranzport_lcdwrite(z, 1, "TRAN", 10);
+ tranzport_lcdwrite(z, 2, "ZPOR", 10);
+ tranzport_lcdwrite(z, 3, "T RO", 10);
+ tranzport_lcdwrite(z, 4, " KS", 10);
+
+ tranzport_lcdwrite(z, 5, "AWES", 10);
+ tranzport_lcdwrite(z, 6, "OMEE", 10);
+ tranzport_lcdwrite(z, 7, "LEEE", 10);
+ tranzport_lcdwrite(z, 8, "UND ", 10);
+ tranzport_lcdwrite(z, 9, "GROK", 10);
+}
+
+int lights_off(tranzport_t *z) {
+ static int i = 0;
+ int j = 0;
+ for(;j<2; j++,i = (i+1) % 7) {
+ tranzport_lightoff(z, i, 10);
+ }
+return 0;
+}
+
+int lights_on(tranzport_t *z) {
+ static int i = 0;
+ int j = 0;
+ for(;j<2; j++,i = (i+1) % 7) {
+ tranzport_lighton(z, i, 10);
+ }
+return 0;
+}
+
+int main()
+{
+ tranzport_t *z;
+ uint8_t status;
+ uint32_t buttons;
+ uint8_t datawheel;
+ int val;
+
+ z = open_tranzport();
+
+ do_lcd(z);
+
+ for(;;) {
+
+ // do_lcd(z);
+ lights_on(z);
+ // do_lcd2(z);
+
+ val = tranzport_read(z, &status, &buttons, &datawheel, 60000);
+ if (val < 0)
+ continue;
+
+ if (status == STATUS_OFFLINE) {
+ printf("offline: ");
+ continue;
+ }
+
+ if (status == STATUS_ONLINE) {
+ printf("online: ");
+ do_lcd(z);
+ }
+
+ if (status == STATUS_OK) {
+ printf("OK: ");
+ do_lcd(z);
+ }
+
+// do_lights(z, buttons);
+ do_buttons(z, buttons, datawheel);
+ lights_off(z);
+ }
+
+ close_tranzport(z);
+
+ return 0;
+}
+
diff --git a/libs/surfaces/frontier/kernel_drivers/tests/tranzport_lights.c b/libs/surfaces/frontier/kernel_drivers/tests/tranzport_lights.c
new file mode 100644
index 0000000000..4096ee680d
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/tests/tranzport_lights.c
@@ -0,0 +1,361 @@
+/*
+ * tranzport 0.1 <tranzport.sf.net>
+ * oct 18, 2005
+ * arthur@artcmusic.com
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <malloc.h>
+
+#define VENDORID 0x165b
+#define PRODUCTID 0x8101
+
+#define READ_ENDPOINT 0x81
+#define WRITE_ENDPOINT 0x02
+
+enum {
+ LIGHT_RECORD = 0,
+ LIGHT_TRACKREC,
+ LIGHT_TRACKMUTE,
+ LIGHT_TRACKSOLO,
+ LIGHT_ANYSOLO,
+ LIGHT_LOOP,
+ LIGHT_PUNCH
+};
+
+#define BUTTONMASK_BATTERY 0x00004000
+#define BUTTONMASK_BACKLIGHT 0x00008000
+#define BUTTONMASK_TRACKLEFT 0x04000000
+#define BUTTONMASK_TRACKRIGHT 0x40000000
+#define BUTTONMASK_TRACKREC 0x00040000
+#define BUTTONMASK_TRACKMUTE 0x00400000
+#define BUTTONMASK_TRACKSOLO 0x00000400
+#define BUTTONMASK_UNDO 0x80000000
+#define BUTTONMASK_IN 0x02000000
+#define BUTTONMASK_OUT 0x20000000
+#define BUTTONMASK_PUNCH 0x00800000
+#define BUTTONMASK_LOOP 0x00080000
+#define BUTTONMASK_PREV 0x00020000
+#define BUTTONMASK_ADD 0x00200000
+#define BUTTONMASK_NEXT 0x00000200
+#define BUTTONMASK_REWIND 0x01000000
+#define BUTTONMASK_FASTFORWARD 0x10000000
+#define BUTTONMASK_STOP 0x00010000
+#define BUTTONMASK_PLAY 0x00100000
+#define BUTTONMASK_RECORD 0x00000100
+#define BUTTONMASK_SHIFT 0x08000000
+
+#define STATUS_OFFLINE 0xff
+#define STATUS_ONLINE 0x01
+#define STATUS_OK 0x00
+
+struct tranzport_s {
+ int *dev;
+ int udev;
+};
+
+typedef struct tranzport_s tranzport_t;
+
+void log_entry(FILE *fp, char *format, va_list ap)
+{
+ vfprintf(fp, format, ap);
+ fputc('\n', fp);
+}
+
+void log_error(char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ log_entry(stderr, format, ap);
+ va_end(ap);
+}
+
+void vlog_error(char *format, va_list ap)
+{
+ log_entry(stderr, format, ap);
+}
+
+void die(char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlog_error(format, ap);
+ va_end(ap);
+ exit(1);
+}
+
+tranzport_t *open_tranzport_core()
+{
+ tranzport_t *z;
+ int val;
+
+ z = malloc(sizeof(tranzport_t));
+ if (!z)
+ die("not enough memory");
+ memset(z, 0, sizeof(tranzport_t));
+
+ z->udev = open("/dev/tranzport0",O_RDWR);
+ if (!z->udev)
+ die("unable to open tranzport");
+
+ return z;
+}
+
+tranzport_t *open_tranzport()
+{
+return open_tranzport_core();
+}
+
+void close_tranzport(tranzport_t *z)
+{
+ int val;
+
+ val = close(z->udev);
+ if (val < 0)
+ log_error("unable to release tranzport");
+
+ free(z);
+}
+
+int tranzport_write_core(tranzport_t *z, uint8_t *cmd, int timeout)
+{
+ int val;
+ val = write(z->udev, cmd, 8);
+ if (val < 0)
+ return val;
+ if (val != 8)
+ return -1;
+ return 0;
+}
+
+int tranzport_lcdwrite(tranzport_t *z, uint8_t cell, char *text, int timeout)
+{
+ uint8_t cmd[8];
+
+ if (cell > 9) {
+ return -1;
+ }
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x01;
+ cmd[2] = cell;
+ cmd[3] = text[0];
+ cmd[4] = text[1];
+ cmd[5] = text[2];
+ cmd[6] = text[3];
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, cmd, timeout);
+}
+
+int tranzport_lighton(tranzport_t *z, uint8_t light, int timeout)
+{
+ uint8_t cmd[8];
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ cmd[2] = light;
+ cmd[3] = 0x01;
+ cmd[4] = 0x00;
+ cmd[5] = 0x00;
+ cmd[6] = 0x00;
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, &cmd[0], timeout);
+}
+
+int tranzport_lightoff(tranzport_t *z, uint8_t light, int timeout)
+{
+ uint8_t cmd[8];
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ cmd[2] = light;
+ cmd[3] = 0x00;
+ cmd[4] = 0x00;
+ cmd[5] = 0x00;
+ cmd[6] = 0x00;
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, &cmd[0], timeout);
+}
+
+int tranzport_read(tranzport_t *z, uint8_t *status, uint32_t *buttons, uint8_t *datawheel, int timeout)
+{
+ uint8_t buf[8];
+ int val;
+
+ memset(buf, 0xff, 8);
+ val = read(z->udev, buf, 8);
+ if (val < 0) {
+ // printf("errno: %d\n",errno);
+ return val;
+ }
+ if (val != 8)
+ return -1;
+
+ /*printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/
+
+ *status = buf[1];
+
+ *buttons = 0;
+ *buttons |= buf[2] << 24;
+ *buttons |= buf[3] << 16;
+ *buttons |= buf[4] << 8;
+ *buttons |= buf[5];
+
+ *datawheel = buf[6];
+
+ return 0;
+}
+
+void lights_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, uint8_t light)
+{
+ if (buttons & buttonmask) {
+ if (buttons & BUTTONMASK_SHIFT) {
+ tranzport_lightoff(z, light, 1000);
+ } else {
+ tranzport_lighton(z, light, 1000);
+ }
+ }
+}
+
+void do_lights(tranzport_t *z, uint32_t buttons)
+{
+ lights_core(z, buttons, BUTTONMASK_RECORD, LIGHT_RECORD);
+ lights_core(z, buttons, BUTTONMASK_TRACKREC, LIGHT_TRACKREC);
+ lights_core(z, buttons, BUTTONMASK_TRACKMUTE, LIGHT_TRACKMUTE);
+ lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_TRACKSOLO);
+ lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_ANYSOLO);
+ lights_core(z, buttons, BUTTONMASK_PUNCH, LIGHT_PUNCH);
+ lights_core(z, buttons, BUTTONMASK_LOOP, LIGHT_LOOP);
+}
+
+void buttons_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, char *str)
+{
+ if (buttons & buttonmask)
+ printf(" %s", str);
+}
+
+void do_buttons(tranzport_t *z, uint32_t buttons, uint8_t datawheel)
+{
+ printf("buttons: %x ", buttons);
+ buttons_core(z, buttons, BUTTONMASK_BATTERY, "battery");
+ buttons_core(z, buttons, BUTTONMASK_BACKLIGHT, "backlight");
+ buttons_core(z, buttons, BUTTONMASK_TRACKLEFT, "trackleft");
+ buttons_core(z, buttons, BUTTONMASK_TRACKRIGHT, "trackright");
+ buttons_core(z, buttons, BUTTONMASK_TRACKREC, "trackrec");
+ buttons_core(z, buttons, BUTTONMASK_TRACKMUTE, "trackmute");
+ buttons_core(z, buttons, BUTTONMASK_TRACKSOLO, "tracksolo");
+ buttons_core(z, buttons, BUTTONMASK_UNDO, "undo");
+ buttons_core(z, buttons, BUTTONMASK_IN, "in");
+ buttons_core(z, buttons, BUTTONMASK_OUT, "out");
+ buttons_core(z, buttons, BUTTONMASK_PUNCH, "punch");
+ buttons_core(z, buttons, BUTTONMASK_LOOP, "loop");
+ buttons_core(z, buttons, BUTTONMASK_PREV, "prev");
+ buttons_core(z, buttons, BUTTONMASK_ADD, "add");
+ buttons_core(z, buttons, BUTTONMASK_NEXT, "next");
+ buttons_core(z, buttons, BUTTONMASK_REWIND, "rewind");
+ buttons_core(z, buttons, BUTTONMASK_FASTFORWARD, "fastforward");
+ buttons_core(z, buttons, BUTTONMASK_STOP, "stop");
+ buttons_core(z, buttons, BUTTONMASK_PLAY, "play");
+ buttons_core(z, buttons, BUTTONMASK_RECORD, "record");
+ buttons_core(z, buttons, BUTTONMASK_SHIFT, "shift");
+ if (datawheel)
+ printf(" datawheel=%02x", datawheel);
+ printf("\n");
+}
+
+void do_lcd(tranzport_t *z)
+{
+ tranzport_lcdwrite(z, 0, " ", 1000);
+ tranzport_lcdwrite(z, 1, "DISL", 1000);
+ tranzport_lcdwrite(z, 2, "EXIA", 1000);
+ tranzport_lcdwrite(z, 3, " FOR", 1000);
+ tranzport_lcdwrite(z, 4, " ", 1000);
+
+ tranzport_lcdwrite(z, 5, " ", 1000);
+ tranzport_lcdwrite(z, 6, " CUR", 1000);
+ tranzport_lcdwrite(z, 7, "E FO", 1000);
+ tranzport_lcdwrite(z, 8, "UND ", 1000);
+ tranzport_lcdwrite(z, 9, " ", 1000);
+}
+
+void do_lcd2(tranzport_t *z)
+{
+ tranzport_lcdwrite(z, 0, "THE ", 1000);
+ tranzport_lcdwrite(z, 1, "TRAN", 1000);
+ tranzport_lcdwrite(z, 2, "ZPOR", 1000);
+ tranzport_lcdwrite(z, 3, "T RO", 1000);
+ tranzport_lcdwrite(z, 4, "KS ", 1000);
+
+ tranzport_lcdwrite(z, 5, "AWES", 1000);
+ tranzport_lcdwrite(z, 6, "OMEE", 1000);
+ tranzport_lcdwrite(z, 7, "LEEE", 1000);
+ tranzport_lcdwrite(z, 8, "WITH", 1000);
+ tranzport_lcdwrite(z, 9, "ARDO", 1000);
+}
+
+lights_off(tranzport_t *z) {
+int i;
+ for(i=0;i<7;i++) {
+ tranzport_lightoff(z, i, 1000);
+ }
+}
+
+lights_on(tranzport_t *z) {
+int i;
+ for(i=0;i<7;i++) {
+ tranzport_lighton(z, i, 1000);
+ }
+}
+
+int main()
+{
+ tranzport_t *z;
+ uint8_t status;
+ uint32_t buttons;
+ uint8_t datawheel;
+ int val;
+
+ z = open_tranzport();
+
+ do_lcd(z);
+
+ for(;;) {
+
+ do_lcd(z);
+ lights_on(z);
+ do_lcd2(z);
+ lights_off(z);
+
+// val = tranzport_read(z, &status, &buttons, &datawheel, 60000);
+ val = -1;
+ if (val < 0)
+ continue;
+
+ if (status == STATUS_OFFLINE) {
+ printf("offline: ");
+ continue;
+ }
+
+ if (status == STATUS_ONLINE) {
+ printf("online: ");
+ do_lcd(z);
+ }
+
+ do_lights(z, buttons);
+ do_buttons(z, buttons, datawheel);
+ }
+
+ close_tranzport(z);
+
+ return 0;
+}
+
diff --git a/libs/surfaces/frontier/kernel_drivers/tests/tranzport_tests.sh b/libs/surfaces/frontier/kernel_drivers/tests/tranzport_tests.sh
new file mode 100755
index 0000000000..540c62fe16
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/tests/tranzport_tests.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+echo "Testing lights"
+tranzport_lights &
+A=$!
+sleep 30
+kill $A
+echo "Testing interleaved_reads/writes"
+tranzport &
+A=$!
+sleep 30
+kill $A
+
+exit 0
+
+# not done yet
+echo "Testing_screen"
+tranzport_screen &
+A=$!
+sleep 30
+kill $A
+echo "Testing_reads"
+tranzport_read &
+A=$!
+sleep 30
+kill $A
+
diff --git a/libs/surfaces/frontier/kernel_drivers/tranzport.c b/libs/surfaces/frontier/kernel_drivers/tranzport.c
new file mode 100644
index 0000000000..6893f66921
--- /dev/null
+++ b/libs/surfaces/frontier/kernel_drivers/tranzport.c
@@ -0,0 +1,1065 @@
+/*
+ * Frontier Designs Tranzport driver
+ *
+ * Copyright (C) 2007 Michael Taht (m@taht.net)
+ *
+ * Based on the usbled driver and ldusb drivers by
+ *
+ * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
+ *
+ * The ldusb driver was, in turn, derived from Lego USB Tower driver
+ * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net>
+ * 2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+/**
+ * This driver uses a ring buffer for time critical reading of
+ * interrupt in reports and provides read and write methods for
+ * raw interrupt reports.
+ */
+
+/* Note: this currently uses a dumb ringbuffer for reads and writes.
+ * A more optimal driver would cache and kill off outstanding urbs that are
+ * now invalid, and ignore ones that already were in the queue but valid
+ * as we only have 17 commands for the tranzport. In particular this is
+ * key for getting lights to flash in time as otherwise many commands
+ * can be buffered up before the light change makes it to the interface.
+*/
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/version.h>
+
+#include <asm/uaccess.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+
+/* Define these values to match your devices */
+#define VENDOR_ID 0x165b
+#define PRODUCT_ID 0x8101
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define USB_TRANZPORT_MINOR_BASE 0
+#else
+// FIXME 176 - is the ldusb driver's minor - apply for that
+#define USB_TRANZPORT_MINOR_BASE 176
+#endif
+
+/* table of devices that work with this driver */
+static struct usb_device_id usb_tranzport_table [] = {
+ { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, usb_tranzport_table);
+MODULE_VERSION("0.29");
+MODULE_AUTHOR("Mike Taht <m@taht.net>");
+MODULE_DESCRIPTION("Tranzport USB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("Frontier Designs Control Surface");
+
+
+/* make this work on older kernel versions */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+
+static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+ return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_INT);
+}
+
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+
+static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+
+static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
+{
+ return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
+}
+
+#endif /* older kernel versions */
+
+/* These two aren't done yet */
+
+#define SUPPRESS_EXTRA_ONLINE_EVENTS 0
+#define BUFFERED_WRITES 0
+
+#define SUPPRESS_EXTRA_OFFLINE_EVENTS 1
+#define COMPRESS_WHEEL_EVENTS 1
+#define BUFFERED_READS 1
+#define RING_BUFFER_SIZE 1000
+#define WRITE_BUFFER_SIZE 34
+#define TRANZPORT_USB_TIMEOUT 10
+
+
+static int debug = 0;
+
+/* Use our own dbg macro */
+#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
+
+/* Module parameters */
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+/* All interrupt in transfers are collected in a ring buffer to
+ * avoid racing conditions and get better performance of the driver.
+ */
+
+static int ring_buffer_size = RING_BUFFER_SIZE;
+
+module_param(ring_buffer_size, int, S_IRUGO);
+MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports");
+
+/* The write_buffer can one day contain more than one interrupt out transfer.
+ */
+static int write_buffer_size = WRITE_BUFFER_SIZE;
+module_param(write_buffer_size, int, S_IRUGO);
+MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
+
+/*
+ * Increase the interval for debugging purposes.
+ * or set to 1 to use the standard interval from the endpoint descriptors.
+ */
+
+static int min_interrupt_in_interval = TRANZPORT_USB_TIMEOUT;
+module_param(min_interrupt_in_interval, int, 0);
+MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms");
+
+static int min_interrupt_out_interval = TRANZPORT_USB_TIMEOUT;
+module_param(min_interrupt_out_interval, int, 0);
+MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms");
+
+struct tranzport_cmd {
+ unsigned char cmd[8];
+};
+
+/* Structure to hold all of our device specific stuff */
+struct usb_tranzport {
+ struct semaphore sem; /* locks this structure */
+ struct usb_interface* intf; /* save off the usb interface pointer */
+
+ int open_count; /* number of times this port has been opened */
+
+ struct tranzport_cmd (*ring_buffer)[RING_BUFFER_SIZE]; /* just make c happy */
+ unsigned int ring_head;
+ unsigned int ring_tail;
+
+ wait_queue_head_t read_wait;
+ wait_queue_head_t write_wait;
+
+ unsigned char* interrupt_in_buffer;
+ struct usb_endpoint_descriptor* interrupt_in_endpoint;
+ struct urb* interrupt_in_urb;
+ int interrupt_in_interval;
+ size_t interrupt_in_endpoint_size;
+ int interrupt_in_running;
+ int interrupt_in_done;
+
+ char* interrupt_out_buffer;
+ struct usb_endpoint_descriptor* interrupt_out_endpoint;
+ struct urb* interrupt_out_urb;
+ int interrupt_out_interval;
+ size_t interrupt_out_endpoint_size;
+ int interrupt_out_busy;
+
+ /* Sysfs support - most of these are not hooked up yet */
+
+ int event; /* alternate interface to events */
+ int wheel; /* - for negative, 0 for none, + for positive */
+ int lights;
+ unsigned char dump_state; /* 0 if disabled 1 if enabled */
+ unsigned char enable; /* 0 if disabled 1 if enabled */
+ unsigned char offline; /* if the device is out of range or asleep */
+ unsigned char compress_wheel; /* flag to compress wheel events */
+ unsigned char LightRecord;
+ unsigned char LightTrackrec;
+ unsigned char LightTrackmute;
+ unsigned char LightTracksolo;
+ unsigned char LightAnysolo;
+ unsigned char LightLoop;
+ unsigned char LightPunch;
+ unsigned char last_cmd[8];
+ unsigned char screen[40]; // We'll also have cells
+
+};
+
+/* prevent races between open() and disconnect() */
+static DEFINE_MUTEX(disconnect_mutex);
+
+static struct usb_driver usb_tranzport_driver;
+
+/**
+ * usb_tranzport_abort_transfers
+ * aborts transfers and frees associated data structures
+ */
+static void usb_tranzport_abort_transfers(struct usb_tranzport *dev)
+{
+ /* shutdown transfer */
+ if (dev->interrupt_in_running) {
+ dev->interrupt_in_running = 0;
+ if (dev->intf)
+ usb_kill_urb(dev->interrupt_in_urb);
+ }
+ if (dev->interrupt_out_busy)
+ if (dev->intf)
+ usb_kill_urb(dev->interrupt_out_urb);
+}
+
+#define show_set_light(value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ \
+ return sprintf(buf, "%d\n", t->value); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ \
+ t->value = temp; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+show_set_light(LightRecord);
+show_set_light(LightTrackrec);
+show_set_light(LightTrackmute);
+show_set_light(LightTracksolo);
+show_set_light(LightAnysolo);
+show_set_light(LightLoop);
+show_set_light(LightPunch);
+
+show_set_light(enable);
+show_set_light(offline);
+show_set_light(compress_wheel);
+show_set_light(dump_state);
+
+#define show_set_int(value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ \
+ return sprintf(buf, "%d\n", t->value); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ \
+ t->value = temp; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+show_set_int(wheel);
+show_set_int(event);
+
+#define show_set_cmd(value) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ \
+ return sprintf(buf, "%d\n", t->value); \
+} \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ struct usb_interface *intf = to_usb_interface(dev); \
+ struct usb_tranzport *t = usb_get_intfdata(intf); \
+ int temp = simple_strtoul(buf, NULL, 10); \
+ \
+ t->value = temp; \
+ return count; \
+} \
+static DEVICE_ATTR(value, S_IWUGO | S_IRUGO, show_##value, set_##value);
+
+
+
+
+/**
+ * usb_tranzport_delete
+ */
+static void usb_tranzport_delete(struct usb_tranzport *dev)
+{
+ usb_tranzport_abort_transfers(dev);
+ /* This is just too twisted to be correct */
+ if(dev->intf != NULL) {
+ device_remove_file(&dev->intf->dev, &dev_attr_LightRecord);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightTrackrec);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightTrackmute);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightTracksolo);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightTrackmute);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightAnysolo);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightLoop);
+ device_remove_file(&dev->intf->dev, &dev_attr_LightPunch);
+ device_remove_file(&dev->intf->dev, &dev_attr_wheel);
+ device_remove_file(&dev->intf->dev, &dev_attr_enable);
+ device_remove_file(&dev->intf->dev, &dev_attr_event);
+ device_remove_file(&dev->intf->dev, &dev_attr_offline);
+ device_remove_file(&dev->intf->dev, &dev_attr_compress_wheel);
+
+ device_remove_file(&dev->intf->dev, &dev_attr_dump_state);
+ }
+
+ /* free data structures */
+ usb_free_urb(dev->interrupt_in_urb);
+ usb_free_urb(dev->interrupt_out_urb);
+ kfree(dev->ring_buffer);
+ kfree(dev->interrupt_in_buffer);
+ kfree(dev->interrupt_out_buffer);
+ kfree(dev);
+}
+
+/**
+ * usb_tranzport_interrupt_in_callback
+ */
+
+static void usb_tranzport_interrupt_in_callback(struct urb *urb)
+{
+ struct usb_tranzport *dev = urb->context;
+ unsigned int next_ring_head;
+ int retval = -1;
+
+ if (urb->status) {
+ if (urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN) {
+ goto exit;
+ } else {
+ dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
+ __FUNCTION__, urb->status);
+ goto resubmit; /* maybe we can recover */
+ }
+ }
+
+ if (urb->actual_length != 8) {
+ dev_warn(&dev->intf->dev,
+ "Urb length was %d bytes!! Do something intelligent \n", urb->actual_length);
+ } else {
+ dbg_info(&dev->intf->dev, "%s: received: %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ __FUNCTION__, dev->interrupt_in_buffer[0],dev->interrupt_in_buffer[1],dev->interrupt_in_buffer[2],dev->interrupt_in_buffer[3],dev->interrupt_in_buffer[4],dev->interrupt_in_buffer[5],dev->interrupt_in_buffer[6],dev->interrupt_in_buffer[7]);
+#if SUPPRESS_EXTRA_OFFLINE_EVENTS
+ if(dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff) { goto resubmit; }
+ if(dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 2; goto resubmit; }
+
+/* Always pass one offline event up the stack */
+ if(dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff) { dev->offline = 0; }
+ if(dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff) { dev->offline = 1; }
+
+#endif
+ dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail);
+
+ next_ring_head = (dev->ring_head+1) % ring_buffer_size;
+
+ if (next_ring_head != dev->ring_tail) {
+ memcpy(&((*dev->ring_buffer)[dev->ring_head]), dev->interrupt_in_buffer, urb->actual_length);
+ dev->ring_head = next_ring_head;
+ retval = 0;
+ memset(dev->interrupt_in_buffer, 0, urb->actual_length);
+ } else {
+ dev_warn(&dev->intf->dev,
+ "Ring buffer overflow, %d bytes dropped\n",
+ urb->actual_length);
+ memset(dev->interrupt_in_buffer, 0, urb->actual_length);
+ }
+ }
+
+resubmit:
+ /* resubmit if we're still running */
+ if (dev->interrupt_in_running && dev->intf) {
+ retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&dev->intf->dev,
+ "usb_submit_urb failed (%d)\n", retval);
+ }
+
+exit:
+ dev->interrupt_in_done = 1;
+ wake_up_interruptible(&dev->read_wait);
+}
+
+/**
+ * usb_tranzport_interrupt_out_callback
+ */
+static void usb_tranzport_interrupt_out_callback(struct urb *urb)
+{
+ struct usb_tranzport *dev = urb->context;
+
+ /* sync/async unlink faults aren't errors */
+ if (urb->status && !(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ dbg_info(&dev->intf->dev,
+ "%s - nonzero write interrupt status received: %d\n",
+ __FUNCTION__, urb->status);
+
+ dev->interrupt_out_busy = 0;
+ wake_up_interruptible(&dev->write_wait);
+}
+
+/**
+ * usb_tranzport_open
+ */
+static int usb_tranzport_open(struct inode *inode, struct file *file)
+{
+ struct usb_tranzport *dev;
+ int subminor;
+ int retval = 0;
+ struct usb_interface *interface;
+
+ nonseekable_open(inode, file);
+ subminor = iminor(inode);
+
+ mutex_lock(&disconnect_mutex);
+
+ interface = usb_find_interface(&usb_tranzport_driver, subminor);
+
+ if (!interface) {
+ err("%s - error, can't find device for minor %d\n",
+ __FUNCTION__, subminor);
+ retval = -ENODEV;
+ goto unlock_disconnect_exit;
+ }
+
+ dev = usb_get_intfdata(interface);
+
+ if (!dev) {
+ retval = -ENODEV;
+ goto unlock_disconnect_exit;
+ }
+
+ /* lock this device */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto unlock_disconnect_exit;
+ }
+
+ /* allow opening only once */
+ if (dev->open_count) {
+ retval = -EBUSY;
+ goto unlock_exit;
+ }
+ dev->open_count = 1;
+
+ /* initialize in direction */
+ dev->ring_head = 0;
+ dev->ring_tail = 0;
+ usb_fill_int_urb(dev->interrupt_in_urb,
+ interface_to_usbdev(interface),
+ usb_rcvintpipe(interface_to_usbdev(interface),
+ dev->interrupt_in_endpoint->bEndpointAddress),
+ dev->interrupt_in_buffer,
+ dev->interrupt_in_endpoint_size,
+ usb_tranzport_interrupt_in_callback,
+ dev,
+ dev->interrupt_in_interval);
+
+ dev->interrupt_in_running = 1;
+ dev->interrupt_in_done = 0;
+ dev->enable = 1;
+ dev->offline = 0;
+ dev->compress_wheel = 1;
+
+ retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval);
+ dev->interrupt_in_running = 0;
+ dev->open_count = 0;
+ goto unlock_exit;
+ }
+
+ /* save device in the file's private structure */
+ file->private_data = dev;
+
+
+unlock_exit:
+ up(&dev->sem);
+
+unlock_disconnect_exit:
+ mutex_unlock(&disconnect_mutex);
+
+ return retval;
+}
+
+/**
+ * usb_tranzport_release
+ */
+static int usb_tranzport_release(struct inode *inode, struct file *file)
+{
+ struct usb_tranzport *dev;
+ int retval = 0;
+
+ dev = file->private_data;
+
+ if (dev == NULL) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ if (dev->open_count != 1) {
+ retval = -ENODEV;
+ goto unlock_exit;
+ }
+
+ if (dev->intf == NULL) {
+ /* the device was unplugged before the file was released */
+ up(&dev->sem);
+ /* unlock here as usb_tranzport_delete frees dev */
+ usb_tranzport_delete(dev);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ /* wait until write transfer is finished */
+ if (dev->interrupt_out_busy)
+ wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ);
+ usb_tranzport_abort_transfers(dev);
+ dev->open_count = 0;
+
+unlock_exit:
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/**
+ * usb_tranzport_poll
+ */
+static unsigned int usb_tranzport_poll(struct file *file, poll_table *wait)
+{
+ struct usb_tranzport *dev;
+ unsigned int mask = 0;
+
+ dev = file->private_data;
+
+ poll_wait(file, &dev->read_wait, wait);
+ poll_wait(file, &dev->write_wait, wait);
+
+ if (dev->ring_head != dev->ring_tail)
+ mask |= POLLIN | POLLRDNORM;
+ if (!dev->interrupt_out_busy)
+ mask |= POLLOUT | POLLWRNORM;
+
+ return mask;
+}
+
+/**
+ * usb_tranzport_read
+ */
+static ssize_t usb_tranzport_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *ppos)
+{
+ struct usb_tranzport *dev;
+ size_t bytes_to_read;
+ int retval = 0;
+
+#if BUFFERED_READS
+ int c = 0;
+#endif
+
+#if COMPRESS_WHEEL_EVENTS
+ signed char oldwheel;
+ signed char newwheel;
+ int cancompress = 1;
+ int next_tail;
+#endif
+
+/* do I have such a thing as a null event? */
+
+ dev = file->private_data;
+
+ /* verify that we actually have some data to read */
+ if (count == 0)
+ goto exit;
+
+ /* lock this object */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ /* verify that the device wasn't unplugged */
+ if (dev->intf == NULL) {
+ retval = -ENODEV;
+ err("No device or device unplugged %d\n", retval);
+ goto unlock_exit;
+ }
+
+ while (dev->ring_head == dev->ring_tail) {
+
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto unlock_exit;
+ }
+ // atomic_cmp_exchange(&dev->interrupt_in_done,0,0);
+ dev->interrupt_in_done = 0 ; /* tiny race - FIXME: make atomic? */
+ retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
+ if (retval < 0) {
+ goto unlock_exit;
+ }
+ }
+
+ dbg_info(&dev->intf->dev, "%s: copying to userspace: %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ __FUNCTION__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]);
+
+#if BUFFERED_READS
+ c = 0;
+ while((c < count) && (dev->ring_tail != dev->ring_head)) {
+
+/* This started off in the lower level service routine, and I moved it here. Then my brain died. Not done yet. */
+#if COMPRESS_WHEEL_EVENTS
+ next_tail = (dev->ring_tail+1) % ring_buffer_size;
+ if(dev->compress_wheel) cancompress = 1;
+ while(dev->ring_head != next_tail && cancompress == 1 ) {
+ newwheel = (*dev->ring_buffer)[next_tail].cmd[6];
+ oldwheel = (*dev->ring_buffer)[dev->ring_tail].cmd[6];
+ // if both are wheel events, and no buttons have changes (FIXME, do I have to check?),
+ // and we are the same sign, we can compress +- 7F
+ // FIXME: saner check for overflow! - max of +- 7F
+ // FIXME the math is wrong for going in reverse, actually, as the midi spec doesn't allow signed chars
+
+ dbg_info(&dev->intf->dev, "%s: trying to compress: %02x%02x%02x%02x%02x %02x %02x %02x\n",
+ __FUNCTION__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]);
+
+
+ if(((*dev->ring_buffer)[dev->ring_tail].cmd[6] != 0 &&
+ (*dev->ring_buffer)[next_tail].cmd[6] != 0 ) &&
+ ((newwheel > 0 && oldwheel > 0) ||
+ (newwheel < 0 && oldwheel < 0)) &&
+ ((*dev->ring_buffer)[dev->ring_tail].cmd[2] == (*dev->ring_buffer)[next_tail].cmd[2]) &&
+ ((*dev->ring_buffer)[dev->ring_tail].cmd[3] == (*dev->ring_buffer)[next_tail].cmd[3]) &&
+ ((*dev->ring_buffer)[dev->ring_tail].cmd[4] == (*dev->ring_buffer)[next_tail].cmd[4]) &&
+ ((*dev->ring_buffer)[dev->ring_tail].cmd[5] == (*dev->ring_buffer)[next_tail].cmd[5]))
+ {
+ dbg_info(&dev->intf->dev, "%s: should compress: %02x%02x%02x%02x%02x%02x%02x%02x\n",
+ __FUNCTION__, (*dev->ring_buffer)[dev->ring_tail].cmd[0],(*dev->ring_buffer)[dev->ring_tail].cmd[1],(*dev->ring_buffer)[dev->ring_tail].cmd[2],(*dev->ring_buffer)[dev->ring_tail].cmd[3],(*dev->ring_buffer)[dev->ring_tail].cmd[4],(*dev->ring_buffer)[dev->ring_tail].cmd[5],(*dev->ring_buffer)[dev->ring_tail].cmd[6],(*dev->ring_buffer)[dev->ring_tail].cmd[7]);
+
+ newwheel += oldwheel;
+ if(oldwheel > 0 && !(newwheel > 0)) {
+ newwheel = 0x7f;
+ cancompress = 0;
+ }
+ if(oldwheel < 0 && !(newwheel < 0)) {
+ newwheel = 0x80;
+ cancompress = 0;
+ }
+
+ (*dev->ring_buffer)[next_tail].cmd[6] = newwheel;
+ dev->ring_tail = next_tail;
+ next_tail = (dev->ring_tail+1) % ring_buffer_size;
+ } else {
+ cancompress = 0;
+ }
+ }
+#endif /* COMPRESS_WHEEL_EVENTS */
+
+ if (copy_to_user(&buffer[c], &(*dev->ring_buffer)[dev->ring_tail], 8)) {
+ retval = -EFAULT;
+ goto unlock_exit;
+ }
+
+ dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
+ c+=8;
+ dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail);
+ }
+ retval = c;
+
+#else
+ if (copy_to_user(buffer, &(*dev->ring_buffer)[dev->ring_tail], 8)) {
+ retval = -EFAULT;
+ goto unlock_exit;
+ }
+
+ dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
+ dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n", __FUNCTION__,dev->ring_head,dev->ring_tail);
+
+ retval = 8;
+#endif /* BUFFERED_READS */
+
+unlock_exit:
+ /* unlock the device */
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/**
+ * usb_tranzport_write
+ */
+static ssize_t usb_tranzport_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct usb_tranzport *dev;
+ size_t bytes_to_write;
+ int retval = 0;
+
+ dev = file->private_data;
+
+ /* verify that we actually have some data to write */
+ if (count == 0)
+ goto exit;
+
+ /* lock this object */
+ if (down_interruptible(&dev->sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+
+ /* verify that the device wasn't unplugged */
+ if (dev->intf == NULL) {
+ retval = -ENODEV;
+ err("No device or device unplugged %d\n", retval);
+ goto unlock_exit;
+ }
+
+ /* wait until previous transfer is finished */
+ if (dev->interrupt_out_busy) {
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto unlock_exit;
+ }
+ retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy);
+ if (retval < 0) {
+ goto unlock_exit;
+ }
+ }
+
+ /* write the data into interrupt_out_buffer from userspace */
+ bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
+ if (bytes_to_write < count)
+ dev_warn(&dev->intf->dev, "Write buffer overflow, %zd bytes dropped\n",count-bytes_to_write);
+
+ dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n", __FUNCTION__, count, bytes_to_write);
+
+ if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
+ retval = -EFAULT;
+ goto unlock_exit;
+ }
+
+ if (dev->interrupt_out_endpoint == NULL) {
+ err("Endpoint should not be be null! \n");
+ goto unlock_exit;
+ }
+
+ /* send off the urb */
+ usb_fill_int_urb(dev->interrupt_out_urb,
+ interface_to_usbdev(dev->intf),
+ usb_sndintpipe(interface_to_usbdev(dev->intf),
+ dev->interrupt_out_endpoint->bEndpointAddress),
+ dev->interrupt_out_buffer,
+ bytes_to_write,
+ usb_tranzport_interrupt_out_callback,
+ dev,
+ dev->interrupt_out_interval);
+
+ dev->interrupt_out_busy = 1;
+ wmb();
+
+ retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
+ if (retval) {
+ dev->interrupt_out_busy = 0;
+ err("Couldn't submit interrupt_out_urb %d\n", retval);
+ goto unlock_exit;
+ }
+ retval = bytes_to_write;
+
+unlock_exit:
+ /* unlock the device */
+ up(&dev->sem);
+
+exit:
+ return retval;
+}
+
+/* file operations needed when we register this driver */
+static const struct file_operations usb_tranzport_fops = {
+ .owner = THIS_MODULE,
+ .read = usb_tranzport_read,
+ .write = usb_tranzport_write,
+ .open = usb_tranzport_open,
+ .release = usb_tranzport_release,
+ .poll = usb_tranzport_poll,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+static struct usb_class_driver usb_tranzport_class = {
+ .name = "tranzport%d",
+ .fops = &usb_tranzport_fops,
+ .minor_base = USB_TRANZPORT_MINOR_BASE,
+};
+
+
+/**
+ * usb_tranzport_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_tranzport *dev = NULL;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int i;
+ int true_size;
+ int retval = -ENOMEM;
+
+ /* allocate memory for our device state and intialize it */
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ dev_err(&intf->dev, "Out of memory\n");
+ goto exit;
+ }
+ init_MUTEX(&dev->sem);
+ dev->intf = intf;
+ init_waitqueue_head(&dev->read_wait);
+ init_waitqueue_head(&dev->write_wait);
+
+ iface_desc = intf->cur_altsetting;
+
+ /* set up the endpoint information */
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (usb_endpoint_is_int_in(endpoint))
+ dev->interrupt_in_endpoint = endpoint;
+
+ if (usb_endpoint_is_int_out(endpoint))
+ dev->interrupt_out_endpoint = endpoint;
+ }
+ if (dev->interrupt_in_endpoint == NULL) {
+ dev_err(&intf->dev, "Interrupt in endpoint not found\n");
+ goto error;
+ }
+ if (dev->interrupt_out_endpoint == NULL)
+ dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");
+
+
+ dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
+
+ if (dev->interrupt_in_endpoint_size != 8)
+ dev_warn(&intf->dev, "Interrupt in endpoint size is not 8!\n");
+
+ if(ring_buffer_size == 0) { ring_buffer_size = RING_BUFFER_SIZE; }
+ true_size = min(ring_buffer_size,RING_BUFFER_SIZE);
+ /* FIXME - there are more usb_alloc routines for dma correctness. Needed? */
+
+ dev->ring_buffer = kmalloc((true_size*sizeof(struct tranzport_cmd))+8, GFP_KERNEL);
+
+ if (!dev->ring_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate ring_buffer of size %d\n",true_size);
+ goto error;
+ }
+ dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
+ if (!dev->interrupt_in_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n");
+ goto error;
+ }
+ dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->interrupt_in_urb) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
+ goto error;
+ }
+ dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) :
+ udev->descriptor.bMaxPacketSize0;
+
+ if (dev->interrupt_out_endpoint_size !=8)
+ dev_warn(&intf->dev, "Interrupt out endpoint size is not 8!)\n");
+
+ dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL);
+ if (!dev->interrupt_out_buffer) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n");
+ goto error;
+ }
+ dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->interrupt_out_urb) {
+ dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
+ goto error;
+ }
+ dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
+ if (dev->interrupt_out_endpoint)
+ dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
+
+ /* we can register the device now, as it is ready */
+ usb_set_intfdata(intf, dev);
+
+ retval = usb_register_dev(intf, &usb_tranzport_class);
+ if (retval) {
+ /* something prevented us from registering this driver */
+ dev_err(&intf->dev, "Not able to get a minor for this device.\n");
+ usb_set_intfdata(intf, NULL);
+ goto error;
+ }
+
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightRecord))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackrec))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackmute))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightTracksolo))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightAnysolo))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightLoop))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_LightPunch))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_wheel))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_event))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_dump_state))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_compress_wheel))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_enable))) goto error;
+ if((retval = device_create_file(&intf->dev, &dev_attr_offline))) goto error;
+
+ /* let the user know what node this device is now attached to */
+ dev_info(&intf->dev, "Tranzport Device #%d now attached to major %d minor %d\n",
+ (intf->minor - USB_TRANZPORT_MINOR_BASE), USB_MAJOR, intf->minor);
+
+exit:
+ return retval;
+
+error:
+ usb_tranzport_delete(dev);
+
+ return retval;
+}
+
+/**
+ * usb_tranzport_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ */
+static void usb_tranzport_disconnect(struct usb_interface *intf)
+{
+ struct usb_tranzport *dev;
+ int minor;
+
+ /* FIXME: The skel code calls lock_kernel here, doesn't use a mutex, needed? */
+ mutex_lock(&disconnect_mutex);
+
+ dev = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
+
+ down(&dev->sem);
+
+ minor = intf->minor;
+
+ /* give back our minor */
+ usb_deregister_dev(intf, &usb_tranzport_class);
+
+ /* if the device is not opened, then we clean up right now */
+ if (!dev->open_count) {
+ up(&dev->sem);
+ usb_tranzport_delete(dev);
+ } else {
+ dev->intf = NULL;
+ up(&dev->sem);
+ }
+
+ mutex_unlock(&disconnect_mutex);
+
+ dev_info(&intf->dev, "Tranzport Surface #%d now disconnected\n",
+ (minor - USB_TRANZPORT_MINOR_BASE));
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver usb_tranzport_driver = {
+ .name = "tranzport",
+ .probe = usb_tranzport_probe,
+ .disconnect = usb_tranzport_disconnect,
+ .id_table = usb_tranzport_table,
+};
+
+/**
+ * usb_tranzport_init
+ */
+static int __init usb_tranzport_init(void)
+{
+ int retval;
+
+ /* register this driver with the USB subsystem */
+ retval = usb_register(&usb_tranzport_driver);
+ if (retval)
+ err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval);
+
+ return retval;
+}
+
+/**
+ * usb_tranzport_exit
+ */
+static void __exit usb_tranzport_exit(void)
+{
+ /* deregister this driver with the USB subsystem */
+ usb_deregister(&usb_tranzport_driver);
+}
+
+module_init(usb_tranzport_init);
+module_exit(usb_tranzport_exit);
+
diff --git a/libs/surfaces/frontier/tests/Makefile b/libs/surfaces/frontier/tests/Makefile
new file mode 100644
index 0000000000..aafb9aaa57
--- /dev/null
+++ b/libs/surfaces/frontier/tests/Makefile
@@ -0,0 +1,17 @@
+# Some basic utilities for testing the tranzport's I/O
+# eventually "tranzport" will become a flexible command
+#
+#
+all: tranzport tranzport_lights
+
+tranzport: tranzport.c
+ gcc -g -Wall -o tranzport tranzport.c
+
+tranzport_lights: tranzport_lights.c
+ gcc -g -Wall -o tranzport_lights tranzport_lights.c
+
+clean::
+ rm -f core .*.cmd *.o *.ko *.mod.c Module.symvers *.bak .\#* *~
+ rm -rf .tmp_versions tranzport tranzport_lights
+
+
diff --git a/libs/surfaces/frontier/tests/README b/libs/surfaces/frontier/tests/README
new file mode 100644
index 0000000000..f9efd18f69
--- /dev/null
+++ b/libs/surfaces/frontier/tests/README
@@ -0,0 +1,104 @@
+tranzport 0.1 <tranzport.sf.net>
+oct 18, 2005
+arthur@artcmusic.com
+---
+
+The Frontier Design Tranzport(tm) (www.frontierdesign.com) is a simple
+wireless USB device. It is not a MIDI device. The document on their web
+site "Tranzport(tm) Native Mode Interface Description" describes the
+Tranzport(tm) as if it were a MIDI device, but this is implemented by their
+Windows and Macintosh software drivers.
+
+This code will allow you to use your Tranzport(tm) at a lower level of
+abstraction. This code relies on libusb, which can be obtained from
+libusb.sourceforge.net.
+
+To compile the program, type "make". You should end up with a executable
+called "tranzport". You'll probably have to run this program as root.
+
+Using the program is straightforward. It will simply tell you which
+buttons are being pressed and what not. If you press one of the buttons
+with a light, the light will turn on. If you hold shift and press one of
+the buttons with a light, the light will turn off. If you take out the
+batteries to the device (or go out of range), it will tell you that the
+device is offline. When you replace the batteries (or come back in
+range), it should tell you it is back online.
+
+Once you understand how everything works, you should be able to
+incorporate it into your own setup however you wish.
+
+This code was developed on a Linux machine, but (theoretically) it
+should work on any system that is supported by libusb, since that is how
+it communicates with the device.
+
+Here are a few more details about the device:
+
+There are two endpoints for communication with the device. All data
+reads and writes are done in 8-byte segments.
+
+One endpoint is for interrupt reads. This is used to read button data
+from the device. It also supplies status information for when the device
+goes out of range and comes back in range, loses power and regains
+power, etc. The format of the data is:
+
+ 00 ss bb bb bb bb dd 00 (hexadecimal)
+
+where:
+
+ ss - status code, 01=online ff=offline
+ bb - button bits
+ dd - data wheel, 01-3f=forward 41-7f=backward
+
+Please refer to the source code for a list of the button bits.
+
+The other endpoint is for interrupt writes. This is used to toggle the
+lights on the device, and to write data to the LCD.
+
+There are 7 lights on the device. To turn a light on, send the following
+sequence of bytes:
+
+ 00 00 nn 01 00 00 00 00 (hexadecimal)
+
+where nn is the light number.
+
+To turn a light off:
+
+ 00 00 nn 00 00 00 00 00 (hexadecimal)
+
+Here is the list of lights:
+
+ 00 Record
+ 01 Track Rec
+ 02 Track Mute
+ 03 Track Solo
+ 04 Any Solo
+ 05 Loop
+ 06 Punch
+
+The size of the LCD is 20x2, and it is split into 10 cells, each cell
+being 4 characters wide. The cells progress across, then down. To write
+to the LCD, send the following sequence of bytes:
+
+ 00 01 cc aa aa aa aa 00 (hexadecimal)
+
+where:
+
+ cc - cell number
+ aa - ASCII code
+
+Here is a list of the cells to clarify:
+
+ 00 row 0, column 0-3
+ 01 row 0, column 4-7
+ 02 row 0, column 8-11
+ 03 row 0, column 12-15
+ 04 row 0, column 16-19
+ 05 row 1, column 0-3
+ 06 row 1, column 4-7
+ 07 row 1, column 8-11
+ 08 row 1, column 12-15
+ 09 row 1, column 16-19
+
+You should refer to the "Tranzport(tm) Native Mode Interface
+Description" document for a listing of the ASCII codes the LCD uses.
+
diff --git a/libs/surfaces/frontier/tests/tranzport.c b/libs/surfaces/frontier/tests/tranzport.c
new file mode 100644
index 0000000000..1eeacd6578
--- /dev/null
+++ b/libs/surfaces/frontier/tests/tranzport.c
@@ -0,0 +1,347 @@
+/*
+ * tranzport 0.1 <tranzport.sf.net>
+ * oct 18, 2005
+ * arthur@artcmusic.com
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <usb.h>
+
+#define VENDORID 0x165b
+#define PRODUCTID 0x8101
+
+#define READ_ENDPOINT 0x81
+#define WRITE_ENDPOINT 0x02
+
+enum {
+ LIGHT_RECORD = 0,
+ LIGHT_TRACKREC,
+ LIGHT_TRACKMUTE,
+ LIGHT_TRACKSOLO,
+ LIGHT_ANYSOLO,
+ LIGHT_LOOP,
+ LIGHT_PUNCH
+};
+
+#define BUTTONMASK_BATTERY 0x00004000
+#define BUTTONMASK_BACKLIGHT 0x00008000
+#define BUTTONMASK_TRACKLEFT 0x04000000
+#define BUTTONMASK_TRACKRIGHT 0x40000000
+#define BUTTONMASK_TRACKREC 0x00040000
+#define BUTTONMASK_TRACKMUTE 0x00400000
+#define BUTTONMASK_TRACKSOLO 0x00000400
+#define BUTTONMASK_UNDO 0x80000000
+#define BUTTONMASK_IN 0x02000000
+#define BUTTONMASK_OUT 0x20000000
+#define BUTTONMASK_PUNCH 0x00800000
+#define BUTTONMASK_LOOP 0x00080000
+#define BUTTONMASK_PREV 0x00020000
+#define BUTTONMASK_ADD 0x00200000
+#define BUTTONMASK_NEXT 0x00000200
+#define BUTTONMASK_REWIND 0x01000000
+#define BUTTONMASK_FASTFORWARD 0x10000000
+#define BUTTONMASK_STOP 0x00010000
+#define BUTTONMASK_PLAY 0x00100000
+#define BUTTONMASK_RECORD 0x00000100
+#define BUTTONMASK_SHIFT 0x08000000
+
+#define STATUS_OFFLINE 0xff
+#define STATUS_ONLINE 0x01
+
+struct tranzport_s {
+ struct usb_device *dev;
+ usb_dev_handle *udev;
+};
+
+typedef struct tranzport_s tranzport_t;
+
+void log_entry(FILE *fp, char *format, va_list ap)
+{
+ vfprintf(fp, format, ap);
+ fputc('\n', fp);
+}
+
+void log_error(char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ log_entry(stderr, format, ap);
+ va_end(ap);
+}
+
+void vlog_error(char *format, va_list ap)
+{
+ log_entry(stderr, format, ap);
+}
+
+void die(char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlog_error(format, ap);
+ va_end(ap);
+ exit(1);
+}
+
+tranzport_t *open_tranzport_core(struct usb_device *dev)
+{
+ tranzport_t *z;
+ int val;
+
+ z = malloc(sizeof(tranzport_t));
+ if (!z)
+ die("not enough memory");
+ memset(z, 0, sizeof(tranzport_t));
+
+ z->dev = dev;
+ z->udev = usb_open(z->dev);
+ if (!z->udev)
+ die("unable to open tranzport");
+
+ val = usb_claim_interface(z->udev, 0);
+ if (val < 0)
+ die("unable to claim tranzport");
+
+ return z;
+}
+
+tranzport_t *open_tranzport()
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ for(bus=usb_busses; bus; bus=bus->next) {
+ for(dev=bus->devices; dev; dev=dev->next) {
+ if (dev->descriptor.idVendor != VENDORID)
+ continue;
+ if (dev->descriptor.idProduct != PRODUCTID)
+ continue;
+
+ return open_tranzport_core(dev);
+ }
+ }
+
+ die("can't find tranzport");
+ return 0;
+}
+
+void close_tranzport(tranzport_t *z)
+{
+ int val;
+
+ val = usb_release_interface(z->udev, 0);
+ if (val < 0)
+ log_error("unable to release tranzport");
+
+ val = usb_close(z->udev);
+ if (val < 0)
+ log_error("unable to close tranzport");
+
+ free(z);
+}
+
+int tranzport_write_core(tranzport_t *z, uint8_t *cmd, int timeout)
+{
+ int val;
+ val = usb_interrupt_write(z->udev, WRITE_ENDPOINT, cmd, 8, timeout);
+ if (val < 0)
+ return val;
+ if (val != 8)
+ return -1;
+ return 0;
+}
+
+int tranzport_lcdwrite(tranzport_t *z, uint8_t cell, char *text, int timeout)
+{
+ uint8_t cmd[8];
+
+ if (cell > 9) {
+ return -1;
+ }
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x01;
+ cmd[2] = cell;
+ cmd[3] = text[0];
+ cmd[4] = text[1];
+ cmd[5] = text[2];
+ cmd[6] = text[3];
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, cmd, timeout);
+}
+
+int tranzport_lighton(tranzport_t *z, uint8_t light, int timeout)
+{
+ uint8_t cmd[8];
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ cmd[2] = light;
+ cmd[3] = 0x01;
+ cmd[4] = 0x00;
+ cmd[5] = 0x00;
+ cmd[6] = 0x00;
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, cmd, timeout);
+}
+
+int tranzport_lightoff(tranzport_t *z, uint8_t light, int timeout)
+{
+ uint8_t cmd[8];
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ cmd[2] = light;
+ cmd[3] = 0x00;
+ cmd[4] = 0x00;
+ cmd[5] = 0x00;
+ cmd[6] = 0x00;
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, cmd, timeout);
+}
+
+int tranzport_read(tranzport_t *z, uint8_t *status, uint32_t *buttons, uint8_t *datawheel, int timeout)
+{
+ uint8_t buf[8];
+ int val;
+
+ memset(buf, 0, 8);
+ val = usb_interrupt_read(z->udev, READ_ENDPOINT, buf, 8, timeout);
+ if (val < 0)
+ return val;
+ if (val != 8)
+ return -1;
+
+ /*printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/
+
+ *status = buf[1];
+
+ *buttons = 0;
+ *buttons |= buf[2] << 24;
+ *buttons |= buf[3] << 16;
+ *buttons |= buf[4] << 8;
+ *buttons |= buf[5];
+
+ *datawheel = buf[6];
+
+ return 0;
+}
+
+void lights_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, uint8_t light)
+{
+ if (buttons & buttonmask) {
+ if (buttons & BUTTONMASK_SHIFT) {
+ tranzport_lightoff(z, light, 1000);
+ } else {
+ tranzport_lighton(z, light, 1000);
+ }
+ }
+}
+
+void do_lights(tranzport_t *z, uint32_t buttons)
+{
+ lights_core(z, buttons, BUTTONMASK_RECORD, LIGHT_RECORD);
+ lights_core(z, buttons, BUTTONMASK_TRACKREC, LIGHT_TRACKREC);
+ lights_core(z, buttons, BUTTONMASK_TRACKMUTE, LIGHT_TRACKMUTE);
+ lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_TRACKSOLO);
+ lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_ANYSOLO);
+ lights_core(z, buttons, BUTTONMASK_PUNCH, LIGHT_PUNCH);
+ lights_core(z, buttons, BUTTONMASK_LOOP, LIGHT_LOOP);
+}
+
+void buttons_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, char *str)
+{
+ if (buttons & buttonmask)
+ printf(" %s", str);
+}
+
+void do_buttons(tranzport_t *z, uint32_t buttons, uint8_t datawheel)
+{
+ printf("buttons:");
+ buttons_core(z, buttons, BUTTONMASK_BATTERY, "battery");
+ buttons_core(z, buttons, BUTTONMASK_BACKLIGHT, "backlight");
+ buttons_core(z, buttons, BUTTONMASK_TRACKLEFT, "trackleft");
+ buttons_core(z, buttons, BUTTONMASK_TRACKRIGHT, "trackright");
+ buttons_core(z, buttons, BUTTONMASK_TRACKREC, "trackrec");
+ buttons_core(z, buttons, BUTTONMASK_TRACKMUTE, "trackmute");
+ buttons_core(z, buttons, BUTTONMASK_TRACKSOLO, "tracksolo");
+ buttons_core(z, buttons, BUTTONMASK_UNDO, "undo");
+ buttons_core(z, buttons, BUTTONMASK_IN, "in");
+ buttons_core(z, buttons, BUTTONMASK_OUT, "out");
+ buttons_core(z, buttons, BUTTONMASK_PUNCH, "punch");
+ buttons_core(z, buttons, BUTTONMASK_LOOP, "loop");
+ buttons_core(z, buttons, BUTTONMASK_PREV, "prev");
+ buttons_core(z, buttons, BUTTONMASK_ADD, "add");
+ buttons_core(z, buttons, BUTTONMASK_NEXT, "next");
+ buttons_core(z, buttons, BUTTONMASK_REWIND, "rewind");
+ buttons_core(z, buttons, BUTTONMASK_FASTFORWARD, "fastforward");
+ buttons_core(z, buttons, BUTTONMASK_STOP, "stop");
+ buttons_core(z, buttons, BUTTONMASK_PLAY, "play");
+ buttons_core(z, buttons, BUTTONMASK_RECORD, "record");
+ buttons_core(z, buttons, BUTTONMASK_SHIFT, "shift");
+ if (datawheel)
+ printf(" datawheel=%02x", datawheel);
+ printf("\n");
+}
+
+void do_lcd(tranzport_t *z)
+{
+ tranzport_lcdwrite(z, 0, " ", 1000);
+ tranzport_lcdwrite(z, 1, "DISL", 1000);
+ tranzport_lcdwrite(z, 2, "EXIA", 1000);
+ tranzport_lcdwrite(z, 3, " FOR", 1000);
+ tranzport_lcdwrite(z, 4, " ", 1000);
+
+ tranzport_lcdwrite(z, 5, " ", 1000);
+ tranzport_lcdwrite(z, 6, " CUR", 1000);
+ tranzport_lcdwrite(z, 7, "E FO", 1000);
+ tranzport_lcdwrite(z, 8, "UND ", 1000);
+ tranzport_lcdwrite(z, 9, " ", 1000);
+}
+
+int main()
+{
+ tranzport_t *z;
+ uint8_t status;
+ uint32_t buttons;
+ uint8_t datawheel;
+ int val;
+
+ z = open_tranzport();
+
+ do_lcd(z);
+
+ for(;;) {
+ val = tranzport_read(z, &status, &buttons, &datawheel, 60000);
+ if (val < 0)
+ continue;
+
+ if (status == STATUS_OFFLINE) {
+ printf("offline\n");
+ continue;
+ }
+
+ if (status == STATUS_ONLINE) {
+ printf("online\n");
+ do_lcd(z);
+ }
+
+ do_lights(z, buttons);
+ do_buttons(z, buttons, datawheel);
+ }
+
+ close_tranzport(z);
+
+ return 0;
+}
+
diff --git a/libs/surfaces/frontier/tests/tranzport_lights.c b/libs/surfaces/frontier/tests/tranzport_lights.c
new file mode 100644
index 0000000000..28a8462d84
--- /dev/null
+++ b/libs/surfaces/frontier/tests/tranzport_lights.c
@@ -0,0 +1,361 @@
+/*
+ * tranzport 0.1 <tranzport.sf.net>
+ * oct 18, 2005
+ * arthur@artcmusic.com
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <malloc.h>
+
+#define VENDORID 0x165b
+#define PRODUCTID 0x8101
+
+#define READ_ENDPOINT 0x81
+#define WRITE_ENDPOINT 0x02
+
+enum {
+ LIGHT_RECORD = 0,
+ LIGHT_TRACKREC,
+ LIGHT_TRACKMUTE,
+ LIGHT_TRACKSOLO,
+ LIGHT_ANYSOLO,
+ LIGHT_LOOP,
+ LIGHT_PUNCH
+};
+
+#define BUTTONMASK_BATTERY 0x00004000
+#define BUTTONMASK_BACKLIGHT 0x00008000
+#define BUTTONMASK_TRACKLEFT 0x04000000
+#define BUTTONMASK_TRACKRIGHT 0x40000000
+#define BUTTONMASK_TRACKREC 0x00040000
+#define BUTTONMASK_TRACKMUTE 0x00400000
+#define BUTTONMASK_TRACKSOLO 0x00000400
+#define BUTTONMASK_UNDO 0x80000000
+#define BUTTONMASK_IN 0x02000000
+#define BUTTONMASK_OUT 0x20000000
+#define BUTTONMASK_PUNCH 0x00800000
+#define BUTTONMASK_LOOP 0x00080000
+#define BUTTONMASK_PREV 0x00020000
+#define BUTTONMASK_ADD 0x00200000
+#define BUTTONMASK_NEXT 0x00000200
+#define BUTTONMASK_REWIND 0x01000000
+#define BUTTONMASK_FASTFORWARD 0x10000000
+#define BUTTONMASK_STOP 0x00010000
+#define BUTTONMASK_PLAY 0x00100000
+#define BUTTONMASK_RECORD 0x00000100
+#define BUTTONMASK_SHIFT 0x08000000
+
+#define STATUS_OFFLINE 0xff
+#define STATUS_ONLINE 0x01
+#define STATUS_OK 0x00
+
+struct tranzport_s {
+ int *dev;
+ int udev;
+};
+
+typedef struct tranzport_s tranzport_t;
+
+void log_entry(FILE *fp, char *format, va_list ap)
+{
+ vfprintf(fp, format, ap);
+ fputc('\n', fp);
+}
+
+void log_error(char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ log_entry(stderr, format, ap);
+ va_end(ap);
+}
+
+void vlog_error(char *format, va_list ap)
+{
+ log_entry(stderr, format, ap);
+}
+
+void die(char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ vlog_error(format, ap);
+ va_end(ap);
+ exit(1);
+}
+
+tranzport_t *open_tranzport_core()
+{
+ tranzport_t *z;
+ int val;
+
+ z = malloc(sizeof(tranzport_t));
+ if (!z)
+ die("not enough memory");
+ memset(z, 0, sizeof(tranzport_t));
+
+ z->udev = open("/dev/tranzport0",O_RDWR);
+ if (!z->udev)
+ die("unable to open tranzport");
+
+ return z;
+}
+
+tranzport_t *open_tranzport()
+{
+return open_tranzport_core();
+}
+
+void close_tranzport(tranzport_t *z)
+{
+ int val;
+
+ val = close(z->udev);
+ if (val < 0)
+ log_error("unable to release tranzport");
+
+ free(z);
+}
+
+int tranzport_write_core(tranzport_t *z, uint8_t *cmd, int timeout)
+{
+ int val;
+ val = write(z->udev, cmd, 8);
+ if (val < 0)
+ return val;
+ if (val != 8)
+ return -1;
+ return 0;
+}
+
+int tranzport_lcdwrite(tranzport_t *z, uint8_t cell, char *text, int timeout)
+{
+ uint8_t cmd[8];
+
+ if (cell > 9) {
+ return -1;
+ }
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x01;
+ cmd[2] = cell;
+ cmd[3] = text[0];
+ cmd[4] = text[1];
+ cmd[5] = text[2];
+ cmd[6] = text[3];
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, cmd, timeout);
+}
+
+int tranzport_lighton(tranzport_t *z, uint8_t light, int timeout)
+{
+ uint8_t cmd[8];
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ cmd[2] = light;
+ cmd[3] = 0x01;
+ cmd[4] = 0x00;
+ cmd[5] = 0x00;
+ cmd[6] = 0x00;
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, &cmd[0], timeout);
+}
+
+int tranzport_lightoff(tranzport_t *z, uint8_t light, int timeout)
+{
+ uint8_t cmd[8];
+
+ cmd[0] = 0x00;
+ cmd[1] = 0x00;
+ cmd[2] = light;
+ cmd[3] = 0x00;
+ cmd[4] = 0x00;
+ cmd[5] = 0x00;
+ cmd[6] = 0x00;
+ cmd[7] = 0x00;
+
+ return tranzport_write_core(z, &cmd[0], timeout);
+}
+
+int tranzport_read(tranzport_t *z, uint8_t *status, uint32_t *buttons, uint8_t *datawheel, int timeout)
+{
+ uint8_t buf[8];
+ int val;
+
+ memset(buf, 0xff, 8);
+ val = read(z->udev, buf, 8);
+ if (val < 0) {
+ // printf("errno: %d\n",errno);
+ return val;
+ }
+ if (val != 8)
+ return -1;
+
+ /*printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/
+
+ *status = buf[1];
+
+ *buttons = 0;
+ *buttons |= buf[2] << 24;
+ *buttons |= buf[3] << 16;
+ *buttons |= buf[4] << 8;
+ *buttons |= buf[5];
+
+ *datawheel = buf[6];
+
+ return 0;
+}
+
+void lights_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, uint8_t light)
+{
+ if (buttons & buttonmask) {
+ if (buttons & BUTTONMASK_SHIFT) {
+ tranzport_lightoff(z, light, 1000);
+ } else {
+ tranzport_lighton(z, light, 1000);
+ }
+ }
+}
+
+void do_lights(tranzport_t *z, uint32_t buttons)
+{
+ lights_core(z, buttons, BUTTONMASK_RECORD, LIGHT_RECORD);
+ lights_core(z, buttons, BUTTONMASK_TRACKREC, LIGHT_TRACKREC);
+ lights_core(z, buttons, BUTTONMASK_TRACKMUTE, LIGHT_TRACKMUTE);
+ lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_TRACKSOLO);
+ lights_core(z, buttons, BUTTONMASK_TRACKSOLO, LIGHT_ANYSOLO);
+ lights_core(z, buttons, BUTTONMASK_PUNCH, LIGHT_PUNCH);
+ lights_core(z, buttons, BUTTONMASK_LOOP, LIGHT_LOOP);
+}
+
+void buttons_core(tranzport_t *z, uint32_t buttons, uint32_t buttonmask, char *str)
+{
+ if (buttons & buttonmask)
+ printf(" %s", str);
+}
+
+void do_buttons(tranzport_t *z, uint32_t buttons, uint8_t datawheel)
+{
+ printf("buttons: %x ", buttons);
+ buttons_core(z, buttons, BUTTONMASK_BATTERY, "battery");
+ buttons_core(z, buttons, BUTTONMASK_BACKLIGHT, "backlight");
+ buttons_core(z, buttons, BUTTONMASK_TRACKLEFT, "trackleft");
+ buttons_core(z, buttons, BUTTONMASK_TRACKRIGHT, "trackright");
+ buttons_core(z, buttons, BUTTONMASK_TRACKREC, "trackrec");
+ buttons_core(z, buttons, BUTTONMASK_TRACKMUTE, "trackmute");
+ buttons_core(z, buttons, BUTTONMASK_TRACKSOLO, "tracksolo");
+ buttons_core(z, buttons, BUTTONMASK_UNDO, "undo");
+ buttons_core(z, buttons, BUTTONMASK_IN, "in");
+ buttons_core(z, buttons, BUTTONMASK_OUT, "out");
+ buttons_core(z, buttons, BUTTONMASK_PUNCH, "punch");
+ buttons_core(z, buttons, BUTTONMASK_LOOP, "loop");
+ buttons_core(z, buttons, BUTTONMASK_PREV, "prev");
+ buttons_core(z, buttons, BUTTONMASK_ADD, "add");
+ buttons_core(z, buttons, BUTTONMASK_NEXT, "next");
+ buttons_core(z, buttons, BUTTONMASK_REWIND, "rewind");
+ buttons_core(z, buttons, BUTTONMASK_FASTFORWARD, "fastforward");
+ buttons_core(z, buttons, BUTTONMASK_STOP, "stop");
+ buttons_core(z, buttons, BUTTONMASK_PLAY, "play");
+ buttons_core(z, buttons, BUTTONMASK_RECORD, "record");
+ buttons_core(z, buttons, BUTTONMASK_SHIFT, "shift");
+ if (datawheel)
+ printf(" datawheel=%02x", datawheel);
+ printf("\n");
+}
+
+void do_lcd(tranzport_t *z)
+{
+ tranzport_lcdwrite(z, 0, " ", 1000);
+ tranzport_lcdwrite(z, 1, "DISL", 1000);
+ tranzport_lcdwrite(z, 2, "EXIA", 1000);
+ tranzport_lcdwrite(z, 3, " FOR", 1000);
+ tranzport_lcdwrite(z, 4, " ", 1000);
+
+ tranzport_lcdwrite(z, 5, " ", 1000);
+ tranzport_lcdwrite(z, 6, " CUR", 1000);
+ tranzport_lcdwrite(z, 7, "E FO", 1000);
+ tranzport_lcdwrite(z, 8, "UND ", 1000);
+ tranzport_lcdwrite(z, 9, " ", 1000);
+}
+
+void do_lcd2(tranzport_t *z)
+{
+ tranzport_lcdwrite(z, 0, "THE ", 1000);
+ tranzport_lcdwrite(z, 1, "TRAN", 1000);
+ tranzport_lcdwrite(z, 2, "ZPOR", 1000);
+ tranzport_lcdwrite(z, 3, "T RO", 1000);
+ tranzport_lcdwrite(z, 4, " KS", 1000);
+
+ tranzport_lcdwrite(z, 5, "AWES", 1000);
+ tranzport_lcdwrite(z, 6, "OMEE", 1000);
+ tranzport_lcdwrite(z, 7, "LEEE", 1000);
+ tranzport_lcdwrite(z, 8, "UND ", 1000);
+ tranzport_lcdwrite(z, 9, "GROK", 1000);
+}
+
+lights_off(tranzport_t *z) {
+int i;
+ for(i=0;i<7;i++) {
+ tranzport_lightoff(z, i, 1000);
+ }
+}
+
+lights_on(tranzport_t *z) {
+int i;
+ for(i=0;i<7;i++) {
+ tranzport_lighton(z, i, 1000);
+ }
+}
+
+int main()
+{
+ tranzport_t *z;
+ uint8_t status;
+ uint32_t buttons;
+ uint8_t datawheel;
+ int val;
+
+ z = open_tranzport();
+
+ do_lcd(z);
+
+ for(;;) {
+
+ do_lcd(z);
+ lights_on(z);
+ do_lcd2(z);
+ lights_off(z);
+
+// val = tranzport_read(z, &status, &buttons, &datawheel, 60000);
+ val = -1;
+ if (val < 0)
+ continue;
+
+ if (status == STATUS_OFFLINE) {
+ printf("offline: ");
+ continue;
+ }
+
+ if (status == STATUS_ONLINE) {
+ printf("online: ");
+ do_lcd(z);
+ }
+
+ do_lights(z, buttons);
+ do_buttons(z, buttons, datawheel);
+ }
+
+ close_tranzport(z);
+
+ return 0;
+}
+
diff --git a/libs/surfaces/frontier/tranzport/SConscript b/libs/surfaces/frontier/tranzport/SConscript
new file mode 100644
index 0000000000..5d390f3e2f
--- /dev/null
+++ b/libs/surfaces/frontier/tranzport/SConscript
@@ -0,0 +1,56 @@
+# -*- python -*-
+
+import os
+import os.path
+import glob
+
+Import('env final_prefix install_prefix final_config_prefix libraries i18n')
+
+tranzport = env.Copy()
+
+#
+# this defines the version number of libardour_tranzport
+#
+
+domain = 'ardour_tranzport'
+
+tranzport.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
+tranzport.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
+tranzport.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+tranzport.Append(PACKAGE = domain)
+tranzport.Append(POTFILE = domain + '.pot')
+
+tranzport_files=Split("""
+interface.cc
+tranzport_control_protocol.cc
+""")
+
+tranzport.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
+tranzport.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
+tranzport.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
+tranzport.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+
+tranzport.Merge ([
+ libraries['ardour'],
+ libraries['ardour_cp'],
+ libraries['sigc2'],
+ libraries['pbd'],
+ libraries['midi++2'],
+ libraries['xml'],
+ libraries['usb'],
+ libraries['glib2'],
+ libraries['glibmm2']
+ ])
+
+libardour_tranzport = tranzport.SharedLibrary('ardour_tranzport', tranzport_files)
+
+if tranzport['TRANZPORT']:
+ Default(libardour_tranzport)
+ if env['NLS']:
+ i18n (tranzport, tranzport_files, env)
+ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2', 'surfaces'), libardour_tranzport))
+
+env.Alias('tarball', env.Distribute (env['DISTTREE'],
+ [ 'SConscript' ] +
+ tranzport_files +
+ glob.glob('po/*.po') + glob.glob('*.h')))
diff --git a/libs/surfaces/frontier/tranzport/interface.cc b/libs/surfaces/frontier/tranzport/interface.cc
new file mode 100644
index 0000000000..f6d0dc8206
--- /dev/null
+++ b/libs/surfaces/frontier/tranzport/interface.cc
@@ -0,0 +1,51 @@
+#include <control_protocol/control_protocol.h>
+#include "tranzport_control_protocol.h"
+
+using namespace ARDOUR;
+
+ControlProtocol*
+new_tranzport_protocol (ControlProtocolDescriptor* descriptor, Session* s)
+{
+ TranzportControlProtocol* tcp = new TranzportControlProtocol (*s);
+
+ if (tcp->set_active (true)) {
+ delete tcp;
+ return 0;
+ }
+
+ return tcp;
+
+}
+
+void
+delete_tranzport_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
+{
+ delete cp;
+}
+
+bool
+probe_tranzport_protocol (ControlProtocolDescriptor* descriptor)
+{
+ return TranzportControlProtocol::probe();
+}
+
+static ControlProtocolDescriptor tranzport_descriptor = {
+ name : "Tranzport",
+ id : "uri://ardour.org/surfaces/tranzport:0",
+ ptr : 0,
+ module : 0,
+ mandatory : 0,
+ supports_feedback : false,
+ probe : probe_tranzport_protocol,
+ initialize : new_tranzport_protocol,
+ destroy : delete_tranzport_protocol
+};
+
+
+extern "C" {
+ControlProtocolDescriptor*
+protocol_descriptor () {
+ return &tranzport_descriptor;
+}
+}
+
diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.cc b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
index bbb78d31d1..c874a05de5 100644
--- a/libs/surfaces/tranzport/tranzport_control_protocol.cc
+++ b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
/* Design notes: The tranzport is a unique device, basically a
@@ -1562,7 +1561,7 @@ TranzportControlProtocol::button_event_record_release (bool shifted)
void button_event_mute (bool pressed, bool shifted)
{
- //static int was_pressed = 0;
+ static int was_pressed = 0;
// if(pressed) { }
}
diff --git a/libs/surfaces/frontier/tranzport/tranzport_control_protocol.h b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.h
new file mode 100644
index 0000000000..f13e4a3a44
--- /dev/null
+++ b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.h
@@ -0,0 +1,320 @@
+
+#ifndef ardour_tranzport_control_protocol_h
+#define ardour_tranzport_control_protocol_h
+
+#include <vector>
+
+#include <sys/time.h>
+#include <pthread.h>
+#include <usb.h>
+
+#include <glibmm/thread.h>
+
+#include <ardour/types.h>
+
+#include <control_protocol/control_protocol.h>
+
+class TranzportControlProtocol : public ARDOUR::ControlProtocol
+{
+ public:
+ TranzportControlProtocol (ARDOUR::Session&);
+ virtual ~TranzportControlProtocol();
+
+ int set_active (bool yn);
+
+ static bool probe ();
+
+ XMLNode& get_state ();
+ int set_state (const XMLNode&);
+
+ private:
+ static const int VENDORID = 0x165b;
+ static const int PRODUCTID = 0x8101;
+ static const int READ_ENDPOINT = 0x81;
+ static const int WRITE_ENDPOINT = 0x02;
+ const static int STATUS_OFFLINE = 0xff;
+ const static int STATUS_ONLINE = 0x01;
+ const static uint8_t WheelDirectionThreshold = 0x3f;
+
+ enum LightID {
+ LightRecord = 0,
+ LightTrackrec,
+ LightTrackmute,
+ LightTracksolo,
+ LightAnysolo,
+ LightLoop,
+ LightPunch
+ };
+
+ enum ButtonID {
+ ButtonBattery = 0x00004000,
+ ButtonBacklight = 0x00008000,
+ ButtonTrackLeft = 0x04000000,
+ ButtonTrackRight = 0x40000000,
+ ButtonTrackRec = 0x00040000,
+ ButtonTrackMute = 0x00400000,
+ ButtonTrackSolo = 0x00000400,
+ ButtonUndo = 0x80000000,
+ ButtonIn = 0x02000000,
+ ButtonOut = 0x20000000,
+ ButtonPunch = 0x00800000,
+ ButtonLoop = 0x00080000,
+ ButtonPrev = 0x00020000,
+ ButtonAdd = 0x00200000,
+ ButtonNext = 0x00000200,
+ ButtonRewind = 0x01000000,
+ ButtonFastForward = 0x10000000,
+ ButtonStop = 0x00010000,
+ ButtonPlay = 0x00100000,
+ ButtonRecord = 0x00000100,
+ ButtonShift = 0x08000000
+ };
+
+ enum WheelShiftMode {
+ WheelShiftGain,
+ WheelShiftPan,
+ WheelShiftMaster,
+ WheelShiftMarker
+ };
+
+ enum WheelMode {
+ WheelTimeline,
+ WheelScrub,
+ WheelShuttle
+ };
+
+ // FIXME - look at gtk2_ardour for snap settings
+
+ enum WheelIncrement {
+ WheelIncrSlave,
+ WheelIncrScreen,
+ WheelIncrSample,
+ WheelIncrBeat,
+ WheelIncrBar,
+ WheelIncrSecond,
+ WheelIncrMinute
+ };
+
+ enum DisplayMode {
+ DisplayNormal,
+ DisplayRecording,
+ DisplayRecordingMeter,
+ DisplayBigMeter,
+ DisplayConfig,
+ DisplayBling,
+ DisplayBlingMeter
+ };
+
+ enum BlingMode {
+ BlingOff,
+ BlingKit,
+ BlingRotating,
+ BlingPairs,
+ BlingRows,
+ BlingFlashAll
+ };
+
+ pthread_t thread;
+ uint32_t buttonmask;
+ uint32_t timeout;
+ uint32_t inflight;
+ uint8_t _datawheel;
+ uint8_t _device_status;
+ uint32_t current_track_id;
+ WheelMode wheel_mode;
+ WheelShiftMode wheel_shift_mode;
+ DisplayMode display_mode;
+ BlingMode bling_mode;
+ WheelIncrement wheel_increment;
+ usb_dev_handle* udev;
+
+ ARDOUR::gain_t gain_fraction;
+
+ Glib::Mutex update_lock;
+
+ bool screen_invalid[2][20];
+ char screen_current[2][20];
+ char screen_pending[2][20];
+ char screen_flash[2][20];
+
+ bool lights_invalid[7];
+ bool lights_current[7];
+ bool lights_pending[7];
+ bool lights_flash[7];
+
+ uint32_t last_bars;
+ uint32_t last_beats;
+ uint32_t last_ticks;
+
+ bool last_negative;
+ uint32_t last_hrs;
+ uint32_t last_mins;
+ uint32_t last_secs;
+ uint32_t last_frames;
+ nframes_t last_where;
+ ARDOUR::gain_t last_track_gain;
+ uint32_t last_meter_fill;
+ struct timeval last_wheel_motion;
+ int last_wheel_dir;
+
+ Glib::Mutex io_lock;
+
+ int open ();
+ int read (uint8_t *buf,uint32_t timeout_override = 0);
+ int write (uint8_t* cmd, uint32_t timeout_override = 0);
+ int write_noretry (uint8_t* cmd, uint32_t timeout_override = 0);
+ int close ();
+ int save(char *name = "default");
+ int load(char *name = "default");
+ void print (int row, int col, const char* text);
+ void print_noretry (int row, int col, const char* text);
+
+ int rtpriority_set(int priority = 52);
+ int rtpriority_unset(int priority = 0);
+
+ int open_core (struct usb_device*);
+
+ static void* _monitor_work (void* arg);
+ void* monitor_work ();
+
+ int process (uint8_t *);
+ int update_state();
+ void invalidate();
+ int flush();
+ // bool isuptodate(); // think on this. It seems futile to update more than 30/sec
+
+ // A screen is a cache of what should be on the lcd
+
+ void screen_init();
+ void screen_validate();
+ void screen_invalidate();
+ int screen_flush();
+ void screen_clear();
+ // bool screen_isuptodate(); // think on this -
+
+ // Commands to write to the lcd
+
+ int lcd_init();
+ bool lcd_damage();
+ bool lcd_isdamaged();
+
+ bool lcd_damage(int row, int col = 0, int length = 20);
+ bool lcd_isdamaged(int row, int col = 0, int length = 20);
+
+ int lcd_flush();
+ int lcd_write(uint8_t* cmd, uint32_t timeout_override = 0); // pedantic alias for write
+ void lcd_fill (uint8_t fill_char);
+ void lcd_clear ();
+ void lcd_print (int row, int col, const char* text);
+ void lcd_print_noretry (int row, int col, const char* text);
+
+ // Commands to write to the lights
+ // FIXME - on some devices lights can have intensity and colors
+
+ void lights_init();
+ void lights_validate();
+ void lights_invalidate();
+ void light_validate(LightID light);
+ void light_invalidate(LightID light);
+ int lights_flush();
+ int lights_write(uint8_t* cmd,uint32_t timeout_override = 0); // pedantic alias to write
+
+ // a cache of what should be lit
+
+ void lights_off ();
+ void lights_on ();
+ int light_set(LightID, bool offon = true);
+ int light_on (LightID);
+ int light_off (LightID);
+
+ // some modes for the lights, should probably be renamed
+
+ int lights_show_normal();
+ int lights_show_recording();
+ int lights_show_tempo();
+ int lights_show_bling();
+
+ void enter_big_meter_mode ();
+ void enter_normal_display_mode ();
+ void enter_config_mode();
+ void enter_recording_mode();
+ void enter_bling_mode();
+
+ void next_display_mode ();
+ void normal_update ();
+
+ void show_current_track ();
+ void show_track_gain ();
+ void show_transport_time ();
+ void show_bbt (nframes_t where);
+ void show_smpte (nframes_t where);
+ void show_wheel_mode ();
+ void show_gain ();
+ void show_pan ();
+ void show_meter ();
+
+ void datawheel ();
+ void scrub ();
+ void scroll ();
+ void shuttle ();
+ void config ();
+
+ void next_wheel_mode ();
+ void next_wheel_shift_mode ();
+
+ void set_current_track (ARDOUR::Route*);
+ void next_track ();
+ void prev_track ();
+ void step_gain_up ();
+ void step_gain_down ();
+ void step_pan_right ();
+ void step_pan_left ();
+
+
+ void button_event_battery_press (bool shifted);
+ void button_event_battery_release (bool shifted);
+ void button_event_backlight_press (bool shifted);
+ void button_event_backlight_release (bool shifted);
+ void button_event_trackleft_press (bool shifted);
+ void button_event_trackleft_release (bool shifted);
+ void button_event_trackright_press (bool shifted);
+ void button_event_trackright_release (bool shifted);
+ void button_event_trackrec_press (bool shifted);
+ void button_event_trackrec_release (bool shifted);
+ void button_event_trackmute_press (bool shifted);
+ void button_event_trackmute_release (bool shifted);
+ void button_event_tracksolo_press (bool shifted);
+ void button_event_tracksolo_release (bool shifted);
+ void button_event_undo_press (bool shifted);
+ void button_event_undo_release (bool shifted);
+ void button_event_in_press (bool shifted);
+ void button_event_in_release (bool shifted);
+ void button_event_out_press (bool shifted);
+ void button_event_out_release (bool shifted);
+ void button_event_punch_press (bool shifted);
+ void button_event_punch_release (bool shifted);
+ void button_event_loop_press (bool shifted);
+ void button_event_loop_release (bool shifted);
+ void button_event_prev_press (bool shifted);
+ void button_event_prev_release (bool shifted);
+ void button_event_add_press (bool shifted);
+ void button_event_add_release (bool shifted);
+ void button_event_next_press (bool shifted);
+ void button_event_next_release (bool shifted);
+ void button_event_rewind_press (bool shifted);
+ void button_event_rewind_release (bool shifted);
+ void button_event_fastforward_press (bool shifted);
+ void button_event_fastforward_release (bool shifted);
+ void button_event_stop_press (bool shifted);
+ void button_event_stop_release (bool shifted);
+ void button_event_play_press (bool shifted);
+ void button_event_play_release (bool shifted);
+ void button_event_record_press (bool shifted);
+ void button_event_record_release (bool shifted);
+
+ // new api
+ void button_event_mute (bool pressed, bool shifted);
+};
+
+
+#endif // ardour_tranzport_control_protocol_h
diff --git a/libs/surfaces/generic_midi/SConscript b/libs/surfaces/generic_midi/SConscript
index 6c76e05464..b092188852 100644
--- a/libs/surfaces/generic_midi/SConscript
+++ b/libs/surfaces/generic_midi/SConscript
@@ -40,8 +40,8 @@ genericmidi.Merge ([
libraries['sigc2'],
libraries['usb'],
libraries['xml'],
- libraries['glib2'],
- libraries['glibmm2']
+ libraries['glib2'],
+ libraries['glibmm2']
])
libardour_genericmidi = genericmidi.SharedLibrary('ardour_genericmidi', genericmidi_files)
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index 0256d5c359..1a9570c6a2 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#define __STDC_FORMAT_MACROS 1
@@ -130,7 +129,18 @@ GenericMidiControlProtocol::start_learning (Controllable* c)
return false;
}
- MIDIControllable* mc = new MIDIControllable (*_port, *c);
+ MIDIControllable* mc = 0;
+
+ for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
+ if ((*i)->get_controllable().id() == c->id()) {
+ mc = *i;
+ break;
+ }
+ }
+
+ if (!mc) {
+ mc = new MIDIControllable (*_port, *c);
+ }
{
Glib::Mutex::Lock lm (pending_lock);
@@ -164,6 +174,8 @@ void
GenericMidiControlProtocol::stop_learning (Controllable* c)
{
Glib::Mutex::Lock lm (pending_lock);
+ Glib::Mutex::Lock lm2 (controllables_lock);
+ MIDIControllable* dptr = 0;
/* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
relevant MIDIControllable and remove it from the pending list.
@@ -172,11 +184,22 @@ GenericMidiControlProtocol::stop_learning (Controllable* c)
for (MIDIControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
if (&(*i)->get_controllable() == c) {
(*i)->stop_learning ();
- delete (*i);
+ dptr = *i;
pending_controllables.erase (i);
break;
}
}
+
+ for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
+ if (&(*i)->get_controllable() == c) {
+ controllables.erase (i);
+ break;
+ }
+ }
+
+ if (dptr) {
+ delete dptr;
+ }
}
XMLNode&
@@ -248,7 +271,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node)
ID id = prop->value ();
- c = session->controllable_by_id (id);
+ c = Controllable::by_id (id);
if (c) {
MIDIControllable* mc = new MIDIControllable (*_port, *c);
@@ -257,8 +280,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node)
}
} else {
- warning << string_compose (_("Generic MIDI control: controllable %1 not found in session (ignored)"),
- id)
+ warning << string_compose (_("Generic MIDI control: controllable %1 not found (ignored)"), id)
<< endmsg;
}
}
diff --git a/libs/surfaces/generic_midi/midicontrollable.cc b/libs/surfaces/generic_midi/midicontrollable.cc
index 75b5699f18..7f6f889df5 100644
--- a/libs/surfaces/generic_midi/midicontrollable.cc
+++ b/libs/surfaces/generic_midi/midicontrollable.cc
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: midicontrollable.cc 629 2006-06-21 23:01:03Z paul $
*/
#include <cstdio> /* for sprintf, sigh */
@@ -99,6 +98,8 @@ MIDIControllable::stop_learning ()
void
MIDIControllable::drop_external_control ()
{
+ cerr << "Dropping existing control using " << connections << " connections\n";
+
if (connections > 0) {
midi_sense_connection[0].disconnect ();
}
@@ -279,6 +280,8 @@ MIDIControllable::bind_midi (channel_t chn, eventType ev, MIDI::byte additional)
default:
break;
}
+
+ cerr << "MIDI bound with " << connections << endl;
}
void
diff --git a/libs/surfaces/generic_midi/midicontrollable.h b/libs/surfaces/generic_midi/midicontrollable.h
index 8b63172916..7e0243971c 100644
--- a/libs/surfaces/generic_midi/midicontrollable.h
+++ b/libs/surfaces/generic_midi/midicontrollable.h
@@ -15,7 +15,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: controllable.h 4 2005-05-13 20:47:18Z taybin $
*/
#ifndef __gm_midicontrollable_h__
diff --git a/libs/surfaces/mackie/SConscript b/libs/surfaces/mackie/SConscript
new file mode 100644
index 0000000000..7bd1357cb3
--- /dev/null
+++ b/libs/surfaces/mackie/SConscript
@@ -0,0 +1,74 @@
+# -*- python -*-
+
+import os
+import os.path
+import glob
+
+Import('env final_prefix install_prefix final_config_prefix libraries i18n')
+
+mackie = env.Copy()
+
+#
+# this defines the version number of libardour_mackie
+#
+
+domain = 'ardour_mackie'
+
+mackie.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
+mackie.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
+mackie.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
+mackie.Append(PACKAGE = domain)
+mackie.Append(POTFILE = domain + '.pot')
+
+mackie_files=Split("""
+interface.cc
+midi_byte_array.cc
+controls.cc
+route_signal.cc
+mackie_midi_builder.cc
+mackie_button_handler.cc
+mackie_control_protocol_poll.cc
+surface_port.cc
+mackie_port.cc
+types.cc
+surface.cc
+mackie_control_protocol.cc
+bcf_surface.cc
+mackie_surface.cc
+""")
+
+mackie.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
+mackie.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
+mackie.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
+mackie.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+
+mackie.Merge ([
+ libraries['ardour'],
+ libraries['ardour_cp'],
+ libraries['sigc2'],
+ libraries['pbd'],
+ libraries['midi++2'],
+ libraries['xml'],
+ libraries['glib2'],
+ libraries['glibmm2'],
+ libraries['sndfile-ardour']
+ ])
+
+libardour_mackie = mackie.SharedLibrary('ardour_mackie', mackie_files)
+
+test_files = Split("""
+midi_byte_array.cc
+test.cc
+""")
+mackie_test = Program('mackie_test', test_files )
+
+if mackie['SURFACES']:
+ Default(libardour_mackie)
+ if env['NLS']:
+ i18n (mackie, mackie_files, env)
+ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2','surfaces'), libardour_mackie))
+
+env.Alias('tarball', env.Distribute (env['DISTTREE'],
+ [ 'SConscript' ] +
+ mackie_files +
+ glob.glob('po/*.po') + glob.glob('*.h')))
diff --git a/libs/surfaces/mackie/TODO b/libs/surfaces/mackie/TODO
new file mode 100644
index 0000000000..a9cb1b9878
--- /dev/null
+++ b/libs/surfaces/mackie/TODO
@@ -0,0 +1,45 @@
+* how long can UI signal callbacks take to execute? What happens if they block?
+ where ENSURE_CORRECT_THREAD is a macro that is modelled on ENSURE_GUI_THREAD
+ if the handler is not called in the "correct thread", it will use a pseudo-RT-safe-enough technique to get the correct thread to recall "handler" later on, and return.
+
+* jog with transport rolling doesn't work properly. My use of ScrollTimeline also doesn't work.
+* make loop button sensitive to current transport state
+* make sure rew button can go past the previous if pressed twice, relatively quickly.
+* finish button mapping. Only shifted buttons left for bcf.
+* concurrency for bank switching? And make sure "old" events aren't sent to "new" faders
+* TODOs in code
+* removal of a route results in a strip that isn't dead, but doesn't have any effect on the session
+* use i18n. see string_compose
+* docs in manual, including button assignment diagram
+
+Later
+-----
+* remove commented couts
+* Queueing of writes?
+* Generic surface code to common location
+* bulk remote id changes cause too many surface updates. use Config->remote_model.
+* which bank switching - overlap or dead faders? Option?
+* signals for buttons?
+* MackieControlProtocol in namespace Mackie?
+* power-cycling of surface. fd_midiport doesn't close.
+* mix busses and/or a "bus-only" bank/mode
+* what about surfaces like Mackie C4 and BCR2000?
+
+Need UI integration
+-------------------
+* Some indication on the UI of currently bank-switched-in routes?
+ Useful for surfaces that don't have a scribble strip.
+* use current zoom setting and snap state for shuttle wheel
+
+Actual Mackie
+-------------
+* docs claim that unit will send a host query on init.
+* test Mackie surface object. Apparently led rings don't work. Stereo busses?
+* timecode & 55 char displays
+* midi bandwidth
+
+Bugs
+----
+
+* definitely something wrong with remote_id assignment on session create
+ (master strip assigned 0).
diff --git a/libs/surfaces/mackie/bcf_surface.cc b/libs/surfaces/mackie/bcf_surface.cc
new file mode 100644
index 0000000000..2aaa70fc3e
--- /dev/null
+++ b/libs/surfaces/mackie/bcf_surface.cc
@@ -0,0 +1,1473 @@
+/*
+ Generated by scripts/generate-surface.rb
+*/
+
+#include "bcf_surface.h"
+
+#include "controls.h"
+#include "mackie_button_handler.h"
+
+using namespace Mackie;
+
+void Mackie::BcfSurface::init_controls()
+{
+ // intialise groups and strips
+ Group * group = 0;
+
+ // make sure there are enough strips
+ strips.resize( 7 );
+
+ group = new Group ( "user" );
+ groups["user"] = group;
+
+ group = new Group ( "assignment" );
+ groups["assignment"] = group;
+
+ group = new Group ( "none" );
+ groups["none"] = group;
+
+ group = new MasterStrip ( "master", 0 );
+ groups["master"] = group;
+ strips[0] = dynamic_cast<Strip*>( group );
+
+ group = new Strip ( "strip_1", 0 );
+ groups["strip_1"] = group;
+ strips[0] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "cursor" );
+ groups["cursor"] = group;
+
+ group = new Strip ( "strip_2", 1 );
+ groups["strip_2"] = group;
+ strips[1] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "functions" );
+ groups["functions"] = group;
+
+ group = new Group ( "automation" );
+ groups["automation"] = group;
+
+ group = new Strip ( "strip_3", 2 );
+ groups["strip_3"] = group;
+ strips[2] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "display" );
+ groups["display"] = group;
+
+ group = new Strip ( "strip_4", 3 );
+ groups["strip_4"] = group;
+ strips[3] = dynamic_cast<Strip*>( group );
+
+ group = new Strip ( "strip_5", 4 );
+ groups["strip_5"] = group;
+ strips[4] = dynamic_cast<Strip*>( group );
+
+ group = new Strip ( "strip_6", 5 );
+ groups["strip_6"] = group;
+ strips[5] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "transport" );
+ groups["transport"] = group;
+
+ group = new Strip ( "strip_7", 6 );
+ groups["strip_7"] = group;
+ strips[6] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "modifiers" );
+ groups["modifiers"] = group;
+
+ group = new Group ( "bank" );
+ groups["bank"] = group;
+
+
+ // initialise controls
+ Control * control = 0;
+
+ group = groups["strip_1"];
+ control = new Fader ( 0, 1, "gain", *group );
+ faders[0x00] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Fader ( 1, 2, "gain", *group );
+ faders[0x01] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Fader ( 2, 3, "gain", *group );
+ faders[0x02] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Fader ( 3, 4, "gain", *group );
+ faders[0x03] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Fader ( 4, 5, "gain", *group );
+ faders[0x04] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Fader ( 5, 6, "gain", *group );
+ faders[0x05] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Fader ( 6, 7, "gain", *group );
+ faders[0x06] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["master"];
+ control = new Fader ( 7, 1, "gain", *group );
+ faders[0x07] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Pot ( 16, 1, "vpot", *group );
+ pots[0x10] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Pot ( 17, 2, "vpot", *group );
+ pots[0x11] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Pot ( 18, 3, "vpot", *group );
+ pots[0x12] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Pot ( 19, 4, "vpot", *group );
+ pots[0x13] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Pot ( 20, 5, "vpot", *group );
+ pots[0x14] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Pot ( 21, 6, "vpot", *group );
+ pots[0x15] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Pot ( 22, 7, "vpot", *group );
+ pots[0x16] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Pot ( 23, 1, "jog", *group );
+ pots[0x17] = control;
+ controls.push_back( control );
+ controls_by_name["jog"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Pot ( 46, 1, "external", *group );
+ pots[0x2e] = control;
+ controls.push_back( control );
+ controls_by_name["external"] = control;
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 24, 1, "recenable", *group );
+ buttons[0x18] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 25, 2, "recenable", *group );
+ buttons[0x19] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 26, 3, "recenable", *group );
+ buttons[0x1a] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 27, 4, "recenable", *group );
+ buttons[0x1b] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 28, 5, "recenable", *group );
+ buttons[0x1c] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 29, 6, "recenable", *group );
+ buttons[0x1d] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 30, 7, "recenable", *group );
+ buttons[0x1e] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 32, 1, "solo", *group );
+ buttons[0x20] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 33, 2, "solo", *group );
+ buttons[0x21] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 34, 3, "solo", *group );
+ buttons[0x22] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 35, 4, "solo", *group );
+ buttons[0x23] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 36, 5, "solo", *group );
+ buttons[0x24] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 37, 6, "solo", *group );
+ buttons[0x25] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 38, 7, "solo", *group );
+ buttons[0x26] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 16, 1, "mute", *group );
+ buttons[0x10] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 17, 2, "mute", *group );
+ buttons[0x11] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 18, 3, "mute", *group );
+ buttons[0x12] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 19, 4, "mute", *group );
+ buttons[0x13] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 20, 5, "mute", *group );
+ buttons[0x14] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 21, 6, "mute", *group );
+ buttons[0x15] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 22, 7, "mute", *group );
+ buttons[0x16] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 0, 1, "select", *group );
+ buttons[0x00] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 1, 2, "select", *group );
+ buttons[0x01] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 2, 3, "select", *group );
+ buttons[0x02] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 3, 4, "select", *group );
+ buttons[0x03] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 4, 5, "select", *group );
+ buttons[0x04] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 5, 6, "select", *group );
+ buttons[0x05] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 6, 7, "select", *group );
+ buttons[0x06] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 8, 1, "vselect", *group );
+ buttons[0x08] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 9, 2, "vselect", *group );
+ buttons[0x09] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 10, 3, "vselect", *group );
+ buttons[0x0a] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 11, 4, "vselect", *group );
+ buttons[0x0b] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 12, 5, "vselect", *group );
+ buttons[0x0c] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 13, 6, "vselect", *group );
+ buttons[0x0d] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 14, 7, "vselect", *group );
+ buttons[0x0e] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 40, 1, "io", *group );
+ buttons[0x28] = control;
+ controls.push_back( control );
+ controls_by_name["io"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 90, 1, "sends", *group );
+ buttons[0x5a] = control;
+ controls.push_back( control );
+ controls_by_name["sends"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 89, 1, "pan", *group );
+ buttons[0x59] = control;
+ controls.push_back( control );
+ controls_by_name["pan"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 87, 1, "plugin", *group );
+ buttons[0x57] = control;
+ controls.push_back( control );
+ controls_by_name["plugin"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 88, 1, "eq", *group );
+ buttons[0x58] = control;
+ controls.push_back( control );
+ controls_by_name["eq"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 45, 1, "dyn", *group );
+ buttons[0x2d] = control;
+ controls.push_back( control );
+ controls_by_name["dyn"] = control;
+ group->add( *control );
+
+ group = groups["bank"];
+ control = new Button ( 46, 1, "left", *group );
+ buttons[0x2e] = control;
+ controls.push_back( control );
+ controls_by_name["left"] = control;
+ group->add( *control );
+
+ group = groups["bank"];
+ control = new Button ( 47, 1, "right", *group );
+ buttons[0x2f] = control;
+ controls.push_back( control );
+ controls_by_name["right"] = control;
+ group->add( *control );
+
+ group = groups["bank"];
+ control = new Button ( 48, 1, "channel_left", *group );
+ buttons[0x30] = control;
+ controls.push_back( control );
+ controls_by_name["channel_left"] = control;
+ group->add( *control );
+
+ group = groups["bank"];
+ control = new Button ( 49, 1, "channel_right", *group );
+ buttons[0x31] = control;
+ controls.push_back( control );
+ controls_by_name["channel_right"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 50, 1, "flip", *group );
+ buttons[0x32] = control;
+ controls.push_back( control );
+ controls_by_name["flip"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 86, 1, "edit", *group );
+ buttons[0x56] = control;
+ controls.push_back( control );
+ controls_by_name["edit"] = control;
+ group->add( *control );
+
+ group = groups["display"];
+ control = new Button ( 52, 1, "name_value", *group );
+ buttons[0x34] = control;
+ controls.push_back( control );
+ controls_by_name["name_value"] = control;
+ group->add( *control );
+
+ group = groups["display"];
+ control = new Button ( 53, 1, "smpte_beats", *group );
+ buttons[0x35] = control;
+ controls.push_back( control );
+ controls_by_name["smpte_beats"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 54, 1, "F1", *group );
+ buttons[0x36] = control;
+ controls.push_back( control );
+ controls_by_name["F1"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 55, 1, "F2", *group );
+ buttons[0x37] = control;
+ controls.push_back( control );
+ controls_by_name["F2"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 56, 1, "F3", *group );
+ buttons[0x38] = control;
+ controls.push_back( control );
+ controls_by_name["F3"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 57, 1, "F4", *group );
+ buttons[0x39] = control;
+ controls.push_back( control );
+ controls_by_name["F4"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 58, 1, "F5", *group );
+ buttons[0x3a] = control;
+ controls.push_back( control );
+ controls_by_name["F5"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 59, 1, "F6", *group );
+ buttons[0x3b] = control;
+ controls.push_back( control );
+ controls_by_name["F6"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 60, 1, "F7", *group );
+ buttons[0x3c] = control;
+ controls.push_back( control );
+ controls_by_name["F7"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 61, 1, "F8", *group );
+ buttons[0x3d] = control;
+ controls.push_back( control );
+ controls_by_name["F8"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 62, 1, "F9", *group );
+ buttons[0x3e] = control;
+ controls.push_back( control );
+ controls_by_name["F9"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 63, 1, "F10", *group );
+ buttons[0x3f] = control;
+ controls.push_back( control );
+ controls_by_name["F10"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 64, 1, "F11", *group );
+ buttons[0x40] = control;
+ controls.push_back( control );
+ controls_by_name["F11"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 65, 1, "F12", *group );
+ buttons[0x41] = control;
+ controls.push_back( control );
+ controls_by_name["F12"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 66, 1, "F13", *group );
+ buttons[0x42] = control;
+ controls.push_back( control );
+ controls_by_name["F13"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 67, 1, "F14", *group );
+ buttons[0x43] = control;
+ controls.push_back( control );
+ controls_by_name["F14"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 68, 1, "F15", *group );
+ buttons[0x44] = control;
+ controls.push_back( control );
+ controls_by_name["F15"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 69, 1, "F16", *group );
+ buttons[0x45] = control;
+ controls.push_back( control );
+ controls_by_name["F16"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 39, 1, "global_solo", *group );
+ buttons[0x27] = control;
+ controls.push_back( control );
+ controls_by_name["global_solo"] = control;
+ group->add( *control );
+
+ group = groups["modifiers"];
+ control = new Button ( 71, 1, "option", *group );
+ buttons[0x47] = control;
+ controls.push_back( control );
+ controls_by_name["option"] = control;
+ group->add( *control );
+
+ group = groups["modifiers"];
+ control = new Button ( 72, 1, "control", *group );
+ buttons[0x48] = control;
+ controls.push_back( control );
+ controls_by_name["control"] = control;
+ group->add( *control );
+
+ group = groups["modifiers"];
+ control = new Button ( 73, 1, "cmd_alt", *group );
+ buttons[0x49] = control;
+ controls.push_back( control );
+ controls_by_name["cmd_alt"] = control;
+ group->add( *control );
+
+ group = groups["automation"];
+ control = new Button ( 74, 1, "on", *group );
+ buttons[0x4a] = control;
+ controls.push_back( control );
+ controls_by_name["on"] = control;
+ group->add( *control );
+
+ group = groups["automation"];
+ control = new Button ( 75, 1, "rec_ready", *group );
+ buttons[0x4b] = control;
+ controls.push_back( control );
+ controls_by_name["rec_ready"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 76, 1, "undo", *group );
+ buttons[0x4c] = control;
+ controls.push_back( control );
+ controls_by_name["undo"] = control;
+ group->add( *control );
+
+ group = groups["automation"];
+ control = new Button ( 77, 1, "snapshot", *group );
+ buttons[0x4d] = control;
+ controls.push_back( control );
+ controls_by_name["snapshot"] = control;
+ group->add( *control );
+
+ group = groups["automation"];
+ control = new Button ( 78, 1, "touch", *group );
+ buttons[0x4e] = control;
+ controls.push_back( control );
+ controls_by_name["touch"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 79, 1, "redo", *group );
+ buttons[0x4f] = control;
+ controls.push_back( control );
+ controls_by_name["redo"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 80, 1, "marker", *group );
+ buttons[0x50] = control;
+ controls.push_back( control );
+ controls_by_name["marker"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 81, 1, "enter", *group );
+ buttons[0x51] = control;
+ controls.push_back( control );
+ controls_by_name["enter"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 82, 1, "cancel", *group );
+ buttons[0x52] = control;
+ controls.push_back( control );
+ controls_by_name["cancel"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 83, 1, "mixer", *group );
+ buttons[0x53] = control;
+ controls.push_back( control );
+ controls_by_name["mixer"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 84, 1, "frm_left", *group );
+ buttons[0x54] = control;
+ controls.push_back( control );
+ controls_by_name["frm_left"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 85, 1, "frm_right", *group );
+ buttons[0x55] = control;
+ controls.push_back( control );
+ controls_by_name["frm_right"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 70, 1, "loop", *group );
+ buttons[0x46] = control;
+ controls.push_back( control );
+ controls_by_name["loop"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 44, 1, "punch_in", *group );
+ buttons[0x2c] = control;
+ controls.push_back( control );
+ controls_by_name["punch_in"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 43, 1, "punch_out", *group );
+ buttons[0x2b] = control;
+ controls.push_back( control );
+ controls_by_name["punch_out"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 42, 1, "home", *group );
+ buttons[0x2a] = control;
+ controls.push_back( control );
+ controls_by_name["home"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 41, 1, "end", *group );
+ buttons[0x29] = control;
+ controls.push_back( control );
+ controls_by_name["end"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 91, 1, "rewind", *group );
+ buttons[0x5b] = control;
+ controls.push_back( control );
+ controls_by_name["rewind"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 92, 1, "ffwd", *group );
+ buttons[0x5c] = control;
+ controls.push_back( control );
+ controls_by_name["ffwd"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 93, 1, "stop", *group );
+ buttons[0x5d] = control;
+ controls.push_back( control );
+ controls_by_name["stop"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 94, 1, "play", *group );
+ buttons[0x5e] = control;
+ controls.push_back( control );
+ controls_by_name["play"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 31, 1, "record", *group );
+ buttons[0x1f] = control;
+ controls.push_back( control );
+ controls_by_name["record"] = control;
+ group->add( *control );
+
+ group = groups["cursor"];
+ control = new Button ( 96, 1, "cursor_up", *group );
+ buttons[0x60] = control;
+ controls.push_back( control );
+ controls_by_name["cursor_up"] = control;
+ group->add( *control );
+
+ group = groups["cursor"];
+ control = new Button ( 97, 1, "cursor_down", *group );
+ buttons[0x61] = control;
+ controls.push_back( control );
+ controls_by_name["cursor_down"] = control;
+ group->add( *control );
+
+ group = groups["cursor"];
+ control = new Button ( 98, 1, "cursor_left", *group );
+ buttons[0x62] = control;
+ controls.push_back( control );
+ controls_by_name["cursor_left"] = control;
+ group->add( *control );
+
+ group = groups["cursor"];
+ control = new Button ( 99, 1, "cursor_right", *group );
+ buttons[0x63] = control;
+ controls.push_back( control );
+ controls_by_name["cursor_right"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 100, 1, "zoom", *group );
+ buttons[0x64] = control;
+ controls.push_back( control );
+ controls_by_name["zoom"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 101, 1, "scrub", *group );
+ buttons[0x65] = control;
+ controls.push_back( control );
+ controls_by_name["scrub"] = control;
+ group->add( *control );
+
+ group = groups["user"];
+ control = new Button ( 102, 1, "user_a", *group );
+ buttons[0x66] = control;
+ controls.push_back( control );
+ controls_by_name["user_a"] = control;
+ group->add( *control );
+
+ group = groups["user"];
+ control = new Button ( 103, 1, "user_b", *group );
+ buttons[0x67] = control;
+ controls.push_back( control );
+ controls_by_name["user_b"] = control;
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 104, 1, "fader_touch", *group );
+ buttons[0x68] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 105, 2, "fader_touch", *group );
+ buttons[0x69] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 106, 3, "fader_touch", *group );
+ buttons[0x6a] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 107, 4, "fader_touch", *group );
+ buttons[0x6b] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 108, 5, "fader_touch", *group );
+ buttons[0x6c] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 109, 6, "fader_touch", *group );
+ buttons[0x6d] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 110, 7, "fader_touch", *group );
+ buttons[0x6e] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["master"];
+ control = new Button ( 111, 1, "fader_touch", *group );
+ buttons[0x6f] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["master"];
+ control = new Button ( 23, 1, "mute", *group );
+ buttons[0x17] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 51, 1, "clicking", *group );
+ buttons[0x33] = control;
+ controls.push_back( control );
+ controls_by_name["clicking"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Led ( 113, 1, "smpte", *group );
+ leds[0x71] = control;
+ controls.push_back( control );
+ controls_by_name["smpte"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Led ( 114, 1, "beats", *group );
+ leds[0x72] = control;
+ controls.push_back( control );
+ controls_by_name["beats"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Led ( 115, 1, "solo", *group );
+ leds[0x73] = control;
+ controls.push_back( control );
+ controls_by_name["solo"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Led ( 118, 1, "relay_click", *group );
+ leds[0x76] = control;
+ controls.push_back( control );
+ controls_by_name["relay_click"] = control;
+ group->add( *control );
+
+}
+
+void Mackie::BcfSurface::handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button )
+{
+ if ( bs != press && bs != release )
+ {
+ mbh.update_led( button, none );
+ return;
+ }
+
+ LedState ls;
+ switch ( button.id() )
+ {
+
+ case 0x28: // io
+ switch ( bs ) {
+ case press: ls = mbh.io_press( button ); break;
+ case release: ls = mbh.io_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5a: // sends
+ switch ( bs ) {
+ case press: ls = mbh.sends_press( button ); break;
+ case release: ls = mbh.sends_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x59: // pan
+ switch ( bs ) {
+ case press: ls = mbh.pan_press( button ); break;
+ case release: ls = mbh.pan_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x57: // plugin
+ switch ( bs ) {
+ case press: ls = mbh.plugin_press( button ); break;
+ case release: ls = mbh.plugin_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x58: // eq
+ switch ( bs ) {
+ case press: ls = mbh.eq_press( button ); break;
+ case release: ls = mbh.eq_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2d: // dyn
+ switch ( bs ) {
+ case press: ls = mbh.dyn_press( button ); break;
+ case release: ls = mbh.dyn_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2e: // left
+ switch ( bs ) {
+ case press: ls = mbh.left_press( button ); break;
+ case release: ls = mbh.left_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2f: // right
+ switch ( bs ) {
+ case press: ls = mbh.right_press( button ); break;
+ case release: ls = mbh.right_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x30: // channel_left
+ switch ( bs ) {
+ case press: ls = mbh.channel_left_press( button ); break;
+ case release: ls = mbh.channel_left_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x31: // channel_right
+ switch ( bs ) {
+ case press: ls = mbh.channel_right_press( button ); break;
+ case release: ls = mbh.channel_right_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x32: // flip
+ switch ( bs ) {
+ case press: ls = mbh.flip_press( button ); break;
+ case release: ls = mbh.flip_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x56: // edit
+ switch ( bs ) {
+ case press: ls = mbh.edit_press( button ); break;
+ case release: ls = mbh.edit_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x34: // name_value
+ switch ( bs ) {
+ case press: ls = mbh.name_value_press( button ); break;
+ case release: ls = mbh.name_value_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x35: // smpte_beats
+ switch ( bs ) {
+ case press: ls = mbh.smpte_beats_press( button ); break;
+ case release: ls = mbh.smpte_beats_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x36: // F1
+ switch ( bs ) {
+ case press: ls = mbh.F1_press( button ); break;
+ case release: ls = mbh.F1_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x37: // F2
+ switch ( bs ) {
+ case press: ls = mbh.F2_press( button ); break;
+ case release: ls = mbh.F2_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x38: // F3
+ switch ( bs ) {
+ case press: ls = mbh.F3_press( button ); break;
+ case release: ls = mbh.F3_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x39: // F4
+ switch ( bs ) {
+ case press: ls = mbh.F4_press( button ); break;
+ case release: ls = mbh.F4_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3a: // F5
+ switch ( bs ) {
+ case press: ls = mbh.F5_press( button ); break;
+ case release: ls = mbh.F5_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3b: // F6
+ switch ( bs ) {
+ case press: ls = mbh.F6_press( button ); break;
+ case release: ls = mbh.F6_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3c: // F7
+ switch ( bs ) {
+ case press: ls = mbh.F7_press( button ); break;
+ case release: ls = mbh.F7_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3d: // F8
+ switch ( bs ) {
+ case press: ls = mbh.F8_press( button ); break;
+ case release: ls = mbh.F8_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3e: // F9
+ switch ( bs ) {
+ case press: ls = mbh.F9_press( button ); break;
+ case release: ls = mbh.F9_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3f: // F10
+ switch ( bs ) {
+ case press: ls = mbh.F10_press( button ); break;
+ case release: ls = mbh.F10_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x40: // F11
+ switch ( bs ) {
+ case press: ls = mbh.F11_press( button ); break;
+ case release: ls = mbh.F11_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x41: // F12
+ switch ( bs ) {
+ case press: ls = mbh.F12_press( button ); break;
+ case release: ls = mbh.F12_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x42: // F13
+ switch ( bs ) {
+ case press: ls = mbh.F13_press( button ); break;
+ case release: ls = mbh.F13_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x43: // F14
+ switch ( bs ) {
+ case press: ls = mbh.F14_press( button ); break;
+ case release: ls = mbh.F14_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x44: // F15
+ switch ( bs ) {
+ case press: ls = mbh.F15_press( button ); break;
+ case release: ls = mbh.F15_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x45: // F16
+ switch ( bs ) {
+ case press: ls = mbh.F16_press( button ); break;
+ case release: ls = mbh.F16_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x27: // global_solo
+ switch ( bs ) {
+ case press: ls = mbh.global_solo_press( button ); break;
+ case release: ls = mbh.global_solo_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x47: // option
+ switch ( bs ) {
+ case press: ls = mbh.option_press( button ); break;
+ case release: ls = mbh.option_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x48: // control
+ switch ( bs ) {
+ case press: ls = mbh.control_press( button ); break;
+ case release: ls = mbh.control_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x49: // cmd_alt
+ switch ( bs ) {
+ case press: ls = mbh.cmd_alt_press( button ); break;
+ case release: ls = mbh.cmd_alt_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4a: // on
+ switch ( bs ) {
+ case press: ls = mbh.on_press( button ); break;
+ case release: ls = mbh.on_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4b: // rec_ready
+ switch ( bs ) {
+ case press: ls = mbh.rec_ready_press( button ); break;
+ case release: ls = mbh.rec_ready_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4c: // undo
+ switch ( bs ) {
+ case press: ls = mbh.undo_press( button ); break;
+ case release: ls = mbh.undo_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4d: // snapshot
+ switch ( bs ) {
+ case press: ls = mbh.snapshot_press( button ); break;
+ case release: ls = mbh.snapshot_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4e: // touch
+ switch ( bs ) {
+ case press: ls = mbh.touch_press( button ); break;
+ case release: ls = mbh.touch_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4f: // redo
+ switch ( bs ) {
+ case press: ls = mbh.redo_press( button ); break;
+ case release: ls = mbh.redo_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x50: // marker
+ switch ( bs ) {
+ case press: ls = mbh.marker_press( button ); break;
+ case release: ls = mbh.marker_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x51: // enter
+ switch ( bs ) {
+ case press: ls = mbh.enter_press( button ); break;
+ case release: ls = mbh.enter_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x52: // cancel
+ switch ( bs ) {
+ case press: ls = mbh.cancel_press( button ); break;
+ case release: ls = mbh.cancel_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x53: // mixer
+ switch ( bs ) {
+ case press: ls = mbh.mixer_press( button ); break;
+ case release: ls = mbh.mixer_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x54: // frm_left
+ switch ( bs ) {
+ case press: ls = mbh.frm_left_press( button ); break;
+ case release: ls = mbh.frm_left_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x55: // frm_right
+ switch ( bs ) {
+ case press: ls = mbh.frm_right_press( button ); break;
+ case release: ls = mbh.frm_right_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x46: // loop
+ switch ( bs ) {
+ case press: ls = mbh.loop_press( button ); break;
+ case release: ls = mbh.loop_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2c: // punch_in
+ switch ( bs ) {
+ case press: ls = mbh.punch_in_press( button ); break;
+ case release: ls = mbh.punch_in_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2b: // punch_out
+ switch ( bs ) {
+ case press: ls = mbh.punch_out_press( button ); break;
+ case release: ls = mbh.punch_out_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2a: // home
+ switch ( bs ) {
+ case press: ls = mbh.home_press( button ); break;
+ case release: ls = mbh.home_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x29: // end
+ switch ( bs ) {
+ case press: ls = mbh.end_press( button ); break;
+ case release: ls = mbh.end_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5b: // rewind
+ switch ( bs ) {
+ case press: ls = mbh.rewind_press( button ); break;
+ case release: ls = mbh.rewind_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5c: // ffwd
+ switch ( bs ) {
+ case press: ls = mbh.ffwd_press( button ); break;
+ case release: ls = mbh.ffwd_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5d: // stop
+ switch ( bs ) {
+ case press: ls = mbh.stop_press( button ); break;
+ case release: ls = mbh.stop_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5e: // play
+ switch ( bs ) {
+ case press: ls = mbh.play_press( button ); break;
+ case release: ls = mbh.play_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x1f: // record
+ switch ( bs ) {
+ case press: ls = mbh.record_press( button ); break;
+ case release: ls = mbh.record_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x60: // cursor_up
+ switch ( bs ) {
+ case press: ls = mbh.cursor_up_press( button ); break;
+ case release: ls = mbh.cursor_up_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x61: // cursor_down
+ switch ( bs ) {
+ case press: ls = mbh.cursor_down_press( button ); break;
+ case release: ls = mbh.cursor_down_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x62: // cursor_left
+ switch ( bs ) {
+ case press: ls = mbh.cursor_left_press( button ); break;
+ case release: ls = mbh.cursor_left_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x63: // cursor_right
+ switch ( bs ) {
+ case press: ls = mbh.cursor_right_press( button ); break;
+ case release: ls = mbh.cursor_right_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x64: // zoom
+ switch ( bs ) {
+ case press: ls = mbh.zoom_press( button ); break;
+ case release: ls = mbh.zoom_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x65: // scrub
+ switch ( bs ) {
+ case press: ls = mbh.scrub_press( button ); break;
+ case release: ls = mbh.scrub_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x66: // user_a
+ switch ( bs ) {
+ case press: ls = mbh.user_a_press( button ); break;
+ case release: ls = mbh.user_a_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x67: // user_b
+ switch ( bs ) {
+ case press: ls = mbh.user_b_press( button ); break;
+ case release: ls = mbh.user_b_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x33: // clicking
+ switch ( bs ) {
+ case press: ls = mbh.clicking_press( button ); break;
+ case release: ls = mbh.clicking_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ }
+ mbh.update_led( button, ls );
+}
diff --git a/libs/surfaces/mackie/bcf_surface.h b/libs/surfaces/mackie/bcf_surface.h
new file mode 100644
index 0000000000..a5fd3bf5a3
--- /dev/null
+++ b/libs/surfaces/mackie/bcf_surface.h
@@ -0,0 +1,27 @@
+#ifndef mackie_surface_bcf_h
+#define mackie_surface_bcf_h
+/*
+ Generated by scripts/generate-surface.rb
+*/
+
+#include "surface.h"
+
+namespace Mackie
+{
+
+class MackieButtonHandler;
+
+class BcfSurface : public Surface
+{
+public:
+ BcfSurface( uint32_t max_strips ) : Surface( max_strips )
+ {
+ }
+
+ virtual void handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button );
+ virtual void init_controls();
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/controls.cc b/libs/surfaces/mackie/controls.cc
new file mode 100644
index 0000000000..e9808119b2
--- /dev/null
+++ b/libs/surfaces/mackie/controls.cc
@@ -0,0 +1,109 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "controls.h"
+#include "types.h"
+#include "mackie_midi_builder.h"
+
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+using namespace Mackie;
+using namespace std;
+
+void Group::add( Control & control )
+{
+ _controls.push_back( &control );
+}
+
+Strip::Strip( const std::string & name, int index )
+ : Group( name )
+ , _solo( 0 )
+ , _recenable( 0 )
+ , _mute( 0 )
+ , _select( 0 )
+ , _vselect( 0 )
+ , _fader_touch( 0 )
+ , _vpot( 0 )
+ , _gain( 0 )
+ , _index( index )
+{
+}
+
+/**
+ generated with
+
+controls[1].each do |x|
+ puts <<EOF
+#{x.class.name} & Strip::#{x.name}()
+{
+ if ( _#{x.name} == 0 )
+ throw MackieControlException( "#{x.name} is null" );
+ return *_#{x.name};
+}
+EOF
+end
+*/
+Fader & Strip::gain()
+{
+ if ( _gain == 0 )
+ throw MackieControlException( "gain is null" );
+ return *_gain;
+}
+Pot & Strip::vpot()
+{
+ if ( _vpot == 0 )
+ throw MackieControlException( "vpot is null" );
+ return *_vpot;
+}
+Button & Strip::recenable()
+{
+ if ( _recenable == 0 )
+ throw MackieControlException( "recenable is null" );
+ return *_recenable;
+}
+Button & Strip::solo()
+{
+ if ( _solo == 0 )
+ throw MackieControlException( "solo is null" );
+ return *_solo;
+}
+Button & Strip::mute()
+{
+ if ( _mute == 0 )
+ throw MackieControlException( "mute is null" );
+ return *_mute;
+}
+Button & Strip::select()
+{
+ if ( _select == 0 )
+ throw MackieControlException( "select is null" );
+ return *_select;
+}
+Button & Strip::vselect()
+{
+ if ( _vselect == 0 )
+ throw MackieControlException( "vselect is null" );
+ return *_vselect;
+}
+Button & Strip::fader_touch()
+{
+ if ( _fader_touch == 0 )
+ throw MackieControlException( "fader_touch is null" );
+ return *_fader_touch;
+}
diff --git a/libs/surfaces/mackie/controls.h b/libs/surfaces/mackie/controls.h
new file mode 100644
index 0000000000..1092c40453
--- /dev/null
+++ b/libs/surfaces/mackie/controls.h
@@ -0,0 +1,301 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef mackie_controls_h
+#define mackie_controls_h
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "mackie_control_exception.h"
+
+namespace Mackie
+{
+
+class Control;
+
+/**
+ This is a loose group of controls, eg cursor buttons,
+ transport buttons, functions buttons etc.
+*/
+class Group
+{
+public:
+ Group( const std::string & name )
+ : _name( name )
+ {
+ }
+
+ virtual ~Group() {}
+
+ virtual bool is_strip() const
+ {
+ return false;
+ }
+
+ virtual bool is_master() const
+ {
+ return false;
+ }
+
+ virtual void add( Control & control );
+
+ const std::string & name() const
+ {
+ return _name;
+ }
+
+ // This is for Surface only
+ void name( const std::string & rhs ) { _name = rhs; }
+
+ typedef std::vector<Control*> Controls;
+ const Controls & controls() const { return _controls; }
+
+protected:
+ Controls _controls;
+
+private:
+ std::string _name;
+};
+
+class Button;
+class Pot;
+class Fader;
+
+/**
+ This is the set of controls that make up a strip.
+*/
+class Strip : public Group
+{
+public:
+ Strip( const std::string & name, int index );
+
+ virtual bool is_strip() const
+ {
+ return true;
+ }
+
+ virtual void add( Control & control );
+
+ /// This is the index of the strip
+ int index() const { return _index; }
+
+ /// This is for Surface only
+ void index( int rhs ) { _index = rhs; }
+
+ Button & solo();
+ Button & recenable();
+ Button & mute();
+ Button & select();
+ Button & vselect();
+ Button & fader_touch();
+ Pot & vpot();
+ Fader & gain();
+
+ bool has_solo() { return _solo != 0; }
+ bool has_recenable() { return _recenable != 0; }
+ bool has_mute() { return _mute != 0; }
+ bool has_select() { return _select != 0; }
+ bool has_vselect() { return _vselect != 0; }
+ bool has_fader_touch() { return _fader_touch != 0; }
+ bool has_vpot() { return _vpot != 0; }
+ bool has_gain() { return _gain != 0; }
+
+private:
+ Button * _solo;
+ Button * _recenable;
+ Button * _mute;
+ Button * _select;
+ Button * _vselect;
+ Button * _fader_touch;
+ Pot * _vpot;
+ Fader * _gain;
+ int _index;
+};
+
+class MasterStrip : public Strip
+{
+public:
+ MasterStrip( const std::string & name, int index )
+ : Strip( name, index )
+ {
+ }
+
+ virtual bool is_master() const
+ {
+ return true;
+ }
+};
+
+class Led;
+
+/**
+ The base class for controls on the surface. They deliberately
+ don't know the midi protocol for updating them.
+*/
+class Control
+{
+public:
+ enum type_t { type_fader, type_button, type_pot, type_led, type_led_ring };
+
+ Control( int id, int ordinal, std::string name, Group & group )
+ : _id( id ), _ordinal( ordinal ), _name( name ), _group( group )
+ {
+ }
+
+ virtual ~Control() {}
+
+ virtual const Led & led() const
+ {
+ throw MackieControlException( "no led available" );
+ }
+
+ /// The midi id of the control
+ int id() const
+ {
+ return _id;
+ }
+
+ /// The 1-based number of the control
+ int ordinal() const
+ {
+ return _ordinal;
+ }
+
+ const std::string & name() const
+ {
+ return _name;
+ }
+
+ const Group & group() const
+ {
+ return _group;
+ }
+
+ const Strip & strip() const
+ {
+ return dynamic_cast<const Strip&>( _group );
+ }
+
+ Strip & strip()
+ {
+ return dynamic_cast<Strip&>( _group );
+ }
+
+ virtual bool accepts_feedback() const
+ {
+ return true;
+ }
+
+ virtual type_t type() const = 0;
+
+private:
+ int _id;
+ int _ordinal;
+ std::string _name;
+ Group & _group;
+};
+
+std::ostream & operator << ( std::ostream & os, const Control & control );
+
+class Fader : public Control
+{
+public:
+ Fader( int id, int ordinal, std::string name, Group & group )
+ : Control( id, ordinal, name, group )
+ , _touch( false )
+ {
+ }
+
+ bool touch() const { return _touch; }
+
+ void touch( bool yn ) { _touch = yn; }
+
+ virtual type_t type() const { return type_fader; }
+
+private:
+ bool _touch;
+};
+
+class Led : public Control
+{
+public:
+ Led( int id, int ordinal, std::string name, Group & group )
+ : Control( id, ordinal, name, group )
+ {
+ }
+
+ virtual const Led & led() const { return *this; }
+
+ virtual type_t type() const { return type_led; }
+};
+
+class Button : public Control
+{
+public:
+ Button( int id, int ordinal, std::string name, Group & group )
+ : Control( id, ordinal, name, group )
+ , _led( id, ordinal, name + "_led", group )
+ {
+ }
+
+ virtual const Led & led() const
+ {
+ return _led;
+ }
+
+ virtual type_t type() const { return type_button; };
+
+private:
+ Led _led;
+};
+
+class LedRing : public Led
+{
+public:
+ LedRing( int id, int ordinal, std::string name, Group & group )
+ : Led( id, ordinal, name, group )
+ {
+ }
+
+ virtual type_t type() const { return type_led_ring; }
+};
+
+class Pot : public Control
+{
+public:
+ Pot( int id, int ordinal, std::string name, Group & group )
+ : Control( id, ordinal, name, group )
+ , _led_ring( id, ordinal, name + "_ring", group )
+ {
+ }
+
+ virtual type_t type() const { return type_pot; }
+
+ virtual const LedRing & led_ring() const
+ {
+ return _led_ring;
+ }
+
+private:
+ LedRing _led_ring;
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/interface.cc b/libs/surfaces/mackie/interface.cc
new file mode 100644
index 0000000000..eda485b5d6
--- /dev/null
+++ b/libs/surfaces/mackie/interface.cc
@@ -0,0 +1,96 @@
+/*
+ Copyright (C) 2006,2007 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include <control_protocol/control_protocol.h>
+#include "mackie_control_protocol.h"
+
+#include <pbd/error.h>
+
+#include <stdexcept>
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace std;
+
+ControlProtocol*
+new_mackie_protocol (ControlProtocolDescriptor* descriptor, Session* s)
+{
+ if ( Config->get_mmc_port_name().substr(0,3) == "mcu" )
+ {
+ error << "mcu already used as mmc port" << endmsg;
+ }
+ else if ( Config->get_mtc_port_name().substr(0,3) == "mcu" )
+ {
+ error << "mcu already used as mtc port" << endmsg;
+ }
+ else if ( Config->get_midi_port_name().substr(0,3) == "mcu" )
+ {
+ error << "mcu already used as midi port" << endmsg;
+ }
+ else
+ {
+ // no one else is using the port, so try instantiate the object
+ MackieControlProtocol * mcp = 0;
+ try
+ {
+ mcp = new MackieControlProtocol (*s);
+ mcp->set_active( true );
+ }
+ catch( exception & e )
+ {
+ error << "Error instantiating MackieControlProtocol: " << e.what() << endmsg;
+ delete mcp;
+ mcp = 0;
+ }
+ return mcp;
+ }
+ return 0;
+}
+
+void
+delete_mackie_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
+{
+ delete cp;
+}
+
+bool
+probe_mackie_protocol (ControlProtocolDescriptor* descriptor)
+{
+ return MackieControlProtocol::probe();
+}
+
+static ControlProtocolDescriptor mackie_descriptor = {
+ name : "Mackie",
+ id : "uri://ardour.org/surfaces/mackie:0",
+ ptr : 0,
+ module : 0,
+ mandatory : 0,
+ supports_feedback : true,
+ probe : probe_mackie_protocol,
+ initialize : new_mackie_protocol,
+ destroy : delete_mackie_protocol
+};
+
+
+extern "C" {
+
+ControlProtocolDescriptor*
+protocol_descriptor () {
+ return &mackie_descriptor;
+}
+
+}
diff --git a/libs/surfaces/mackie/mackie_button_handler.cc b/libs/surfaces/mackie/mackie_button_handler.cc
new file mode 100644
index 0000000000..f7ac2ab6d5
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_button_handler.cc
@@ -0,0 +1,691 @@
+/*
+ Generated by scripts/generate-button-handlers.erb
+*/
+#include "mackie_button_handler.h"
+#include "controls.h"
+
+#include <iostream>
+
+using namespace std;
+using namespace Mackie;
+
+LedState MackieButtonHandler::default_button_press( Button & button )
+{
+ cout << "press: " << button << endl;
+ return on;
+}
+LedState MackieButtonHandler::default_button_release( Button & button )
+{
+ cout << "release: " << button << endl;
+ return off;
+}
+
+LedState MackieButtonHandler::io_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::io_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::sends_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::sends_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::pan_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::pan_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::plugin_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::plugin_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::eq_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::eq_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::dyn_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::dyn_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::left_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::left_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::right_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::right_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::channel_left_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::channel_left_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::channel_right_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::channel_right_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::flip_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::flip_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::edit_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::edit_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::name_value_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::name_value_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::smpte_beats_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::smpte_beats_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F1_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F1_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F2_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F2_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F3_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F3_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F4_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F4_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F5_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F5_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F6_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F6_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F7_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F7_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F8_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F8_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F9_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F9_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F10_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F10_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F11_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F11_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F12_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F12_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F13_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F13_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F14_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F14_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F15_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F15_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::F16_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::F16_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::shift_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::shift_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::option_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::option_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::control_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::control_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::cmd_alt_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::cmd_alt_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::on_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::on_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::rec_ready_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::rec_ready_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::undo_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::undo_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::snapshot_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::snapshot_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::touch_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::touch_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::redo_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::redo_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::marker_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::marker_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::enter_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::enter_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::cancel_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::cancel_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::mixer_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::mixer_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::frm_left_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::frm_left_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::frm_right_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::frm_right_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::loop_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::loop_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::punch_in_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::punch_in_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::punch_out_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::punch_out_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::home_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::home_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::end_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::end_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::rewind_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::rewind_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::ffwd_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::ffwd_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::stop_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::stop_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::play_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::play_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::record_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::record_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::cursor_up_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::cursor_up_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::cursor_down_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::cursor_down_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::cursor_left_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::cursor_left_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::cursor_right_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::cursor_right_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::zoom_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::zoom_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::scrub_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::scrub_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::user_a_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::user_a_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::user_b_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::user_b_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::fader_touch_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::fader_touch_release( Button & button )
+{
+ return default_button_release( button );
+}
+
+LedState MackieButtonHandler::clicking_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::clicking_release( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::global_solo_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::global_solo_release( Button & button )
+{
+ return default_button_press( button );
+}
diff --git a/libs/surfaces/mackie/mackie_button_handler.h b/libs/surfaces/mackie/mackie_button_handler.h
new file mode 100644
index 0000000000..ee4187c7ce
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_button_handler.h
@@ -0,0 +1,227 @@
+#ifndef mackie_button_handler_h
+#define mackie_button_handler_h
+/*
+ Generated by scripts/generate-button-handlers.erb
+*/
+
+#include "types.h"
+
+namespace Mackie
+{
+
+class MackieButtonHandler
+{
+public:
+ virtual ~MackieButtonHandler() {}
+
+ virtual LedState default_button_press( Button & button );
+ virtual LedState default_button_release( Button & button );
+
+ virtual void update_led( Button & button, LedState ls ) = 0;
+
+
+ virtual LedState io_press( Button & );
+ virtual LedState io_release( Button & );
+
+ virtual LedState sends_press( Button & );
+ virtual LedState sends_release( Button & );
+
+ virtual LedState pan_press( Button & );
+ virtual LedState pan_release( Button & );
+
+ virtual LedState plugin_press( Button & );
+ virtual LedState plugin_release( Button & );
+
+ virtual LedState eq_press( Button & );
+ virtual LedState eq_release( Button & );
+
+ virtual LedState dyn_press( Button & );
+ virtual LedState dyn_release( Button & );
+
+ virtual LedState left_press( Button & );
+ virtual LedState left_release( Button & );
+
+ virtual LedState right_press( Button & );
+ virtual LedState right_release( Button & );
+
+ virtual LedState channel_left_press( Button & );
+ virtual LedState channel_left_release( Button & );
+
+ virtual LedState channel_right_press( Button & );
+ virtual LedState channel_right_release( Button & );
+
+ virtual LedState flip_press( Button & );
+ virtual LedState flip_release( Button & );
+
+ virtual LedState edit_press( Button & );
+ virtual LedState edit_release( Button & );
+
+ virtual LedState name_value_press( Button & );
+ virtual LedState name_value_release( Button & );
+
+ virtual LedState smpte_beats_press( Button & );
+ virtual LedState smpte_beats_release( Button & );
+
+ virtual LedState F1_press( Button & );
+ virtual LedState F1_release( Button & );
+
+ virtual LedState F2_press( Button & );
+ virtual LedState F2_release( Button & );
+
+ virtual LedState F3_press( Button & );
+ virtual LedState F3_release( Button & );
+
+ virtual LedState F4_press( Button & );
+ virtual LedState F4_release( Button & );
+
+ virtual LedState F5_press( Button & );
+ virtual LedState F5_release( Button & );
+
+ virtual LedState F6_press( Button & );
+ virtual LedState F6_release( Button & );
+
+ virtual LedState F7_press( Button & );
+ virtual LedState F7_release( Button & );
+
+ virtual LedState F8_press( Button & );
+ virtual LedState F8_release( Button & );
+
+ virtual LedState F9_press( Button & );
+ virtual LedState F9_release( Button & );
+
+ virtual LedState F10_press( Button & );
+ virtual LedState F10_release( Button & );
+
+ virtual LedState F11_press( Button & );
+ virtual LedState F11_release( Button & );
+
+ virtual LedState F12_press( Button & );
+ virtual LedState F12_release( Button & );
+
+ virtual LedState F13_press( Button & );
+ virtual LedState F13_release( Button & );
+
+ virtual LedState F14_press( Button & );
+ virtual LedState F14_release( Button & );
+
+ virtual LedState F15_press( Button & );
+ virtual LedState F15_release( Button & );
+
+ virtual LedState F16_press( Button & );
+ virtual LedState F16_release( Button & );
+
+ virtual LedState shift_press( Button & );
+ virtual LedState shift_release( Button & );
+
+ virtual LedState option_press( Button & );
+ virtual LedState option_release( Button & );
+
+ virtual LedState control_press( Button & );
+ virtual LedState control_release( Button & );
+
+ virtual LedState cmd_alt_press( Button & );
+ virtual LedState cmd_alt_release( Button & );
+
+ virtual LedState on_press( Button & );
+ virtual LedState on_release( Button & );
+
+ virtual LedState rec_ready_press( Button & );
+ virtual LedState rec_ready_release( Button & );
+
+ virtual LedState undo_press( Button & );
+ virtual LedState undo_release( Button & );
+
+ virtual LedState snapshot_press( Button & );
+ virtual LedState snapshot_release( Button & );
+
+ virtual LedState touch_press( Button & );
+ virtual LedState touch_release( Button & );
+
+ virtual LedState redo_press( Button & );
+ virtual LedState redo_release( Button & );
+
+ virtual LedState marker_press( Button & );
+ virtual LedState marker_release( Button & );
+
+ virtual LedState enter_press( Button & );
+ virtual LedState enter_release( Button & );
+
+ virtual LedState cancel_press( Button & );
+ virtual LedState cancel_release( Button & );
+
+ virtual LedState mixer_press( Button & );
+ virtual LedState mixer_release( Button & );
+
+ virtual LedState frm_left_press( Button & );
+ virtual LedState frm_left_release( Button & );
+
+ virtual LedState frm_right_press( Button & );
+ virtual LedState frm_right_release( Button & );
+
+ virtual LedState loop_press( Button & );
+ virtual LedState loop_release( Button & );
+
+ virtual LedState punch_in_press( Button & );
+ virtual LedState punch_in_release( Button & );
+
+ virtual LedState punch_out_press( Button & );
+ virtual LedState punch_out_release( Button & );
+
+ virtual LedState home_press( Button & );
+ virtual LedState home_release( Button & );
+
+ virtual LedState end_press( Button & );
+ virtual LedState end_release( Button & );
+
+ virtual LedState rewind_press( Button & );
+ virtual LedState rewind_release( Button & );
+
+ virtual LedState ffwd_press( Button & );
+ virtual LedState ffwd_release( Button & );
+
+ virtual LedState stop_press( Button & );
+ virtual LedState stop_release( Button & );
+
+ virtual LedState play_press( Button & );
+ virtual LedState play_release( Button & );
+
+ virtual LedState record_press( Button & );
+ virtual LedState record_release( Button & );
+
+ virtual LedState cursor_up_press( Button & );
+ virtual LedState cursor_up_release( Button & );
+
+ virtual LedState cursor_down_press( Button & );
+ virtual LedState cursor_down_release( Button & );
+
+ virtual LedState cursor_left_press( Button & );
+ virtual LedState cursor_left_release( Button & );
+
+ virtual LedState cursor_right_press( Button & );
+ virtual LedState cursor_right_release( Button & );
+
+ virtual LedState zoom_press( Button & );
+ virtual LedState zoom_release( Button & );
+
+ virtual LedState scrub_press( Button & );
+ virtual LedState scrub_release( Button & );
+
+ virtual LedState user_a_press( Button & );
+ virtual LedState user_a_release( Button & );
+
+ virtual LedState user_b_press( Button & );
+ virtual LedState user_b_release( Button & );
+
+ virtual LedState fader_touch_press( Button & );
+ virtual LedState fader_touch_release( Button & );
+
+ virtual LedState clicking_press( Button & );
+ virtual LedState clicking_release( Button & );
+
+ virtual LedState global_solo_press( Button & );
+ virtual LedState global_solo_release( Button & );
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/mackie_control_exception.h b/libs/surfaces/mackie/mackie_control_exception.h
new file mode 100644
index 0000000000..afe7016948
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_control_exception.h
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef mackie_control_exception_h
+#define mackie_control_exception_h
+
+#include <stdexcept>
+
+namespace Mackie
+{
+
+class MackieControlException : public std::exception
+{
+public:
+ MackieControlException( const std::string & msg )
+ : _msg( msg )
+ {
+ }
+
+ virtual ~MackieControlException() throw () {}
+
+ const char * what() const throw ()
+ {
+ return _msg.c_str();
+ }
+
+private:
+ std::string _msg;
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
new file mode 100644
index 0000000000..81d249588e
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -0,0 +1,1378 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+#include <sstream>
+#include <vector>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <float.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <poll.h>
+
+#include <boost/shared_array.hpp>
+
+#include <midi++/types.h>
+#include <midi++/port.h>
+#include <midi++/manager.h>
+#include <pbd/pthread_utils.h>
+#include <pbd/error.h>
+
+#include <ardour/route.h>
+#include <ardour/session.h>
+#include <ardour/location.h>
+#include <ardour/dB.h>
+#include <ardour/panner.h>
+
+#include "mackie_control_protocol.h"
+
+#include "midi_byte_array.h"
+#include "mackie_control_exception.h"
+#include "route_signal.h"
+#include "mackie_midi_builder.h"
+#include "surface_port.h"
+#include "surface.h"
+#include "bcf_surface.h"
+#include "mackie_surface.h"
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace Mackie;
+using namespace PBD;
+
+using boost::shared_ptr;
+
+#include "i18n.h"
+
+MackieMidiBuilder builder;
+
+// Copied from tranzport_control_protocol.cc
+static inline double
+gain_to_slider_position (ARDOUR::gain_t g)
+{
+ if (g == 0) return 0;
+ return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
+}
+
+/*
+ Copied from tranzport_control_protocol.cc
+ TODO this seems to return slightly wrong values, namely
+ with the UI slider at max, we get a 0.99something value.
+*/
+static inline ARDOUR::gain_t
+slider_position_to_gain (double pos)
+{
+ /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
+ if (pos == 0.0) return 0;
+ return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
+}
+
+MackieControlProtocol::MackieControlProtocol (Session& session)
+ : ControlProtocol (session, X_("Mackie"))
+ , _current_initial_bank( 0 )
+ , connections_back( _connections )
+ , _surface( 0 )
+ , _ports_changed( false )
+ , _polling( true )
+ , pfd( 0 )
+ , nfds( 0 )
+{
+ //cout << "MackieControlProtocol::MackieControlProtocol" << endl;
+ // will start reading from ports, as soon as there are some
+ pthread_create_and_store (X_("mackie monitor"), &thread, 0, _monitor_work, this);
+}
+
+MackieControlProtocol::~MackieControlProtocol()
+{
+ //cout << "~MackieControlProtocol::MackieControlProtocol" << endl;
+ try
+ {
+ close();
+ }
+ catch ( exception & e )
+ {
+ cout << "~MackieControlProtocol caught " << e.what() << endl;
+ }
+ catch ( ... )
+ {
+ cout << "~MackieControlProtocol caught unknown" << endl;
+ }
+ //cout << "finished ~MackieControlProtocol::MackieControlProtocol" << endl;
+}
+
+Mackie::Surface & MackieControlProtocol::surface()
+{
+ if ( _surface == 0 )
+ {
+ throw MackieControlException( "_surface is 0 in MackieControlProtocol::surface" );
+ }
+ return *_surface;
+}
+
+const Mackie::MackiePort & MackieControlProtocol::mcu_port() const
+{
+ return dynamic_cast<const MackiePort &>( *_ports[0] );
+}
+
+Mackie::MackiePort & MackieControlProtocol::mcu_port()
+{
+ return dynamic_cast<const MackiePort &>( *_ports[0] );
+}
+
+// go to the previous track.
+// Assume that get_sorted_routes().size() > route_table.size()
+void MackieControlProtocol::prev_track()
+{
+ if ( _current_initial_bank >= 1 )
+ {
+ session->set_dirty();
+ switch_banks( _current_initial_bank - 1 );
+ }
+}
+
+// go to the next track.
+// Assume that get_sorted_routes().size() > route_table.size()
+void MackieControlProtocol::next_track()
+{
+ Sorted sorted = get_sorted_routes();
+ if ( _current_initial_bank + route_table.size() < sorted.size() )
+ {
+ session->set_dirty();
+ switch_banks( _current_initial_bank + 1 );
+ }
+}
+
+void MackieControlProtocol::clear_route_signals()
+{
+ for( RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it )
+ {
+ delete *it;
+ }
+ route_signals.clear();
+}
+
+// return the port for a given id - 0 based
+// throws an exception if no port found
+MackiePort & MackieControlProtocol::port_for_id( uint32_t index )
+{
+ uint32_t current_max = 0;
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
+ {
+ current_max += (*it)->strips();
+ if ( index < current_max ) return **it;
+ }
+
+ // oops - no matching port
+ ostringstream os;
+ os << "No port for index " << index;
+ throw MackieControlException( os.str() );
+}
+
+// predicate for sort call in get_sorted_routes
+struct RouteByRemoteId
+{
+ bool operator () ( const shared_ptr<Route> & a, const shared_ptr<Route> & b ) const
+ {
+ return a->remote_control_id() < b->remote_control_id();
+ }
+
+ bool operator () ( const Route & a, const Route & b ) const
+ {
+ return a.remote_control_id() < b.remote_control_id();
+ }
+
+ bool operator () ( const Route * a, const Route * b ) const
+ {
+ return a->remote_control_id() < b->remote_control_id();
+ }
+};
+
+MackieControlProtocol::Sorted MackieControlProtocol::get_sorted_routes()
+{
+ Sorted sorted;
+
+ // fetch all routes
+ boost::shared_ptr<Session::RouteList> routes = session->get_routes();
+ set<uint32_t> remote_ids;
+
+ // routes with remote_id 0 should never be added
+ // TODO verify this with ardour devs
+ // remote_ids.insert( 0 );
+
+ // sort in remote_id order, and exclude master, control and hidden routes
+ // and any routes that are already set.
+ for ( Session::RouteList::iterator it = routes->begin(); it != routes->end(); ++it )
+ {
+ Route & route = **it;
+ if (
+ route.active()
+ && !route.master()
+ && !route.hidden()
+ && !route.control()
+ && remote_ids.find( route.remote_control_id() ) == remote_ids.end()
+ )
+ {
+ sorted.push_back( *it );
+ remote_ids.insert( route.remote_control_id() );
+ }
+ }
+ sort( sorted.begin(), sorted.end(), RouteByRemoteId() );
+ return sorted;
+}
+
+void MackieControlProtocol::refresh_current_bank()
+{
+ switch_banks( _current_initial_bank );
+}
+
+void MackieControlProtocol::switch_banks( int initial )
+{
+ // DON'T prevent bank switch if initial == _current_initial_bank
+ // because then this method can't be used as a refresh
+
+ // sanity checking
+ Sorted sorted = get_sorted_routes();
+ int delta = sorted.size() - route_table.size();
+ if ( initial < 0 || ( delta > 0 && initial > delta ) )
+ {
+ cout << "not switching to " << initial << endl;
+ return;
+ }
+ _current_initial_bank = initial;
+
+ // first clear the signals from old routes
+ // taken care of by the RouteSignal destructors
+ clear_route_signals();
+
+ // now set the signals for new routes
+ if ( _current_initial_bank <= sorted.size() )
+ {
+ // fetch the bank start and end to switch to
+ uint32_t end_pos = min( route_table.size(), sorted.size() );
+ Sorted::iterator it = sorted.begin() + _current_initial_bank;
+ Sorted::iterator end = sorted.begin() + _current_initial_bank + end_pos;
+ //cout << "switch to " << _current_initial_bank << ", " << end_pos << endl;
+
+ // link routes to strips
+ uint32_t i = 0;
+ for ( ; it != end && it != sorted.end(); ++it, ++i )
+ {
+ boost::shared_ptr<Route> route = *it;
+ Strip & strip = *surface().strips[i];
+ //cout << "remote id " << route->remote_control_id() << " connecting " << route->name() << " to " << strip.name() << " with port " << port_for_id(i) << endl;
+ route_table[i] = route;
+ RouteSignal * rs = new RouteSignal( *route, *this, strip, port_for_id(i) );
+ route_signals.push_back( rs );
+ // update strip from route
+ rs->notify_all();
+ }
+
+ // create dead strips if there aren't enough routes to
+ // fill a bank
+ for ( ; i < route_table.size(); ++i )
+ {
+ Strip & strip = *surface().strips[i];
+ // send zero for this strip
+ port_for_id(i).write( builder.zero_strip( strip ) );
+ }
+ }
+
+ // display the current start bank.
+ if ( mcu_port().emulation() == MackiePort::bcf2000 )
+ {
+ if ( _current_initial_bank == 0 )
+ {
+ // send Ar. to 2-char display on the master
+ mcu_port().write( builder.two_char_display( "Ar", ".." ) );
+ }
+ else
+ {
+ // write the current first remote_id to the 2-char display
+ mcu_port().write( builder.two_char_display( _current_initial_bank ) );
+ }
+ }
+}
+
+void MackieControlProtocol::zero_all()
+{
+ // TODO turn off 55-char and SMPTE displays
+
+ if ( mcu_port().emulation() == MackiePort::bcf2000 )
+ {
+ // clear 2-char display
+ mcu_port().write( builder.two_char_display( "LC" ) );
+ }
+
+ // zero all strips
+ for ( Surface::Strips::iterator it = surface().strips.begin(); it != surface().strips.end(); ++it )
+ {
+ port_for_id( (*it)->index() ).write( builder.zero_strip( **it ) );
+ }
+
+ // and the master strip
+ mcu_port().write( builder.zero_strip( master_strip() ) );
+
+ // and the led ring for the master strip, in bcf mode
+ if ( mcu_port().emulation() == MackiePort::bcf2000 )
+ {
+ Control & control = *surface().controls_by_name["jog"];
+ mcu_port().write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
+ }
+
+ // turn off global buttons and leds
+ // global buttons are only ever on mcu_port, so we don't have
+ // to figure out which port.
+ for ( Surface::Controls::iterator it = surface().controls.begin(); it != surface().controls.end(); ++it )
+ {
+ Control & control = **it;
+ if ( !control.group().is_strip() && control.accepts_feedback() )
+ {
+ mcu_port().write( builder.zero_control( control ) );
+ }
+ }
+}
+
+int MackieControlProtocol::set_active (bool yn)
+{
+ if ( yn != _active )
+ {
+ try
+ {
+ // the reason for the locking and unlocking is that
+ // glibmm can't do a condition wait on a RecMutex
+ if ( yn )
+ {
+ // TODO what happens if this fails half way?
+
+ // create MackiePorts
+ {
+ Glib::Mutex::Lock lock( update_mutex );
+ create_ports();
+ }
+
+ // make sure the ports are being listened to
+ update_ports();
+
+ // wait until poll thread is running, with ports to poll
+ // the mutex is only there because conditions require a mutex
+ {
+ Glib::Mutex::Lock lock( update_mutex );
+ while ( nfds == 0 ) update_cond.wait( update_mutex );
+ }
+
+ // now initialise MackiePorts - ie exchange sysex messages
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
+ {
+ (*it)->open();
+ }
+
+ // wait until all ports are active
+ // TODO a more sophisticated approach would
+ // allow things to start up with only an MCU, even if
+ // extenders were specified but not responding.
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
+ {
+ (*it)->wait_for_init();
+ }
+
+ // create surface object. This depends on the ports being
+ // correctly initialised
+ initialize_surface();
+ connect_session_signals();
+
+ // yeehah!
+ _active = true;
+
+ // send current control positions to surface
+ // must come after _active = true otherwise it won't run
+ update_surface();
+ }
+ else
+ {
+ close();
+ _active = false;
+ }
+ }
+ catch( exception & e )
+ {
+ cout << "set_active to false because exception caught: " << e.what() << endl;
+ _active = false;
+ throw;
+ }
+ }
+
+ return 0;
+}
+
+bool MackieControlProtocol::handle_strip_button( Control & control, ButtonState bs, boost::shared_ptr<Route> route )
+{
+ bool state = false;
+
+ if ( bs == press )
+ {
+ if ( control.name() == "recenable" )
+ {
+ state = !route->record_enabled();
+ route->set_record_enable( state, this );
+ }
+ else if ( control.name() == "mute" )
+ {
+ state = !route->muted();
+ route->set_mute( state, this );
+ }
+ else if ( control.name() == "solo" )
+ {
+ state = !route->soloed();
+ route->set_solo( state, this );
+ }
+ else if ( control.name() == "select" )
+ {
+ // TODO make the track selected. Whatever that means.
+ //state = default_button_press( dynamic_cast<Button&>( control ) );
+ }
+ else if ( control.name() == "vselect" )
+ {
+ // TODO could be used to select different things to apply the pot to?
+ //state = default_button_press( dynamic_cast<Button&>( control ) );
+ }
+ }
+
+ if ( control.name() == "fader_touch" )
+ {
+ state = bs == press;
+ control.strip().gain().touch( state );
+ }
+
+ return state;
+}
+
+void MackieControlProtocol::update_led( Mackie::Button & button, Mackie::LedState ls )
+{
+ MackiePort * port = 0;
+ if ( button.group().is_strip() )
+ {
+ if ( button.group().is_master() )
+ {
+ port = &mcu_port();
+ }
+ else
+ {
+ port = &port_for_id( dynamic_cast<const Strip&>( button.group() ).index() );
+ }
+ }
+ else
+ {
+ port = &mcu_port();
+ }
+ if ( ls != none ) port->write( builder.build_led( button, ls ) );
+}
+
+void MackieControlProtocol::update_global_button( const string & name, LedState ls )
+{
+ if ( surface().controls_by_name.find( name ) !=surface().controls_by_name.end() )
+ {
+ Button * button = dynamic_cast<Button*>( surface().controls_by_name[name] );
+ mcu_port().write( builder.build_led( button->led(), ls ) );
+ }
+ else
+ {
+ cout << "Button " << name << " not found" << endl;
+ }
+}
+
+// send messages to surface to set controls to correct values
+void MackieControlProtocol::update_surface()
+{
+ if ( _active )
+ {
+ // do the initial bank switch to connect signals
+ // _current_initial_bank is initialised by set_state
+ switch_banks( _current_initial_bank );
+
+ // create a RouteSignal for the master route
+ // but only the first time around
+ master_route_signal = shared_ptr<RouteSignal>( new RouteSignal( *master_route(), *this, master_strip(), mcu_port() ) );
+ // update strip from route
+ master_route_signal->notify_all();
+
+ // update global buttons and displays
+ notify_record_state_changed();
+ notify_transport_state_changed();
+ }
+}
+
+void MackieControlProtocol::connect_session_signals()
+{
+ // receive routes added
+ connections_back = session->RouteAdded.connect( ( mem_fun (*this, &MackieControlProtocol::notify_route_added) ) );
+ // receive record state toggled
+ connections_back = session->RecordStateChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_record_state_changed) ) );
+ // receive transport state changed
+ connections_back = session->TransportStateChange.connect( ( mem_fun (*this, &MackieControlProtocol::notify_transport_state_changed) ) );
+ // receive punch-in and punch-out
+ connections_back = Config->ParameterChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_parameter_changed) ) );
+ // receive rude solo changed
+ connections_back = session->SoloActive.connect( ( mem_fun (*this, &MackieControlProtocol::notify_solo_active_changed) ) );
+
+ // make sure remote id changed signals reach here
+ // see also notify_route_added
+ Sorted sorted = get_sorted_routes();
+ for ( Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it )
+ {
+ connections_back = (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
+ }
+}
+
+void MackieControlProtocol::add_port( MIDI::Port & midi_port, int number )
+{
+ MackiePort * sport = new MackiePort( *this, midi_port, number );
+ _ports.push_back( sport );
+
+ connections_back = sport->init_event.connect(
+ sigc::bind (
+ mem_fun (*this, &MackieControlProtocol::handle_port_init)
+ , sport
+ )
+ );
+
+ connections_back = sport->active_event.connect(
+ sigc::bind (
+ mem_fun (*this, &MackieControlProtocol::handle_port_active)
+ , sport
+ )
+ );
+
+ connections_back = sport->inactive_event.connect(
+ sigc::bind (
+ mem_fun (*this, &MackieControlProtocol::handle_port_inactive)
+ , sport
+ )
+ );
+
+ _ports_changed = true;
+}
+
+void MackieControlProtocol::create_ports()
+{
+ MIDI::Manager * mm = MIDI::Manager::instance();
+
+ // open main port
+ {
+ MIDI::Port * midi_port = mm->port( default_port_name );
+
+ if ( midi_port == 0 ) {
+ ostringstream os;
+ os << string_compose( _("no MIDI port named \"%1\" exists - Mackie control disabled"), default_port_name );
+ error << os.str() << endmsg;
+ throw MackieControlException( os.str() );
+ }
+ add_port( *midi_port, 0 );
+ }
+
+ // open extender ports. Up to 9. Should be enough.
+ // could also use mm->get_midi_ports()
+ string ext_port_base = "mcu_xt_";
+ for ( int index = 1; index <= 9; ++index )
+ {
+ ostringstream os;
+ os << ext_port_base << index;
+ MIDI::Port * midi_port = mm->port( os.str() );
+ if ( midi_port != 0 ) add_port( *midi_port, index );
+ }
+}
+
+shared_ptr<Route> MackieControlProtocol::master_route()
+{
+ shared_ptr<Route> retval;
+ retval = session->route_by_name( "master" );
+ if ( retval == 0 )
+ {
+ // TODO search through all routes for one with the master attribute set
+ }
+ return retval;
+}
+
+Strip & MackieControlProtocol::master_strip()
+{
+ return dynamic_cast<Strip&>( *surface().groups["master"] );
+}
+
+void MackieControlProtocol::initialize_surface()
+{
+ // set up the route table
+ int strips = 0;
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
+ {
+ strips += (*it)->strips();
+ }
+
+ set_route_table_size( strips );
+
+ switch ( mcu_port().emulation() )
+ {
+ case MackiePort::bcf2000: _surface = new BcfSurface( strips ); break;
+ case MackiePort::mackie: _surface = new MackieSurface( strips ); break;
+ default:
+ ostringstream os;
+ os << "no Surface class found for emulation: " << mcu_port().emulation();
+ throw MackieControlException( os.str() );
+ }
+ _surface->init();
+
+ // Connect events. Must be after route table otherwise there will be trouble
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
+ {
+ connections_back = (*it)->control_event.connect( ( mem_fun (*this, &MackieControlProtocol::handle_control_event) ) );
+ }
+}
+
+void MackieControlProtocol::close()
+{
+ // TODO disconnect port active/inactive signals
+ // Or at least put a lock here
+
+ // disconnect global signals from Session
+ // TODO Since *this is a sigc::trackable, this shouldn't be necessary
+ // but it is for some reason
+#if 0
+ for( vector<sigc::connection>::iterator it = _connections.begin(); it != _connections.end(); ++it )
+ {
+ it->disconnect();
+ }
+#endif
+
+ if ( _surface != 0 )
+ {
+ // These will fail if the port has gone away.
+ // So catch the exception and do the rest of the
+ // close afterwards
+ // because the bcf doesn't respond to the next 3 sysex messages
+ try
+ {
+ zero_all();
+ }
+ catch ( exception & e )
+ {
+ cout << "MackieControlProtocol::close caught exception: " << e.what() << endl;
+ }
+
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
+ {
+ try
+ {
+ MackiePort & port = **it;
+ // faders to minimum
+ port.write_sysex( 0x61 );
+ // All LEDs off
+ port.write_sysex( 0x62 );
+ // Reset (reboot into offline mode)
+ port.write_sysex( 0x63 );
+ }
+ catch ( exception & e )
+ {
+ cout << "MackieControlProtocol::close caught exception: " << e.what() << endl;
+ }
+ }
+
+ // disconnect routes from strips
+ clear_route_signals();
+
+ delete _surface;
+ _surface = 0;
+ }
+
+ // stop polling, and wait for it...
+ _polling = false;
+ pthread_join( thread, 0 );
+
+ // shut down MackiePorts
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
+ {
+ delete *it;
+ }
+ _ports.clear();
+
+ // this is done already in monitor_work. But it's here so we know.
+ delete[] pfd;
+ pfd = 0;
+ nfds = 0;
+}
+
+void* MackieControlProtocol::_monitor_work (void* arg)
+{
+ return static_cast<MackieControlProtocol*>(arg)->monitor_work ();
+}
+
+XMLNode & MackieControlProtocol::get_state()
+{
+ //cout << "MackieControlProtocol::get_state" << endl;
+
+ // add name of protocol
+ XMLNode* node = new XMLNode( X_("Protocol") );
+ node->add_property( X_("name"), _name );
+
+ // add current bank
+ ostringstream os;
+ os << _current_initial_bank;
+ node->add_property( X_("bank"), os.str() );
+
+ return *node;
+}
+
+int MackieControlProtocol::set_state( const XMLNode & node )
+{
+ //cout << "MackieControlProtocol::set_state: active " << _active << endl;
+ int retval = 0;
+
+ // fetch current bank
+ if ( node.property( X_("bank") ) != 0 )
+ {
+ string bank = node.property( X_("bank") )->value();
+ try
+ {
+ set_active( true );
+ uint32_t new_bank = atoi( bank.c_str() );
+ if ( _current_initial_bank != new_bank ) switch_banks( new_bank );
+ }
+ catch ( exception & e )
+ {
+ cout << "exception in MackieControlProtocol::set_state: " << e.what() << endl;
+ return -1;
+ }
+ }
+
+ return retval;
+}
+
+void MackieControlProtocol::handle_control_event( SurfacePort & port, Control & control, const ControlState & state )
+{
+ uint32_t index = control.ordinal() - 1 + ( port.number() * port.strips() );
+ boost::shared_ptr<Route> route;
+ if ( control.group().is_strip() )
+ {
+ if ( control.group().is_master() )
+ {
+ route = master_route();
+ }
+ else if ( index < route_table.size() )
+ route = route_table[index];
+ else
+ cerr << "Warning: index is " << index << " which is not in the route table, size: " << route_table.size() << endl;
+ }
+
+ // This handles control element events from the surface
+ // the state of the controls on the surface is usually updated
+ // from UI events.
+ switch ( control.type() )
+ {
+ case Control::type_fader:
+ if ( control.group().is_strip() )
+ {
+ // find the route in the route table for the id
+ // if the route isn't available, skip it
+ // at which point the fader should just reset itself
+ if ( route != 0 )
+ {
+ route->set_gain( slider_position_to_gain( state.pos ), this );
+
+ // must echo bytes back to slider now, because
+ // the notifier only works if the fader is not being
+ // touched. Which it is if we're getting input.
+ port.write( builder.build_fader( (Fader&)control, state.pos ) );
+ }
+ }
+ else
+ {
+ // master fader
+ boost::shared_ptr<Route> route = master_route();
+ if ( route )
+ {
+ route->set_gain( slider_position_to_gain( state.pos ), this );
+ port.write( builder.build_fader( (Fader&)control, state.pos ) );
+ }
+ }
+ break;
+
+ case Control::type_button:
+ if ( control.group().is_strip() )
+ {
+ // strips
+ if ( route != 0 )
+ {
+ handle_strip_button( control, state.button_state, route );
+ }
+ else
+ {
+ // no route so always switch the light off
+ // because no signals will be emitted by a non-route
+ port.write( builder.build_led( control.led(), off ) );
+ }
+ }
+ else if ( control.group().is_master() )
+ {
+ // master fader touch
+ boost::shared_ptr<Route> route = master_route();
+ if ( route )
+ handle_strip_button( control, state.button_state, route );
+ }
+ else
+ {
+ // handle all non-strip buttons
+ surface().handle_button( *this, state.button_state, dynamic_cast<Button&>( control ) );
+ }
+ break;
+
+ // pot (jog wheel, external control)
+ case Control::type_pot:
+ if ( control.group().is_strip() )
+ {
+ if ( route != 0 )
+ {
+ if ( route->panner().size() == 1 )
+ {
+ // assume pan for now
+ float xpos;
+ route->panner()[0]->get_effective_position (xpos);
+
+ // calculate new value, and trim
+ xpos += state.delta;
+ if ( xpos > 1.0 )
+ xpos = 1.0;
+ else if ( xpos < 0.0 )
+ xpos = 0.0;
+
+ route->panner()[0]->set_position( xpos );
+ }
+ }
+ else
+ {
+ // it's a pot for an umnapped route, so turn all the lights off
+ port.write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
+ }
+ }
+ else
+ {
+ if ( control.name() == "jog" )
+ {
+ // TODO use current snap-to setting?
+ long delta = state.ticks * 1000;
+ nframes_t next = session->transport_frame() + delta;
+ if ( delta < 0 && session->transport_frame() < (nframes_t) abs( delta ) )
+ {
+ next = session->current_start_frame();
+ }
+ else if ( next > session->current_end_frame() )
+ {
+ next = session->current_end_frame();
+ }
+
+ // doesn't work very well
+ session->request_locate( next, session->transport_rolling() );
+
+ // turn off the led ring, for bcf emulation mode
+ port.write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
+ }
+ else
+ {
+ cout << "external controller" << state.ticks << endl;
+ }
+ }
+ break;
+
+ default:
+ cout << "Control::type not handled: " << control.type() << endl;
+ }
+}
+
+/////////////////////////////////////////////////
+// handlers for Route signals
+// TODO should these be part of RouteSignal?
+// They started off as sigc handlers for signals
+// from Route, but they're also used in polling for automation
+/////////////////////////////////////////////////
+
+void MackieControlProtocol::notify_solo_changed( RouteSignal * route_signal )
+{
+ try
+ {
+ Button & button = route_signal->strip().solo();
+ route_signal->port().write( builder.build_led( button, route_signal->route().soloed() ) );
+ }
+ catch( exception & e )
+ {
+ cout << e.what() << endl;
+ }
+}
+
+void MackieControlProtocol::notify_mute_changed( RouteSignal * route_signal )
+{
+ try
+ {
+ Button & button = route_signal->strip().mute();
+ route_signal->port().write( builder.build_led( button, route_signal->route().muted() ) );
+ }
+ catch( exception & e )
+ {
+ cout << e.what() << endl;
+ }
+}
+
+void MackieControlProtocol::notify_record_enable_changed( RouteSignal * route_signal )
+{
+ try
+ {
+ Button & button = route_signal->strip().recenable();
+ route_signal->port().write( builder.build_led( button, route_signal->route().record_enabled() ) );
+ }
+ catch( exception & e )
+ {
+ cout << e.what() << endl;
+ }
+}
+
+void MackieControlProtocol::notify_gain_changed( RouteSignal * route_signal )
+{
+ try
+ {
+ Fader & fader = route_signal->strip().gain();
+ if ( !fader.touch() )
+ {
+ route_signal->port().write( builder.build_fader( fader, gain_to_slider_position( route_signal->route().effective_gain() ) ) );
+ }
+ }
+ catch( exception & e )
+ {
+ cout << e.what() << endl;
+ }
+}
+
+void MackieControlProtocol::notify_name_changed( void *, RouteSignal * route_signal )
+{
+ try
+ {
+ // TODO implement MackieControlProtocol::notify_name_changed
+ }
+ catch( exception & e )
+ {
+ cout << e.what() << endl;
+ }
+}
+
+// TODO deal with > 1 channel being panned
+void MackieControlProtocol::notify_panner_changed( RouteSignal * route_signal )
+{
+ try
+ {
+ Pot & pot = route_signal->strip().vpot();
+
+ if ( route_signal->route().panner().size() == 1 )
+ {
+ float pos;
+ route_signal->route().panner()[0]->get_effective_position( pos);
+ route_signal->port().write( builder.build_led_ring( pot, ControlState( on, pos ) ) );
+ }
+ else
+ {
+ route_signal->port().write( builder.zero_control( pot ) );
+ }
+ }
+ catch( exception & e )
+ {
+ cout << e.what() << endl;
+ }
+}
+
+// TODO handle plugin automation polling
+void MackieControlProtocol::update_automation( RouteSignal & rs )
+{
+ ARDOUR::AutoState gain_state = rs.route().gain_automation_state();
+ if ( gain_state == Touch || gain_state == Play )
+ {
+ notify_gain_changed( &rs );
+ }
+
+ ARDOUR::AutoState panner_state = rs.route().panner().automation_state();
+ if ( panner_state == Touch || panner_state == Play )
+ {
+ notify_panner_changed( &rs );
+ }
+}
+
+void MackieControlProtocol::poll_automation()
+{
+ if ( _active )
+ {
+ // do all currently mapped routes
+ for( RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it )
+ {
+ update_automation( **it );
+ }
+
+ // and the master strip
+ if ( master_route_signal != 0 ) update_automation( *master_route_signal );
+ }
+}
+
+/////////////////////////////////////
+// Transport Buttons
+/////////////////////////////////////
+
+LedState MackieControlProtocol::rewind_press( Button & button )
+{
+ // can use first_mark_before/after as well
+ Location * loc = session->locations()->first_location_before (
+ session->transport_frame()
+ );
+ if ( loc != 0 ) session->request_locate( loc->start(), session->transport_rolling() );
+ return on;
+}
+
+LedState MackieControlProtocol::rewind_release( Button & button )
+{
+ return off;
+}
+
+LedState MackieControlProtocol::ffwd_press( Button & button )
+{
+ // can use first_mark_before/after as well
+ Location * loc = session->locations()->first_location_after (
+ session->transport_frame()
+ );
+ if ( loc != 0 ) session->request_locate( loc->start(), session->transport_rolling() );
+ return on;
+}
+
+LedState MackieControlProtocol::ffwd_release( Button & button )
+{
+ return off;
+}
+
+LedState MackieControlProtocol::stop_press( Button & button )
+{
+ session->request_stop();
+ return on;
+}
+
+LedState MackieControlProtocol::stop_release( Button & button )
+{
+ return session->transport_stopped();
+}
+
+LedState MackieControlProtocol::play_press( Button & button )
+{
+ session->request_transport_speed( 1.0 );
+ return on;
+}
+
+LedState MackieControlProtocol::play_release( Button & button )
+{
+ return session->transport_rolling();
+}
+
+LedState MackieControlProtocol::record_press( Button & button )
+{
+ if ( session->get_record_enabled() )
+ session->disable_record( false );
+ else
+ session->maybe_enable_record();
+ return on;
+}
+
+LedState MackieControlProtocol::record_release( Button & button )
+{
+ if ( session->get_record_enabled() )
+ {
+ if ( session->transport_rolling() )
+ return on;
+ else
+ return flashing;
+ }
+ else
+ return off;
+}
+
+///////////////////////////////////////////
+// Session signals
+///////////////////////////////////////////
+
+void MackieControlProtocol::notify_parameter_changed( const char * name_str )
+{
+ string name( name_str );
+ if ( name == "punch-in" )
+ {
+ update_global_button( "punch_in", Config->get_punch_in() );
+ }
+ else if ( name == "punch-out" )
+ {
+ update_global_button( "punch_out", Config->get_punch_out() );
+ }
+ else if ( name == "clicking" )
+ {
+ update_global_button( "clicking", Config->get_clicking() );
+ }
+ else
+ {
+ cout << "parameter changed: " << name << endl;
+ }
+}
+
+// RouteList is the set of routes that have just been added
+void MackieControlProtocol::notify_route_added( ARDOUR::Session::RouteList & rl )
+{
+ // currently assigned banks are less than the full set of
+ // strips, so activate the new strip now.
+ if ( route_signals.size() < route_table.size() )
+ {
+ refresh_current_bank();
+ }
+ // otherwise route added, but current bank needs no updating
+
+ // make sure remote id changes in the new route are handled
+ typedef ARDOUR::Session::RouteList ARS;
+ for ( ARS::iterator it = rl.begin(); it != rl.end(); ++it )
+ {
+ connections_back = (*it)->RemoteControlIDChanged.connect( ( mem_fun (*this, &MackieControlProtocol::notify_remote_id_changed) ) );
+ }
+}
+
+void MackieControlProtocol::notify_solo_active_changed( bool active )
+{
+ Button * rude_solo = reinterpret_cast<Button*>( surface().controls_by_name["solo"] );
+ mcu_port().write( builder.build_led( *rude_solo, active ? flashing : off ) );
+}
+
+void MackieControlProtocol::notify_remote_id_changed()
+{
+ Sorted sorted = get_sorted_routes();
+
+ // if a remote id has been moved off the end, we need to shift
+ // the current bank backwards.
+ if ( sorted.size() - _current_initial_bank < route_signals.size() )
+ {
+ // but don't shift backwards past the zeroth channel
+ switch_banks( max((Sorted::size_type) 0, sorted.size() - route_signals.size() ) );
+ }
+ // Otherwise just refresh the current bank
+ else
+ {
+ refresh_current_bank();
+ }
+}
+
+///////////////////////////////////////////
+// Transport signals
+///////////////////////////////////////////
+
+void MackieControlProtocol::notify_record_state_changed()
+{
+ // switch rec button on / off / flashing
+ Button * rec = reinterpret_cast<Button*>( surface().controls_by_name["record"] );
+ mcu_port().write( builder.build_led( *rec, record_release( *rec ) ) );
+}
+
+void MackieControlProtocol::notify_transport_state_changed()
+{
+ // switch various play and stop buttons on / off
+ update_global_button( "play", session->transport_rolling() );
+ update_global_button( "stop", !session->transport_rolling() );
+ update_global_button( "loop", session->get_play_loop() );
+
+ // rec is special because it's tristate
+ Button * rec = reinterpret_cast<Button*>( surface().controls_by_name["record"] );
+ mcu_port().write( builder.build_led( *rec, record_release( *rec ) ) );
+}
+
+LedState MackieControlProtocol::loop_press( Button & button )
+{
+ session->request_play_loop( !session->get_play_loop() );
+ return on;
+}
+
+LedState MackieControlProtocol::loop_release( Button & button )
+{
+ return session->get_play_loop();
+}
+
+LedState MackieControlProtocol::punch_in_press( Button & button )
+{
+ bool state = !Config->get_punch_in();
+ Config->set_punch_in( state );
+ return state;
+}
+
+LedState MackieControlProtocol::punch_in_release( Button & button )
+{
+ return Config->get_punch_in();
+}
+
+LedState MackieControlProtocol::punch_out_press( Button & button )
+{
+ bool state = !Config->get_punch_out();
+ Config->set_punch_out( state );
+ return state;
+}
+
+LedState MackieControlProtocol::punch_out_release( Button & button )
+{
+ return Config->get_punch_out();
+}
+
+LedState MackieControlProtocol::home_press( Button & button )
+{
+ session->goto_start();
+ return on;
+}
+
+LedState MackieControlProtocol::home_release( Button & button )
+{
+ return off;
+}
+
+LedState MackieControlProtocol::end_press( Button & button )
+{
+ session->goto_end();
+ return on;
+}
+
+LedState MackieControlProtocol::end_release( Button & button )
+{
+ return off;
+}
+
+LedState MackieControlProtocol::clicking_press( Button & button )
+{
+ bool state = !Config->get_clicking();
+ Config->set_clicking( state );
+ return state;
+}
+
+LedState MackieControlProtocol::clicking_release( Button & button )
+{
+ return Config->get_clicking();
+}
+
+LedState MackieControlProtocol::global_solo_press( Button & button )
+{
+ bool state = !session->soloing();
+ session->set_all_solo ( state );
+ return state;
+}
+
+LedState MackieControlProtocol::global_solo_release( Button & button )
+{
+ return session->soloing();
+}
+
+/////////////////////////////////////
+// Bank Switching
+/////////////////////////////////////
+LedState MackieControlProtocol::left_press( Button & button )
+{
+ Sorted sorted = get_sorted_routes();
+ if ( sorted.size() > route_table.size() )
+ {
+ int new_initial = _current_initial_bank - route_table.size();
+ if ( new_initial < 0 ) new_initial = 0;
+ if ( new_initial != int( _current_initial_bank ) )
+ {
+ session->set_dirty();
+ switch_banks( new_initial );
+ }
+
+ return on;
+ }
+ else
+ {
+ return flashing;
+ }
+}
+
+LedState MackieControlProtocol::left_release( Button & button )
+{
+ return off;
+}
+
+LedState MackieControlProtocol::right_press( Button & button )
+{
+ Sorted sorted = get_sorted_routes();
+ if ( sorted.size() > route_table.size() )
+ {
+ uint32_t delta = sorted.size() - ( route_table.size() + _current_initial_bank );
+ if ( delta > route_table.size() ) delta = route_table.size();
+ if ( delta > 0 )
+ {
+ session->set_dirty();
+ switch_banks( _current_initial_bank + delta );
+ }
+
+ return on;
+ }
+ else
+ {
+ return flashing;
+ }
+}
+
+LedState MackieControlProtocol::right_release( Button & button )
+{
+ return off;
+}
+
+LedState MackieControlProtocol::channel_left_press( Button & button )
+{
+ Sorted sorted = get_sorted_routes();
+ if ( sorted.size() > route_table.size() )
+ {
+ prev_track();
+ return on;
+ }
+ else
+ {
+ return flashing;
+ }
+}
+
+LedState MackieControlProtocol::channel_left_release( Button & button )
+{
+ return off;
+}
+
+LedState MackieControlProtocol::channel_right_press( Button & button )
+{
+ Sorted sorted = get_sorted_routes();
+ if ( sorted.size() > route_table.size() )
+ {
+ next_track();
+ return on;
+ }
+ else
+ {
+ return flashing;
+ }
+}
+
+LedState MackieControlProtocol::channel_right_release( Button & button )
+{
+ return off;
+}
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
new file mode 100644
index 0000000000..d71979b463
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -0,0 +1,307 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef ardour_mackie_control_protocol_h
+#define ardour_mackie_control_protocol_h
+
+#include <vector>
+
+#include <sys/time.h>
+#include <pthread.h>
+
+#include <glibmm/thread.h>
+
+#include <ardour/types.h>
+#include <ardour/session.h>
+#include <midi++/types.h>
+
+#include <control_protocol/control_protocol.h>
+#include "midi_byte_array.h"
+#include "controls.h"
+#include "route_signal.h"
+#include "mackie_button_handler.h"
+#include "mackie_port.h"
+
+namespace MIDI {
+ class Port;
+ class Parser;
+}
+
+namespace Mackie {
+ class Surface;
+}
+
+/**
+ This handles the plugin duties, and the midi encoding and decoding,
+ and the signal callbacks, mostly from ARDOUR::Route.
+
+ The model of the control surface is handled by classes in controls.h
+
+ What happens is that each strip on the control surface has
+ a corresponding route in ControlProtocol::route_table. When
+ an incoming midi message is signaled, the correct route
+ is looked up, and the relevant changes made to it.
+
+ For each route currently in route_table, there's a RouteSignal object
+ which encapsulates the signals that indicate that there are changes
+ to be sent to the surface. The signals are handled by this class.
+
+ Calls to signal handlers pass a Route object which is used to look
+ up the relevant Strip in Surface. Then the state is retrieved from
+ the Route and encoded as the correct midi message.
+*/
+class MackieControlProtocol
+: public ARDOUR::ControlProtocol
+, public Mackie::MackieButtonHandler
+{
+ public:
+ MackieControlProtocol( ARDOUR::Session & );
+ virtual ~MackieControlProtocol();
+
+ int set_active (bool yn);
+
+ XMLNode& get_state ();
+ int set_state (const XMLNode&);
+
+ static bool probe();
+
+ Mackie::Surface & surface();
+
+ // control events
+ void handle_control_event( Mackie::SurfacePort & port, Mackie::Control & control, const Mackie::ControlState & state );
+
+ // strip/route related stuff
+ public:
+ /// Signal handler for Route::solo
+ void notify_solo_changed( Mackie::RouteSignal * );
+ /// Signal handler for Route::mute
+ void notify_mute_changed( Mackie::RouteSignal * );
+ /// Signal handler for Route::record_enable_changed
+ void notify_record_enable_changed( Mackie::RouteSignal * );
+ /// Signal handler for Route::gain_changed ( from IO )
+ void notify_gain_changed( Mackie::RouteSignal * );
+ /// Signal handler for Route::name_change
+ void notify_name_changed( void *, Mackie::RouteSignal * );
+ /// Signal handler from Panner::Change
+ void notify_panner_changed( Mackie::RouteSignal * );
+ /// Signal handler for new routes added
+ void notify_route_added( ARDOUR::Session::RouteList & );
+
+ void notify_remote_id_changed();
+
+ /// rebuild the current bank. Called on route added/removed and
+ /// remote id changed.
+ void refresh_current_bank();
+
+ // global buttons (ie button not part of strips)
+ public:
+ // button-related signals
+ void notify_record_state_changed();
+ void notify_transport_state_changed();
+ // mainly to pick up punch-in and punch-out
+ void notify_parameter_changed( const char * );
+ void notify_solo_active_changed( bool );
+
+ // this is called to generate the midi to send in response to
+ // a button press.
+ void update_led( Mackie::Button & button, Mackie::LedState );
+
+ // calls update_led, but looks up the button by name
+ void update_global_button( const std::string & name, Mackie::LedState );
+
+ // transport button handler methods from MackieButtonHandler
+ virtual Mackie::LedState rewind_press( Mackie::Button & );
+ virtual Mackie::LedState rewind_release( Mackie::Button & );
+
+ virtual Mackie::LedState ffwd_press( Mackie::Button & );
+ virtual Mackie::LedState ffwd_release( Mackie::Button & );
+
+ virtual Mackie::LedState stop_press( Mackie::Button & );
+ virtual Mackie::LedState stop_release( Mackie::Button & );
+
+ virtual Mackie::LedState play_press( Mackie::Button & );
+ virtual Mackie::LedState play_release( Mackie::Button & );
+
+ virtual Mackie::LedState record_press( Mackie::Button & );
+ virtual Mackie::LedState record_release( Mackie::Button & );
+
+ virtual Mackie::LedState loop_press( Mackie::Button & );
+ virtual Mackie::LedState loop_release( Mackie::Button & );
+
+ virtual Mackie::LedState punch_in_press( Mackie::Button & );
+ virtual Mackie::LedState punch_in_release( Mackie::Button & );
+
+ virtual Mackie::LedState punch_out_press( Mackie::Button & );
+ virtual Mackie::LedState punch_out_release( Mackie::Button & );
+
+ virtual Mackie::LedState home_press( Mackie::Button & );
+ virtual Mackie::LedState home_release( Mackie::Button & );
+
+ virtual Mackie::LedState end_press( Mackie::Button & );
+ virtual Mackie::LedState end_release( Mackie::Button & );
+
+ // bank switching button handler methods from MackieButtonHandler
+ virtual Mackie::LedState left_press( Mackie::Button & );
+ virtual Mackie::LedState left_release( Mackie::Button & );
+
+ virtual Mackie::LedState right_press( Mackie::Button & );
+ virtual Mackie::LedState right_release( Mackie::Button & );
+
+ virtual Mackie::LedState channel_left_press( Mackie::Button & );
+ virtual Mackie::LedState channel_left_release( Mackie::Button & );
+
+ virtual Mackie::LedState channel_right_press( Mackie::Button & );
+ virtual Mackie::LedState channel_right_release( Mackie::Button & );
+
+ virtual Mackie::LedState clicking_press( Mackie::Button & );
+ virtual Mackie::LedState clicking_release( Mackie::Button & );
+
+ virtual Mackie::LedState global_solo_press( Mackie::Button & );
+ virtual Mackie::LedState global_solo_release( Mackie::Button & );
+
+ protected:
+ // create instances of MackiePort, depending on what's found in ardour.rc
+ void create_ports();
+
+ // shut down the surface
+ void close();
+
+ // create the Surface object, with the correct number
+ // of strips for the currently connected ports and
+ // hook up the control event notification
+ void initialize_surface();
+
+ // This sets up the notifications and sets the
+ // controls to the correct values
+ void update_surface();
+
+ // connects global (not strip) signals from the Session to here
+ // so the surface can be notified of changes from the other UIs.
+ void connect_session_signals();
+
+ // set all controls to their zero position
+ void zero_all();
+
+ /**
+ Fetch the set of routes to be considered for control by the
+ surface. Excluding master, hidden and control routes, and inactive routes
+ */
+ typedef std::vector<boost::shared_ptr<ARDOUR::Route> > Sorted;
+ Sorted get_sorted_routes();
+
+ // bank switching
+ void switch_banks( int initial );
+ void prev_track();
+ void next_track();
+
+ // delete all RouteSignal objects connecting Routes to Strips
+ void clear_route_signals();
+
+ /// This is the main MCU port, ie not an extender port
+ const Mackie::MackiePort & mcu_port() const;
+ Mackie::MackiePort & mcu_port();
+
+ typedef std::vector<Mackie::RouteSignal*> RouteSignals;
+ RouteSignals route_signals;
+
+ // return which of the ports a particular route_table
+ // index belongs to
+ Mackie::MackiePort & port_for_id( uint32_t index );
+
+ /**
+ Handle a button press for the control and return whether
+ the corresponding light should be on or off.
+ */
+ bool handle_strip_button( Mackie::Control &, Mackie::ButtonState, boost::shared_ptr<ARDOUR::Route> );
+
+ /// thread started. Calls monitor_work.
+ static void* _monitor_work (void* arg);
+
+ /// Polling midi port(s) for incoming messages
+ void* monitor_work ();
+
+ /// rebuild the set of ports for this surface
+ void update_ports();
+
+ /// Returns true if there is pending data, false otherwise
+ bool poll_ports();
+
+ /// Trigger the MIDI::Parser
+ void read_ports();
+
+ void add_port( MIDI::Port &, int number );
+
+ /// read automation data from the currently active routes and send to surface
+ void poll_automation();
+
+ // called from poll_automation to figure out which automations need to be sent
+ void update_automation( Mackie::RouteSignal & );
+
+ /**
+ notification that the port is about to start it's init sequence.
+ We must make sure that before this exits, the port is being polled
+ for new data.
+ */
+ void handle_port_init( Mackie::SurfacePort * );
+
+ /// notification from a MackiePort that it's now active
+ void handle_port_active( Mackie::SurfacePort * );
+
+ /// notification from a MackiePort that it's now inactive
+ void handle_port_inactive( Mackie::SurfacePort * );
+
+ boost::shared_ptr<ARDOUR::Route> master_route();
+ Mackie::Strip & master_strip();
+
+ private:
+ boost::shared_ptr<Mackie::RouteSignal> master_route_signal;
+
+ static const char * default_port_name;
+
+ /// The Midi port(s) connected to the units
+ typedef vector<Mackie::MackiePort*> MackiePorts;
+ MackiePorts _ports;
+
+ // the thread that polls the ports for incoming midi data
+ pthread_t thread;
+
+ /// The initial remote_id of the currently switched in bank.
+ uint32_t _current_initial_bank;
+
+ /// protects the port list, and polling structures
+ Glib::Mutex update_mutex;
+
+ /// Protects set_active, and allows waiting on the poll thread
+ Glib::Cond update_cond;
+
+ // because sigc::trackable doesn't seem to be working
+ std::vector<sigc::connection> _connections;
+ std::back_insert_iterator<std::vector<sigc::connection> > connections_back;
+
+ /// The representation of the physical controls on the surface.
+ Mackie::Surface * _surface;
+
+ /// If a port is opened or closed, this will be
+ /// true until the port configuration is updated;
+ bool _ports_changed;
+
+ bool _polling;
+ struct pollfd * pfd;
+ int nfds;
+};
+
+#endif // ardour_mackie_control_protocol_h
diff --git a/libs/surfaces/mackie/mackie_control_protocol_poll.cc b/libs/surfaces/mackie/mackie_control_protocol_poll.cc
new file mode 100644
index 0000000000..05681c0c25
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_control_protocol_poll.cc
@@ -0,0 +1,192 @@
+#include "mackie_control_protocol.h"
+
+#include "midi_byte_array.h"
+#include "surface_port.h"
+
+#include <pbd/pthread_utils.h>
+#include <pbd/error.h>
+
+#include <midi++/types.h>
+#include <midi++/port.h>
+#include <midi++/manager.h>
+#include <midi++/port_request.h>
+#include "i18n.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using namespace std;
+using namespace Mackie;
+using namespace PBD;
+
+const char * MackieControlProtocol::default_port_name = "mcu";
+
+bool MackieControlProtocol::probe()
+{
+ return MIDI::Manager::instance()->port( default_port_name ) != 0;
+}
+
+void * MackieControlProtocol::monitor_work()
+{
+ // What does ThreadCreatedWithRequestSize do?
+ PBD::ThreadCreated (pthread_self(), X_("Mackie"));
+
+ pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+
+ // read from midi ports
+ while ( _polling )
+ {
+ try
+ {
+ if ( poll_ports() )
+ {
+ try { read_ports(); }
+ catch ( exception & e ) {
+ cout << "MackieControlProtocol::poll_ports caught exception: " << e.what() << endl;
+ _ports_changed = true;
+ update_ports();
+ }
+ }
+ // poll for automation data from the routes
+ poll_automation();
+ }
+ catch ( exception & e )
+ {
+ cout << "caught exception in MackieControlProtocol::monitor_work " << e.what() << endl;
+ }
+ }
+
+ // TODO ports and pfd and nfds should be in a separate class
+ delete[] pfd;
+ pfd = 0;
+ nfds = 0;
+
+ return (void*) 0;
+}
+
+void MackieControlProtocol::update_ports()
+{
+ if ( _ports_changed )
+ {
+ Glib::Mutex::Lock ul( update_mutex );
+ // yes, this is a double-test locking paradigm, or whatever it's called
+ // because we don't *always* need to acquire the lock for the first test
+ if ( _ports_changed )
+ {
+ // create new pollfd structures
+ if ( pfd != 0 ) delete[] pfd;
+ // TODO This might be a memory leak. How does thread cancellation cleanup work?
+ pfd = new pollfd[_ports.size()];
+ nfds = 0;
+
+ for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
+ {
+ //cout << "adding port " << (*it)->port().name() << " to pollfd" << endl;
+ pfd[nfds].fd = (*it)->port().selectable();
+ pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
+ ++nfds;
+ }
+ _ports_changed = false;
+ }
+ update_cond.signal();
+ }
+}
+
+void MackieControlProtocol::read_ports()
+{
+ /* now read any data on the ports */
+ Glib::Mutex::Lock lock( update_mutex );
+ for ( int p = 0; p < nfds; ++p )
+ {
+ // this will cause handle_midi_any in the MackiePort to be triggered
+ if ( pfd[p].revents & POLLIN > 0 )
+ {
+ // avoid deadlocking?
+ // doesn't seem to make a difference
+ //lock.release();
+ _ports[p]->read();
+ //lock.acquire();
+ }
+ }
+}
+
+bool MackieControlProtocol::poll_ports()
+{
+ int timeout = 10; // milliseconds
+ int no_ports_sleep = 1000; // milliseconds
+
+ Glib::Mutex::Lock lock( update_mutex );
+ // if there are no ports
+ if ( nfds < 1 )
+ {
+ lock.release();
+ //cout << "poll_ports no ports" << endl;
+ usleep( no_ports_sleep * 1000 );
+ return false;
+ }
+
+ int retval = poll( pfd, nfds, timeout );
+ if ( retval < 0 )
+ {
+ // gdb at work, perhaps
+ if ( errno != EINTR )
+ {
+ error << string_compose(_("Mackie MIDI thread poll failed (%1)"), strerror( errno ) ) << endmsg;
+ }
+ return false;
+ }
+
+ return retval > 0;
+}
+
+void MackieControlProtocol::handle_port_inactive( SurfacePort * port )
+{
+ // port gone away. So stop polling it ASAP
+ {
+ // delete the port instance
+ Glib::Mutex::Lock lock( update_mutex );
+ MackiePorts::iterator it = find( _ports.begin(), _ports.end(), port );
+ if ( it != _ports.end() )
+ {
+ delete *it;
+ _ports.erase( it );
+ }
+ }
+ _ports_changed = true;
+ update_ports();
+
+ // TODO all the rebuilding of surfaces and so on
+}
+
+void MackieControlProtocol::handle_port_active( SurfacePort * port )
+{
+ // no need to re-add port because it was already added
+ // during the init phase. So just update the local surface
+ // representation and send the representation to
+ // all existing ports
+
+ // TODO update bank size
+
+ // TODO rebuild surface, to have new units
+
+ // finally update session state to the surface
+ // TODO but this is also done in set_active, and
+ // in fact update_surface won't execute unless
+ // _active == true
+ //cout << "update_surface in handle_port_active" << endl;
+ update_surface();
+}
+
+void MackieControlProtocol::handle_port_init( Mackie::SurfacePort * sport )
+{
+ //cout << "MackieControlProtocol::handle_port_init" << endl;
+ _ports_changed = true;
+ update_ports();
+}
diff --git a/libs/surfaces/mackie/mackie_midi_builder.cc b/libs/surfaces/mackie/mackie_midi_builder.cc
new file mode 100644
index 0000000000..8ed98a5720
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_midi_builder.cc
@@ -0,0 +1,173 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "mackie_midi_builder.h"
+
+#include <typeinfo>
+#include <sstream>
+#include <iomanip>
+
+#include "controls.h"
+#include "midi_byte_array.h"
+
+using namespace Mackie;
+using namespace std;
+
+MIDI::byte MackieMidiBuilder::calculate_pot_value( midi_pot_mode mode, const ControlState & state )
+{
+ // TODO do an exact calc for 0.50? To allow manually re-centering the port.
+
+ // center on or off
+ MIDI::byte retval = ( state.pos > 0.45 && state.pos < 0.55 ? 1 : 0 ) << 6;
+
+ // mode
+ retval |= ( mode << 4 );
+
+ // value, but only if off hasn't explicitly been set
+ if ( state.led_state != off )
+ retval += ( int(state.pos * 10.0) + 1 ) & 0x0f; // 0b00001111
+
+ return retval;
+}
+
+MidiByteArray MackieMidiBuilder::build_led_ring( const Pot & pot, const ControlState & state )
+{
+ return build_led_ring( pot.led_ring(), state );
+}
+
+MidiByteArray MackieMidiBuilder::build_led_ring( const LedRing & led_ring, const ControlState & state )
+{
+ // The other way of doing this:
+ // 0x30 + pot/ring number (0-7)
+ //, 0x30 + led_ring.ordinal() - 1
+ return MidiByteArray ( 3
+ // the control type
+ , midi_pot_id
+ // the id
+ , 0x20 + led_ring.id()
+ // the value
+ , calculate_pot_value( midi_pot_mode_dot, state )
+ );
+}
+
+MidiByteArray MackieMidiBuilder::build_led( const Button & button, LedState ls )
+{
+ return build_led( button.led(), ls );
+}
+
+MidiByteArray MackieMidiBuilder::build_led( const Led & led, LedState ls )
+{
+ MIDI::byte state = 0;
+ switch ( ls.state() )
+ {
+ case LedState::on: state = 0x7f; break;
+ case LedState::off: state = 0x00; break;
+ case LedState::none: state = 0x00; break; // actually, this should never happen.
+ case LedState::flashing: state = 0x01; break;
+ }
+
+ return MidiByteArray ( 3
+ , midi_button_id
+ , led.id()
+ , state
+ );
+}
+
+MidiByteArray MackieMidiBuilder::build_fader( const Fader & fader, float pos )
+{
+ int posi = int( 0x3fff * pos );
+
+ return MidiByteArray ( 3
+ , midi_fader_id | fader.id()
+ // lower-order bits
+ , posi & 0x7f
+ // higher-order bits
+ , ( posi >> 7 )
+ );
+}
+
+MidiByteArray MackieMidiBuilder::zero_strip( const Strip & strip )
+{
+ Group::Controls::const_iterator it = strip.controls().begin();
+ MidiByteArray retval;
+ for (; it != strip.controls().end(); ++it )
+ {
+ Control & control = **it;
+ if ( control.accepts_feedback() )
+ retval << zero_control( control );
+ }
+ return retval;
+}
+
+MidiByteArray MackieMidiBuilder::zero_control( const Control & control )
+{
+ switch( control.type() )
+ {
+ case Control::type_button:
+ return build_led( (Button&)control, off );
+
+ case Control::type_led:
+ return build_led( (Led&)control, off );
+
+ case Control::type_fader:
+ return build_fader( (Fader&)control, 0.0 );
+
+ case Control::type_pot:
+ return build_led_ring( dynamic_cast<const Pot&>( control ), off );
+
+ case Control::type_led_ring:
+ return build_led_ring( dynamic_cast<const LedRing&>( control ), off );
+
+ default:
+ ostringstream os;
+ os << "Unknown control type " << control << " in Strip::zero_control";
+ throw MackieControlException( os.str() );
+ }
+}
+
+char translate_seven_segment( char achar )
+{
+ achar = toupper( achar );
+ if ( achar >= 0x40 && achar <= 0x60 )
+ return achar - 0x40;
+ else if ( achar >= 0x21 && achar <= 0x3f )
+ return achar;
+ else
+ return 0x00;
+}
+
+MidiByteArray MackieMidiBuilder::two_char_display( const std::string & msg, const std::string & dots )
+{
+ if ( msg.length() != 2 ) throw MackieControlException( "MackieMidiBuilder::two_char_display: msg must be exactly 2 characters" );
+ if ( dots.length() != 2 ) throw MackieControlException( "MackieMidiBuilder::two_char_display: dots must be exactly 2 characters" );
+
+ MidiByteArray bytes( 5, 0xb0, 0x4a, 0x00, 0x4b, 0x00 );
+
+ // chars are understood by the surface in right-to-left order
+ // could also exchange the 0x4a and 0x4b, above
+ bytes[4] = translate_seven_segment( msg[0] ) + ( dots[0] == '.' ? 0x40 : 0x00 );
+ bytes[2] = translate_seven_segment( msg[1] ) + ( dots[1] == '.' ? 0x40 : 0x00 );
+
+ return bytes;
+}
+
+MidiByteArray MackieMidiBuilder::two_char_display( unsigned int value, const std::string & dots )
+{
+ ostringstream os;
+ os << setfill('0') << setw(2) << value % 100;
+ return two_char_display( os.str() );
+}
diff --git a/libs/surfaces/mackie/mackie_midi_builder.h b/libs/surfaces/mackie/mackie_midi_builder.h
new file mode 100644
index 0000000000..f0c3d51a54
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_midi_builder.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef mackie_midi_builder_h
+#define mackie_midi_builder_h
+
+#include "midi_byte_array.h"
+#include "types.h"
+
+namespace Mackie
+{
+
+/**
+ This knows how to build midi messages given a control and
+ a state.
+*/
+class MackieMidiBuilder
+{
+public:
+ /**
+ The first byte of a midi message from the surface
+ will contain one of these, sometimes bitmasked
+ with the control id
+ */
+ enum midi_types {
+ midi_fader_id = 0xe0
+ , midi_button_id = 0x90
+ , midi_pot_id = 0xb0
+ };
+
+ /**
+ The LED rings have these modes.
+ */
+ enum midi_pot_mode {
+ midi_pot_mode_dot = 0
+ , midi_pot_mode_boost_cut = 1
+ , midi_pot_mode_wrap = 2
+ , midi_pot_mode_spread = 3
+ };
+
+ MidiByteArray build_led_ring( const Pot & pot, const ControlState & );
+ MidiByteArray build_led_ring( const LedRing & led_ring, const ControlState & );
+
+ MidiByteArray build_led( const Led & led, LedState ls );
+ MidiByteArray build_led( const Button & button, LedState ls );
+
+ MidiByteArray build_fader( const Fader & fader, float pos );
+
+ /// return bytes that will reset all controls to their zero positions
+ MidiByteArray zero_strip( const Strip & strip );
+
+ // provide bytes to zero the given control
+ MidiByteArray zero_control( const Control & control );
+
+ // display the first 2 chars of the msg in the 2 char display
+ // . is appended to the previous character, so A.B. would
+ // be two characters
+ MidiByteArray two_char_display( const std::string & msg, const std::string & dots = " " );
+ MidiByteArray two_char_display( unsigned int value, const std::string & dots = " " );
+
+protected:
+ static MIDI::byte calculate_pot_value( midi_pot_mode mode, const ControlState & );
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/mackie_port.cc b/libs/surfaces/mackie/mackie_port.cc
new file mode 100644
index 0000000000..9bcee638fb
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_port.cc
@@ -0,0 +1,399 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "mackie_port.h"
+
+#include "mackie_control_exception.h"
+#include "mackie_control_protocol.h"
+#include "mackie_midi_builder.h"
+#include "controls.h"
+#include "surface.h"
+
+#include <midi++/types.h>
+#include <midi++/port.h>
+#include <sigc++/sigc++.h>
+#include <boost/shared_array.hpp>
+#include <ardour/configuration.h>
+
+#include "i18n.h"
+
+#include <sstream>
+
+using namespace std;
+using namespace Mackie;
+
+// The MCU sysex header
+MidiByteArray mackie_sysex_hdr ( 5, MIDI::sysex, 0x0, 0x0, 0x66, 0x10 );
+
+// The MCU extender sysex header
+MidiByteArray mackie_sysex_hdr_xt ( 5, MIDI::sysex, 0x0, 0x0, 0x66, 0x11 );
+
+MackiePort::MackiePort( MackieControlProtocol & mcp, MIDI::Port & port, int number, port_type_t port_type )
+: SurfacePort( port, number )
+, _mcp( mcp )
+, _port_type( port_type )
+, _emulation( none )
+, _initialising( true )
+{
+ //cout << "MackiePort::MackiePort" <<endl;
+}
+
+MackiePort::~MackiePort()
+{
+ //cout << "~MackiePort" << endl;
+ close();
+ //cout << "~MackiePort finished" << endl;
+}
+
+int MackiePort::strips() const
+{
+ if ( _port_type == mcu )
+ {
+ switch ( _emulation )
+ {
+ // BCF2000 only has 8 faders, so reserve one for master
+ case bcf2000: return 7;
+ case mackie: return 8;
+ case none:
+ default:
+ throw MackieControlException( "MackiePort::strips: don't know what emulation we're using" );
+ }
+ }
+ else
+ {
+ // must be an extender, ie no master fader
+ return 8;
+ }
+}
+
+// should really be in MackiePort
+void MackiePort::open()
+{
+ //cout << "MackiePort::open " << *this << endl;
+ _sysex = port().input()->sysex.connect( ( mem_fun (*this, &MackiePort::handle_midi_sysex) ) );
+
+ // make sure the device is connected
+ init();
+}
+
+void MackiePort::close()
+{
+ //cout << "MackiePort::close" << endl;
+
+ // disconnect signals
+ _any.disconnect();
+ _sysex.disconnect();
+
+ // TODO emit a "closing" signal?
+ //cout << "MackiePort::close finished" << endl;
+}
+
+const MidiByteArray & MackiePort::sysex_hdr() const
+{
+ switch ( _port_type )
+ {
+ case mcu: return mackie_sysex_hdr;
+ case ext: return mackie_sysex_hdr_xt;
+ }
+ cout << "MackiePort::sysex_hdr _port_type not known" << endl;
+ return mackie_sysex_hdr;
+}
+
+Control & MackiePort::lookup_control( const MidiByteArray & bytes )
+{
+ Control * control = 0;
+ int midi_id = -1;
+ MIDI::byte midi_type = bytes[0] & 0xf0; //0b11110000
+ switch( midi_type )
+ {
+ // fader
+ case MackieMidiBuilder::midi_fader_id:
+ midi_id = bytes[0] & 0x0f;
+ control = _mcp.surface().faders[midi_id];
+ if ( control == 0 )
+ {
+ ostringstream os;
+ os << "control for fader" << midi_id << " is null";
+ throw MackieControlException( os.str() );
+ }
+ break;
+
+ // button
+ case MackieMidiBuilder::midi_button_id:
+ midi_id = bytes[1];
+ control = _mcp.surface().buttons[midi_id];
+ if ( control == 0 )
+ {
+ ostringstream os;
+ os << "control for button" << midi_id << " is null";
+ throw MackieControlException( os.str() );
+ }
+ break;
+
+ // pot (jog wheel, external control)
+ case MackieMidiBuilder::midi_pot_id:
+ midi_id = bytes[1] & 0x1f;
+ control = _mcp.surface().pots[midi_id];
+ if ( control == 0 )
+ {
+ ostringstream os;
+ os << "control for button" << midi_id << " is null";
+ throw MackieControlException( os.str() );
+ }
+ break;
+
+ default:
+ ostringstream os;
+ os << "Cannot find control for " << bytes;
+ throw MackieControlException( os.str() );
+ }
+ return *control;
+}
+
+MidiByteArray calculate_challenge_response( MidiByteArray::iterator begin, MidiByteArray::iterator end )
+{
+ MidiByteArray l;
+ back_insert_iterator<MidiByteArray> back ( l );
+ copy( begin, end, back );
+
+ MidiByteArray retval;
+
+ // this is how to calculate the response to the challenge.
+ // from the Logic docs.
+ retval << ( 0x7f & ( l[0] + ( l[1] ^ 0xa ) - l[3] ) );
+ retval << ( 0x7f & ( ( l[2] >> l[3] ) ^ ( l[0] + l[3] ) ) );
+ retval << ( 0x7f & ( l[3] - ( l[2] << 2 ) ^ ( l[0] | l[1] ) ) );
+ retval << ( 0x7f & ( l[1] - l[2] + ( 0xf0 ^ ( l[3] << 4 ) ) ) );
+
+ return retval;
+}
+
+// not used right now
+MidiByteArray MackiePort::host_connection_query( MidiByteArray & bytes )
+{
+ // handle host connection query
+ //cout << "host connection query: " << bytes << endl;
+
+ if ( bytes.size() != 18 )
+ {
+ finalise_init( false );
+ ostringstream os;
+ os << "expecting 18 bytes, read " << bytes << " from " << port().name();
+ throw MackieControlException( os.str() );
+ }
+
+ // build and send host connection reply
+ MidiByteArray response;
+ response << 0x02;
+ copy( bytes.begin() + 6, bytes.begin() + 6 + 7, back_inserter( response ) );
+ response << calculate_challenge_response( bytes.begin() + 6 + 7, bytes.begin() + 6 + 7 + 4 );
+ return response;
+}
+
+// not used right now
+MidiByteArray MackiePort::host_connection_confirmation( const MidiByteArray & bytes )
+{
+ //cout << "host_connection_confirmation: " << bytes << endl;
+
+ // decode host connection confirmation
+ if ( bytes.size() != 14 )
+ {
+ finalise_init( false );
+ ostringstream os;
+ os << "expecting 14 bytes, read " << bytes << " from " << port().name();
+ throw MackieControlException( os.str() );
+ }
+
+ // send version request
+ return MidiByteArray( 2, 0x13, 0x00 );
+}
+
+void MackiePort::probe_emulation( const MidiByteArray & bytes )
+{
+ //cout << "MackiePort::probe_emulation: " << bytes.size() << ", " << bytes << endl;
+ string version_string;
+ for ( int i = 6; i < 11; ++i ) version_string.append( 1, (char)bytes[i] );
+ //cout << "version_string: " << version_string << endl;
+
+ // TODO investigate using serial number. Also, possibly size of bytes might
+ // give an indication. Also, apparently MCU sends non-documented messages
+ // sometimes.
+ if (!_initialising)
+ {
+ cout << "MackiePort::probe_emulation out of sequence." << endl;
+ return;
+ }
+
+ finalise_init( true );
+}
+
+void MackiePort::init()
+{
+ //cout << "MackiePort::init" << endl;
+ init_mutex.lock();
+ _initialising = true;
+
+ //cout << "MackiePort::lock acquired" << endl;
+ // emit pre-init signal
+ init_event();
+
+ // kick off initialisation. See docs in header file for init()
+
+ // bypass the init sequence because sometimes the first
+ // message doesn't get to the unit, and there's no way
+ // to do a timed lock in Glib.
+ //write_sysex ( MidiByteArray ( 2, 0x13, 0x00 ) );
+
+ finalise_init( true );
+}
+
+void MackiePort::finalise_init( bool yn )
+{
+ //cout << "MackiePort::finalise_init" << endl;
+ bool emulation_ok = false;
+
+ // probing doesn't work very well, so just use a config variable
+ // to set the emulation mode
+ if ( _emulation == none )
+ {
+ if ( ARDOUR::Config->get_mackie_emulation() == "bcf" )
+ {
+ _emulation = bcf2000;
+ emulation_ok = true;
+ }
+ else if ( ARDOUR::Config->get_mackie_emulation() == "mcu" )
+ {
+ _emulation = mackie;
+ emulation_ok = true;
+ }
+ else
+ {
+ cout << "unknown mackie emulation: " << ARDOUR::Config->get_mackie_emulation() << endl;
+ emulation_ok = false;
+ }
+ }
+
+ yn = yn && emulation_ok;
+
+ SurfacePort::active( yn );
+
+ if ( yn )
+ {
+ active_event();
+
+ // start handling messages from controls
+ _any = port().input()->any.connect( ( mem_fun (*this, &MackiePort::handle_midi_any) ) );
+ }
+ _initialising = false;
+ init_cond.signal();
+ init_mutex.unlock();
+}
+
+bool MackiePort::wait_for_init()
+{
+ Glib::Mutex::Lock lock( init_mutex );
+ while ( _initialising )
+ {
+ //cout << "MackiePort::wait_for_active waiting" << endl;
+ init_cond.wait( init_mutex );
+ //cout << "MackiePort::wait_for_active released" << endl;
+ }
+ //cout << "MackiePort::wait_for_active returning" << endl;
+ return SurfacePort::active();
+}
+
+void MackiePort::handle_midi_sysex (MIDI::Parser & parser, MIDI::byte * raw_bytes, size_t count )
+{
+ MidiByteArray bytes( count, raw_bytes );
+ //cout << "handle_midi_sysex: " << bytes << endl;
+ switch( bytes[5] )
+ {
+ case 0x01:
+ // not used right now
+ write_sysex( host_connection_query( bytes ) );
+ break;
+ case 0x03:
+ // not used right now
+ write_sysex( host_connection_confirmation( bytes ) );
+ break;
+ case 0x04:
+ inactive_event();
+ cout << "host connection error" << bytes << endl;
+ break;
+ case 0x14:
+ probe_emulation( bytes );
+ break;
+ default:
+ cout << "unknown sysex: " << bytes << endl;
+ }
+}
+
+// converts midi messages into control_event signals
+void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes, size_t count )
+{
+ MidiByteArray bytes( count, raw_bytes );
+ try
+ {
+ // ignore sysex messages
+ if ( bytes[0] == MIDI::sysex ) return;
+
+ Control & control = lookup_control( bytes );
+
+ // This handles incoming bytes. Outgoing bytes
+ // are sent by the signal handlers.
+ switch ( control.type() )
+ {
+ // fader
+ case Control::type_fader:
+ {
+ // for a BCF2000, max is 7f for high-order byte and 0x70 for low-order byte
+ // According to the Logic docs, these should both be 0x7f.
+ // Although it does mention something about only the top-order
+ // 10 bits out of 14 being used
+ int midi_pos = ( bytes[2] << 7 ) + bytes[1];
+ control_event( *this, control, float(midi_pos) / float(0x3fff) );
+ }
+ break;
+
+ // button
+ case Control::type_button:
+ control_event( *this, control, bytes[2] == 0x7f ? press : release );
+ break;
+
+ // pot (jog wheel, external control)
+ case Control::type_pot:
+ {
+ ControlState state;
+
+ // bytes[2] & 0b01000000 (0x40) give sign
+ int sign = ( bytes[2] & 0x40 ) == 0 ? 1 : -1;
+ // bytes[2] & 0b00111111 (0x3f) gives delta
+ state.ticks = ( bytes[2] & 0x3f) * sign;
+ state.delta = float( state.ticks ) / float( 0x3f );
+
+ control_event( *this, control, state );
+ }
+ break;
+ default:
+ cerr << "Do not understand control type " << control;
+ }
+ }
+ catch( MackieControlException & e )
+ {
+ //cout << bytes << ' ' << e.what() << endl;
+ }
+}
diff --git a/libs/surfaces/mackie/mackie_port.h b/libs/surfaces/mackie/mackie_port.h
new file mode 100644
index 0000000000..2ad5cf6154
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_port.h
@@ -0,0 +1,122 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef mackie_port_h
+#define mackie_port_h
+
+#include "surface_port.h"
+
+#include <midi++/types.h>
+#include <sigc++/signal.h>
+#include <sigc++/connection.h>
+
+#include <glibmm/thread.h>
+
+#include "midi_byte_array.h"
+#include "types.h"
+
+namespace MIDI {
+ class Port;
+ class Parser;
+}
+
+class MackieControlProtocol;
+
+namespace Mackie
+{
+
+class MackiePort : public SurfacePort
+{
+public:
+ enum port_type_t { mcu, ext };
+ enum emulation_t { none, mackie, bcf2000 };
+
+ MackiePort( MackieControlProtocol & mcp, MIDI::Port & port, int number, port_type_t = mcu );
+ ~MackiePort();
+
+ virtual void open();
+ virtual void close();
+
+ /// MCU and extenders have different sysex headers
+ virtual const MidiByteArray & sysex_hdr() const;
+
+ /// Handle device initialisation
+ void handle_midi_sysex( MIDI::Parser &, MIDI::byte *, size_t );
+
+ /// Handle all control messags
+ void handle_midi_any( MIDI::Parser &, MIDI::byte *, size_t );
+
+ Control & lookup_control( const MidiByteArray & bytes );
+
+ /// return the number of strips associated with this port
+ virtual int strips() const;
+
+ /// Block until the port has finished initialising, and then return
+ /// whether the intialisation succeeded
+ bool wait_for_init();
+
+ emulation_t emulation() const { return _emulation; }
+
+protected:
+ /**
+ The initialisation sequence is fairly complex. First a lock is acquired
+ so that a condition can be used to signal the end of the init process.
+ Then a sysex is sent to the device. The response to the sysex
+ is handled by a switch in handle_midi_sysex which calls one of the
+ other methods.
+
+ However, windows DAWs ignore the documented init sequence and so we
+ do too. Thanks to Essox for helping with this.
+
+ So we use the version firmware to figure out what device is on
+ the other end of the cable.
+ */
+ void init();
+
+ /**
+ Once the device is initialised, finalise_init(true) is called, which
+ releases the lock and signals the condition, and starts handling incoming
+ messages. finalise_init(false) will also release the lock but doesn't
+ start handling messages.
+ */
+ void finalise_init( bool yn );
+
+ MidiByteArray host_connection_query( MidiByteArray & bytes );
+ MidiByteArray host_connection_confirmation( const MidiByteArray & bytes );
+
+ /**
+ Will set _emulation to what it thinks is correct, based
+ on responses from the device. Or get/set parameters. Or
+ environment variables. Or existence of a file.
+ */
+ void probe_emulation( const MidiByteArray & bytes );
+
+private:
+ MackieControlProtocol & _mcp;
+ port_type_t _port_type;
+ sigc::connection _any;
+ sigc::connection _sysex;
+ emulation_t _emulation;
+
+ bool _initialising;
+ Glib::Cond init_cond;
+ Glib::Mutex init_mutex;
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/mackie_surface.cc b/libs/surfaces/mackie/mackie_surface.cc
new file mode 100644
index 0000000000..b527f710cc
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_surface.cc
@@ -0,0 +1,1504 @@
+/*
+ Generated by scripts/generate-surface.rb
+*/
+
+#include "mackie_surface.h"
+
+#include "controls.h"
+#include "mackie_button_handler.h"
+
+using namespace Mackie;
+
+void Mackie::MackieSurface::init_controls()
+{
+ // intialise groups and strips
+ Group * group = 0;
+
+ // make sure there are enough strips
+ strips.resize( 8 );
+
+ group = new Group ( "user" );
+ groups["user"] = group;
+
+ group = new Group ( "assignment" );
+ groups["assignment"] = group;
+
+ group = new Group ( "none" );
+ groups["none"] = group;
+
+ group = new MasterStrip ( "master", 0 );
+ groups["master"] = group;
+ strips[0] = dynamic_cast<Strip*>( group );
+
+ group = new Strip ( "strip_1", 0 );
+ groups["strip_1"] = group;
+ strips[0] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "cursor" );
+ groups["cursor"] = group;
+
+ group = new Strip ( "strip_2", 1 );
+ groups["strip_2"] = group;
+ strips[1] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "functions" );
+ groups["functions"] = group;
+
+ group = new Group ( "automation" );
+ groups["automation"] = group;
+
+ group = new Strip ( "strip_3", 2 );
+ groups["strip_3"] = group;
+ strips[2] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "display" );
+ groups["display"] = group;
+
+ group = new Strip ( "strip_4", 3 );
+ groups["strip_4"] = group;
+ strips[3] = dynamic_cast<Strip*>( group );
+
+ group = new Strip ( "strip_5", 4 );
+ groups["strip_5"] = group;
+ strips[4] = dynamic_cast<Strip*>( group );
+
+ group = new Strip ( "strip_6", 5 );
+ groups["strip_6"] = group;
+ strips[5] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "transport" );
+ groups["transport"] = group;
+
+ group = new Strip ( "strip_7", 6 );
+ groups["strip_7"] = group;
+ strips[6] = dynamic_cast<Strip*>( group );
+
+ group = new Group ( "modifiers" );
+ groups["modifiers"] = group;
+
+ group = new Group ( "bank" );
+ groups["bank"] = group;
+
+ group = new Strip ( "strip_8", 7 );
+ groups["strip_8"] = group;
+ strips[7] = dynamic_cast<Strip*>( group );
+
+
+ // initialise controls
+ Control * control = 0;
+
+ group = groups["strip_1"];
+ control = new Fader ( 0, 1, "gain", *group );
+ faders[0x00] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Fader ( 1, 2, "gain", *group );
+ faders[0x01] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Fader ( 2, 3, "gain", *group );
+ faders[0x02] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Fader ( 3, 4, "gain", *group );
+ faders[0x03] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Fader ( 4, 5, "gain", *group );
+ faders[0x04] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Fader ( 5, 6, "gain", *group );
+ faders[0x05] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Fader ( 6, 7, "gain", *group );
+ faders[0x06] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_8"];
+ control = new Fader ( 7, 8, "gain", *group );
+ faders[0x07] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["master"];
+ control = new Fader ( 8, 1, "gain", *group );
+ faders[0x08] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Pot ( 16, 1, "vpot", *group );
+ pots[0x10] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Pot ( 17, 2, "vpot", *group );
+ pots[0x11] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Pot ( 18, 3, "vpot", *group );
+ pots[0x12] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Pot ( 19, 4, "vpot", *group );
+ pots[0x13] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Pot ( 20, 5, "vpot", *group );
+ pots[0x14] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Pot ( 21, 6, "vpot", *group );
+ pots[0x15] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Pot ( 22, 7, "vpot", *group );
+ pots[0x16] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_8"];
+ control = new Pot ( 23, 8, "vpot", *group );
+ pots[0x17] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Pot ( 60, 1, "jog", *group );
+ pots[0x3c] = control;
+ controls.push_back( control );
+ controls_by_name["jog"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Pot ( 46, 1, "external", *group );
+ pots[0x2e] = control;
+ controls.push_back( control );
+ controls_by_name["external"] = control;
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 0, 1, "recenable", *group );
+ buttons[0x00] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 1, 2, "recenable", *group );
+ buttons[0x01] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 2, 3, "recenable", *group );
+ buttons[0x02] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 3, 4, "recenable", *group );
+ buttons[0x03] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 4, 5, "recenable", *group );
+ buttons[0x04] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 5, 6, "recenable", *group );
+ buttons[0x05] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 6, 7, "recenable", *group );
+ buttons[0x06] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_8"];
+ control = new Button ( 7, 8, "recenable", *group );
+ buttons[0x07] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 8, 1, "solo", *group );
+ buttons[0x08] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 9, 2, "solo", *group );
+ buttons[0x09] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 10, 3, "solo", *group );
+ buttons[0x0a] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 11, 4, "solo", *group );
+ buttons[0x0b] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 12, 5, "solo", *group );
+ buttons[0x0c] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 13, 6, "solo", *group );
+ buttons[0x0d] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 14, 7, "solo", *group );
+ buttons[0x0e] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_8"];
+ control = new Button ( 15, 8, "solo", *group );
+ buttons[0x0f] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 16, 1, "mute", *group );
+ buttons[0x10] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 17, 2, "mute", *group );
+ buttons[0x11] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 18, 3, "mute", *group );
+ buttons[0x12] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 19, 4, "mute", *group );
+ buttons[0x13] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 20, 5, "mute", *group );
+ buttons[0x14] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 21, 6, "mute", *group );
+ buttons[0x15] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 22, 7, "mute", *group );
+ buttons[0x16] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_8"];
+ control = new Button ( 23, 8, "mute", *group );
+ buttons[0x17] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 24, 1, "select", *group );
+ buttons[0x18] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 25, 2, "select", *group );
+ buttons[0x19] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 26, 3, "select", *group );
+ buttons[0x1a] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 27, 4, "select", *group );
+ buttons[0x1b] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 28, 5, "select", *group );
+ buttons[0x1c] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 29, 6, "select", *group );
+ buttons[0x1d] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 30, 7, "select", *group );
+ buttons[0x1e] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_8"];
+ control = new Button ( 31, 8, "select", *group );
+ buttons[0x1f] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 32, 1, "vselect", *group );
+ buttons[0x20] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 33, 2, "vselect", *group );
+ buttons[0x21] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 34, 3, "vselect", *group );
+ buttons[0x22] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 35, 4, "vselect", *group );
+ buttons[0x23] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 36, 5, "vselect", *group );
+ buttons[0x24] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 37, 6, "vselect", *group );
+ buttons[0x25] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 38, 7, "vselect", *group );
+ buttons[0x26] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_8"];
+ control = new Button ( 39, 8, "vselect", *group );
+ buttons[0x27] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 40, 1, "io", *group );
+ buttons[0x28] = control;
+ controls.push_back( control );
+ controls_by_name["io"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 41, 1, "sends", *group );
+ buttons[0x29] = control;
+ controls.push_back( control );
+ controls_by_name["sends"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 42, 1, "pan", *group );
+ buttons[0x2a] = control;
+ controls.push_back( control );
+ controls_by_name["pan"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 43, 1, "plugin", *group );
+ buttons[0x2b] = control;
+ controls.push_back( control );
+ controls_by_name["plugin"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 44, 1, "eq", *group );
+ buttons[0x2c] = control;
+ controls.push_back( control );
+ controls_by_name["eq"] = control;
+ group->add( *control );
+
+ group = groups["assignment"];
+ control = new Button ( 45, 1, "dyn", *group );
+ buttons[0x2d] = control;
+ controls.push_back( control );
+ controls_by_name["dyn"] = control;
+ group->add( *control );
+
+ group = groups["bank"];
+ control = new Button ( 46, 1, "left", *group );
+ buttons[0x2e] = control;
+ controls.push_back( control );
+ controls_by_name["left"] = control;
+ group->add( *control );
+
+ group = groups["bank"];
+ control = new Button ( 47, 1, "right", *group );
+ buttons[0x2f] = control;
+ controls.push_back( control );
+ controls_by_name["right"] = control;
+ group->add( *control );
+
+ group = groups["bank"];
+ control = new Button ( 48, 1, "channel_left", *group );
+ buttons[0x30] = control;
+ controls.push_back( control );
+ controls_by_name["channel_left"] = control;
+ group->add( *control );
+
+ group = groups["bank"];
+ control = new Button ( 49, 1, "channel_right", *group );
+ buttons[0x31] = control;
+ controls.push_back( control );
+ controls_by_name["channel_right"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 50, 1, "flip", *group );
+ buttons[0x32] = control;
+ controls.push_back( control );
+ controls_by_name["flip"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 51, 1, "edit", *group );
+ buttons[0x33] = control;
+ controls.push_back( control );
+ controls_by_name["edit"] = control;
+ group->add( *control );
+
+ group = groups["display"];
+ control = new Button ( 52, 1, "name_value", *group );
+ buttons[0x34] = control;
+ controls.push_back( control );
+ controls_by_name["name_value"] = control;
+ group->add( *control );
+
+ group = groups["display"];
+ control = new Button ( 53, 1, "smpte_beats", *group );
+ buttons[0x35] = control;
+ controls.push_back( control );
+ controls_by_name["smpte_beats"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 54, 1, "F1", *group );
+ buttons[0x36] = control;
+ controls.push_back( control );
+ controls_by_name["F1"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 55, 1, "F2", *group );
+ buttons[0x37] = control;
+ controls.push_back( control );
+ controls_by_name["F2"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 56, 1, "F3", *group );
+ buttons[0x38] = control;
+ controls.push_back( control );
+ controls_by_name["F3"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 57, 1, "F4", *group );
+ buttons[0x39] = control;
+ controls.push_back( control );
+ controls_by_name["F4"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 58, 1, "F5", *group );
+ buttons[0x3a] = control;
+ controls.push_back( control );
+ controls_by_name["F5"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 59, 1, "F6", *group );
+ buttons[0x3b] = control;
+ controls.push_back( control );
+ controls_by_name["F6"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 60, 1, "F7", *group );
+ buttons[0x3c] = control;
+ controls.push_back( control );
+ controls_by_name["F7"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 61, 1, "F8", *group );
+ buttons[0x3d] = control;
+ controls.push_back( control );
+ controls_by_name["F8"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 62, 1, "F9", *group );
+ buttons[0x3e] = control;
+ controls.push_back( control );
+ controls_by_name["F9"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 63, 1, "F10", *group );
+ buttons[0x3f] = control;
+ controls.push_back( control );
+ controls_by_name["F10"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 64, 1, "F11", *group );
+ buttons[0x40] = control;
+ controls.push_back( control );
+ controls_by_name["F11"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 65, 1, "F12", *group );
+ buttons[0x41] = control;
+ controls.push_back( control );
+ controls_by_name["F12"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 66, 1, "F13", *group );
+ buttons[0x42] = control;
+ controls.push_back( control );
+ controls_by_name["F13"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 67, 1, "F14", *group );
+ buttons[0x43] = control;
+ controls.push_back( control );
+ controls_by_name["F14"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 68, 1, "F15", *group );
+ buttons[0x44] = control;
+ controls.push_back( control );
+ controls_by_name["F15"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 69, 1, "F16", *group );
+ buttons[0x45] = control;
+ controls.push_back( control );
+ controls_by_name["F16"] = control;
+ group->add( *control );
+
+ group = groups["modifiers"];
+ control = new Button ( 70, 1, "shift", *group );
+ buttons[0x46] = control;
+ controls.push_back( control );
+ controls_by_name["shift"] = control;
+ group->add( *control );
+
+ group = groups["modifiers"];
+ control = new Button ( 71, 1, "option", *group );
+ buttons[0x47] = control;
+ controls.push_back( control );
+ controls_by_name["option"] = control;
+ group->add( *control );
+
+ group = groups["modifiers"];
+ control = new Button ( 72, 1, "control", *group );
+ buttons[0x48] = control;
+ controls.push_back( control );
+ controls_by_name["control"] = control;
+ group->add( *control );
+
+ group = groups["modifiers"];
+ control = new Button ( 73, 1, "cmd_alt", *group );
+ buttons[0x49] = control;
+ controls.push_back( control );
+ controls_by_name["cmd_alt"] = control;
+ group->add( *control );
+
+ group = groups["automation"];
+ control = new Button ( 74, 1, "on", *group );
+ buttons[0x4a] = control;
+ controls.push_back( control );
+ controls_by_name["on"] = control;
+ group->add( *control );
+
+ group = groups["automation"];
+ control = new Button ( 75, 1, "rec_ready", *group );
+ buttons[0x4b] = control;
+ controls.push_back( control );
+ controls_by_name["rec_ready"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 76, 1, "undo", *group );
+ buttons[0x4c] = control;
+ controls.push_back( control );
+ controls_by_name["undo"] = control;
+ group->add( *control );
+
+ group = groups["automation"];
+ control = new Button ( 77, 1, "snapshot", *group );
+ buttons[0x4d] = control;
+ controls.push_back( control );
+ controls_by_name["snapshot"] = control;
+ group->add( *control );
+
+ group = groups["automation"];
+ control = new Button ( 78, 1, "touch", *group );
+ buttons[0x4e] = control;
+ controls.push_back( control );
+ controls_by_name["touch"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 79, 1, "redo", *group );
+ buttons[0x4f] = control;
+ controls.push_back( control );
+ controls_by_name["redo"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 80, 1, "marker", *group );
+ buttons[0x50] = control;
+ controls.push_back( control );
+ controls_by_name["marker"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 81, 1, "enter", *group );
+ buttons[0x51] = control;
+ controls.push_back( control );
+ controls_by_name["enter"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 82, 1, "cancel", *group );
+ buttons[0x52] = control;
+ controls.push_back( control );
+ controls_by_name["cancel"] = control;
+ group->add( *control );
+
+ group = groups["functions"];
+ control = new Button ( 83, 1, "mixer", *group );
+ buttons[0x53] = control;
+ controls.push_back( control );
+ controls_by_name["mixer"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 84, 1, "frm_left", *group );
+ buttons[0x54] = control;
+ controls.push_back( control );
+ controls_by_name["frm_left"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 85, 1, "frm_right", *group );
+ buttons[0x55] = control;
+ controls.push_back( control );
+ controls_by_name["frm_right"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 86, 1, "loop", *group );
+ buttons[0x56] = control;
+ controls.push_back( control );
+ controls_by_name["loop"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 87, 1, "punch_in", *group );
+ buttons[0x57] = control;
+ controls.push_back( control );
+ controls_by_name["punch_in"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 88, 1, "punch_out", *group );
+ buttons[0x58] = control;
+ controls.push_back( control );
+ controls_by_name["punch_out"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 89, 1, "home", *group );
+ buttons[0x59] = control;
+ controls.push_back( control );
+ controls_by_name["home"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 90, 1, "end", *group );
+ buttons[0x5a] = control;
+ controls.push_back( control );
+ controls_by_name["end"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 91, 1, "rewind", *group );
+ buttons[0x5b] = control;
+ controls.push_back( control );
+ controls_by_name["rewind"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 92, 1, "ffwd", *group );
+ buttons[0x5c] = control;
+ controls.push_back( control );
+ controls_by_name["ffwd"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 93, 1, "stop", *group );
+ buttons[0x5d] = control;
+ controls.push_back( control );
+ controls_by_name["stop"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 94, 1, "play", *group );
+ buttons[0x5e] = control;
+ controls.push_back( control );
+ controls_by_name["play"] = control;
+ group->add( *control );
+
+ group = groups["transport"];
+ control = new Button ( 95, 1, "record", *group );
+ buttons[0x5f] = control;
+ controls.push_back( control );
+ controls_by_name["record"] = control;
+ group->add( *control );
+
+ group = groups["cursor"];
+ control = new Button ( 96, 1, "cursor_up", *group );
+ buttons[0x60] = control;
+ controls.push_back( control );
+ controls_by_name["cursor_up"] = control;
+ group->add( *control );
+
+ group = groups["cursor"];
+ control = new Button ( 97, 1, "cursor_down", *group );
+ buttons[0x61] = control;
+ controls.push_back( control );
+ controls_by_name["cursor_down"] = control;
+ group->add( *control );
+
+ group = groups["cursor"];
+ control = new Button ( 98, 1, "cursor_left", *group );
+ buttons[0x62] = control;
+ controls.push_back( control );
+ controls_by_name["cursor_left"] = control;
+ group->add( *control );
+
+ group = groups["cursor"];
+ control = new Button ( 99, 1, "cursor_right", *group );
+ buttons[0x63] = control;
+ controls.push_back( control );
+ controls_by_name["cursor_right"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 100, 1, "zoom", *group );
+ buttons[0x64] = control;
+ controls.push_back( control );
+ controls_by_name["zoom"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Button ( 101, 1, "scrub", *group );
+ buttons[0x65] = control;
+ controls.push_back( control );
+ controls_by_name["scrub"] = control;
+ group->add( *control );
+
+ group = groups["user"];
+ control = new Button ( 102, 1, "user_a", *group );
+ buttons[0x66] = control;
+ controls.push_back( control );
+ controls_by_name["user_a"] = control;
+ group->add( *control );
+
+ group = groups["user"];
+ control = new Button ( 103, 1, "user_b", *group );
+ buttons[0x67] = control;
+ controls.push_back( control );
+ controls_by_name["user_b"] = control;
+ group->add( *control );
+
+ group = groups["strip_1"];
+ control = new Button ( 104, 1, "fader_touch", *group );
+ buttons[0x68] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_2"];
+ control = new Button ( 105, 2, "fader_touch", *group );
+ buttons[0x69] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_3"];
+ control = new Button ( 106, 3, "fader_touch", *group );
+ buttons[0x6a] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_4"];
+ control = new Button ( 107, 4, "fader_touch", *group );
+ buttons[0x6b] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_5"];
+ control = new Button ( 108, 5, "fader_touch", *group );
+ buttons[0x6c] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_6"];
+ control = new Button ( 109, 6, "fader_touch", *group );
+ buttons[0x6d] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_7"];
+ control = new Button ( 110, 7, "fader_touch", *group );
+ buttons[0x6e] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["strip_8"];
+ control = new Button ( 111, 8, "fader_touch", *group );
+ buttons[0x6f] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["master"];
+ control = new Button ( 112, 1, "fader_touch", *group );
+ buttons[0x70] = control;
+ controls.push_back( control );
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Led ( 113, 1, "smpte", *group );
+ leds[0x71] = control;
+ controls.push_back( control );
+ controls_by_name["smpte"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Led ( 114, 1, "beats", *group );
+ leds[0x72] = control;
+ controls.push_back( control );
+ controls_by_name["beats"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Led ( 115, 1, "solo", *group );
+ leds[0x73] = control;
+ controls.push_back( control );
+ controls_by_name["solo"] = control;
+ group->add( *control );
+
+ group = groups["none"];
+ control = new Led ( 118, 1, "relay_click", *group );
+ leds[0x76] = control;
+ controls.push_back( control );
+ controls_by_name["relay_click"] = control;
+ group->add( *control );
+
+}
+
+void Mackie::MackieSurface::handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button )
+{
+ if ( bs != press && bs != release )
+ {
+ mbh.update_led( button, none );
+ return;
+ }
+
+ LedState ls;
+ switch ( button.id() )
+ {
+
+ case 0x28: // io
+ switch ( bs ) {
+ case press: ls = mbh.io_press( button ); break;
+ case release: ls = mbh.io_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x29: // sends
+ switch ( bs ) {
+ case press: ls = mbh.sends_press( button ); break;
+ case release: ls = mbh.sends_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2a: // pan
+ switch ( bs ) {
+ case press: ls = mbh.pan_press( button ); break;
+ case release: ls = mbh.pan_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2b: // plugin
+ switch ( bs ) {
+ case press: ls = mbh.plugin_press( button ); break;
+ case release: ls = mbh.plugin_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2c: // eq
+ switch ( bs ) {
+ case press: ls = mbh.eq_press( button ); break;
+ case release: ls = mbh.eq_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2d: // dyn
+ switch ( bs ) {
+ case press: ls = mbh.dyn_press( button ); break;
+ case release: ls = mbh.dyn_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2e: // left
+ switch ( bs ) {
+ case press: ls = mbh.left_press( button ); break;
+ case release: ls = mbh.left_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x2f: // right
+ switch ( bs ) {
+ case press: ls = mbh.right_press( button ); break;
+ case release: ls = mbh.right_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x30: // channel_left
+ switch ( bs ) {
+ case press: ls = mbh.channel_left_press( button ); break;
+ case release: ls = mbh.channel_left_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x31: // channel_right
+ switch ( bs ) {
+ case press: ls = mbh.channel_right_press( button ); break;
+ case release: ls = mbh.channel_right_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x32: // flip
+ switch ( bs ) {
+ case press: ls = mbh.flip_press( button ); break;
+ case release: ls = mbh.flip_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x33: // edit
+ switch ( bs ) {
+ case press: ls = mbh.edit_press( button ); break;
+ case release: ls = mbh.edit_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x34: // name_value
+ switch ( bs ) {
+ case press: ls = mbh.name_value_press( button ); break;
+ case release: ls = mbh.name_value_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x35: // smpte_beats
+ switch ( bs ) {
+ case press: ls = mbh.smpte_beats_press( button ); break;
+ case release: ls = mbh.smpte_beats_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x36: // F1
+ switch ( bs ) {
+ case press: ls = mbh.F1_press( button ); break;
+ case release: ls = mbh.F1_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x37: // F2
+ switch ( bs ) {
+ case press: ls = mbh.F2_press( button ); break;
+ case release: ls = mbh.F2_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x38: // F3
+ switch ( bs ) {
+ case press: ls = mbh.F3_press( button ); break;
+ case release: ls = mbh.F3_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x39: // F4
+ switch ( bs ) {
+ case press: ls = mbh.F4_press( button ); break;
+ case release: ls = mbh.F4_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3a: // F5
+ switch ( bs ) {
+ case press: ls = mbh.F5_press( button ); break;
+ case release: ls = mbh.F5_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3b: // F6
+ switch ( bs ) {
+ case press: ls = mbh.F6_press( button ); break;
+ case release: ls = mbh.F6_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3c: // F7
+ switch ( bs ) {
+ case press: ls = mbh.F7_press( button ); break;
+ case release: ls = mbh.F7_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3d: // F8
+ switch ( bs ) {
+ case press: ls = mbh.F8_press( button ); break;
+ case release: ls = mbh.F8_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3e: // F9
+ switch ( bs ) {
+ case press: ls = mbh.F9_press( button ); break;
+ case release: ls = mbh.F9_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x3f: // F10
+ switch ( bs ) {
+ case press: ls = mbh.F10_press( button ); break;
+ case release: ls = mbh.F10_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x40: // F11
+ switch ( bs ) {
+ case press: ls = mbh.F11_press( button ); break;
+ case release: ls = mbh.F11_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x41: // F12
+ switch ( bs ) {
+ case press: ls = mbh.F12_press( button ); break;
+ case release: ls = mbh.F12_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x42: // F13
+ switch ( bs ) {
+ case press: ls = mbh.F13_press( button ); break;
+ case release: ls = mbh.F13_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x43: // F14
+ switch ( bs ) {
+ case press: ls = mbh.F14_press( button ); break;
+ case release: ls = mbh.F14_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x44: // F15
+ switch ( bs ) {
+ case press: ls = mbh.F15_press( button ); break;
+ case release: ls = mbh.F15_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x45: // F16
+ switch ( bs ) {
+ case press: ls = mbh.F16_press( button ); break;
+ case release: ls = mbh.F16_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x46: // shift
+ switch ( bs ) {
+ case press: ls = mbh.shift_press( button ); break;
+ case release: ls = mbh.shift_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x47: // option
+ switch ( bs ) {
+ case press: ls = mbh.option_press( button ); break;
+ case release: ls = mbh.option_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x48: // control
+ switch ( bs ) {
+ case press: ls = mbh.control_press( button ); break;
+ case release: ls = mbh.control_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x49: // cmd_alt
+ switch ( bs ) {
+ case press: ls = mbh.cmd_alt_press( button ); break;
+ case release: ls = mbh.cmd_alt_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4a: // on
+ switch ( bs ) {
+ case press: ls = mbh.on_press( button ); break;
+ case release: ls = mbh.on_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4b: // rec_ready
+ switch ( bs ) {
+ case press: ls = mbh.rec_ready_press( button ); break;
+ case release: ls = mbh.rec_ready_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4c: // undo
+ switch ( bs ) {
+ case press: ls = mbh.undo_press( button ); break;
+ case release: ls = mbh.undo_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4d: // snapshot
+ switch ( bs ) {
+ case press: ls = mbh.snapshot_press( button ); break;
+ case release: ls = mbh.snapshot_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4e: // touch
+ switch ( bs ) {
+ case press: ls = mbh.touch_press( button ); break;
+ case release: ls = mbh.touch_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x4f: // redo
+ switch ( bs ) {
+ case press: ls = mbh.redo_press( button ); break;
+ case release: ls = mbh.redo_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x50: // marker
+ switch ( bs ) {
+ case press: ls = mbh.marker_press( button ); break;
+ case release: ls = mbh.marker_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x51: // enter
+ switch ( bs ) {
+ case press: ls = mbh.enter_press( button ); break;
+ case release: ls = mbh.enter_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x52: // cancel
+ switch ( bs ) {
+ case press: ls = mbh.cancel_press( button ); break;
+ case release: ls = mbh.cancel_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x53: // mixer
+ switch ( bs ) {
+ case press: ls = mbh.mixer_press( button ); break;
+ case release: ls = mbh.mixer_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x54: // frm_left
+ switch ( bs ) {
+ case press: ls = mbh.frm_left_press( button ); break;
+ case release: ls = mbh.frm_left_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x55: // frm_right
+ switch ( bs ) {
+ case press: ls = mbh.frm_right_press( button ); break;
+ case release: ls = mbh.frm_right_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x56: // loop
+ switch ( bs ) {
+ case press: ls = mbh.loop_press( button ); break;
+ case release: ls = mbh.loop_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x57: // punch_in
+ switch ( bs ) {
+ case press: ls = mbh.punch_in_press( button ); break;
+ case release: ls = mbh.punch_in_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x58: // punch_out
+ switch ( bs ) {
+ case press: ls = mbh.punch_out_press( button ); break;
+ case release: ls = mbh.punch_out_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x59: // home
+ switch ( bs ) {
+ case press: ls = mbh.home_press( button ); break;
+ case release: ls = mbh.home_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5a: // end
+ switch ( bs ) {
+ case press: ls = mbh.end_press( button ); break;
+ case release: ls = mbh.end_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5b: // rewind
+ switch ( bs ) {
+ case press: ls = mbh.rewind_press( button ); break;
+ case release: ls = mbh.rewind_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5c: // ffwd
+ switch ( bs ) {
+ case press: ls = mbh.ffwd_press( button ); break;
+ case release: ls = mbh.ffwd_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5d: // stop
+ switch ( bs ) {
+ case press: ls = mbh.stop_press( button ); break;
+ case release: ls = mbh.stop_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5e: // play
+ switch ( bs ) {
+ case press: ls = mbh.play_press( button ); break;
+ case release: ls = mbh.play_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x5f: // record
+ switch ( bs ) {
+ case press: ls = mbh.record_press( button ); break;
+ case release: ls = mbh.record_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x60: // cursor_up
+ switch ( bs ) {
+ case press: ls = mbh.cursor_up_press( button ); break;
+ case release: ls = mbh.cursor_up_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x61: // cursor_down
+ switch ( bs ) {
+ case press: ls = mbh.cursor_down_press( button ); break;
+ case release: ls = mbh.cursor_down_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x62: // cursor_left
+ switch ( bs ) {
+ case press: ls = mbh.cursor_left_press( button ); break;
+ case release: ls = mbh.cursor_left_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x63: // cursor_right
+ switch ( bs ) {
+ case press: ls = mbh.cursor_right_press( button ); break;
+ case release: ls = mbh.cursor_right_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x64: // zoom
+ switch ( bs ) {
+ case press: ls = mbh.zoom_press( button ); break;
+ case release: ls = mbh.zoom_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x65: // scrub
+ switch ( bs ) {
+ case press: ls = mbh.scrub_press( button ); break;
+ case release: ls = mbh.scrub_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x66: // user_a
+ switch ( bs ) {
+ case press: ls = mbh.user_a_press( button ); break;
+ case release: ls = mbh.user_a_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ case 0x67: // user_b
+ switch ( bs ) {
+ case press: ls = mbh.user_b_press( button ); break;
+ case release: ls = mbh.user_b_release( button ); break;
+ case neither: break;
+ }
+ break;
+
+ }
+ mbh.update_led( button, ls );
+}
diff --git a/libs/surfaces/mackie/mackie_surface.h b/libs/surfaces/mackie/mackie_surface.h
new file mode 100644
index 0000000000..735cbc5851
--- /dev/null
+++ b/libs/surfaces/mackie/mackie_surface.h
@@ -0,0 +1,27 @@
+#ifndef mackie_surface_mackie_h
+#define mackie_surface_mackie_h
+/*
+ Generated by scripts/generate-surface.rb
+*/
+
+#include "surface.h"
+
+namespace Mackie
+{
+
+class MackieButtonHandler;
+
+class MackieSurface : public Surface
+{
+public:
+ MackieSurface( uint32_t max_strips ) : Surface( max_strips )
+ {
+ }
+
+ virtual void handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button );
+ virtual void init_controls();
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/midi_byte_array.cc b/libs/surfaces/mackie/midi_byte_array.cc
new file mode 100644
index 0000000000..192af6a1ce
--- /dev/null
+++ b/libs/surfaces/mackie/midi_byte_array.cc
@@ -0,0 +1,98 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "midi_byte_array.h"
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include <cstdarg>
+#include <iomanip>
+
+using namespace std;
+
+MidiByteArray::MidiByteArray( size_t size, MIDI::byte array[] )
+: std::vector<MIDI::byte>()
+{
+ for ( size_t i = 0; i < size; ++i )
+ {
+ push_back( array[i] );
+ }
+}
+
+MidiByteArray::MidiByteArray( size_t count, MIDI::byte first, ... )
+: vector<MIDI::byte>()
+{
+ push_back( first );
+ va_list var_args;
+ va_start( var_args, first );
+ for ( size_t i = 1; i < count; ++i )
+ {
+ MIDI::byte b = va_arg( var_args, int );
+ push_back( b );
+ }
+ va_end( var_args );
+}
+
+boost::shared_array<MIDI::byte> MidiByteArray::bytes() const
+{
+ MIDI::byte * buf = new MIDI::byte[size()];
+ const_iterator it = begin();
+ for( MIDI::byte * ptr = buf; it != end(); ++it )
+ {
+ *ptr++ = *it;
+ }
+ return boost::shared_array<MIDI::byte>( buf );
+}
+
+void MidiByteArray::copy( size_t count, MIDI::byte * arr )
+{
+ for( size_t i = 0; i < count; ++i )
+ {
+ push_back( arr[i] );
+ }
+}
+
+MidiByteArray & operator << ( MidiByteArray & mba, const MIDI::byte & b )
+{
+ mba.push_back( b );
+ return mba;
+}
+
+MidiByteArray & operator << ( MidiByteArray & mba, const MidiByteArray & barr )
+{
+ back_insert_iterator<MidiByteArray> bit( mba );
+ copy( barr.begin(), barr.end(), bit );
+ return mba;
+}
+
+ostream & operator << ( ostream & os, const MidiByteArray & mba )
+{
+ os << "[";
+ char fill = os.fill('0');
+ for( MidiByteArray::const_iterator it = mba.begin(); it != mba.end(); ++it )
+ {
+ if ( it != mba.begin() ) os << " ";
+ os << hex << setw(2) << (int)*it;
+ }
+ os.fill( fill );
+ os << dec;
+ os << "]";
+ return os;
+}
diff --git a/libs/surfaces/mackie/midi_byte_array.h b/libs/surfaces/mackie/midi_byte_array.h
new file mode 100644
index 0000000000..e77ece1b88
--- /dev/null
+++ b/libs/surfaces/mackie/midi_byte_array.h
@@ -0,0 +1,76 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef midi_byte_array_h
+#define midi_byte_array_h
+
+#include <iostream>
+#include <vector>
+
+#include <boost/shared_array.hpp>
+
+//#include <midi++/types.h>
+namespace MIDI {
+ typedef unsigned char byte;
+}
+
+/**
+ To make building arrays of bytes easier. Thusly:
+
+ MidiByteArray mba;
+ mba << 0xf0 << 0x00 << 0xf7;
+
+ MidiByteArray buf;
+ buf << mba;
+
+ MidiByteArray direct( 3, 0xf0, 0x00, 0xf7 );
+
+ cout << mba << endl;
+ cout << buf << endl;
+ cout << direct << endl;
+
+ will all result in "f0 00 f7" being output to stdout
+*/
+class MidiByteArray : public std::vector<MIDI::byte>
+{
+public:
+ MidiByteArray() : std::vector<MIDI::byte>() {}
+
+ MidiByteArray( size_t count, MIDI::byte array[] );
+
+ /**
+ Accepts a preceding count, and then a list of bytes
+ */
+ MidiByteArray( size_t count, MIDI::byte first, ... );
+
+ /// return smart pointer to a copy of the bytes
+ boost::shared_array<MIDI::byte> bytes() const;
+
+ /// copy the given number of bytes from the given array
+ void copy( size_t count, MIDI::byte arr[] );
+};
+
+/// append the given byte to the end of the array
+MidiByteArray & operator << ( MidiByteArray & mba, const MIDI::byte & b );
+
+/// append the given array to the end of this array
+MidiByteArray & operator << ( MidiByteArray & mba, const MidiByteArray & barr );
+
+/// output the bytes as hex to the given stream
+std::ostream & operator << ( std::ostream & os, const MidiByteArray & mba );
+
+#endif
diff --git a/libs/surfaces/mackie/route_signal.cc b/libs/surfaces/mackie/route_signal.cc
new file mode 100644
index 0000000000..d77d0520a1
--- /dev/null
+++ b/libs/surfaces/mackie/route_signal.cc
@@ -0,0 +1,95 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "route_signal.h"
+
+#include <ardour/route.h>
+#include <ardour/track.h>
+#include <ardour/panner.h>
+
+#include "mackie_control_protocol.h"
+
+#include <stdexcept>
+
+using namespace Mackie;
+
+void RouteSignal::connect()
+{
+ if ( _strip.has_solo() )
+ _solo_changed_connection = _route.solo_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_solo_changed ), this ) );
+
+ if ( _strip.has_mute() )
+ _mute_changed_connection = _route.mute_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_mute_changed ), this ) );
+
+ if ( _strip.has_gain() )
+ _gain_changed_connection = _route.gain_control().Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_gain_changed ), this ) );
+
+ _name_changed_connection = _route.name_changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_name_changed ), this ) );
+
+ if ( _route.panner().size() == 1 )
+ {
+ _panner_changed_connection = _route.panner()[0]->Changed.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_panner_changed ), this ) );
+ }
+
+ try
+ {
+ _record_enable_changed_connection =
+ dynamic_cast<ARDOUR::Track&>( _route ).rec_enable_control().Changed
+ .connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_record_enable_changed ), this ) )
+ ;
+ }
+ catch ( std::bad_cast & )
+ {
+ // this should catch the dynamic_cast to Track, if what we're working
+ // with can't be record-enabled
+ }
+
+ // TODO
+ // active_changed
+ // SelectedChanged
+ // RemoteControlIDChanged. Better handled at Session level.
+}
+
+void RouteSignal::disconnect()
+{
+ _solo_changed_connection.disconnect();
+ _mute_changed_connection.disconnect();
+ _gain_changed_connection.disconnect();
+ _name_changed_connection.disconnect();
+ _panner_changed_connection.disconnect();
+ _record_enable_changed_connection.disconnect();
+}
+
+void RouteSignal::notify_all()
+{
+ if ( _strip.has_solo() )
+ _mcp.notify_solo_changed( this );
+
+ if ( _strip.has_mute() )
+ _mcp.notify_mute_changed( this );
+
+ if ( _strip.has_gain() )
+ _mcp.notify_gain_changed( this );
+
+ _mcp.notify_name_changed( &_route, this );
+
+ if ( _strip.has_vpot() )
+ _mcp.notify_panner_changed( this );
+
+ if ( _strip.has_recenable() )
+ _mcp.notify_record_enable_changed( this );
+}
diff --git a/libs/surfaces/mackie/route_signal.h b/libs/surfaces/mackie/route_signal.h
new file mode 100644
index 0000000000..0239980fd4
--- /dev/null
+++ b/libs/surfaces/mackie/route_signal.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef route_signal_h
+#define route_signal_h
+
+#include <sigc++/sigc++.h>
+
+class MackieControlProtocol;
+
+namespace ARDOUR {
+ class Route;
+}
+
+namespace Mackie
+{
+
+class Strip;
+class MackiePort;
+
+/**
+ This class is intended to easily create and destroy the set of
+ connections from a route to a control surface strip. Instantiating
+ it will connect the signals, and destructing it will disconnect
+ the signals.
+*/
+class RouteSignal
+{
+public:
+ RouteSignal( ARDOUR::Route & route, MackieControlProtocol & mcp, Strip & strip, MackiePort & port )
+ : _route( route ), _mcp( mcp ), _strip( strip ), _port( port )
+ {
+ connect();
+ }
+
+ ~RouteSignal()
+ {
+ disconnect();
+ }
+
+ void connect();
+ void disconnect();
+
+ // call all signal handlers manually
+ void notify_all();
+
+ const ARDOUR::Route & route() const { return _route; }
+ Strip & strip() { return _strip; }
+ MackiePort & port() { return _port; }
+
+private:
+ ARDOUR::Route & _route;
+ MackieControlProtocol & _mcp;
+ Strip & _strip;
+ MackiePort & _port;
+
+ sigc::connection _solo_changed_connection;
+ sigc::connection _mute_changed_connection;
+ sigc::connection _record_enable_changed_connection;
+ sigc::connection _gain_changed_connection;
+ sigc::connection _name_changed_connection;
+ sigc::connection _panner_changed_connection;
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/scripts/bank.rb b/libs/surfaces/mackie/scripts/bank.rb
new file mode 100644
index 0000000000..e1482545ee
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/bank.rb
@@ -0,0 +1,32 @@
+#! /usr/bin/ruby
+
+class Bank
+ attr_accessor :routes, :strips, :current
+
+ def initialize( routes = 17, strips = 8, current = 0 )
+ @routes = routes
+ @strips = strips
+ @current = current
+ end
+
+ def left
+ new_initial = current - routes
+ if new_initial < 0
+ new_initial = 0
+ end
+ current = new_initial
+ self
+ end
+
+ def right
+ delta = routes - ( strips + current ) - 1
+ puts "delta: #{delta}"
+ if delta > strips
+ delta = strips
+ end
+ @current += delta
+ self
+ end
+end
+
+b=Bank.new
diff --git a/libs/surfaces/mackie/scripts/bcf-controls.csv b/libs/surfaces/mackie/scripts/bcf-controls.csv
new file mode 100644
index 0000000000..6a6d66f6ac
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/bcf-controls.csv
@@ -0,0 +1,96 @@
+type,count,group,name,switch,led,id
+# faders
+fader,7,strip,gain,1,0,0x00
+fader,1,master,gain,1,0,0x07
+
+# pots
+pot,7,strip,vpot,1,1,0x10
+pot,1,,jog,1,0,0x17
+pot,1,,external,1,0,0x2e
+
+# strip buttons
+button,7,strip,recenable,1,1,0x18
+button,7,strip,solo,1,1,0x20
+button,7,strip,mute,1,1,0x10
+button,7,strip,select,1,1,0x0
+button,7,strip,vselect,1,0,0x08
+
+# overlay buttons
+button,1,assignment,io,1,1,0x28
+button,1,assignment,sends,1,1,0x5a
+button,1,assignment,pan,1,1,0x59
+button,1,assignment,plugin,1,1,0x57
+button,1,assignment,eq,1,1,0x58
+button,1,assignment,dyn,1,1,0x2d
+button,1,bank,left,1,0,0x2e
+button,1,bank,right,1,0,0x2f
+button,1,bank,channel_left,1,0,0x30
+button,1,bank,channel_right,1,0,0x31
+button,1,,flip,1,1,0x32
+button,1,,edit,1,1,0x56
+
+button,1,display,name_value,1,0,0x34
+button,1,display,smpte_beats,1,0,0x35
+button,1,,F1,1,0,0x36
+button,1,,F2,1,0,0x37
+button,1,,F3,1,0,0x38
+button,1,,F4,1,0,0x39
+button,1,,F5,1,0,0x3a
+button,1,,F6,1,0,0x3b
+button,1,,F7,1,0,0x3c
+button,1,,F8,1,0,0x3d
+button,1,,F9,1,0,0x3e
+button,1,,F10,1,0,0x3f
+button,1,,F11,1,0,0x40
+button,1,,F12,1,0,0x41
+button,1,,F13,1,0,0x42
+button,1,,F14,1,0,0x43
+button,1,,F15,1,0,0x44
+button,1,,F16,1,0,0x45
+# turn on/off all solos
+button,1,,global_solo,1,0,0x27
+button,1,modifiers,option,1,0,0x47
+button,1,modifiers,control,1,0,0x48
+button,1,modifiers,cmd_alt,1,0,0x49
+button,1,automation,on,1,1,0x4a
+button,1,automation,rec_ready,1,1,0x4b
+button,1,functions,undo,1,1,0x4c
+button,1,automation,snapshot,1,1,0x4d
+button,1,automation,touch,1,1,0x4e
+button,1,functions,redo,1,1,0x4f
+button,1,functions,marker,1,1,0x50
+button,1,functions,enter,1,1,0x51
+button,1,functions,cancel,1,0,0x52
+button,1,functions,mixer,1,0,0x53
+button,1,transport,frm_left,1,1,0x54
+button,1,transport,frm_right,1,1,0x55
+button,1,transport,loop,1,1,0x46
+button,1,transport,punch_in,1,1,0x2c
+button,1,transport,punch_out,1,1,0x2b
+button,1,transport,home,1,1,0x2a
+button,1,transport,end,1,1,0x29
+
+# transport buttons
+button,1,transport,"rewind",1,1,0x5b
+button,1,transport,"ffwd",1,1,0x5c
+button,1,transport,"stop",1,1,0x5d
+button,1,transport,"play",1,1,0x5e
+button,1,transport,"record",1,1,0x1f
+button,1,cursor,"cursor_up",1,0,0x60
+button,1,cursor,"cursor_down",1,0,0x61
+button,1,cursor,"cursor_left",1,0,0x62
+button,1,cursor,"cursor_right",1,0,0x63
+button,1,,"zoom",1,1,0x64
+button,1,,"scrub",1,1,0x65
+button,1,user,"user_a",1,0,0x66
+button,1,user,"user_b",1,0,0x67
+
+button,7,strip,"fader_touch",1,0,0x68
+button,1,master,"fader_touch",1,0,0x6f
+button,1,master,mute,1,0,0x17
+button,1,,clicking,1,1,0x33
+
+button,1,,"smpte",0,1,0x71
+button,1,,"beats",0,1,0x72
+button,1,,"solo",0,1,0x73
+button,1,,"relay_click",0,1,0x76
diff --git a/libs/surfaces/mackie/scripts/controls.rb b/libs/surfaces/mackie/scripts/controls.rb
new file mode 100644
index 0000000000..b56fd6010d
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/controls.rb
@@ -0,0 +1,208 @@
+#! /usr/bin/ruby
+# Copyright (C) 2006,2007 John Anderson
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+require 'faster_csv'
+require 'mackie.rb'
+
+class Control
+ attr_accessor :id, :led, :group, :name, :ordinal, :switch
+
+ def initialize( obj, group )
+ @id = obj.id
+ @name = obj.name
+ @ordinal = obj.ordinal
+ @switch = obj.switch
+ @group = group
+ end
+
+ def ordinal_name
+ end
+end
+
+class Fader < Control
+ def self.midi_zero_byte
+ 0xe0
+ end
+
+ def self.mask_for_id( bytes )
+ bytes[0] & 0b00001111
+ end
+end
+
+class Button < Control
+ def self.midi_zero_byte
+ 0x90
+ end
+
+ def self.mask_for_id( bytes )
+ bytes[1]
+ end
+end
+
+class Led < Control
+end
+
+class LedRing < Led
+end
+
+class Pot < Control
+ def self.midi_zero_byte
+ 0xb0
+ end
+
+ def self.mask_for_id( bytes )
+ bytes[1] & 0b00011111
+ end
+
+ def led=( rhs )
+ @led = LedRing.new( rhs, group )
+ end
+end
+
+class Group < Array
+ attr_accessor :name, :controls
+
+ def initialize( name )
+ @name = name
+ end
+
+ def add_control( control )
+ @controls ||= Array.new
+ @controls << control
+ end
+end
+
+class Strip < Group
+
+ attr_accessor :ordinal
+ def initialize( name, ordinal )
+ super( name )
+ @ordinal = ordinal
+ end
+
+ def name
+ @name == 'master' ? @name : "#{@name}_#{@ordinal}"
+ end
+
+ def is_master
+ name == 'master'
+ end
+
+end
+
+types = { 0xe0 => Fader, 0x90 => Button, 0xb0 => Pot }
+
+# number of controls, name, switch, led, id
+# anything that doesn't have the correct number
+# of columns will be ignored
+# actually, 'switch' means it generates data
+# whereas 'led' means it receives data
+
+class Row
+ attr_accessor :count, :name, :switch, :led, :start_id, :type, :group
+ attr_accessor :id, :ordinal_name, :ordinal_group, :ordinal
+
+ def initialize( hash )
+ @count = hash['count'].to_i
+ @name = hash['name']
+ @switch = hash['switch'].to_b
+ @led = hash['led'].to_b
+ @start_id = hash['id'].hex
+ @type = hash['type']
+ @group = hash['group']
+
+ @hash = hash
+ end
+
+ def each_ordinal( &block )
+ for i in 0...count
+ @ordinal = i + 1
+ @ordinal_name = count > 1 ? "#{name}_#{ordinal}" : name
+ @ordinal_group = count > 1 ? "#{group}_#{ordinal}" : group
+ @id = start_id + i
+
+ @hash['ordinal_name'] = @ordinal_name
+ @hash['ordinal_group'] = @ordinal_group
+
+ yield( self )
+ end
+ self
+ end
+
+ def to_hash
+ @hash
+ end
+end
+
+class Surface
+ attr_reader :groups, :controls_by_id, :types, :midis, :controls, :name
+
+ def initialize( name = 'none' )
+ @name = name
+ @types = Hash.new
+ @groups = Hash.new
+ @controls = Array.new
+ @controls_by_id = Hash.new
+ @midis = Hash.new
+ end
+
+ def add_or_create_group( name, ordinal = nil )
+ if name.nil?
+ @groups['none'] = Group.new('none')
+ else
+ group = name =~ /strip/ || name == 'master' ? Strip.new( name, ordinal ) : Group.new( name )
+ @groups[group.name] ||= group
+ end
+ end
+
+ def parse( control_data )
+ FasterCSV.parse( control_data, :headers => true ) do |csv_row|
+ next if csv_row.entries.size < 5 || csv_row[0] =~ /^\s*#/ || csv_row['id'].nil?
+ row = Row.new( csv_row )
+
+ row.each_ordinal do |row|
+ group = add_or_create_group( row.group, row.ordinal )
+ if row.switch
+ # for controls
+ control = eval "#{row.type.capitalize}.new( row, group )"
+
+ # for controls with leds
+ control.led = Led.new( row, group ) if row.led
+ else
+ # for LED-only entries
+ if row.led
+ control = Led.new( row, group )
+ control.led = control
+ end
+ end
+
+ # add the new control to the various lookups
+ @controls_by_id[row.id] = control
+ @controls << control
+ group << control
+
+ # add incoming midi bytes
+ if row.switch
+ types[control.class.midi_zero_byte] = control.class
+ midis[control.class.midi_zero_byte] ||= Hash.new
+ midis[control.class.midi_zero_byte][row.id] = control
+ end
+ end
+ end
+ self
+ end
+end
diff --git a/libs/surfaces/mackie/scripts/dump.rb b/libs/surfaces/mackie/scripts/dump.rb
new file mode 100755
index 0000000000..f1e341fb34
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/dump.rb
@@ -0,0 +1,11 @@
+#! /usr/bin/ruby
+
+while !File.exist? ARGV[0]
+ sleep 0.010
+end
+
+file = File.open ARGV[0], 'r'
+
+while bytes = file.sysread( 3 )
+ puts "%02x %02x %02x" % [ bytes[0], bytes[1], bytes[2] ]
+end
diff --git a/libs/surfaces/mackie/scripts/generate-button-handlers-cc.erb b/libs/surfaces/mackie/scripts/generate-button-handlers-cc.erb
new file mode 100644
index 0000000000..62bc65d0c3
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/generate-button-handlers-cc.erb
@@ -0,0 +1,59 @@
+<%#
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-%>
+<%-
+require 'controls.rb'
+
+sf = Surface.new
+sf.parse( File.open "mackie-controls.csv" )
+buttons = sf.controls.find_all{|x| x.class == Button && x.group.class != Strip}
+-%>
+/*
+ Generated by scripts/generate-button-handlers.erb
+*/
+#include "mackie_button_handler.h"
+#include "controls.h"
+
+#include <iostream>
+
+using namespace std;
+using namespace Mackie;
+
+LedState MackieButtonHandler::default_button_press( Button & button )
+{
+ cout << "press: " << button << endl;
+ return on;
+}
+LedState MackieButtonHandler::default_button_release( Button & button )
+{
+ cout << "release: " << button << endl;
+ return off;
+}
+
+<%-
+buttons.each do |button|
+%>
+LedState MackieButtonHandler::<%=button.name%>_press( Button & button )
+{
+ return default_button_press( button );
+}
+
+LedState MackieButtonHandler::<%=button.name%>_release( Button & button )
+{
+ return default_button_release( button );
+}
+<% end %>
diff --git a/libs/surfaces/mackie/scripts/generate-button-handlers-h.erb b/libs/surfaces/mackie/scripts/generate-button-handlers-h.erb
new file mode 100644
index 0000000000..605b6c29dc
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/generate-button-handlers-h.erb
@@ -0,0 +1,54 @@
+<%#
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-%>
+<%-
+require 'controls.rb'
+
+sf = Surface.new
+sf.parse( File.open "mackie-controls.csv" )
+buttons = sf.controls.find_all{|x| x.class == Button && x.group.class != Strip}
+-%>
+#ifndef mackie_button_handler_h
+#define mackie_button_handler_h
+/*
+ Generated by scripts/generate-button-handlers.erb
+*/
+
+#include "types.h"
+
+namespace Mackie
+{
+
+class MackieButtonHandler
+{
+public:
+ virtual ~MackieButtonHandler() {}
+
+ virtual LedState default_button_press( Button & button );
+ virtual LedState default_button_release( Button & button );
+
+ virtual void update_led( Button & button, LedState ls ) = 0;
+
+<%- buttons.each do |button| %>
+ virtual LedState <%=button.name%>_press( Button & );
+ virtual LedState <%=button.name%>_release( Button & );
+<% end %>
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/scripts/generate-surface.rb b/libs/surfaces/mackie/scripts/generate-surface.rb
new file mode 100755
index 0000000000..c6a028804a
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/generate-surface.rb
@@ -0,0 +1,26 @@
+#! /usr/bin/ruby
+
+require 'erb'
+
+require File.dirname(__FILE__) + '/controls.rb'
+
+cc_template = ''
+File.open( File.dirname(__FILE__) + "/surface-cc-template.erb", "r" ) { |f| cc_template = f.read }
+
+h_template = ''
+File.open( File.dirname(__FILE__) + "/surface-h-template.erb", "r" ) { |f| h_template = f.read }
+
+sf = Surface.new( ARGV[0] )
+control_data = ''
+File.open( File.dirname(__FILE__) + "/#{sf.name.downcase}-controls.csv", "r") { |f| control_data = f.read }
+sf.parse control_data
+
+@result = ""
+erb = ERB.new( cc_template , 0, "%<>-", "@result" )
+erb.result
+File.open( "#{sf.name.downcase}_surface.cc", "w" ) { |f| f.write @result }
+
+erb = ERB.new( h_template , 0, "%<>-", "@result" )
+erb.result
+File.open( "#{sf.name.downcase}_surface.h", "w" ) { |f| f.write @result }
+
diff --git a/libs/surfaces/mackie/scripts/host.rb b/libs/surfaces/mackie/scripts/host.rb
new file mode 100755
index 0000000000..8972cba137
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/host.rb
@@ -0,0 +1,133 @@
+#! /usr/bin/ruby
+# Copyright (C) 2006,2007 John Anderson
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+require 'controls.rb'
+require 'mackie.rb'
+
+while !File.exist? ARGV[0]
+ sleep 0.010
+end
+
+#mapping_csv = ARGV[1] || "mackie-controls.csv"
+mapping_csv = ARGV[1]
+puts "mapping_csv: #{mapping_csv}"
+puts ""
+
+file = File.open ARGV[0], 'r+'
+mck = Mackie.new( file )
+
+# send device query
+response = mck.sysex( "\x00" )
+puts "response: #{response.to_hex}"
+
+# decode host connection query
+status = response[0]
+if status != 1
+ puts "expected 01, got " + response.to_hex.inspect
+ exit(1)
+end
+serial = response[1..7]
+challenge = response[8..11]
+puts <<EOF
+serial: #{serial.to_hex.inspect}
+challenge: #{challenge.to_hex.inspect}
+EOF
+
+# send host connection reply
+response = mck.sysex( "\x02" + serial.pack('C*') + challenge.pack('C*') )
+
+# decode host connection confirmation
+status = response[0]
+if status != 3
+ puts "expected 03, got " + response.to_hex.inspect
+ exit(1)
+end
+
+serial = response[1..7]
+puts <<EOF
+serial: #{serial.to_hex.inspect}
+EOF
+
+# faders to minimum. bcf2000 doesn't respond
+#file.write( hdr + "\x61\xf7" )
+
+# all leds off. bcf2000 doesn't respond
+#file.write( hdr + "\x62\xf7" )
+
+# get version. comes back as ASCII bytes
+version = mck.sysex( "\x13\x00" )
+puts "version: #{version.map{|x| x.chr}}"
+
+# write a welcome message. bcf2000 responds with exact
+# string but doesn't display anything
+# 0 offset,
+#~ file.write hdr + "\x12\x3fLCDE\xf7"
+#~ file.flush
+#~ answer = read_sysex file
+#~ puts "answer: #{answer[hdr.length..-1].map{|x| x.chr}}"
+
+# write to BBT display
+#~ file.write hdr + "\x10LCDE\xf7"
+#~ file.flush
+#~ bbt = []
+#~ while ( nc = file.read( 1 ) )[0] != 0xf7
+ #~ bbt << nc[0]
+#~ end
+#~ puts "bbt: #{bbt[hdr.length..-1].map{|x| x.chr}}"
+
+# write 7-segment display
+#~ file.write hdr + "\x11LCDE\xf7"
+#~ file.flush
+
+# go offline. bcf2000 doesn't respond
+#~ file.write( hdr + "\x0f\x7f\xf7" )
+#~ file.flush
+
+sf = Surface.new
+control_data = ""
+File.open( mapping_csv ) { |f| control_data = f.read }
+sf.parse( control_data )
+
+# send all faders to 0, but bounce them first
+# otherwise the bcf gets confused
+sf.midis[0xe0].values.find_all{|x| x.class == Fader}.each do |x|
+ bytes = Array.new
+ bytes[0] = 0xe0 + x.ordinal - 1
+ bytes[1] = 0x1
+ bytes[2] = 0x1
+ file.write bytes.pack( 'C*' )
+ bytes[0] = 0xe0 + x.ordinal - 1
+ bytes[1] = 0x0
+ bytes[2] = 0x0
+ file.write bytes.pack( 'C*' )
+end
+file.flush
+
+# respond to control movements
+while bytes = mck.file.read( 3 )
+ print "received: %02.x %02.x %02.x" % [ bytes[0], bytes[1], bytes[2] ]
+ midi_type = bytes[0] & 0b11110000
+
+ control_id = sf.types[midi_type].mask_for_id( bytes )
+ control = sf.midis[midi_type][control_id]
+
+ print " Control Type: %-7s, " % sf.types[midi_type]
+ print "id: %4i" % control_id
+ print ", control: %15s" % ( control ? control.name : "nil control" )
+ print ", %15s" % ( control ? control.group.name : "nil group" )
+ print "\n"
+end
diff --git a/libs/surfaces/mackie/scripts/mackie-controls.csv b/libs/surfaces/mackie/scripts/mackie-controls.csv
new file mode 100644
index 0000000000..5dbb6297f8
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/mackie-controls.csv
@@ -0,0 +1,93 @@
+type,count,group,name,switch,led,id
+# faders
+fader,8,strip,gain,1,0,0x00
+fader,1,master,gain,1,0,0x08
+
+# pots
+pot,8,strip,vpot,1,1,0x10
+pot,1,,jog,1,0,0x3c
+pot,1,,external,1,0,0x2e
+
+# strip buttons
+button,8,strip,recenable,1,1,0x0
+button,8,strip,solo,1,1,0x08
+button,8,strip,mute,1,1,0x10
+button,8,strip,select,1,1,0x18
+button,8,strip,vselect,1,0,0x20
+
+# overlay buttons
+button,1,assignment,io,1,1,0x28
+button,1,assignment,sends,1,1,0x29
+button,1,assignment,pan,1,1,0x2a
+button,1,assignment,plugin,1,1,0x2b
+button,1,assignment,eq,1,1,0x2c
+button,1,assignment,dyn,1,1,0x2d
+button,1,bank,left,1,0,0x2e
+button,1,bank,right,1,0,0x2f
+button,1,bank,channel_left,1,0,0x30
+button,1,bank,channel_right,1,0,0x31
+button,1,,flip,1,1,0x32
+button,1,,edit,1,1,0x33
+
+button,1,display,name_value,1,0,0x34
+button,1,display,smpte_beats,1,0,0x35
+button,1,,F1,1,0,0x36
+button,1,,F2,1,0,0x37
+button,1,,F3,1,0,0x38
+button,1,,F4,1,0,0x39
+button,1,,F5,1,0,0x3a
+button,1,,F6,1,0,0x3b
+button,1,,F7,1,0,0x3c
+button,1,,F8,1,0,0x3d
+button,1,,F9,1,0,0x3e
+button,1,,F10,1,0,0x3f
+button,1,,F11,1,0,0x40
+button,1,,F12,1,0,0x41
+button,1,,F13,1,0,0x42
+button,1,,F14,1,0,0x43
+button,1,,F15,1,0,0x44
+button,1,,F16,1,0,0x45
+button,1,modifiers,shift,1,0,0x46
+button,1,modifiers,option,1,0,0x47
+button,1,modifiers,control,1,0,0x48
+button,1,modifiers,cmd_alt,1,0,0x49
+button,1,automation,on,1,1,0x4a
+button,1,automation,rec_ready,1,1,0x4b
+button,1,functions,undo,1,1,0x4c
+button,1,automation,snapshot,1,1,0x4d
+button,1,automation,touch,1,1,0x4e
+button,1,functions,redo,1,1,0x4f
+button,1,functions,marker,1,1,0x50
+button,1,functions,enter,1,1,0x51
+button,1,functions,cancel,1,0,0x52
+button,1,functions,mixer,1,0,0x53
+button,1,transport,frm_left,1,1,0x54
+button,1,transport,frm_right,1,1,0x55
+button,1,transport,loop,1,1,0x56
+button,1,transport,punch_in,1,1,0x57
+button,1,transport,punch_out,1,1,0x58
+button,1,transport,home,1,1,0x59
+button,1,transport,end,1,1,0x5a
+
+# transport buttons
+button,1,transport,"rewind",1,1,0x5b
+button,1,transport,"ffwd",1,1,0x5c
+button,1,transport,"stop",1,1,0x5d
+button,1,transport,"play",1,1,0x5e
+button,1,transport,"record",1,1,0x5f
+button,1,cursor,"cursor_up",1,0,0x60
+button,1,cursor,"cursor_down",1,0,0x61
+button,1,cursor,"cursor_left",1,0,0x62
+button,1,cursor,"cursor_right",1,0,0x63
+button,1,,"zoom",1,1,0x64
+button,1,,"scrub",1,1,0x65
+button,1,user,"user_a",1,0,0x66
+button,1,user,"user_b",1,0,0x67
+
+button,8,strip,"fader_touch",1,0,0x68
+button,1,master,"fader_touch",1,0,0x70
+
+button,1,,"smpte",0,1,0x71
+button,1,,"beats",0,1,0x72
+button,1,,"solo",0,1,0x73
+button,1,,"relay_click",0,1,0x76
diff --git a/libs/surfaces/mackie/scripts/mackie.rb b/libs/surfaces/mackie/scripts/mackie.rb
new file mode 100644
index 0000000000..4c4080ad10
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/mackie.rb
@@ -0,0 +1,119 @@
+class String
+ def to_bytes
+ arr = []
+ each_byte{|x| arr << x}
+ arr
+ end
+end
+
+class Array
+ def to_hex
+ map{|x| "%2.0x" % x}
+ end
+
+ alias as_hex to_hex
+end
+
+class String
+ def to_b
+ to_i != 0 || %w{true t yes y}.include?( self.downcase )
+ end
+end
+
+class Fixnum
+ def to_hex
+ "%02x" % self
+ end
+end
+
+class Mackie
+ attr_accessor :file
+
+ def initialize( file )
+ @file = file
+ end
+
+ # send and receive a sysex message
+ # after wrapping in the header and the eox byte
+ def sysex( msg )
+ puts "Mackie write: #{msg.unpack('C*').to_hex.inspect}"
+ write_sysex( msg )
+ response = read_sysex
+ puts "Mackie response: #{response.to_hex.inspect}"
+ response[5..-1]
+ end
+
+ # returns an array of bytes
+ def read_sysex
+ buf = []
+ while ( nc = @file.read( 1 ) )[0] != 0xf7
+ buf << nc[0]
+ end
+ buf
+ end
+
+ # send and flush a sysex message
+ # after wrapping in the header and the eox byte
+ def write_sysex( msg )
+ @file.write( hdrlc + msg + "\xf7" )
+ @file.flush
+ end
+
+ def write( msg )
+ @file.write msg
+ @file.flush
+ end
+
+ def translate_seven_segment( char )
+ case char
+ when 0x40..0x60
+ char - 0x40
+ when 0x21..0x3f
+ char
+ else
+ 0x00
+ end
+ end
+
+ # display the msg (which can be only 2 characters)
+ # append the number of stops. Options are '..', '. ', '. ', ' '
+ def two_char( msg, stops = ' ' )
+ two = Array.new
+ two << translate_seven_segment( msg.upcase[0] )
+ two << translate_seven_segment( msg.upcase[1] )
+
+ two[0] += 0x40 if stops[0] == '.'[0]
+ two[1] += 0x40 if stops[1] == '.'[0]
+
+ midi_msg = [0xb0, 0x4a, two[1], 0x4b, two[0] ]
+ write midi_msg.pack( 'C*' )
+ end
+
+ # send and receive the device initialisation
+ def init
+ response = sysex( "\x00" )
+
+ # decode host connection query
+ status = response[0]
+ raise( "expected 01, got " + response.inspect ) if status != 1
+
+ serial = response[1..7]
+ challenge = response[8..11]
+
+ # send host connection reply
+ reply = "\x02" + serial.pack('C*') + challenge.pack('C*')
+ response = sysex reply
+
+ # decode host connection confirmation
+ status = response[0]
+ raise ( "expected 03, got " + response.inspect ) if status != 3
+ end
+
+ def hdrlc
+ "\xf0\x00\x00\x66\x10"
+ end
+
+ def hdrlcxt
+ "\xf0\x00\x00\x66\x11"
+ end
+end
diff --git a/libs/surfaces/mackie/scripts/parse.rb b/libs/surfaces/mackie/scripts/parse.rb
new file mode 100644
index 0000000000..3a225a5756
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/parse.rb
@@ -0,0 +1,61 @@
+#! /usr/bin/ruby
+# Copyright (C) 2006,2007 John Anderson
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+require "rexml/document"
+file = File.new( ARGV[0] )
+doc = REXML::Document.new file
+
+# fetch the node containing the controls
+controls = XPath.first( doc, 'Session/ControlProtocols/Protocol[@name="Generic MIDI"]/controls' )
+
+channel = 1
+
+# A Control is a button or slider. It has an internal ID
+# an incoming MIDI message, and an outgoing midi message
+class Control
+
+end
+
+# Strips have solo,rec,mute,pan,fader
+# Strips have midi input
+# Strips have midi output
+# Strips have an XML representation, or something like that
+class Strip
+ def initialize( node )
+ @solo = node.elements['solo']
+ @mute = node.elements['mute']
+ @rec = node.elements['recenable']
+ @fader = node.elements['IO/gaincontrol']
+ @panner = node.elements['IO/Panner/StreamPanner/panner']
+ end
+end
+
+# This knows how to extract a set of controls from a Route
+
+doc.elements.each( 'Session/Routes/Route' ) do |node|
+ strip = Strip.new( node )
+
+ controls.add_element( 'mute',
+ 'id' => mute.attribute('id').value,
+ 'event' => "0xb0",
+ 'channel' => channel.to_s,
+ 'additional' => "0x41"
+ )
+
+end
+
+pp controls.elements
diff --git a/libs/surfaces/mackie/scripts/signals.rb b/libs/surfaces/mackie/scripts/signals.rb
new file mode 100644
index 0000000000..8182e562a3
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/signals.rb
@@ -0,0 +1,137 @@
+#~ /usr/bin/ruby
+# Copyright (C) 2006,2007 John Anderson
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+require 'erb'
+
+signals = %w{
+solo_changed
+mute_changed
+record_enable_changed
+gain_changed
+name_changed
+panner_changed
+}
+
+@signal_calls = { 'panner_changed' => 'panner()[0]->Changed' }
+
+def connection_call( x )
+ if @signal_calls.include? x
+ @signal_calls[x]
+ else
+ x
+ end
+end
+
+signals.each do |x|
+ puts <<EOF
+void MackieControlProtocol::notify_#{x}( void *, ARDOUR::Route * route )
+{
+ try
+ {
+ strip_from_route( route ).#{x.gsub( /_changed/, '' )}();
+ }
+ catch( exception & e )
+ {
+ cout << e.what() << endl;
+ }
+}
+
+EOF
+end
+
+class_def = <<EOF
+#ifndef route_signal_h
+#define route_signal_h
+
+#include <sigc++/sigc++.h>
+
+class MackieControlProtocol;
+
+namespace ARDOUR {
+ class Route;
+}
+
+namespace Mackie
+{
+
+class Strip;
+
+/**
+ This class is intended to easily create and destroy the set of
+ connections from a route to a control surface strip. Instanting
+ it will connect the signals, and destructing it will disconnect
+ the signals.
+*/
+class RouteSignal
+{
+public:
+ RouteSignal( ARDOUR::Route & route, MackieControlProtocol & mcp, Strip & strip )
+ : _route( route ), _mcp( mcp ), _strip( strip )
+ {
+ connect();
+ }
+
+ ~RouteSignal()
+ {
+ disconnect();
+ }
+
+private:
+ ARDOUR::Route & _route;
+ MackieControlProtocol & _mcp;
+ Strip & _strip;
+
+<% signals.each do |x| -%>
+ sigc::connection _<%= x %>_connection;
+<% end -%>
+};
+
+}
+
+#endif
+EOF
+
+erb = ERB.new( class_def, 0, ">-" )
+erb.run
+
+impl_def = <<EOF
+#include "route_signal.h"
+
+#include <ardour/route.h>
+#include <ardour/panner.h>
+
+#include "mackie_control_protocol.h"
+
+using namespace Mackie;
+
+void RouteSignal::connect()
+{
+<% signals.each do |x| -%>
+ _<%=x%>_connection = _route.<%=connection_call(x)%>.connect( sigc::bind ( mem_fun ( _mcp, &MackieControlProtocol::notify_<%=x%> ), &_route ) );
+<% end -%>
+}
+
+void RouteSignal::disconnect()
+{
+<% signals.each do |x| -%>
+ _<%= x %>_connection.disconnect();
+<% end -%>
+}
+EOF
+
+erb = ERB.new( impl_def, 0, ">-" )
+erb.run
diff --git a/libs/surfaces/mackie/scripts/simple_host.rb b/libs/surfaces/mackie/scripts/simple_host.rb
new file mode 100644
index 0000000000..a5c07f2abb
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/simple_host.rb
@@ -0,0 +1,137 @@
+#! /usr/bin/ruby
+# Copyright (C) 2006,2007 John Anderson
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+require 'mackie'
+
+buttons = {}
+pots = {}
+
+while !File.exist? ARGV[0]
+ sleep 0.010
+end
+
+file = File.open( ARGV[0], 'r+' )
+mck = Mackie.new( file )
+
+# faders to minimum. bcf2000 doesn't respond
+mck.write_sysex "\x61"
+
+# all leds off. bcf2000 doesn't respond
+mck.write_sysex "\x62"
+
+# get version. comes back as ASCII bytes
+version = mck.sysex "\x13\x00"
+puts "version: #{version.map{|x| x.chr}}"
+
+# respond to control movements
+while bytes = file.read( 3 )
+ puts "received: %02.x %02.x %02.x" % [ bytes[0], bytes[1], bytes[2] ]
+ output = nil
+ case bytes[0] & 0b11110000
+ when 0xe0
+ # fader moved, so respond if move is OK
+ output = bytes
+ when 0x90
+ # button pressed
+ case bytes[1]
+ when 0x68..0x6f
+ # do nothing - touch detection
+ puts "touch detect: %02.x" % bytes[2]
+ else
+ # treat all buttons as toggles
+ button_id = bytes[1]
+
+ # only toggle on release. Not working. All buttons send press
+ # and then release signals
+ if bytes[2] == 0
+ if buttons.include?( button_id )
+ # toggle button state
+ puts "button id #{buttons[button_id]} to #{!buttons[button_id]}"
+ buttons[button_id] = !buttons[button_id]
+ else
+ # create a new button as on
+ puts "adding button id #{button_id}"
+ buttons[button_id] = true
+ end
+ bytes[2] = buttons[button_id] ? 0x7f : 0
+ output = bytes
+ end
+ end
+ when 0xb0
+ # pots, jog wheel, external
+ case bytes[1]
+ when 0x10..0x17
+ #pot turned
+ pot_id = bytes[1] & 0b00000111
+ direction = bytes[2] & 0b01000000
+ delta = bytes[2] & 0b00111111
+ sign = direction == 0 ? 1 : -1
+
+ if pots.include? pot_id
+ current_led_pos = pots[pot_id]
+ else
+ current_led_pos = pots[pot_id] = 6
+ end
+ new_led_pos = current_led_pos + sign
+ new_led_pos = case
+ when new_led_pos <= 0
+ 0
+ when new_led_pos >= 11
+ 11
+ else
+ new_led_pos
+ end
+
+ pots[pot_id] = new_led_pos
+
+ puts "pot #{pot_id} turned #{sign} #{direction == 0 ? 'clockwise' : 'widdershins'}: %02.x to #{new_led_pos}" % delta
+
+ output = bytes
+ output[1] += 0x20
+ output[2] = 0b01000000
+ #~ modes:
+ #~ 0 - single dot
+ #~ 1 - boost/cut
+ #~ 2 - wrap
+ #~ 3 - spread
+ mode = pot_id < 4 ? pot_id : 0
+ output[2] |= ( mode << 4 )
+ output[2] += ( new_led_pos ) & 0b00001111
+ when 0x2e
+ # external controller
+ when 0x3c
+ # jog wheel
+ end
+ else
+ puts "don't know what this means"
+ end
+
+ # output bytes
+ if output
+ #sleep 0.1
+ puts "sending: %02.x %02.x %02.x" % [ output[0], output[1], output[2] ]
+ begin
+ res = file.write output
+ puts "res: #{res}"
+ file.flush
+ rescue => e
+ puts "oops #{e}"
+ file.close
+ file = File.open ARGV[0], 'r+'
+ end
+ end
+end
diff --git a/libs/surfaces/mackie/scripts/surface-cc-template.erb b/libs/surfaces/mackie/scripts/surface-cc-template.erb
new file mode 100644
index 0000000000..3b29be3249
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/surface-cc-template.erb
@@ -0,0 +1,95 @@
+<%#
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-%>
+/*
+ Generated by scripts/generate-surface.rb
+*/
+
+#include "<%= sf.name.downcase %>_surface.h"
+
+#include "controls.h"
+#include "mackie_button_handler.h"
+
+using namespace Mackie;
+
+void Mackie::<%= sf.name %>Surface::init_controls()
+{
+ // intialise groups and strips
+ Group * group = 0;
+
+ // make sure there are enough strips
+ strips.resize( <%= sf.groups.values.find_all{|x| x.name =~ /strip/}.size %> );
+
+% sf.groups.values.each do |group|
+ <%- if group.class == Strip -%>
+ <%- if group.name == 'master' -%>
+ group = new MasterStrip ( "<%=group.name%>", 0 );
+ <%- else -%>
+ group = new <%= group.class.name %> ( "<%=group.name%>", <%=group.ordinal - 1%> );
+ <%- end -%>
+ <%- else -%>
+ group = new <%= group.class.name %> ( "<%=group.name%>" );
+ <%- end -%>
+ groups["<%=group.name%>"] = group;
+ <%- if group.class == Strip -%>
+ strips[<%=group.ordinal - 1%>] = dynamic_cast<Strip*>( group );
+ <%- end -%>
+
+% end
+
+ // initialise controls
+ Control * control = 0;
+
+% sf.controls.each do |control|
+ group = groups["<%=control.group.name%>"];
+ control = new <%= control.class.name %> ( <%= control.id %>, <%= control.ordinal %>, "<%=control.name%>", *group );
+ <%=control.class.name.downcase%>s[0x<%=control.id.to_hex %>] = control;
+ controls.push_back( control );
+ <%- if control.group.class != Strip -%>
+ controls_by_name["<%= control.name %>"] = control;
+ <%- end -%>
+ group->add( *control );
+
+% end
+}
+
+void Mackie::<%= sf.name %>Surface::handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button )
+{
+ if ( bs != press && bs != release )
+ {
+ mbh.update_led( button, none );
+ return;
+ }
+
+ LedState ls;
+ switch ( button.id() )
+ {
+<%-
+buttons = sf.controls.find_all{|x| x.class == Button && x.group.class != Strip}
+buttons.each do |button|
+%>
+ case 0x<%= button.id.to_hex %>: // <%= button.name %>
+ switch ( bs ) {
+ case press: ls = mbh.<%= button.name %>_press( button ); break;
+ case release: ls = mbh.<%= button.name %>_release( button ); break;
+ case neither: break;
+ }
+ break;
+<% end %>
+ }
+ mbh.update_led( button, ls );
+}
diff --git a/libs/surfaces/mackie/scripts/surface-h-template.erb b/libs/surfaces/mackie/scripts/surface-h-template.erb
new file mode 100644
index 0000000000..2f54f66c47
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/surface-h-template.erb
@@ -0,0 +1,27 @@
+#ifndef mackie_surface_<%= sf.name.downcase %>_h
+#define mackie_surface_<%= sf.name.downcase %>_h
+/*
+ Generated by scripts/generate-surface.rb
+*/
+
+#include "surface.h"
+
+namespace Mackie
+{
+
+class MackieButtonHandler;
+
+class <%= sf.name %>Surface : public Surface
+{
+public:
+ <%= sf.name %>Surface( uint32_t max_strips ) : Surface( max_strips )
+ {
+ }
+
+ virtual void handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button );
+ virtual void init_controls();
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/scripts/test_controls.rb b/libs/surfaces/mackie/scripts/test_controls.rb
new file mode 100755
index 0000000000..782b0d427c
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/test_controls.rb
@@ -0,0 +1,9 @@
+#! /usr/bin/ruby
+
+require 'controls.rb'
+require 'pp'
+
+sf = Surface.new
+sf.parse
+sf.types.each{|k,v| puts "%02.x #{v}" % k}
+
diff --git a/libs/surfaces/mackie/scripts/transform.rb b/libs/surfaces/mackie/scripts/transform.rb
new file mode 100644
index 0000000000..e0221e188b
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/transform.rb
@@ -0,0 +1,26 @@
+class ElementHandler
+
+ def apply( anElement )
+ anElement.each {|e| handle(e)} if anElement
+ end
+
+ def handle( aNode )
+ if aNode.kind_of? REXML::Text
+ handleTextNode(aNode)
+ elsif aNode.kind_of? REXML::Element
+ handle_element aNode
+ else
+ return #ignore comments and processing instructions
+ end
+ end
+
+ def handle_element( anElement )
+ handler_method = "handle_" + anElement.name.tr("-","_")
+ if self.respond_to? handler_method
+ self.send(handler_method, anElement)
+ else
+ default_handler(anElement)
+ end
+ end
+
+end
diff --git a/libs/surfaces/mackie/scripts/write.rb b/libs/surfaces/mackie/scripts/write.rb
new file mode 100644
index 0000000000..20b72477e8
--- /dev/null
+++ b/libs/surfaces/mackie/scripts/write.rb
@@ -0,0 +1,10 @@
+#! /usr/bin/ruby
+
+require 'mackie.rb'
+
+@file = File.open '/dev/snd/midiC2D0', 'r+'
+
+@led_8_on = [ 0x90, 0x18, 0x7f ]
+@hci = [ 0, 0xf7 ]
+@version_req = [ 0x13, 0, 0xf7 ]
+
diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc
new file mode 100644
index 0000000000..01be2c60c2
--- /dev/null
+++ b/libs/surfaces/mackie/surface.cc
@@ -0,0 +1,142 @@
+#include "surface.h"
+
+#include <sstream>
+#include <iomanip>
+#include <iostream>
+
+using namespace std;
+using namespace Mackie;
+
+Surface::Surface( uint32_t max_strips, uint32_t unit_strips )
+: _max_strips( max_strips ), _unit_strips( unit_strips )
+{
+}
+
+void Surface::init()
+{
+ init_controls();
+ init_strips( _max_strips, _unit_strips );
+}
+
+Surface::~Surface()
+{
+ // delete groups
+ for( Groups::iterator it = groups.begin(); it != groups.end(); ++it )
+ {
+ delete it->second;
+ }
+
+ // delete controls
+ for( Controls::iterator it = controls.begin(); it != controls.end(); ++it )
+ {
+ delete *it;
+ }
+}
+
+// Mackie-specific, because of multiple devices on separate ports
+// add the strips from 9..max_strips
+// unit_strips is the number of strips for additional units.
+void Surface::init_strips( uint32_t max_strips, uint32_t unit_strips )
+{
+ if ( strips.size() < max_strips )
+ {
+ strips.resize( max_strips );
+ for ( uint32_t i = strips.size(); i < max_strips; ++i )
+ {
+ // because I can't find itoa
+ ostringstream os;
+ os << "strip_" << i + 1;
+ string name = os.str();
+
+ // shallow copy existing strip
+ // which works because the controls
+ // have the same ids across units
+ Strip * strip = new Strip( *strips[i % unit_strips] );
+
+ // update the relevant values
+ strip->index( i );
+ strip->name( name );
+
+ // add to data structures
+ groups[name] = strip;
+ strips[i] = strip;
+ }
+ }
+}
+
+ostream & Mackie::operator << ( ostream & os, const Mackie::Control & control )
+{
+ os << typeid( control ).name();
+ os << " { ";
+ os << "name: " << control.name();
+ os << ", ";
+ os << "id: " << "0x" << setw(2) << setfill('0') << hex << control.id() << setfill(' ');
+ os << ", ";
+ os << "ordinal: " << dec << control.ordinal();
+ os << ", ";
+ os << "group: " << control.group().name();
+ os << " }";
+
+ return os;
+}
+
+/**
+ TODO could optimise this to use enum, but it's only
+ called during the protocol class instantiation.
+
+ generated using
+
+ irb -r controls.rb
+ sf=Surface.new
+ sf.parse
+ controls = sf.groups.find{|x| x[0] =~ /strip/}.each{|x| puts x[1]}
+ controls[1].each {|x| puts "\telse if ( control.name() == \"#{x.name}\" )\n\t{\n\t\t_#{x.name} = reinterpret_cast<#{x.class.name}*>(&control);\n\t}\n"}
+*/
+void Strip::add( Control & control )
+{
+ Group::add( control );
+ if ( control.name() == "gain" )
+ {
+ _gain = reinterpret_cast<Fader*>(&control);
+ }
+ else if ( control.name() == "vpot" )
+ {
+ _vpot = reinterpret_cast<Pot*>(&control);
+ }
+ else if ( control.name() == "recenable" )
+ {
+ _recenable = reinterpret_cast<Button*>(&control);
+ }
+ else if ( control.name() == "solo" )
+ {
+ _solo = reinterpret_cast<Button*>(&control);
+ }
+ else if ( control.name() == "mute" )
+ {
+ _mute = reinterpret_cast<Button*>(&control);
+ }
+ else if ( control.name() == "select" )
+ {
+ _select = reinterpret_cast<Button*>(&control);
+ }
+ else if ( control.name() == "vselect" )
+ {
+ _vselect = reinterpret_cast<Button*>(&control);
+ }
+ else if ( control.name() == "fader_touch" )
+ {
+ _fader_touch = reinterpret_cast<Button*>(&control);
+ }
+ else if ( control.type() == Control::type_led || control.type() == Control::type_led_ring )
+ {
+ // do nothing
+ cout << "Strip::add not adding " << control << endl;
+ }
+ else
+ {
+ ostringstream os;
+ os << "Strip::add: unknown control type " << control;
+ throw MackieControlException( os.str() );
+ }
+}
+
diff --git a/libs/surfaces/mackie/surface.h b/libs/surfaces/mackie/surface.h
new file mode 100644
index 0000000000..0ccde75537
--- /dev/null
+++ b/libs/surfaces/mackie/surface.h
@@ -0,0 +1,94 @@
+#ifndef mackie_surface_h
+#define mackie_surface_h
+
+#include "controls.h"
+#include "types.h"
+#include <stdint.h>
+
+namespace Mackie
+{
+
+class MackieButtonHandler;
+
+/**
+ This represents an entire control surface, made up of Groups,
+ Strips and Controls. There are several collections for
+ ease of addressing in different ways, but only one collection
+ has definitive ownership.
+
+ It handles mapping button ids to press_ and release_ calls.
+
+ There are various emulations of the Mackie around, so specific
+ emulations will inherit from this to change button mapping, or
+ have 7 fader channels instead of 8, or whatever.
+
+ Currently there are BcfSurface and MackieSurface.
+
+ TODO maybe make Group inherit from Control, for ease of ownership.
+*/
+class Surface
+{
+public:
+ /**
+ A Surface can be made up of multiple units. eg one Mackie MCU plus
+ one or more Mackie MCU extenders.
+
+ \param max_strips is the number of strips for the entire surface.
+ \param unit_strips is the number of strips per unit.
+ */
+ Surface( uint32_t max_strips, uint32_t unit_strips = 8 );
+ virtual ~Surface();
+
+ /// Calls the virtual initialisation methods. This *must* be called after
+ /// construction, because c++ is too dumb to call virtual methods from
+ /// inside a constructor
+ void init();
+
+ typedef std::vector<Control*> Controls;
+
+ /// This collection has ownership of all the controls
+ Controls controls;
+
+ /**
+ These are alternative addressing schemes
+ They use maps because the indices aren't always
+ 0-based.
+ */
+ std::map<int,Control*> faders;
+ std::map<int,Control*> pots;
+ std::map<int,Control*> buttons;
+ std::map<int,Control*> leds;
+
+ /// no strip controls in here because they usually
+ /// have the same names.
+ std::map<std::string,Control*> controls_by_name;
+
+ /// The collection of all numbered strips. No master
+ /// strip in here.
+ typedef std::vector<Strip*> Strips;
+ Strips strips;
+
+ /// This collection owns the groups
+ typedef std::map<std::string,Group*> Groups;
+ Groups groups;
+
+ uint32_t max_strips() const
+ {
+ return _max_strips;
+ }
+
+ /// map button ids to calls to press_ and release_ in mbh
+ virtual void handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button ) = 0;
+
+protected:
+ virtual void init_controls() = 0;
+ virtual void init_strips( uint32_t max_strips, uint32_t unit_strips );
+
+private:
+ uint32_t _max_strips;
+ uint32_t _unit_strips;
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/surface_port.cc b/libs/surfaces/mackie/surface_port.cc
new file mode 100644
index 0000000000..8aa1be7fe9
--- /dev/null
+++ b/libs/surfaces/mackie/surface_port.cc
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include "surface_port.h"
+
+#include "mackie_control_exception.h"
+#include "controls.h"
+
+#include <midi++/types.h>
+#include <midi++/port.h>
+#include <sigc++/sigc++.h>
+#include <boost/shared_array.hpp>
+
+#include "i18n.h"
+
+#include <sstream>
+
+#include <cstring>
+#include <cerrno>
+
+using namespace std;
+using namespace Mackie;
+
+SurfacePort::SurfacePort( MIDI::Port & port, int number )
+: _port( port ), _number( number ), _active( false )
+{
+}
+
+SurfacePort::~SurfacePort()
+{
+ //cout << "~SurfacePort::SurfacePort()" << endl;
+ // make sure another thread isn't reading or writing as we close the port
+ Glib::RecMutex::Lock lock( _rwlock );
+ _active = false;
+ //cout << "~SurfacePort::SurfacePort() finished" << endl;
+}
+
+// wrapper for one day when strerror_r is working properly
+string fetch_errmsg( int error_number )
+{
+ char * msg = strerror( error_number );
+ return msg;
+}
+
+MidiByteArray SurfacePort::read()
+{
+ const int max_buf_size = 512;
+ MIDI::byte buf[max_buf_size];
+ MidiByteArray retval;
+
+ // check active. Mainly so that the destructor
+ // doesn't destroy the mutex while it's still locked
+ if ( !active() ) return retval;
+
+ // return nothing read if the lock isn't acquired
+ Glib::RecMutex::Lock lock( _rwlock, Glib::TRY_LOCK );
+
+ if ( !lock.locked() )
+ {
+ //cout << "SurfacePort::read not locked" << endl;
+ return retval;
+ }
+
+ // check active again - destructor sequence
+ if ( !active() ) return retval;
+
+ // read port and copy to return value
+ int nread = port().read( buf, sizeof (buf), 0 );
+
+ if (nread >= 0) {
+ retval.copy( nread, buf );
+ if ((size_t) nread == sizeof (buf))
+ {
+ retval << read();
+ }
+ }
+ else
+ {
+ if ( errno != EAGAIN )
+ {
+ ostringstream os;
+ os << "Surface: error reading from port: " << port().name();
+ os << ": " << errno << fetch_errmsg( errno );
+
+ cout << os.str() << endl;
+ inactive_event();
+ throw MackieControlException( os.str() );
+ }
+ }
+ return retval;
+}
+
+void SurfacePort::write( const MidiByteArray & mba )
+{
+ //if ( mba[0] == 0xf0 ) cout << "SurfacePort::write: " << mba << endl;
+ //cout << "SurfacePort::write: " << mba << endl;
+
+ // check active before and after lock - to make sure
+ // that the destructor doesn't destroy the mutex while
+ // it's still in use
+ if ( !active() ) return;
+ Glib::RecMutex::Lock lock( _rwlock );
+ if ( !active() ) return;
+
+ int count = port().write( mba.bytes().get(), mba.size(), 0 );
+ if ( count != (int)mba.size() )
+ {
+ if ( errno != EAGAIN )
+ {
+ ostringstream os;
+ os << "Surface: couldn't write to port " << port().name();
+ os << ": " << errno << fetch_errmsg( errno );
+
+ cout << os.str();
+ inactive_event();
+ throw MackieControlException( os.str() );
+ }
+ }
+ //if ( mba[0] == 0xf0 ) cout << "SurfacePort::write " << count << endl;
+}
+
+void SurfacePort::write_sysex( const MidiByteArray & mba )
+{
+ MidiByteArray buf;
+ buf << sysex_hdr() << mba << MIDI::eox;
+ write( buf );
+}
+
+void SurfacePort::write_sysex( MIDI::byte msg )
+{
+ MidiByteArray buf;
+ buf << sysex_hdr() << msg << MIDI::eox;
+ write( buf );
+}
+
+// This should be moved to midi++ at some point
+ostream & operator << ( ostream & os, const MIDI::Port & port )
+{
+ os << "device: " << port.device();
+ os << "; ";
+ os << "name: " << port.name();
+ os << "; ";
+ os << "type: " << port.type();
+ os << "; ";
+ os << "mode: " << port.mode();
+ os << "; ";
+ os << "ok: " << port.ok();
+ os << "; ";
+ os << "number: " << port.number();
+ os << "; ";
+ return os;
+}
+
+ostream & Mackie::operator << ( ostream & os, const SurfacePort & port )
+{
+ os << "{ ";
+ os << "device: " << port.port().device();
+ os << "; ";
+ os << "name: " << port.port().name();
+ os << "; ";
+ os << "number: " << port.number();
+ os << " }";
+ return os;
+}
diff --git a/libs/surfaces/mackie/surface_port.h b/libs/surfaces/mackie/surface_port.h
new file mode 100644
index 0000000000..87419f1bcd
--- /dev/null
+++ b/libs/surfaces/mackie/surface_port.h
@@ -0,0 +1,100 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef surface_port_h
+#define surface_port_h
+
+#include <sigc++/signal.h>
+#include <glibmm/thread.h>
+
+#include "midi_byte_array.h"
+#include "types.h"
+
+namespace MIDI {
+ class Port;
+}
+
+namespace Mackie
+{
+
+/**
+ Make a relationship between a midi port and a Mackie device.
+*/
+class SurfacePort : public sigc::trackable
+{
+public:
+ SurfacePort( MIDI::Port & port, int number );
+ virtual ~SurfacePort();
+
+ // when this is successful, active() should return true
+ virtual void open() = 0;
+
+ // subclasses should call this before doing their own close
+ virtual void close() = 0;
+
+ /// read bytes from the port. They'll either end up in the
+ /// parser, or if that's not active they'll be returned
+ MidiByteArray read();
+
+ /// an easier way to output bytes via midi
+ void write( const MidiByteArray & );
+
+ /// write a sysex message
+ void write_sysex( const MidiByteArray & mba );
+ void write_sysex( MIDI::byte msg );
+
+ // return the correct sysex header for this port
+ virtual const MidiByteArray & sysex_hdr() const = 0;
+
+ MIDI::Port & port() { return _port; }
+ const MIDI::Port & port() const { return _port; }
+
+ // all control notofications are sent from here
+ sigc::signal<void, SurfacePort &, Control &, const ControlState &> control_event;
+
+ // emitted just before the port goes into initialisation
+ // where it tries to establish that its device is connected
+ sigc::signal<void> init_event;
+
+ // emitted when the port completes initialisation successfully
+ sigc::signal<void> active_event;
+
+ // emitted when the port goes inactive (ie a read or write failed)
+ sigc::signal<void> inactive_event;
+
+ // the port number - master is 0, extenders are 1,2,3,4
+ virtual int number() const { return _number; }
+
+ // number of strips handled by this port. Usually 8.
+ virtual int strips() const = 0;
+
+ virtual bool active() const { return _active; }
+ virtual void active( bool yn ) { _active = yn; }
+
+private:
+ MIDI::Port & _port;
+ int _number;
+ bool _active;
+
+ Glib::RecMutex _rwlock;
+};
+
+std::ostream & operator << ( std::ostream & , const SurfacePort & port );
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/test.cc b/libs/surfaces/mackie/test.cc
new file mode 100644
index 0000000000..351058523f
--- /dev/null
+++ b/libs/surfaces/mackie/test.cc
@@ -0,0 +1,25 @@
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include <cstdarg>
+#include <iomanip>
+
+#include "midi_byte_array.h"
+
+using namespace std;
+
+namespace MIDI {
+ typedef unsigned char byte;
+ byte sysex = 0xf0;
+ byte eox = 0xf7;
+}
+
+int main()
+{
+ MidiByteArray bytes( 4, 0xf0, 0x01, 0x03, 0x7f );
+ cout << bytes << endl;
+ return 0;
+}
+
diff --git a/libs/surfaces/mackie/types.cc b/libs/surfaces/mackie/types.cc
new file mode 100644
index 0000000000..d2818d7340
--- /dev/null
+++ b/libs/surfaces/mackie/types.cc
@@ -0,0 +1,9 @@
+#include "types.h"
+
+namespace Mackie
+{
+ LedState on( LedState::on );
+ LedState off( LedState::off );
+ LedState flashing( LedState::flashing );
+ LedState none( LedState::none );
+}
diff --git a/libs/surfaces/mackie/types.h b/libs/surfaces/mackie/types.h
new file mode 100644
index 0000000000..2b47e15640
--- /dev/null
+++ b/libs/surfaces/mackie/types.h
@@ -0,0 +1,93 @@
+/*
+ Copyright (C) 2006,2007 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef mackie_types_h
+#define mackie_types_h
+
+namespace Mackie
+{
+
+/**
+ This started off as an enum, but it got really annoying
+ typing ? on : off
+*/
+class LedState
+{
+public:
+ enum state_t { none, off, flashing, on };
+ LedState() : _state( none ) {}
+ LedState( bool yn ): _state( yn ? on : off ) {}
+ LedState( state_t state ): _state( state ) {}
+
+ bool operator == ( const LedState & other ) const
+ {
+ return state() == other.state();
+ }
+
+ bool operator != ( const LedState & other ) const
+ {
+ return state() != other.state();
+ }
+
+ state_t state() const { return _state; }
+
+private:
+ state_t _state;
+};
+
+extern LedState on;
+extern LedState off;
+extern LedState flashing;
+extern LedState none;
+
+enum ButtonState { neither = -1, release = 0, press = 1 };
+
+/**
+ Contains the state for a control, with some convenience
+ constructors
+*/
+struct ControlState
+{
+ ControlState(): pos(0.0), delta(0.0), button_state(neither) {}
+
+ ControlState( LedState ls ): pos(0.0), delta(0.0), led_state(ls), button_state(neither) {}
+
+ // Note that this sets both pos and delta to the flt value
+ ControlState( LedState ls, float flt ): pos(flt), delta(flt), ticks(0), led_state(ls), button_state(neither) {}
+ ControlState( float flt ): pos(flt), delta(flt), ticks(0), led_state(none), button_state(neither) {}
+ ControlState( float flt, int tcks ): pos(flt), delta(flt), ticks(tcks), led_state(none), button_state(neither) {}
+ ControlState( ButtonState bs ): pos(0.0), delta(0.0), ticks(0), led_state(none), button_state(bs) {}
+
+ float pos;
+ float delta;
+ int ticks;
+ LedState led_state;
+ ButtonState button_state;
+};
+
+class Control;
+class Fader;
+class Button;
+class Strip;
+class Group;
+class Pot;
+class Led;
+class LedRing;
+
+}
+
+#endif
diff --git a/libs/surfaces/tranzport/README b/libs/surfaces/tranzport/README
new file mode 100644
index 0000000000..e2d37c84bf
--- /dev/null
+++ b/libs/surfaces/tranzport/README
@@ -0,0 +1,90 @@
+
+I'm putting this here because I don't really have a place to put it, unless I create a web page and have a place to keep the code.
+
+While doing some exaustive testing of my latest code (read - playing a ton of music) I have done some thinking about the ui, and decided that under apparent simplicity should lie complexity.
+
+The "flash" screen idea I am going to drop, and replace it with the idea of a notify area being declared on each screen.
+
+When the unit is idle, these messages will appear in that area statically. When the transport is running, these messages will still appear in that space, which is usually where the meter is. It's actually possible to rapidly flash the area between the competing writers and get a nifty faded effect. (I came across this idea accidentally when I had a pointer overrun)
+
+Also certain things will update on top of each other, whatever was updated
+last will stay on the screen. This is Pan/Gain primarily.
+
+I need a way to get messages back into the tranzport. Example - I hit Undo, what was undone? Redo, same problem.
+
+I've already found many uses for being able to control more than 1 track at a time, so I think that although I'm *usually* controlling one track at a time, being able to quickly access all tracks would be good.
+
+Example - want to have meters for all tracks running and be able to control the
+db/pan settings of the track I'm on....
+
+What I am going to go with is multifold - but first my design goal: I want to do everything required for a solo musician wielding an instrument to NOT have to touch a keyboard or look at a big screen. When you are wrapped behind a bass, it's difficult to cope with that - but the tranzport is a great alternative.
+
+Most screens will have *4* items on them.
+
+There will be "display views" - which are more informational and bling oriented.
+
+There will be "Track based views"- which basically do track specific things
+
+There will be "interactive views",which basically allow for more input than output. They will do something to highlight the current selection.
+Scroll wheel will select between values for a field. Track Next/Prev will move between fields. I would like to have a "No/Yes" option (hit record for yes? Stop for no?) but I'm still a little vague on that.
+
+Things to do:
+
+A) Hitting "Shift->Spacebar" will switch "views". There are ultimately going to be dozens of views. At present, there are only the "Normal" and "Big Meter" views.
+
+Each view will change somewhat based on the state of the transport. Holding down shift for a second will switch to the "underlying display"....
+
+Here's how the "normal" view looks today in my tree:
+
+VIEW: NORMAL
+
+Play Mode: Stopped
+[Trackname[16]] [gain/pan[4]]
+[Modes[9]] long smpte/bar counter]
+
+Play Mode: Playing > 1.0 speed
+[Trackname[16]] [gain/pan[4]]
+[meter[16]] short smpte/bar counter]
+
+Play Mode: Playing < 1.0
+[Trackname[16]] [gain/pan[4]]
+[meter[9]] long smpte/bar counter]
+
+Play Mode: Recording
+[Trackname[16]] [gain/pan[4]]
+[meter[16]] short smpte/bar counter]
+
+Other views (in order of development priority)
+
+Marker Mode: Edit markers, setup loops and punch in points.
+Config Mode: Load/Save settings, Load/Save project. Set wheel SnapTo
+Loop Mode: Show track, raise layers to top for playback, editing, deletion, loop on and off, etc
+
+It's possible that config mode will have a "MORE" field, or ways to move around the configuration (ffw/Play?)
+
+(the first two are the two modes I most need personally. If you have a suggestion...)
+
+Mastering Mode - display master and current track with meters and panner/db
+Automation Mode - I really don't think I have the pixels for this
+
+(I've already abstracted out the code to do most of these, but it's bling, I'm not going to bother much with it soon)
+
+Quad Meter Mode
+Inverted Meter mode (draws meters backwards)
+Quad Inverted Meter mode (bling, but my car stereo has it, and it's cool)
+10 8 bar meter mode
+5 8 bar meter mode
+
+I haven't written the panner yet, doing the stereo meter killed me.
+
+From a development perspective I'm going to keep revising the code to make it more stable and merely tie the new mode modes to the "bling mode"s until they are ready for prime time. I should be able to put out releases once a week for a while.
+
+A big help would be moving these items into a higher level of abstraction (revising the baseUI class).
+
+In particular, I'd really like "slave" mode. Snapto increment is really important....
+
+Here's an example of something that should be fairly easy to export to the Base::UI subclasses - the current state of the main keyboard's shift key.
+
+That way, when shift is held down for a few seconds on the regular keyboard, I can see what's underneath the current tranzport display mode (I do like big meters) (Also, it's somewhat easier to hit shift on the main keyboard and play on the tranzport or the shuttle wheel, if that's what you are doing).
+
+Should be fairly easy to tap into the gdk event for this but the "right way" to propagate this event into the class is beyond me.
diff --git a/libs/surfaces/tranzport/SConscript b/libs/surfaces/tranzport/SConscript
index 5d390f3e2f..a154685299 100644
--- a/libs/surfaces/tranzport/SConscript
+++ b/libs/surfaces/tranzport/SConscript
@@ -22,13 +22,36 @@ tranzport.Append(POTFILE = domain + '.pot')
tranzport_files=Split("""
interface.cc
-tranzport_control_protocol.cc
+buttons.cc
+io.cc
+io_usb.cc
+panner.cc
+lights.cc
+screen.cc
+state.cc
+wheel_modes.cc
+button_events.cc
+general.cc
+lcd.cc
+mode.cc
+show.cc
+init.cc
+wheel.cc
""")
+#figure out when to do
+#io_usb.cc
+#io_midi.cc
+#io_kernel.cc
+
tranzport.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
tranzport.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
tranzport.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
tranzport.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
+#if env['HAVE_TRANZPORT_KERNEL_DRIVER']:
+# tranzport.Append(CXXFLAGS="-DHAVE_TRANZPORT_KERNEL_DRIVER=1")
+
+#merge more into tranzport files for the right io lib
tranzport.Merge ([
libraries['ardour'],
@@ -37,20 +60,23 @@ tranzport.Merge ([
libraries['pbd'],
libraries['midi++2'],
libraries['xml'],
- libraries['usb'],
libraries['glib2'],
- libraries['glibmm2']
+ libraries['glibmm2'],
+ libraries['usb'],
+ libraries['sndfile-ardour']
])
libardour_tranzport = tranzport.SharedLibrary('ardour_tranzport', tranzport_files)
if tranzport['TRANZPORT']:
- Default(libardour_tranzport)
- if env['NLS']:
- i18n (tranzport, tranzport_files, env)
- env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2', 'surfaces'), libardour_tranzport))
+ Default(libardour_tranzport)
+ if env['NLS']:
+ i18n (tranzport, tranzport_files, env)
+# if env['HAVE_TRANZPORT_KERNEL_DRIVER']:
+# tranzport.Merge([ libraries['usb'] ])
+ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2', 'surfaces'), libardour_tranzport))
env.Alias('tarball', env.Distribute (env['DISTTREE'],
- [ 'SConscript' ] +
- tranzport_files +
- glob.glob('po/*.po') + glob.glob('*.h')))
+ [ 'SConscript' ] +
+ tranzport_files +
+ glob.glob('po/*.po') + glob.glob('*.h')))
diff --git a/libs/surfaces/tranzport/TODO b/libs/surfaces/tranzport/TODO
new file mode 100644
index 0000000000..216a5bc9d0
--- /dev/null
+++ b/libs/surfaces/tranzport/TODO
@@ -0,0 +1,6 @@
+BREAK APART DRIVER INTO SIMPLER CHUNKS - done
+GET KERNEL DRIVER WORKING
+GET TRIPLE THREADED DRIVER WORKING
+STABLIZE THE API
+ADOPT SOME CONVENTIONS FROM THE MACKIE
+GET SAVING STATE WORKING
diff --git a/libs/surfaces/tranzport/bling.cc b/libs/surfaces/tranzport/bling.cc
new file mode 100644
index 0000000000..c60b699f3d
--- /dev/null
+++ b/libs/surfaces/tranzport/bling.cc
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* The Bling class theoretically knows nothing about the device it's blinging
+ and depends on the overlying implementation to tell it about the format of the
+ device. Maybe this will become a template or people will inherit from it */
+
+/* Bling is where all the bad, bad, marketing driven ideas go */
+
+class bling {
+public:
+ enum BlingMode {
+ BlingOff = 0,
+ BlingOn = 1,
+ BlingEnter = 2,
+ BlingExit = 4,
+ // Light Specific Stuff
+ BlingKit = 8,
+ BlingRotating = 16,
+ BlingPairs = 32,
+ BlingRows = 64,
+ BlingColumns = 128,
+ BlingFlashAllLights = 256,
+ // Screen Specific Stuff
+ // Slider Specific Stuff
+ BlingSliderMax,
+ BlingSliderMid,
+ BlingSliderMin,
+ // Random stuff
+ BlingRandomLight,
+ BlingRandomSlider,
+ BlingRandomScreen,
+ BlingAllSliders
+ };
+ bling();
+ ~bling();
+ set(BlingMode);
+ unset(BlingMode);
+ run();
+ next();
+ prev();
+ msg(string&);
+ scrollmsg(string&);
+
+protected:
+// The as yet undefined "advanced_ui" class provides methods to find out at run time
+// what the heck is what
+ BlingMode blingmode;
+ advancedUI *intf;
+ int last_light;
+// I don't think these actually need to be part of the public definition of the class
+ enter();
+ exit();
+ rotate();
+// etc
+};
+
+// make absolutely sure we have the pointer to the interface
+// something like this
+
+#define BLING_INTFA(a) (intf)? 0:intf->a
+#define BLING_INTF(a) { if (intf) { intf->a; } else { return 0; } }
+
+// Should any of these bother to return a status code?
+
+bling::rotate() {
+ BLING_INTF(light(last_light,off));
+ last_light = BLING_INTFA(next_light(last_light));
+ BLING_INTF(light(last_light,on));
+}
+
+bling::enter() {
+}
+
+bling::exit() {
+}
+
+bling::flashall() {
+}
+
+bling::rows() {
+}
+
+bling::columns() {
+}
+
+bling::msg() {
+}
+
+bling::scrollmsg() {
+}
+
+// Based on the current bling mode, do whatever it is you are going to do
+bling::run() {
+
+}
+
+// etc
diff --git a/libs/surfaces/tranzport/button_events.cc b/libs/surfaces/tranzport/button_events.cc
new file mode 100644
index 0000000000..37c62a6ab7
--- /dev/null
+++ b/libs/surfaces/tranzport/button_events.cc
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <tranzport_common.h>
+#include <tranzport_control_protocol.h>
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace PBD;
+
+#include "i18n.h"
+
+#include <pbd/abstract_ui.cc>
+
+
+
+void
+TranzportControlProtocol::button_event_battery_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_battery_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_backlight_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_backlight_release (bool shifted)
+{
+#if DEBUG_TRANZPORT
+ printf("backlight released, redrawing (and possibly crashing) display\n");
+#endif
+ if (shifted) {
+ lcd_damage();
+ lcd_clear();
+ last_where += 1; /* force time redisplay */
+ last_track_gain = FLT_MAX;
+ }
+}
+
+void
+TranzportControlProtocol::button_event_trackleft_press (bool shifted)
+{
+ prev_track ();
+ // not really the right layer for this
+ if(display_mode == DisplayBigMeter) {
+ if (route_table[0] != 0) {
+ notify(route_get_name (0).substr (0, 15).c_str());
+ }
+ }
+}
+
+void
+TranzportControlProtocol::button_event_trackleft_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackright_press (bool shifted)
+{
+ next_track ();
+ // not really the right layer for this
+ if(display_mode == DisplayBigMeter) {
+ if (route_table[0] != 0) {
+ notify(route_get_name (0).substr (0, 15).c_str());
+ }
+ }
+}
+
+void
+TranzportControlProtocol::button_event_trackright_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackrec_press (bool shifted)
+{
+ if (shifted) {
+ toggle_all_rec_enables ();
+ } else {
+ route_set_rec_enable (0, !route_get_rec_enable (0));
+ }
+}
+
+void
+TranzportControlProtocol::button_event_trackrec_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackmute_press (bool shifted)
+{
+ if (shifted) {
+ // Mute ALL? Something useful when a phone call comes in. Mute master?
+ } else {
+ route_set_muted (0, !route_get_muted (0));
+ }
+}
+
+void
+TranzportControlProtocol::button_event_trackmute_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_tracksolo_press (bool shifted)
+{
+#if DEBUG_TRANZPORT
+ printf("solo pressed\n");
+#endif
+ if (display_mode == DisplayBigMeter) {
+ light_off (LightAnysolo);
+ return;
+ }
+
+ if (shifted) {
+ session->set_all_solo (!session->soloing());
+ } else {
+ route_set_soloed (0, !route_get_soloed (0));
+ }
+}
+
+void
+TranzportControlProtocol::button_event_tracksolo_release (bool shifted)
+{
+#if DEBUG_TRANZPORT
+ printf("solo released\n");
+#endif
+}
+
+void
+TranzportControlProtocol::button_event_undo_press (bool shifted)
+{
+// undohistory->get_state(1);
+//XMLNode&
+//UndoHistory::get_state (uint32_t depth)
+
+ if (shifted) {
+ redo (); // someday flash the screen with what was redone
+ notify("Redone!!");
+ } else {
+ undo (); // someday flash the screen with what was undone
+ notify("Undone!!");
+ }
+}
+
+void
+TranzportControlProtocol::button_event_undo_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_in_press (bool shifted)
+{
+ if (shifted) {
+ toggle_punch_in ();
+ } else {
+ ControlProtocol::ZoomIn (); /* EMIT SIGNAL */
+ }
+}
+
+void
+TranzportControlProtocol::button_event_in_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_out_press (bool shifted)
+{
+ if (shifted) {
+ toggle_punch_out ();
+ } else {
+ ControlProtocol::ZoomOut (); /* EMIT SIGNAL */
+ }
+}
+
+void
+TranzportControlProtocol::button_event_out_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_punch_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_punch_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_loop_press (bool shifted)
+{
+ if (shifted) {
+ next_wheel_shift_mode ();
+ } else {
+ loop_toggle ();
+ }
+}
+
+void
+TranzportControlProtocol::button_event_loop_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_prev_press (bool shifted)
+{
+ if (shifted) {
+ ControlProtocol::ZoomToSession (); /* EMIT SIGNAL */
+ } else {
+ prev_marker ();
+ }
+}
+
+void
+TranzportControlProtocol::button_event_prev_release (bool shifted)
+{
+}
+
+// Note - add_marker should adhere to the snap to setting
+// maybe session->audible_frame does that
+
+void
+TranzportControlProtocol::button_event_add_press (bool shifted)
+{
+ add_marker ();
+}
+
+void
+TranzportControlProtocol::button_event_add_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_next_press (bool shifted)
+{
+ if (shifted) {
+ next_wheel_mode ();
+ } else {
+ next_marker ();
+ }
+}
+
+void
+TranzportControlProtocol::button_event_next_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_rewind_press (bool shifted)
+{
+ if (shifted) {
+ goto_start ();
+ } else {
+ rewind ();
+ }
+}
+
+void
+TranzportControlProtocol::button_event_rewind_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_fastforward_press (bool shifted)
+{
+ if (shifted) {
+ goto_end ();
+ } else {
+ ffwd ();
+ }
+}
+
+void
+TranzportControlProtocol::button_event_fastforward_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_stop_press (bool shifted)
+{
+ if (shifted) {
+ next_display_mode ();
+ } else {
+ transport_stop ();
+ }
+}
+
+void
+TranzportControlProtocol::button_event_stop_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_play_press (bool shifted)
+{
+ if (shifted) {
+ set_transport_speed (1.0f);
+ } else {
+ transport_play ();
+ }
+}
+
+void
+TranzportControlProtocol::button_event_play_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_record_press (bool shifted)
+{
+ if (shifted) {
+ save_state ();
+ } else {
+ rec_enable_toggle ();
+ }
+}
+
+void
+TranzportControlProtocol::button_event_record_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_footswitch_press (bool shifted)
+{
+ if (shifted) {
+ next_marker (); // think this through, we could also do punch in
+ } else {
+ prev_marker (); // think this through, we could also do punch in
+ }
+}
+
+void
+TranzportControlProtocol::button_event_footswitch_release (bool shifted)
+{
+ if(session->transport_speed() == 0.0)
+ {
+ transport_play ();
+ }
+}
+
+// Possible new api example
+// tries harder to do the right thing if we somehow missed a button down event
+// which currently happens... a lot.
+
+void button_event_mute (bool pressed, bool shifted)
+{
+ static int was_pressed = 0;
+ if((!pressed && !was_pressed) || pressed) {
+ was_pressed = 1;
+ }
+
+ was_pressed = 0;
+}
diff --git a/libs/surfaces/tranzport/button_yn.cc b/libs/surfaces/tranzport/button_yn.cc
new file mode 100644
index 0000000000..04b6ab5668
--- /dev/null
+++ b/libs/surfaces/tranzport/button_yn.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* placeholder for button definitions for user edits like yes/no */
diff --git a/libs/surfaces/tranzport/buttons.cc b/libs/surfaces/tranzport/buttons.cc
new file mode 100644
index 0000000000..df5a88e6d9
--- /dev/null
+++ b/libs/surfaces/tranzport/buttons.cc
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include "tranzport_control_protocol.h"
+
+#define TRANZPORT_BUTTON_HANDLER(callback, button_arg) if (button_changes & button_arg) { \
+ if (buttonmask & button_arg) { \
+ callback##_press (buttonmask&ButtonShift); } else { callback##_release (buttonmask&ButtonShift); } }
+
+int
+TranzportControlProtocol::process (uint8_t* buf)
+{
+
+ uint32_t this_button_mask;
+ uint32_t button_changes;
+
+ _device_status = buf[1];
+
+#if DEBUG_TRANZPORT > 10
+ // Perhaps the device can go offline due to flow control, print command bits to see if we have anything interesting
+ if(_device_status == STATUS_ONLINE) {
+ printf("ONLINE : %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ buf[0],buf[1],buf[2], buf[3], buf[4], buf[5],buf[6],buf[7]);
+ }
+ if(_device_status == STATUS_OFFLINE) {
+ printf("OFFLINE : %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ buf[0],buf[1],buf[2], buf[3], buf[4], buf[5],buf[6],buf[7]);
+ }
+
+ if(_device_status != STATUS_OK) { return 1; }
+
+#endif
+
+
+ this_button_mask = 0;
+ this_button_mask |= buf[2] << 24;
+ this_button_mask |= buf[3] << 16;
+ this_button_mask |= buf[4] << 8;
+ this_button_mask |= buf[5];
+ _datawheel = buf[6];
+
+#if DEBUG_TRANZPORT_STATE > 1
+ // Is the state machine incomplete?
+ const unsigned int knownstates = 0x00004000|0x00008000|
+ 0x04000000| 0x40000000| 0x00040000| 0x00400000|
+ 0x00000400| 0x80000000| 0x02000000| 0x20000000|
+ 0x00800000| 0x00080000| 0x00020000| 0x00200000|
+ 0x00000200| 0x01000000| 0x10000000| 0x00010000|
+ 0x00100000| 0x00000100| 0x08000000| 0x00001000;
+
+ std::bitset<32> bi(knownstates);
+ std::bitset<32> vi(this_button_mask);
+
+ // if an bi & vi == vi the same - it's a valid set
+
+ if(vi != (bi & vi)) {
+ printf("UNKNOWN STATE: %s also, datawheel= %d\n", vi.to_string().c_str(), _datawheel);
+ }
+#endif
+
+ button_changes = (this_button_mask ^ buttonmask);
+ buttonmask = this_button_mask;
+
+ if (_datawheel) {
+ datawheel ();
+ }
+
+ // SHIFT + STOP + PLAY for bling mode?
+ // if (button_changes & ButtonPlay & ButtonStop) {
+ // bling_mode_toggle();
+ // } or something like that
+
+ TRANZPORT_BUTTON_HANDLER(button_event_battery,ButtonBattery);
+ TRANZPORT_BUTTON_HANDLER(button_event_backlight,ButtonBacklight);
+ TRANZPORT_BUTTON_HANDLER(button_event_trackleft,ButtonTrackLeft);
+ TRANZPORT_BUTTON_HANDLER(button_event_trackright,ButtonTrackRight);
+ TRANZPORT_BUTTON_HANDLER(button_event_trackrec,ButtonTrackRec);
+ TRANZPORT_BUTTON_HANDLER(button_event_trackmute,ButtonTrackMute);
+ TRANZPORT_BUTTON_HANDLER(button_event_tracksolo,ButtonTrackSolo);
+ TRANZPORT_BUTTON_HANDLER(button_event_undo,ButtonUndo);
+ TRANZPORT_BUTTON_HANDLER(button_event_in,ButtonIn);
+ TRANZPORT_BUTTON_HANDLER(button_event_out,ButtonOut);
+ TRANZPORT_BUTTON_HANDLER(button_event_punch,ButtonPunch);
+ TRANZPORT_BUTTON_HANDLER(button_event_loop,ButtonLoop);
+ TRANZPORT_BUTTON_HANDLER(button_event_prev,ButtonPrev);
+ TRANZPORT_BUTTON_HANDLER(button_event_add,ButtonAdd);
+ TRANZPORT_BUTTON_HANDLER(button_event_next,ButtonNext);
+ TRANZPORT_BUTTON_HANDLER(button_event_rewind,ButtonRewind);
+ TRANZPORT_BUTTON_HANDLER(button_event_fastforward,ButtonFastForward);
+ TRANZPORT_BUTTON_HANDLER(button_event_stop,ButtonStop);
+ TRANZPORT_BUTTON_HANDLER(button_event_play,ButtonPlay);
+ TRANZPORT_BUTTON_HANDLER(button_event_record,ButtonRecord);
+ TRANZPORT_BUTTON_HANDLER(button_event_footswitch,ButtonFootswitch);
+ return 0;
+}
+
diff --git a/libs/surfaces/tranzport/general.cc b/libs/surfaces/tranzport/general.cc
new file mode 100644
index 0000000000..103a3b7681
--- /dev/null
+++ b/libs/surfaces/tranzport/general.cc
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <tranzport_common.h>
+#include <tranzport_control_protocol.h>
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace PBD;
+
+#include "i18n.h"
+
+#include <pbd/abstract_ui.cc>
+// HA, I don't need this anymore
+#include <slider_gain.h>
+
+// FIXME, flash recording light when recording and transport is moving
+int TranzportControlProtocol::lights_show_recording()
+{
+ return lights_show_normal();
+}
+
+void TranzportControlProtocol::show_bling() {
+ lights_show_bling();
+ screen_show_bling();
+}
+
+void TranzportControlProtocol::notify(const char *msg) {
+ last_notify=100;
+ if(strlen(msg) < 21) {
+ strcpy(last_notify_msg,msg);
+ } else {
+ strncpy(last_notify_msg,msg,16);
+ last_notify_msg[16] = '\n';
+ }
+}
+
+void TranzportControlProtocol::show_notify() {
+// FIXME: Get width of the notify area somehow
+ if(last_notify==0) {
+ print(1,0," ");
+ last_notify=-1;
+ }
+ if(last_notify > 0) {
+ print(1,0,last_notify_msg);
+ --last_notify;
+ }
+}
+
+// Need more bling!
+
+int TranzportControlProtocol::lights_show_bling()
+{
+ switch (bling_mode) {
+ case BlingOff: break;
+ case BlingKit: break; // rotate rec/mute/solo/any solo back and forth
+ case BlingRotating: break; // switch between lights
+ case BlingPairs: break; // Show pairs of lights
+ case BlingRows: break; // light each row in sequence
+ case BlingFlashAll: break; // Flash everything randomly
+ case BlingEnter: lights_on(); // Show intro
+ case BlingExit:
+ lights_off();
+ break;
+ }
+ return 0;
+}
+
+int TranzportControlProtocol::screen_show_bling()
+{
+ switch (bling_mode) {
+ case BlingOff: break;
+ case BlingKit: break; // rotate rec/mute/solo/any solo back and forth
+ case BlingRotating: break; // switch between lights
+ case BlingPairs: break; // Show pairs of lights
+ case BlingRows: break; // light each row in sequence
+ case BlingFlashAll: break; // Flash everything randomly
+ case BlingEnter: // Show intro
+ print(0,0,"!!Welcome to Ardour!");
+ print(1,0,"Peace through Music!");
+ break;
+ case BlingExit:
+ break;
+ }
+ return 0;
+}
+
+int TranzportControlProtocol::lights_show_normal()
+{
+ /* Track only */
+
+ if (route_table[0]) {
+ boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack> (route_table[0]);
+ lights_pending[LightTrackrec] = at && at->record_enabled();
+ lights_pending[LightTrackmute] = route_get_muted(0);
+ lights_pending[LightTracksolo] = route_get_soloed(0);
+ } else {
+ lights_pending[LightTrackrec] = false;
+ lights_pending[LightTracksolo] = false;
+ lights_pending[LightTrackmute] = false;
+ }
+
+ /* Global settings */
+
+ lights_pending[LightLoop] = session->get_play_loop();
+ lights_pending[LightPunch] = Config->get_punch_in() || Config->get_punch_out();
+ lights_pending[LightRecord] = session->get_record_enabled();
+ lights_pending[LightAnysolo] = session->soloing();
+
+ return 0;
+}
+
+int TranzportControlProtocol::lights_show_tempo()
+{
+ // someday soon fiddle with the lights more sanely based on the tempo
+ return lights_show_normal();
+}
+
+int
+TranzportControlProtocol::update_state ()
+{
+ /* do the text and light updates */
+
+ switch (display_mode) {
+ case DisplayBigMeter:
+ lights_show_tempo();
+ show_meter ();
+ break;
+
+ case DisplayNormal:
+ lights_show_normal();
+ normal_update();
+ break;
+
+ case DisplayConfig:
+ break;
+
+ case DisplayRecording:
+ lights_show_recording();
+ normal_update();
+ break;
+
+ case DisplayRecordingMeter:
+ lights_show_recording();
+ show_meter();
+ break;
+
+ case DisplayBling:
+ show_bling();
+ break;
+
+ case DisplayBlingMeter:
+ lights_show_bling();
+ show_meter();
+ break;
+ }
+ show_notify();
+
+ return 0;
+
+}
+
+void
+TranzportControlProtocol::prev_marker ()
+{
+ Location *location = session->locations()->first_location_before (session->transport_frame());
+
+ if (location) {
+ session->request_locate (location->start(), session->transport_rolling());
+ notify(location->name().c_str());
+ } else {
+ session->goto_start ();
+ notify("START");
+ }
+
+}
+
+void
+TranzportControlProtocol::next_marker ()
+{
+ Location *location = session->locations()->first_location_after (session->transport_frame());
+
+ if (location) {
+ session->request_locate (location->start(), session->transport_rolling());
+ notify(location->name().c_str());
+ } else {
+ session->request_locate (session->current_end_frame());
+ notify("END ");
+ }
+}
+
+
+void
+TranzportControlProtocol::show_current_track ()
+{
+ char pad[COLUMNS];
+ char *v;
+ int len;
+ if (route_table[0] == 0) {
+ print (0, 0, "---------------");
+ last_track_gain = FLT_MAX;
+ } else {
+ strcpy(pad," ");
+ v = (char *)route_get_name (0).substr (0, 14).c_str();
+ if((len = strlen(v)) > 0) {
+ strncpy(pad,(char *)v,len);
+ }
+ print (0, 0, pad);
+ }
+}
+
+
+#if 0
+void
+TranzportControlProtocol::step_gain (float increment)
+{
+// FIXME: buttonstop is used elsewhere
+ if (buttonmask & ButtonStop) {
+ gain_fraction += 0.001*increment;
+ } else {
+ gain_fraction += 0.01*increment;
+ }
+
+ if (fabsf(gain_fraction) > 2.0) {
+ gain_fraction = 2.0*sign(gain_fraction);
+ }
+
+ route_set_gain (0, slider_position_to_gain (gain_fraction));
+}
+#endif
+
+void
+TranzportControlProtocol::step_gain_up ()
+{
+ if (buttonmask & ButtonStop) {
+ gain_fraction += 0.001;
+ } else {
+ gain_fraction += 0.01;
+ }
+
+ if (gain_fraction > 2.0) {
+ gain_fraction = 2.0;
+ }
+
+ route_set_gain (0, slider_position_to_gain (gain_fraction));
+}
+
+void
+TranzportControlProtocol::step_gain_down ()
+{
+ if (buttonmask & ButtonStop) {
+ gain_fraction -= 0.001;
+ } else {
+ gain_fraction -= 0.01;
+ }
+
+ if (gain_fraction < 0.0) {
+ gain_fraction = 0.0;
+ }
+
+ route_set_gain (0, slider_position_to_gain (gain_fraction));
+}
+
+
+void
+TranzportControlProtocol::next_track ()
+{
+ ControlProtocol::next_track (current_track_id);
+ gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
+// notify("NextTrak"); // not needed til we have more modes
+}
+
+void
+TranzportControlProtocol::prev_track ()
+{
+ ControlProtocol::prev_track (current_track_id);
+ gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
+// notify("PrevTrak");
+}
+
+// This should kind of switch to using notify
+
+// Was going to keep state around saying to retry or not
+// haven't got to it yet, still not sure it's a good idea
+
+void
+TranzportControlProtocol::print (int row, int col, const char *text) {
+ print_noretry(row,col,text);
+}
+
+// -1 on failure
+// 0 on no damage
+// count of bit set on damage?
+
+void
+TranzportControlProtocol::print_noretry (int row, int col, const char *text)
+{
+ uint32_t length = strlen (text);
+ if (row*COLUMNS+col+length > (ROWS*COLUMNS)) {
+ return;
+ }
+ // FIXME - be able to print the whole screen at a go.
+ uint32_t t,r,c;
+ std::bitset<ROWS*COLUMNS> mask(screen_invalid);
+ for(r = row, c = col, t = 0 ; t < length; c++,t++) {
+ screen_pending[r][c] = text[t];
+ mask[r*COLUMNS+c] = (screen_current[r][c] != screen_pending[r][c]);
+ }
+ screen_invalid = mask;
+}
+
+void TranzportControlProtocol::invalidate()
+{
+ lcd_damage(); lights_invalidate(); screen_invalidate(); // one of these days lcds can be fine but screens not
+}
diff --git a/libs/surfaces/tranzport/init.cc b/libs/surfaces/tranzport/init.cc
new file mode 100644
index 0000000000..94f85bdc56
--- /dev/null
+++ b/libs/surfaces/tranzport/init.cc
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <tranzport_common.h>
+#include <tranzport_control_protocol.h>
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace PBD;
+
+#include "i18n.h"
+
+#include <pbd/abstract_ui.cc>
+
+void*
+TranzportControlProtocol::_monitor_work (void* arg)
+{
+ return static_cast<TranzportControlProtocol*>(arg)->monitor_work ();
+}
+
+TranzportControlProtocol::~TranzportControlProtocol ()
+{
+ set_active (false);
+}
+
+int TranzportControlProtocol::rtpriority_set(int priority)
+{
+ struct sched_param rtparam;
+ int err;
+ char *a = (char*) alloca(4096*2); a[0] = 'a'; a[4096] = 'b';
+ memset (&rtparam, 0, sizeof (rtparam));
+ rtparam.sched_priority = priority; /* XXX should be relative to audio (JACK) thread */
+ // Note - try SCHED_RR with a low limit
+ // - we don't care if we can't write everything this ms
+ // and it will help if we lose the device
+ if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
+ PBD::info << string_compose (_("%1: thread not running with realtime scheduling (%2)"), name(), strerror (errno)) << endmsg;
+ return 1;
+ }
+ return 0;
+}
+
+// Running with realtime privs is bad when you have problems
+
+int TranzportControlProtocol::rtpriority_unset(int priority)
+{
+ struct sched_param rtparam;
+ int err;
+ memset (&rtparam, 0, sizeof (rtparam));
+ rtparam.sched_priority = priority;
+ if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
+ PBD::info << string_compose (_("%1: can't stop realtime scheduling (%2)"), name(), strerror (errno)) << endmsg;
+ return 1;
+ }
+ PBD::info << string_compose (_("%1: realtime scheduling stopped (%2)"), name(), strerror (errno)) << endmsg;
+ return 0;
+}
+
+
+int
+TranzportControlProtocol::set_active (bool yn)
+{
+ if (yn != _active) {
+
+ if (yn) {
+
+ if (open ()) {
+ return -1;
+ }
+
+ if (pthread_create_and_store (X_("tranzport monitor"), &thread, 0, _monitor_work, this) == 0) {
+ _active = true;
+#if TRANZPORT_THREADS
+ if (pthread_create_and_store (X_("tranzport read"), &thread_read, 0, _read_work, this) == 0) {
+ _active_read = true;
+ if (pthread_create_and_store (X_("tranzport write"), &thread_write, 0, _write_work, this) == 0) {
+ _active_write = true;
+ if (pthread_create_and_store (X_("tranzport process"), &thread_process, 0, _process_work, this) == 0) {
+ _active_process = true;
+ if (pthread_create_and_store (X_("tranzport timer"), &thread_timer, 0, _process_timer, this) == 0) {
+ _active_process = true;
+#endif
+ } else {
+ return -1;
+ }
+
+ } else {
+ cerr << "Begin tranzport shutdown\n";
+// if we got here due to an error, prettifying things will only make it worse
+// And with threads involved, oh boy...
+ if(!(last_write_error || last_read_error)) {
+ bling_mode = BlingExit;
+ enter_bling_mode();
+// thread FIXME - wait til all writes are done
+ for(int x = 0; (x < 20/MAX_TRANZPORT_INFLIGHT) && flush(); x++) { usleep(100); }
+ }
+#if TRANZPORT_THREADS
+ pthread_cancel_one (_thread_timer);
+ pthread_cancel_one (_thread_process);
+ pthread_cancel_one (_thread_read);
+ pthread_cancel_one (_thread_write);
+#endif
+ pthread_cancel_one (thread);
+
+ cerr << "Tranzport Thread dead\n";
+ close ();
+ _active = false;
+ cerr << "End tranzport shutdown\n";
+ }
+ }
+
+ return 0;
+}
+
+TranzportControlProtocol::TranzportControlProtocol (Session& s)
+ : ControlProtocol (s, X_("Tranzport"))
+{
+ /* tranzport controls one track at a time */
+
+ set_route_table_size (1);
+ timeout = 6000; // what is this for?
+ buttonmask = 0;
+ _datawheel = 0;
+ _device_status = STATUS_OFFLINE;
+ udev = 0;
+ current_track_id = 0;
+ last_where = max_frames;
+ wheel_mode = WheelTimeline;
+ wheel_shift_mode = WheelShiftGain;
+ wheel_increment = WheelIncrScreen;
+ bling_mode = BlingEnter;
+ last_notify_msg[0] = '\0';
+ last_notify = 0;
+ timerclear (&last_wheel_motion);
+ last_wheel_dir = 1;
+ last_track_gain = FLT_MAX;
+ last_write_error = 0;
+ last_read_error = 0;
+ display_mode = DisplayBling;
+ gain_fraction = 0.0;
+ invalidate();
+ screen_init();
+ lights_init();
+// FIXME: Wait til device comes online somewhere
+// About 3 reads is enough
+// enter_bling_mode();
+
+}
+
+void*
+TranzportControlProtocol::monitor_work ()
+{
+ uint8_t buf[8]; // = { 0,0,0,0,0,0,0,0 };
+ int val = 0, pending = 0;
+ bool first_time = true;
+ uint8_t offline = 0;
+
+ PBD::ThreadCreated (pthread_self(), X_("Tranzport"));
+ pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
+ rtpriority_set();
+ inflight=0;
+ //int intro = 20;
+
+ // wait for the device to come online
+ invalidate();
+ screen_init();
+ lights_init();
+ update_state();
+// There has to be some specific command to enable the device!!
+// while((val = read(buf,DEFAULT_USB_TIMEOUT*5)) == -110 && pending !=0) {
+// pending = lights_flush(); // poke the device for a while
+// }
+
+// pending = 1;
+// while(intro-- > 0 && pending != 0) {
+// usleep(1000);
+// pending = screen_flush(); // kinder, gentler init
+// }
+// usleep(1000);
+// lights_on();
+// while(flush()!=0) ;
+// lights_off();
+ display_mode = DisplayNormal;
+
+ while (true) {
+
+ /* bInterval for this beastie is 10ms */
+
+ if (_device_status == STATUS_OFFLINE) {
+ first_time = true; offline++;
+#if TRANZPORT_DEBUG > 3
+ if(offline == 1) {
+ cerr << "Transport has gone offline\n";
+ }
+#endif
+ } else {
+ offline = 0; // hate writing this
+ }
+ unsigned int s = (last_write_error == 0) | ((last_read_error == 0) << 1);
+ switch (s) {
+ case 0: val = read(buf,DEFAULT_USB_TIMEOUT); break;
+ case 1: val = read(buf,DEFAULT_USB_TIMEOUT); break;
+ case 2: val = read(buf,DEFAULT_USB_TIMEOUT); break;
+ case 3: val = read(buf,DEFAULT_USB_TIMEOUT*2); break; // Hoo, boy, we're in trouble
+ default: break; // not reached
+ }
+
+#if DEBUG_TRANZPORT_BITS > 9
+ if(_device_status != STATUS_OFFLINE && _device_status != STATUS_ONLINE && _device_status != STATUS_OK) {
+ printf("The device has more status bits than off or online: %d\n",_device_status);
+ }
+#endif
+
+#if DEBUG_TRANZPORT_BITS > 99
+ if (val != 8) {
+ printf("val = %d errno = %d\n",val,errno);
+ buf[0] = buf[1] = buf[2] = buf[3] =
+ buf[4] = buf[5] = buf[6] = buf[7] =
+ buf[8] = 0;
+ }
+#endif
+
+ if(val == 8) {
+ last_write_error = 0;
+ process (buf);
+ }
+
+#if DEBUG_TRANZPORT > 9
+ if(inflight > 1) printf("Inflight: %d\n", inflight);
+#endif
+
+ if (_device_status == STATUS_ONLINE) {
+ if (first_time) {
+ invalidate();
+ lcd_clear ();
+ lights_off ();
+ first_time = false;
+ last_write_error = 0;
+ offline = 0;
+ pending = 3; // Give some time for the device to recover
+ }
+#if DEBUG_TRANZPORT_BITS > 10
+ // Perhaps an online message indicates something
+
+ if(_device_status != buf[1]) {
+ printf("WTF- val: %d, device status != buf! %d != %d \n",val,_device_status,buf[1]); _device_status = buf[1];
+ }
+#endif
+
+ }
+
+#if DEBUG_TRANZPORT_BITS > 10
+
+ if(val == 8) {
+
+ if(_device_status == STATUS_ONLINE) {
+ printf("ONLINE : %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ buf[0],buf[1],buf[2], buf[3], buf[4], buf[5],buf[6],buf[7]);
+ }
+ if(_device_status == STATUS_OFFLINE) {
+ printf("OFFLINE : %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ buf[0],buf[1],buf[2], buf[3], buf[4], buf[5],buf[6],buf[7]);
+ }
+
+ if(_device_status == STATUS_OK) {
+ printf("OK : %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ buf[0],buf[1],buf[2], buf[3], buf[4], buf[5],buf[6],buf[7]);
+ }
+
+ }
+
+#endif
+
+ /* update whatever needs updating */
+ if(last_write_error == 0 && (_device_status == STATUS_ONLINE || _device_status == STATUS_OK)) {
+ update_state ();
+
+ /* still struggling with a good means of exerting flow control without having to create threads */
+ // pending = flush();
+
+ if(pending == 0) {
+ pending = flush();
+ } else {
+ if(inflight > 0) {
+ pending = --inflight; // we just did a whole bunch of writes so wait
+ } else {
+ pending = 0;
+ }
+ }
+ }
+ // pending = 0;
+ }
+ return (void*) 0;
+}
+
diff --git a/libs/surfaces/tranzport/interface.cc b/libs/surfaces/tranzport/interface.cc
index f6d0dc8206..f9b82fa651 100644
--- a/libs/surfaces/tranzport/interface.cc
+++ b/libs/surfaces/tranzport/interface.cc
@@ -1,3 +1,23 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
#include <control_protocol/control_protocol.h>
#include "tranzport_control_protocol.h"
diff --git a/libs/surfaces/tranzport/io.cc b/libs/surfaces/tranzport/io.cc
new file mode 100644
index 0000000000..14242ea0ec
--- /dev/null
+++ b/libs/surfaces/tranzport/io.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* The routines in here should know absolutely nothing about how io is actually done */
+
+#include <tranzport_control_protocol.h>
+
+int
+TranzportControlProtocol::flush ()
+{
+ int pending = 0;
+
+// Always write the lights first
+ if(!(pending = lights_flush())) {
+ pending = screen_flush();
+ }
+
+#if DEBUG_TRANZPORT_BITS > 9
+ int s;
+ if(s = (screen_invalid.count())) { // + lights_invalid.count())) {
+ printf("VALID : %s %s\n",
+ screen_invalid.to_string().c_str(),
+ lights_invalid.to_string().c_str());
+ printf("CURR : %s %s\n",
+ screen_invalid.to_string().c_str(),
+ lights_current.to_string().c_str());
+ printf("PENDING : %s %s\n",
+ screen_invalid.to_string().c_str(),
+ lights_pending.to_string().c_str());
+#if DEBUG_TRANZPORT_BITS > 10
+ printf("invalid bits: %d\n",s);
+#endif
+ }
+#endif
+ return pending;
+}
+
+
+int
+TranzportControlProtocol::lights_flush ()
+{
+ std::bitset<LIGHTS> light_state;
+ light_state = lights_pending ^ lights_current;
+ if ( (light_state.none() || lights_invalid.none()))
+ {
+ return (0);
+ }
+
+#if DEBUG_TRANZPORT_LIGHTS
+ printf("LPEND : %s\n", lights_pending.to_string().c_str());
+ printf("LCURR : %s\n", lights_current.to_string().c_str());
+#endif
+
+ // if ever we thread reads/writes STATUS_OK will have to move into the loop
+ int i;
+
+ if ( _device_status == STATUS_OK || _device_status == STATUS_ONLINE) {
+ for (i = 0; i<LIGHTS; i++) {
+ if(light_state[i]) {
+ if(light_set ((LightID)i,lights_pending[i])) {
+#if DEBUG_TRANZPORT_LIGHTS > 2
+ printf("Did %d light writes\n",i);
+#endif
+ return light_state.count();
+ } else {
+ light_state[i] = 0;
+ }
+
+ }
+ }
+ }
+ light_state = lights_pending ^ lights_current;
+#if DEBUG_TRANZPORT_LIGHTS > 2
+ printf("Did %d light writes, left: %d\n",i, light_state.count());
+#endif
+
+ return light_state.count();
+}
diff --git a/libs/surfaces/tranzport/io_kernel.cc b/libs/surfaces/tranzport/io_kernel.cc
new file mode 100644
index 0000000000..5e29e9ac7b
--- /dev/null
+++ b/libs/surfaces/tranzport/io_kernel.cc
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#if HAVE_TRANZPORT_KERNEL_DRIVER
+#include <fcntl.h>
+#include <errno.h>
+#include <poll.h>
+#include "tranzport_control_protocol.h"
+
+// Something like open(/dev/surface/tranzport/event) for reading and raw for writing) would be better in the long run
+// Also support for multiple tranzports needs to be figured out
+// And bulk reads/writes in general
+
+bool
+TranzportControlProtocol::probe ()
+{
+ if((udev = ::open(TRANZPORT_DEVICE,O_RDWR))> 0) {
+ ::close(udev);
+ return true;
+ }
+ error << _("Tranzport: Can't open device for Read/Write: ") << endmsg;
+ return false;
+}
+
+int
+TranzportControlProtocol::open ()
+{
+ if((udev=::open(TRANZPORT_DEVICE,O_RDWR))> 0) {
+ return(udev);
+ }
+ error << _("Tranzport: no device detected") << endmsg;
+ return udev;
+}
+
+int
+TranzportControlProtocol::close ()
+{
+ int ret = 0;
+
+ if (udev < 1) {
+ return 0;
+ }
+
+ if ((ret = ::close (udev)) != 0) {
+ error << _("Tranzport: cannot close device") << endmsg;
+ }
+
+ return ret;
+}
+
+// someday do buffered reads, presently this does blocking reads, which is bad...
+
+int TranzportControlProtocol::read(uint8_t *buf, uint32_t timeout_override)
+{
+ last_read_error = ::read (udev, (char *) buf, 8);
+ switch(errno) {
+ case -ENOENT:
+ case -ENXIO:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ case -ENODEV:
+ cerr << "Tranzport disconnected, errno: " << last_read_error;
+ set_active(false);
+ break;
+ case -ETIMEDOUT: // This is not normal, but lets see what happened
+ cerr << "Tranzport read timed out, errno: " << last_read_error;
+ break;
+ default:
+#if DEBUG_TRANZPORT
+ cerr << "Got an unknown error on read:" << last_read_error "\n";
+#endif
+ break;
+ }
+
+ return last_read_error;
+}
+
+
+int
+TranzportControlProtocol::write_noretry (uint8_t* cmd, uint32_t timeout_override)
+{
+ // inflight is now taken care of by the driver, but...
+ if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
+ int val = ::write (udev, (char*) cmd, 8);
+
+ if (val < 0 && val !=8) {
+#if DEBUG_TRANZPORT
+ printf("write failed: %d\n", val);
+#endif
+ last_write_error = errno;
+ switch(last_write_error) {
+ case -ENOENT:
+ case -ENXIO:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ case -ENODEV:
+ cerr << "Tranzport disconnected, errno: " << last_write_error;
+ set_active(false);
+ break;
+ case -ETIMEDOUT: // This is not normal but
+ cerr << "Tranzport disconnected, errno: " << last_write_error;
+ break;
+ default:
+#if DEBUG_TRANZPORT
+ cerr << "Got an unknown error on read:" << last_write_error "\n";
+#endif
+ break;
+ }
+ return last_write_error;
+ }
+
+ last_write_error = 0;
+ ++inflight;
+
+ return 0;
+
+}
+
+int
+TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
+{
+ return (write_noretry(cmd,timeout_override));
+}
+
+// FIXME - install poll semantics
+#endif /* HAVE_TRANZPORT_KERNEL_DRIVER */
+
diff --git a/libs/surfaces/tranzport/io_midi.cc b/libs/surfaces/tranzport/io_midi.cc
new file mode 100644
index 0000000000..0fd10cfbf3
--- /dev/null
+++ b/libs/surfaces/tranzport/io_midi.cc
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* io_midi: Implements reading and writing tranzport events via the normal
+ tranzport midi specification */
+
+/* One day
+#include <tranzport_control_protocol.h>
+*/
diff --git a/libs/surfaces/tranzport/io_usb.cc b/libs/surfaces/tranzport/io_usb.cc
new file mode 100644
index 0000000000..c4a004a160
--- /dev/null
+++ b/libs/surfaces/tranzport/io_usb.cc
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <iostream>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <float.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <tranzport_control_protocol.h>
+
+#if !HAVE_TRANZPORT_KERNEL_DRIVER
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace PBD;
+
+#include "i18n.h"
+
+#include <pbd/abstract_ui.cc>
+
+// I note that these usb specific open, close, probe, read routines are basically
+// pure boilerplate and could easily be abstracted elsewhere
+
+bool
+TranzportControlProtocol::probe ()
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ for (bus = usb_busses; bus; bus = bus->next) {
+
+ for(dev = bus->devices; dev; dev = dev->next) {
+ if (dev->descriptor.idVendor == VENDORID && dev->descriptor.idProduct == PRODUCTID) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+int
+TranzportControlProtocol::open ()
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ for (bus = usb_busses; bus; bus = bus->next) {
+
+ for(dev = bus->devices; dev; dev = dev->next) {
+ if (dev->descriptor.idVendor != VENDORID)
+ continue;
+ if (dev->descriptor.idProduct != PRODUCTID)
+ continue;
+ return open_core (dev);
+ }
+ }
+
+ cerr << _("Tranzport: no device detected") << endmsg;
+ return -1;
+}
+
+int
+TranzportControlProtocol::open_core (struct usb_device* dev)
+{
+ if (!(udev = usb_open (dev))) {
+ cerr << _("Tranzport: cannot open USB transport") << endmsg;
+ return -1;
+ }
+
+ if (usb_claim_interface (udev, 0) < 0) {
+ cerr << _("Tranzport: cannot claim USB interface") << endmsg;
+ usb_close (udev);
+ udev = 0;
+ return -1;
+ }
+
+ if (usb_set_configuration (udev, 1) < 0) {
+ cerr << _("Tranzport: cannot configure USB interface") << endmsg;
+ }
+
+ return 0;
+}
+
+int
+TranzportControlProtocol::close ()
+{
+ int ret = 0;
+
+ if (udev == 0) {
+ return 0;
+ }
+
+ if (usb_release_interface (udev, 0) < 0) {
+ cerr << _("Tranzport: cannot release interface") << endmsg;
+ ret = -1;
+ }
+
+ if (usb_close (udev)) {
+ cerr << _("Tranzport: cannot close device") << endmsg;
+ udev = 0;
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int TranzportControlProtocol::read(uint8_t *buf, uint32_t timeout_override)
+{
+ last_read_error = usb_interrupt_read (udev, READ_ENDPOINT, (char *) buf, 8, timeout_override);
+ switch(last_read_error) {
+ case -ENOENT:
+ case -ENXIO:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ case -ENODEV:
+ cerr << "Tranzport disconnected, errno: " << last_read_error;
+ set_active(false);
+ case -ETIMEDOUT: // This is normal
+ break;
+ default:
+#if DEBUG_TRANZPORT
+ cerr << "Got an unknown error on read:" << last_read_error "\n";
+#endif
+ break;
+ }
+
+ return last_read_error;
+}
+
+
+int
+TranzportControlProtocol::write_noretry (uint8_t* cmd, uint32_t timeout_override)
+{
+ int val;
+ if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
+ val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
+
+ if (val < 0 && val !=8) {
+#if DEBUG_TRANZPORT
+ printf("usb_interrupt_write failed: %d\n", val);
+#endif
+ last_write_error = val;
+ switch(last_write_error) {
+ case -ENOENT:
+ case -ENXIO:
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ case -ENODEV:
+ cerr << "Tranzport disconnected, errno: " << last_write_error;
+ set_active(false);
+ case -ETIMEDOUT: // This is normal
+ break;
+ default:
+#if DEBUG_TRANZPORT
+ cerr << "Got an unknown error on read:" << last_write_error "\n";
+#endif
+ break;
+ }
+ return val;
+ }
+
+ last_write_error = 0;
+ ++inflight;
+
+ return 0;
+
+}
+
+int
+TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
+{
+#if MAX_RETRY > 1
+ int val;
+ int retry = 0;
+ if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
+
+ while((val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout))!=8 && retry++ < MAX_RETRY) {
+ printf("usb_interrupt_write failed, retrying: %d\n", val);
+ }
+
+ if (retry == MAX_RETRY) {
+ printf("Too many retries on a tranzport write, aborting\n");
+ }
+
+ if (val < 0) {
+ printf("usb_interrupt_write failed: %d\n", val);
+ return val;
+ }
+ if (val != 8) {
+ printf("usb_interrupt_write failed: %d\n", val);
+ return -1;
+ }
+ ++inflight;
+ return 0;
+#else
+ return (write_noretry(cmd,timeout_override));
+#endif
+
+}
+
+#endif
diff --git a/libs/surfaces/tranzport/lcd.cc b/libs/surfaces/tranzport/lcd.cc
new file mode 100644
index 0000000000..88f9ea36d6
--- /dev/null
+++ b/libs/surfaces/tranzport/lcd.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <tranzport_control_protocol.h>
+
+// doing these functions made me realize that screen_invalid should be lcd_isdamaged FIXME soon
+
+bool TranzportControlProtocol::lcd_damage()
+{
+ screen_invalidate();
+ return true;
+}
+
+bool TranzportControlProtocol::lcd_damage (int row, int col, int length)
+{
+ std::bitset<ROWS*COLUMNS> mask1(0);
+ // there's an intrinsic to do this fast, darn it, or I'm just sleepy
+ for (int i = 0; i < length; i++) { mask1[i] = 1; }
+ std::bitset<ROWS*COLUMNS> mask(mask1 << (row*COLUMNS+col));
+ screen_invalid |= mask;
+ return true;
+}
+
+// Still working on the layering, arguably screen_invalid should be lcd_invalid
+// or vice versa
+
+bool TranzportControlProtocol::lcd_isdamaged ()
+{
+ if(screen_invalid.any()) {
+#if DEBUG_TRANZPORT > 5
+ printf("LCD is damaged somewhere, should redraw it\n");
+#endif
+ return true;
+ }
+ return false;
+}
+
+bool TranzportControlProtocol::lcd_isdamaged (int row, int col, int length)
+{
+ // there's an intrinsic to do this fast, darn it
+ std::bitset<ROWS*COLUMNS> mask1(0);
+ for (int i = 0; i < length; i++) { mask1[i] = 1; }
+ std::bitset<ROWS*COLUMNS> mask(mask1 << (row*COLUMNS+col));
+ mask &= screen_invalid;
+ if(mask.any()) {
+#if DEBUG_TRANZPORT > 5
+ printf("row: %d,col: %d is damaged, should redraw it\n", row,col);
+#endif
+ return true;
+ }
+ return false;
+}
+
+// lcd_clear would be a separate function for a smart display
+// here it does nothing, but for the sake of completeness it should
+// probably write the lcd, and while I'm on the topic it should probably
+// take a row, col, length argument....
+
+void
+TranzportControlProtocol::lcd_clear ()
+{
+
+}
+
+// These lcd commands are not universally used yet and may drop out of the api
+
+int
+TranzportControlProtocol::lcd_flush ()
+{
+ return 0;
+}
+
+int
+TranzportControlProtocol::lcd_write(uint8_t* cmd, uint32_t timeout_override)
+{
+ int result;
+#if (DEBUG_TRANZPORT_SCREEN > 0)
+ printf("VALID : %s\n", (screen_invalid.to_string()).c_str());
+#endif
+ if ((result = write(cmd,timeout_override))) {
+#if DEBUG_TRANZPORT > 4
+ printf("usb screen update failed for some reason... why? \nresult, cmd and data were %d %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ result, cmd[0],cmd[1],cmd[2], cmd[3], cmd[4], cmd[5],cmd[6],cmd[7]);
+#endif
+ }
+ return result;
+}
+
+void
+TranzportControlProtocol::lcd_fill (uint8_t fill_char)
+{
+}
+
+void
+TranzportControlProtocol::lcd_print (int row, int col, const char* text)
+{
+ print(row,col,text);
+}
+
+void TranzportControlProtocol::lcd_print_noretry (int row, int col, const char* text)
+{
+ print(row,col,text);
+}
diff --git a/libs/surfaces/tranzport/lights.cc b/libs/surfaces/tranzport/lights.cc
new file mode 100644
index 0000000000..c0e8092f45
--- /dev/null
+++ b/libs/surfaces/tranzport/lights.cc
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <tranzport_control_protocol.h>
+
+// Lights are buffered, and arguably these functions should be eliminated or inlined
+
+void
+TranzportControlProtocol::lights_on ()
+{
+ lights_pending.set();
+}
+
+void
+TranzportControlProtocol::lights_off ()
+{
+ lights_pending.reset();
+}
+
+int
+TranzportControlProtocol::light_on (LightID light)
+{
+ lights_pending.set(light);
+ return 0;
+}
+
+int
+TranzportControlProtocol::light_off (LightID light)
+{
+ lights_pending.reset(light);
+ return 0;
+}
+
+void TranzportControlProtocol::lights_init()
+{
+ lights_invalid.set();
+ lights_flash = lights_pending = lights_current.reset();
+}
+
+
+// Now that all this is bitsets, I don't see much
+// need for these 4 to remain in the API
+
+void TranzportControlProtocol::light_validate (LightID light)
+{
+ lights_invalid.reset(light);
+}
+
+void TranzportControlProtocol::light_invalidate (LightID light)
+{
+ lights_invalid.set(light);
+}
+
+void TranzportControlProtocol::lights_validate ()
+{
+ lights_invalid.reset();
+}
+
+void TranzportControlProtocol::lights_invalidate ()
+{
+ lights_invalid.set();
+}
+
+int
+TranzportControlProtocol::light_set (LightID light, bool offon)
+{
+ uint8_t cmd[8];
+ cmd[0] = 0x00; cmd[1] = 0x00; cmd[2] = light; cmd[3] = offon;
+ cmd[4] = 0x00; cmd[5] = 0x00; cmd[6] = 0x00; cmd[7] = 0x00;
+
+ if (write (cmd) == 0) {
+ lights_current[light] = offon;
+ lights_invalid.reset(light);
+ return 0;
+ } else {
+ return 1;
+ }
+}
diff --git a/libs/surfaces/tranzport/meter.cc b/libs/surfaces/tranzport/meter.cc
new file mode 100644
index 0000000000..cc57846058
--- /dev/null
+++ b/libs/surfaces/tranzport/meter.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* Generic support for character based metering on a track */
diff --git a/libs/surfaces/tranzport/mode.cc b/libs/surfaces/tranzport/mode.cc
new file mode 100644
index 0000000000..03d715e66f
--- /dev/null
+++ b/libs/surfaces/tranzport/mode.cc
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <tranzport_control_protocol.h>
+
+void
+TranzportControlProtocol::normal_update ()
+{
+ show_current_track ();
+ show_transport_time ();
+ show_track_gain ();
+ show_wheel_mode ();
+}
+
+void
+TranzportControlProtocol::next_display_mode ()
+{
+ switch (display_mode) {
+
+ case DisplayNormal:
+ enter_big_meter_mode();
+ break;
+
+ case DisplayBigMeter:
+ enter_normal_display_mode();
+ break;
+
+ case DisplayRecording:
+ enter_normal_display_mode();
+ break;
+
+ case DisplayRecordingMeter:
+ enter_big_meter_mode();
+ break;
+
+ case DisplayConfig:
+ case DisplayBling:
+ case DisplayBlingMeter:
+ enter_normal_display_mode();
+ break;
+ }
+}
+
+// FIXME: There should be both enter and exits
+// EXIT would erase the portions of the screen being written
+// to.
+/* not sure going macro crazy is a good idea
+#define DECLARE_ENTER_MODE(mode,modename) void TranzportControlProtocol::enter_##mode##_mode() \{\screen_clear(); lights_off(); display_mode=Display##modename;\;
+*/
+void
+TranzportControlProtocol::enter_recording_mode ()
+{
+ screen_clear ();
+ lights_off ();
+ display_mode = DisplayRecording;
+}
+
+void
+TranzportControlProtocol::enter_bling_mode ()
+{
+ screen_clear ();
+ lights_off ();
+ display_mode = DisplayBling;
+}
+
+void
+TranzportControlProtocol::enter_config_mode ()
+{
+ lights_off ();
+ screen_clear ();
+ display_mode = DisplayConfig;
+}
+
+
+void
+TranzportControlProtocol::enter_big_meter_mode ()
+{
+ lights_off (); // it will clear the screen for you
+ last_meter_fill = 0;
+ display_mode = DisplayBigMeter;
+}
+
+void
+TranzportControlProtocol::enter_normal_display_mode ()
+{
+ lights_off ();
+ screen_clear ();
+ display_mode = DisplayNormal;
+}
+
diff --git a/libs/surfaces/tranzport/mode_loop.cc b/libs/surfaces/tranzport/mode_loop.cc
new file mode 100644
index 0000000000..b9ea9f239e
--- /dev/null
+++ b/libs/surfaces/tranzport/mode_loop.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* placeholder for Marker Mode: Edit Markers, Setup Loops, and Punch in points */
diff --git a/libs/surfaces/tranzport/mode_tuner.cc b/libs/surfaces/tranzport/mode_tuner.cc
new file mode 100644
index 0000000000..a686f81be1
--- /dev/null
+++ b/libs/surfaces/tranzport/mode_tuner.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* Placeholder for a tuner mode at some point */
diff --git a/libs/surfaces/tranzport/panner.cc b/libs/surfaces/tranzport/panner.cc
new file mode 100644
index 0000000000..4a177db9a7
--- /dev/null
+++ b/libs/surfaces/tranzport/panner.cc
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <tranzport_common.h>
+#include <tranzport_control_protocol.h>
+
+void
+TranzportControlProtocol::step_pan_right ()
+{
+}
+
+void
+TranzportControlProtocol::step_pan_left ()
+{
+}
+
+
diff --git a/libs/surfaces/tranzport/screen.cc b/libs/surfaces/tranzport/screen.cc
new file mode 100644
index 0000000000..51062de3ad
--- /dev/null
+++ b/libs/surfaces/tranzport/screen.cc
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <tranzport_control_protocol.h>
+
+void
+TranzportControlProtocol::screen_clear ()
+{
+ const char *blank = " ";
+ print(0,0,blank);
+ print(1,0,blank);
+}
+
+void TranzportControlProtocol::screen_invalidate ()
+{
+ screen_invalid.set();
+ for(int row = 0; row < ROWS; row++) {
+ for(int col = 0; col < COLUMNS; col++) {
+ screen_current[row][col] = 0x7f;
+ screen_pending[row][col] = ' ';
+ screen_flash[row][col] = ' ';
+ }
+ }
+}
+
+void TranzportControlProtocol::screen_validate ()
+{
+}
+
+void TranzportControlProtocol::screen_init ()
+{
+ screen_invalidate();
+}
+
+// FIXME: Switch to a column oriented flush to make the redraw of the
+// meters look better
+
+int
+TranzportControlProtocol::screen_flush ()
+{
+ int cell = 0, row=0, col_base, pending = 0;
+ const unsigned long CELL_BITS = 0x0F;
+ if ( _device_status == STATUS_OFFLINE) { return (-1); }
+
+ std::bitset<ROWS*COLUMNS> mask(CELL_BITS);
+ std::bitset<ROWS*COLUMNS> imask(CELL_BITS);
+ for(cell = 0; cell < 10 && pending == 0; cell++) {
+ mask = imask << (cell*4);
+ if((screen_invalid & mask).any()) {
+ /* something in this cell is different, so dump the cell to the device. */
+#if DEBUG_TRANZPORT_SCREEN
+ printf("MASK : %s\n", mask.to_string().c_str());
+#endif
+ if(cell > 4) { row = 1; } else { row = 0; }
+ col_base = (cell*4)%COLUMNS;
+
+ uint8_t cmd[8];
+ cmd[0] = 0x00;
+ cmd[1] = 0x01;
+ cmd[2] = cell;
+ cmd[3] = screen_pending[row][col_base];
+ cmd[4] = screen_pending[row][col_base+1];
+ cmd[5] = screen_pending[row][col_base+2];
+ cmd[6] = screen_pending[row][col_base+3];
+ cmd[7] = 0x00;
+
+ if((pending = lcd_write(cmd)) == 0) {
+ /* successful write: copy to current cached display */
+ screen_invalid &= mask.flip();
+ memcpy (&screen_current[row][col_base], &screen_pending[row][col_base], 4);
+ }
+ }
+ }
+ return pending;
+}
+
diff --git a/libs/surfaces/tranzport/show.cc b/libs/surfaces/tranzport/show.cc
new file mode 100644
index 0000000000..30c8fbffa9
--- /dev/null
+++ b/libs/surfaces/tranzport/show.cc
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <float.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include <pbd/pthread_utils.h>
+
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/session.h>
+#include <ardour/tempo.h>
+#include <ardour/location.h>
+#include <ardour/dB.h>
+
+#include <tranzport_control_protocol.h>
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace PBD;
+
+#include "i18n.h"
+
+#include <pbd/abstract_ui.cc>
+
+float
+log_meter (float db)
+{
+ float def = 0.0f; /* Meter deflection %age */
+
+ if (db < -70.0f) return 0.0f;
+ if (db > 6.0f) return 1.0f;
+
+ if (db < -60.0f) {
+ def = (db + 70.0f) * 0.25f;
+ } else if (db < -50.0f) {
+ def = (db + 60.0f) * 0.5f + 2.5f;
+ } else if (db < -40.0f) {
+ def = (db + 50.0f) * 0.75f + 7.5f;
+ } else if (db < -30.0f) {
+ def = (db + 40.0f) * 1.5f + 15.0f;
+ } else if (db < -20.0f) {
+ def = (db + 30.0f) * 2.0f + 30.0f;
+ } else if (db < 6.0f) {
+ def = (db + 20.0f) * 2.5f + 50.0f;
+ }
+
+ /* 115 is the deflection %age that would be
+ when db=6.0. this is an arbitrary
+ endpoint for our scaling.
+ */
+
+ return def/115.0f;
+}
+
+#define TRANZ_U 0x1 /* upper */
+#define TRANZ_BL 0x2 /* lower left */
+#define TRANZ_Q2 0x3 /* 2 quadrant block */
+#define TRANZ_ULB 0x4 /* Upper + lower left */
+#define TRANZ_L 0x5 /* lower */
+#define TRANZ_UBL 0x6 /* upper left + bottom all */
+#define TRANZ_Q4 0x7 /* 4 quadrant block */
+#define TRANZ_UL 0x08 /* upper left */
+
+// Shift Space - switches your "view"
+// Currently defined views are:
+// BigMeter
+//
+// Shift Record - SAVE SNAPSHOT
+// Somewhere I was rewriting this
+// Other meters
+// Inverted - show meters "inside out" For example 4 meters covering 2 cells each, and the
+//
+// each 4 character cell could be an 8 bar meter = 10 meters!
+// Dual Meter mode - master and current track
+// We have 16 rows of pixels so we COULD do a vertical meter
+// BEAT BLOCKS - For each beat, flash a 8 block (could use the center for vertical meters)
+// Could have something generic that could handle up to /20 time
+// Odd times could flash the whole top bar for the first beat
+
+
+// Vertical Meter _ .colon - + ucolon A P R I H FULLBLACK
+// MV@$%&*()-
+
+// 3 char block rotating beat `\'/
+// 1 char rotating beat {/\}
+// 4 char in block rotating beat {/\}
+// {\/)
+
+void TranzportControlProtocol::show_mini_meter()
+{
+ // FIXME - show the current marker in passing
+ const int meter_buf_size = 41;
+ static uint32_t last_meter_fill_l = 0;
+ static uint32_t last_meter_fill_r = 0;
+ uint32_t meter_size;
+
+ float speed = fabsf(session->transport_speed());
+ char buf[meter_buf_size];
+
+ if (speed == 1.0) {
+ meter_size = 32;
+ }
+
+ if (speed == 0.0) {
+ meter_size = 20; // not actually reached
+ }
+
+ if (speed > 0.0 && (speed < 1.0)) {
+ meter_size = 20; // may shrink more one day
+ }
+
+ if (speed > 1.0 && (speed < 2.0)) {
+ meter_size = 20;
+ }
+
+ if (speed >= 2.0) {
+ meter_size = 24;
+ }
+
+
+ // you only seem to get a route_table[0] == 0 on moving forward - bug in next_track?
+
+ if (route_table[0] == 0) {
+ // Principle of least surprise
+ print (1, 0, "NoAUDIO ");
+ return;
+ }
+
+ float level_l = route_get_peak_input_power (0, 0);
+ float fraction_l = log_meter (level_l);
+
+ // how to figure out if we are mono?
+
+ float level_r = route_get_peak_input_power (0, 1);
+ float fraction_r = log_meter (level_r);
+
+ uint32_t fill_left = (uint32_t) floor (fraction_l * ((int) meter_size));
+ uint32_t fill_right = (uint32_t) floor (fraction_r * ((int) meter_size));
+
+ if (fill_left == last_meter_fill_l && fill_right == last_meter_fill_r && !lcd_isdamaged(1,0,meter_size/2)) {
+ /* nothing to do */
+ return;
+ }
+
+ last_meter_fill_l = fill_left; last_meter_fill_r = fill_right;
+
+ // give some feedback when overdriving - override yellow and red lights
+
+ if (fraction_l > 0.96 || fraction_r > 0.96) {
+ light_on (LightLoop);
+ }
+
+ if (fraction_l == 1.0 || fraction_r == 1.0) {
+ light_on (LightTrackrec);
+ }
+
+ const uint8_t char_map[16] = { ' ', TRANZ_UL,
+ TRANZ_U, TRANZ_U,
+ TRANZ_BL, TRANZ_Q2,
+ TRANZ_Q2, TRANZ_ULB,
+ TRANZ_L, TRANZ_UBL,
+ ' ',' ',
+ TRANZ_L, TRANZ_UBL,
+ TRANZ_Q4,TRANZ_Q4
+ };
+ unsigned int val,j,i;
+
+ for(j = 1, i = 0; i < meter_size/2; i++, j+=2) {
+ val = (fill_left >= j) | ((fill_left >= j+1) << 1) |
+ ((fill_right >=j) << 2) | ((fill_right >= j+1) << 3);
+ buf[i] = char_map[val];
+ }
+
+ /* print() requires this */
+
+ buf[meter_size/2] = '\0';
+
+ print (1, 0, buf);
+
+ /* Add a peak bar, someday do falloff */
+
+ // char peak[2]; peak[0] = ' '; peak[1] = '\0';
+ // if(fraction_l == 1.0 || fraction_r == 1.0) peak[0] = 'P';
+ // print (1,8,peak); // Put a peak meter - P in if we peaked.
+
+}
+
+void
+TranzportControlProtocol::show_meter ()
+{
+ // you only seem to get a route_table[0] on moving forward - bug elsewhere
+ if (route_table[0] == 0) {
+ // Principle of least surprise
+ print (0, 0, "No audio to meter!!!");
+ print (1, 0, "Select another track");
+ return;
+ }
+
+ float level = route_get_peak_input_power (0, 0);
+ float fraction = log_meter (level);
+
+ /* Someday add a peak bar*/
+
+ /* we draw using a choice of a sort of double colon-like character ("::") or a single, left-aligned ":".
+ the screen is 20 chars wide, so we can display 40 different levels. compute the level,
+ then figure out how many "::" to fill. if the answer is odd, make the last one a ":"
+ */
+
+ uint32_t fill = (uint32_t) floor (fraction * 40);
+ char buf[21];
+ uint32_t i;
+
+ if (fill == last_meter_fill) {
+ /* nothing to do */
+ return;
+ }
+
+ last_meter_fill = fill;
+
+ bool add_single_level = (fill % 2 != 0);
+ fill /= 2;
+
+ if (fraction > 0.96) {
+ light_on (LightLoop);
+ }
+
+
+ if (fraction == 1.0) {
+ light_on (LightTrackrec);
+ }
+
+
+ /* add all full steps */
+
+ for (i = 0; i < fill; ++i) {
+ buf[i] = 0x07; /* tranzport special code for 4 quadrant LCD block */
+ }
+
+ /* add a possible half-step */
+
+ if (i < 20 && add_single_level) {
+ buf[i] = 0x03; /* tranzport special code for 2 left quadrant LCD block */
+ ++i;
+ }
+
+ /* fill rest with space */
+
+ for (; i < 20; ++i) {
+ buf[i] = ' ';
+ }
+
+ /* print() requires this */
+
+ buf[21] = '\0';
+
+ print (0, 0, buf);
+ print (1, 0, buf);
+}
+
+void
+TranzportControlProtocol::show_bbt (nframes_t where)
+{
+ if (where != last_where) {
+ char buf[16];
+ BBT_Time bbt;
+
+ // When recording or playing back < 1.0 speed do 1 or 2
+ // FIXME - clean up state machine & break up logic
+ // this has to co-operate with the mini-meter and
+ // this is NOT the right way.
+
+ session->tempo_map().bbt_time (where, bbt);
+ last_bars = bbt.bars;
+ last_beats = bbt.beats;
+ last_ticks = bbt.ticks;
+ last_where = where;
+
+ float speed = fabsf(session->transport_speed());
+
+ if (speed == 1.0) {
+ sprintf (buf, "%03" PRIu32 "%1" PRIu32, bbt.bars,bbt.beats); // switch to hex one day
+ print (1, 16, buf);
+ }
+
+ if (speed == 0.0) {
+ sprintf (buf, "%03" PRIu32 "|%1" PRIu32 "|%04" PRIu32, bbt.bars,bbt.beats,bbt.ticks);
+ print (1, 10, buf);
+ }
+
+ if (speed > 0.0 && (speed < 1.0)) {
+ sprintf (buf, "%03" PRIu32 "|%1" PRIu32 "|%04" PRIu32, bbt.bars,bbt.beats,bbt.ticks);
+ print (1, 10, buf);
+ }
+
+ if (speed > 1.0 && (speed < 2.0)) {
+ sprintf (buf, "%03" PRIu32 "|%1" PRIu32 "|%04" PRIu32, bbt.bars,bbt.beats,bbt.ticks);
+ print (1, 10, buf);
+ }
+
+ if (speed >= 2.0) {
+ sprintf (buf, "%03" PRIu32 "|%1" PRIu32 "|%02" PRIu32, bbt.bars,bbt.beats,bbt.ticks);
+ print (1, 12, buf);
+ }
+
+ TempoMap::Metric m (session->tempo_map().metric_at (where));
+
+ // the lights stop working well at above 100 bpm so don't bother
+ if(m.tempo().beats_per_minute() < 101.0 && (speed > 0.0)) {
+
+ // something else can reset these, so we need to
+
+ lights_pending[LightRecord] = false;
+ lights_pending[LightAnysolo] = false;
+ switch(last_beats) {
+ case 1: if(last_ticks < 250 || last_ticks >= 0) lights_pending[LightRecord] = true; break;
+ default: if(last_ticks < 250) lights_pending[LightAnysolo] = true;
+ }
+ }
+ }
+}
+
+void
+TranzportControlProtocol::show_transport_time ()
+{
+ nframes_t where = session->transport_frame();
+ show_bbt(where);
+}
+
+void
+TranzportControlProtocol::show_smpte (nframes_t where)
+{
+ if ((where != last_where) || lcd_isdamaged(1,9,10)) {
+
+ char buf[5];
+ SMPTE::Time smpte;
+
+ session->smpte_time (where, smpte);
+
+ if (smpte.negative) {
+ sprintf (buf, "-%02" PRIu32 ":", smpte.hours);
+ } else {
+ sprintf (buf, " %02" PRIu32 ":", smpte.hours);
+ }
+ print (1, 8, buf);
+
+ sprintf (buf, "%02" PRIu32 ":", smpte.minutes);
+ print (1, 12, buf);
+
+ sprintf (buf, "%02" PRIu32 ":", smpte.seconds);
+ print (1, 15, buf);
+
+ sprintf (buf, "%02" PRIu32, smpte.frames);
+ print_noretry (1, 18, buf);
+
+ last_where = where;
+ }
+}
+
+void
+TranzportControlProtocol::show_track_gain ()
+{
+// FIXME last_track gain has to become meter/track specific
+ if (route_table[0]) {
+ gain_t g = route_get_gain (0);
+ if ((g != last_track_gain) || lcd_isdamaged(0,12,8)) {
+ char buf[16];
+ snprintf (buf, sizeof (buf), "%6.1fdB", coefficient_to_dB (route_get_effective_gain (0)));
+ print (0, 12, buf);
+ last_track_gain = g;
+ }
+ } else {
+ print (0, 9, " ");
+ }
+}
diff --git a/libs/surfaces/tranzport/slider_gain.h b/libs/surfaces/tranzport/slider_gain.h
new file mode 100644
index 0000000000..1bb497178f
--- /dev/null
+++ b/libs/surfaces/tranzport/slider_gain.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#ifndef ardour_slider_gain
+#define ardour_slider_gain
+
+static inline double
+gain_to_slider_position (ARDOUR::gain_t g)
+{
+ if (g == 0) return 0;
+ return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0);
+
+}
+
+static inline ARDOUR::gain_t
+slider_position_to_gain (double pos)
+{
+ /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
+ if (pos == 0.0) return 0;
+ return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0);
+}
+
+#endif
diff --git a/libs/surfaces/tranzport/state.cc b/libs/surfaces/tranzport/state.cc
new file mode 100644
index 0000000000..1cb55b4fc3
--- /dev/null
+++ b/libs/surfaces/tranzport/state.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <float.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/session.h>
+#include <ardour/location.h>
+#include <ardour/dB.h>
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace PBD;
+
+#include "i18n.h"
+
+#include <pbd/abstract_ui.cc>
+
+#include "tranzport_control_protocol.h"
+
+
+// FIXME: How to handle multiple tranzports in a system?
+
+XMLNode&
+TranzportControlProtocol::get_state ()
+{
+ XMLNode* node = new XMLNode (X_("Protocol"));
+ node->add_property (X_("name"), _name);
+ return *node;
+}
+
+int
+TranzportControlProtocol::set_state (const XMLNode& node)
+{
+ cout << "TranzportControlProtocol::set_state: active " << _active << endl;
+ int retval = 0;
+
+// I think I want to make these strings rather than numbers
+#if 0
+ // fetch current display mode
+ if ( node.property( X_("display_mode") ) != 0 )
+ {
+ string display = node.property( X_("display_mode") )->value();
+ try
+ {
+ set_active( true );
+ int32_t new_display = atoi( display.c_str() );
+ if ( display_mode != new_display ) display_mode = (DisplayMode)new_display;
+ }
+ catch ( exception & e )
+ {
+ cout << "exception in TranzportControlProtocol::set_state: " << e.what() << endl;
+ return -1;
+ }
+ }
+
+ if ( node.property( X_("wheel_mode") ) != 0 )
+ {
+ string wheel = node.property( X_("wheel_mode") )->value();
+ try
+ {
+ int32_t new_wheel = atoi( wheel.c_str() );
+ if ( wheel_mode != new_wheel ) wheel_mode = (WheelMode) new_wheel;
+ }
+ catch ( exception & e )
+ {
+ cout << "exception in TranzportControlProtocol::set_state: " << e.what() << endl;
+ return -1;
+ }
+ }
+
+ // fetch current bling mode
+ if ( node.property( X_("bling") ) != 0 )
+ {
+ string bling = node.property( X_("bling_mode") )->value();
+ try
+ {
+ int32_t new_bling = atoi( bling.c_str() );
+ if ( bling_mode != new_bling ) bling_mode = (BlingMode) new_bling;
+ }
+ catch ( exception & e )
+ {
+ cout << "exception in TranzportControlProtocol::set_state: " << e.what() << endl;
+ return -1;
+ }
+ }
+#endif
+
+ return retval;
+
+}
+
+// These are intended for the day we have more options for tranzport modes
+// And perhaps we could load up sessions this way, too
+
+int
+TranzportControlProtocol::save (char *name)
+{
+ // Presently unimplemented
+ return 0;
+}
+
+int
+TranzportControlProtocol::load (char *name)
+{
+ // Presently unimplemented
+ return 0;
+}
+
+int
+TranzportControlProtocol::save_config (char *name)
+{
+ // Presently unimplemented
+ return 0;
+}
+
+int
+TranzportControlProtocol::load_config (char *name)
+{
+ // Presently unimplemented
+ return 0;
+}
diff --git a/libs/surfaces/tranzport/tranzport_base.h b/libs/surfaces/tranzport/tranzport_base.h
new file mode 100644
index 0000000000..510f24fdfe
--- /dev/null
+++ b/libs/surfaces/tranzport/tranzport_base.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* This header file is basically where all the tranzport debuggable options go.
+ Try to only check it in with minimal debugging enabled so production
+ systems don't have to fiddle with it. */
+
+/* Design notes: The tranzport is a unique device, basically a
+ 20x2 character lcd gui with (almost) 22 shift keys and 8 blinking lights.
+
+ As such it has several unique constraints. In the libusb driver,
+ the device exerts flow control
+ by having a usb write fail. It is pointless to retry madly at that point,
+ the device is busy, and it's not going to become unbusy very quickly.
+
+ So writes need to be either "mandatory" or "unreliable", and therein
+ lies the rub, as the kernel can also drop writes, and missing an
+ interrupt in userspace is also generally bad.
+
+ However, the kernel driver retries writes for you and also buffers and
+ compresses incoming wheel events - it will rarely, if ever, drop data.
+
+ A more complex surface might have hundreds of lights and several displays.
+
+ mike@taht.net
+*/
+
+#ifndef ardour_tranzport_base
+#define ardour_tranzport_base
+
+#define DEFAULT_USB_TIMEOUT 10
+#define MAX_RETRY 1
+#define MAX_TRANZPORT_INFLIGHT 4
+#define DEBUG_TRANZPORT 0
+#define TRANZPORT_THREADS 0
+
+#ifndef HAVE_TRANZPORT_KERNEL_DRIVER
+#define HAVE_TRANZPORT_KERNEL_DRIVER 0
+#endif
+
+#ifndef HAVE_TRANZPORT_MIDI_DRIVER
+#define HAVE_TRANZPORT_MIDI_DRIVER 0
+#endif
+
+// for now, this is what the device is called
+#define TRANZPORT_DEVICE "/dev/tranzport0"
+
+#if DEBUG_TRANZPORT > 0
+#define DEBUG_TRANZPORT_SCREEN 10
+#define DEBUG_TRANZPORT_BITS 10
+#define DEBUG_TRANZPORT_LIGHTS 10
+#define DEBUG_TRANZPORT_STATE 10
+#else
+#define DEBUG_TRANZPORT 0
+#define DEBUG_TRANZPORT_BITS 0
+#define DEBUG_TRANZPORT_SCREEN 0
+#define DEBUG_TRANZPORT_LIGHTS 0
+#define DEBUG_TRANZPORT_STATE 0
+#endif
+#endif /* ardour_tranzport_base */
+
diff --git a/libs/surfaces/tranzport/tranzport_common.h b/libs/surfaces/tranzport/tranzport_common.h
new file mode 100644
index 0000000000..06b07bd62a
--- /dev/null
+++ b/libs/surfaces/tranzport/tranzport_common.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* The most common header files that the tranzport uses */
+
+#ifndef ardour_tranzport_common
+#define ardour_tranzport_common
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <float.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include <pbd/pthread_utils.h>
+
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/session.h>
+#include <ardour/tempo.h>
+#include <ardour/location.h>
+#include <ardour/dB.h>
+
+#endif /* ardour_tranzport_common */
diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.h b/libs/surfaces/tranzport/tranzport_control_protocol.h
index f13e4a3a44..929cca3e2b 100644
--- a/libs/surfaces/tranzport/tranzport_control_protocol.h
+++ b/libs/surfaces/tranzport/tranzport_control_protocol.h
@@ -1,22 +1,46 @@
+/*
+ Copyright (C) 2006 Paul Davis
+ Copyright (C) 2007 Mike Taht
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
#ifndef ardour_tranzport_control_protocol_h
#define ardour_tranzport_control_protocol_h
-#include <vector>
+#include "tranzport_base.h"
+#include <vector>
+#include <bitset>
#include <sys/time.h>
#include <pthread.h>
+
+#if !HAVE_TRANZPORT_KERNEL_DRIVER
#include <usb.h>
+#endif
#include <glibmm/thread.h>
-
#include <ardour/types.h>
#include <control_protocol/control_protocol.h>
class TranzportControlProtocol : public ARDOUR::ControlProtocol
{
- public:
+public:
TranzportControlProtocol (ARDOUR::Session&);
virtual ~TranzportControlProtocol();
@@ -27,14 +51,19 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
XMLNode& get_state ();
int set_state (const XMLNode&);
- private:
+private:
static const int VENDORID = 0x165b;
static const int PRODUCTID = 0x8101;
static const int READ_ENDPOINT = 0x81;
static const int WRITE_ENDPOINT = 0x02;
const static int STATUS_OFFLINE = 0xff;
const static int STATUS_ONLINE = 0x01;
- const static uint8_t WheelDirectionThreshold = 0x3f;
+ const static int STATUS_OK = 0x00;
+
+ const static int LIGHTS = 7;
+ const static int ROWS = 2;
+ const static int COLUMNS = 20;
+ const static uint8_t WheelDirectionThreshold = 0x7f;
enum LightID {
LightRecord = 0,
@@ -67,7 +96,8 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
ButtonStop = 0x00010000,
ButtonPlay = 0x00100000,
ButtonRecord = 0x00000100,
- ButtonShift = 0x08000000
+ ButtonShift = 0x08000000,
+ ButtonFootswitch = 0x00001000
};
enum WheelShiftMode {
@@ -86,13 +116,13 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
// FIXME - look at gtk2_ardour for snap settings
enum WheelIncrement {
- WheelIncrSlave,
- WheelIncrScreen,
- WheelIncrSample,
- WheelIncrBeat,
- WheelIncrBar,
- WheelIncrSecond,
- WheelIncrMinute
+ WheelIncrSlave,
+ WheelIncrScreen,
+ WheelIncrSample,
+ WheelIncrBeat,
+ WheelIncrBar,
+ WheelIncrSecond,
+ WheelIncrMinute
};
enum DisplayMode {
@@ -111,37 +141,55 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
BlingRotating,
BlingPairs,
BlingRows,
- BlingFlashAll
+ BlingFlashAll,
+ BlingEnter,
+ BlingExit
};
pthread_t thread;
+#if HAVE_TRANZPORT_KERNEL_DRIVER
+ int udev;
+#else
+ usb_dev_handle* udev;
+#endif
+
+#if TRANZPORT_THREADS
+ pthread_t thread_read;
+#endif
+ int last_read_error;
+
uint32_t buttonmask;
uint32_t timeout;
uint32_t inflight;
+ uint32_t current_track_id;
+#if TRANZPORT_THREADS
+ pthread_t thread_write;
+#endif
+ int last_write_error;
uint8_t _datawheel;
uint8_t _device_status;
- uint32_t current_track_id;
WheelMode wheel_mode;
WheelShiftMode wheel_shift_mode;
DisplayMode display_mode;
BlingMode bling_mode;
WheelIncrement wheel_increment;
- usb_dev_handle* udev;
ARDOUR::gain_t gain_fraction;
Glib::Mutex update_lock;
- bool screen_invalid[2][20];
- char screen_current[2][20];
- char screen_pending[2][20];
- char screen_flash[2][20];
+ std::bitset<ROWS*COLUMNS> screen_invalid;
+ char screen_current[ROWS][COLUMNS];
+ char screen_pending[ROWS][COLUMNS];
+ char screen_flash[ROWS][COLUMNS];
- bool lights_invalid[7];
- bool lights_current[7];
- bool lights_pending[7];
- bool lights_flash[7];
+ std::bitset<LIGHTS> lights_invalid;
+ std::bitset<LIGHTS> lights_current;
+ std::bitset<LIGHTS> lights_pending;
+ std::bitset<LIGHTS> lights_flash;
+ int32_t last_notify;
+ char last_notify_msg[COLUMNS+1];
uint32_t last_bars;
uint32_t last_beats;
uint32_t last_ticks;
@@ -151,7 +199,7 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
uint32_t last_mins;
uint32_t last_secs;
uint32_t last_frames;
- nframes_t last_where;
+ nframes_t last_where;
ARDOUR::gain_t last_track_gain;
uint32_t last_meter_fill;
struct timeval last_wheel_motion;
@@ -164,16 +212,25 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
int write (uint8_t* cmd, uint32_t timeout_override = 0);
int write_noretry (uint8_t* cmd, uint32_t timeout_override = 0);
int close ();
- int save(char *name = "default");
- int load(char *name = "default");
- void print (int row, int col, const char* text);
+ int save_config(char *name = "default");
+ int load_config(char *name = "default");
+ int save(char *name);
+ int load(char *name);
+ void print (int row, int col, const char* text);
void print_noretry (int row, int col, const char* text);
+ void notify(const char *msg);
+#if HAVE_TRANZPORT_KERNEL_DRIVER
+ int rtpriority_set(int priority = 3); // we don't need serious rt privs anymore
+#else
int rtpriority_set(int priority = 52);
+#endif
int rtpriority_unset(int priority = 0);
+ // I hate changing the api to do either but until I have clean io class what can you do?
+#if !HAVE_TRANZPORT_KERNEL_DRIVER
int open_core (struct usb_device*);
-
+#endif
static void* _monitor_work (void* arg);
void* monitor_work ();
@@ -191,6 +248,7 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
int screen_flush();
void screen_clear();
// bool screen_isuptodate(); // think on this -
+ int screen_show_bling();
// Commands to write to the lcd
@@ -198,8 +256,8 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
bool lcd_damage();
bool lcd_isdamaged();
- bool lcd_damage(int row, int col = 0, int length = 20);
- bool lcd_isdamaged(int row, int col = 0, int length = 20);
+ bool lcd_damage(int row, int col = 0, int length = COLUMNS);
+ bool lcd_isdamaged(int row, int col = 0, int length = COLUMNS);
int lcd_flush();
int lcd_write(uint8_t* cmd, uint32_t timeout_override = 0); // pedantic alias for write
@@ -240,6 +298,9 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
void enter_recording_mode();
void enter_bling_mode();
+ void next_marker (); // basicui doesn't give me enough info
+ void prev_marker ();
+
void next_display_mode ();
void normal_update ();
@@ -252,6 +313,9 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
void show_gain ();
void show_pan ();
void show_meter ();
+ void show_mini_meter ();
+ void show_bling();
+ void show_notify();
void datawheel ();
void scrub ();
@@ -311,8 +375,10 @@ class TranzportControlProtocol : public ARDOUR::ControlProtocol
void button_event_play_release (bool shifted);
void button_event_record_press (bool shifted);
void button_event_record_release (bool shifted);
+ void button_event_footswitch_press(bool shifted);
+ void button_event_footswitch_release (bool shifted);
- // new api
+ // new api - still thinking about it
void button_event_mute (bool pressed, bool shifted);
};
diff --git a/libs/surfaces/tranzport/view_automation.cc b/libs/surfaces/tranzport/view_automation.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_automation.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_bigmeter.cc b/libs/surfaces/tranzport/view_bigmeter.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_bigmeter.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_bling.cc b/libs/surfaces/tranzport/view_bling.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_bling.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_bus.cc b/libs/surfaces/tranzport/view_bus.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_bus.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_config.cc b/libs/surfaces/tranzport/view_config.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_config.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_layer.cc b/libs/surfaces/tranzport/view_layer.cc
new file mode 100644
index 0000000000..8de9e3ad14
--- /dev/null
+++ b/libs/surfaces/tranzport/view_layer.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+/* ultimately this view will let you: rotate layers (takes) on the currently selected track/region, do cross fades, and the like */
diff --git a/libs/surfaces/tranzport/view_loop.cc b/libs/surfaces/tranzport/view_loop.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_loop.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_manymeter.cc b/libs/surfaces/tranzport/view_manymeter.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_manymeter.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_marker.cc b/libs/surfaces/tranzport/view_marker.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_marker.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_master.cc b/libs/surfaces/tranzport/view_master.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_master.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_plugins.cc b/libs/surfaces/tranzport/view_plugins.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_plugins.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_std.cc b/libs/surfaces/tranzport/view_std.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_std.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_tempo.cc b/libs/surfaces/tranzport/view_tempo.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_tempo.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/view_tuner.cc b/libs/surfaces/tranzport/view_tuner.cc
new file mode 100644
index 0000000000..4c0b18acf0
--- /dev/null
+++ b/libs/surfaces/tranzport/view_tuner.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+
diff --git a/libs/surfaces/tranzport/wheel.cc b/libs/surfaces/tranzport/wheel.cc
new file mode 100644
index 0000000000..bc9683e6d7
--- /dev/null
+++ b/libs/surfaces/tranzport/wheel.cc
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <float.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/session.h>
+#include <ardour/location.h>
+#include <ardour/dB.h>
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace PBD;
+
+#include "i18n.h"
+
+#include <pbd/abstract_ui.cc>
+
+BaseUI::RequestType LEDChange = BaseUI::new_request_type ();
+BaseUI::RequestType Print = BaseUI::new_request_type ();
+BaseUI::RequestType SetCurrentTrack = BaseUI::new_request_type ();
+
+
+#include <tranzport_control_protocol.h>
+
+void
+TranzportControlProtocol::datawheel ()
+{
+ if ((buttonmask & ButtonTrackRight) || (buttonmask & ButtonTrackLeft)) {
+
+ /* track scrolling */
+
+ if (_datawheel < WheelDirectionThreshold) {
+ next_track ();
+ } else {
+ prev_track ();
+ }
+
+ timerclear (&last_wheel_motion);
+
+ } else if ((buttonmask & ButtonPrev) || (buttonmask & ButtonNext)) {
+
+ if (_datawheel < WheelDirectionThreshold) {
+ next_marker ();
+ } else {
+ prev_marker ();
+ }
+
+ timerclear (&last_wheel_motion);
+
+ } else if (buttonmask & ButtonShift) {
+
+ /* parameter control */
+
+ if (route_table[0]) {
+ switch (wheel_shift_mode) {
+ case WheelShiftGain:
+ if (_datawheel < WheelDirectionThreshold) {
+ step_gain_up ();
+ } else {
+ step_gain_down ();
+ }
+ break;
+ case WheelShiftPan:
+ if (_datawheel < WheelDirectionThreshold) {
+ step_pan_right ();
+ } else {
+ step_pan_left ();
+ }
+ break;
+
+ case WheelShiftMarker:
+ break;
+
+ case WheelShiftMaster:
+ break;
+
+ }
+ }
+
+ timerclear (&last_wheel_motion);
+
+ } else {
+
+ switch (wheel_mode) {
+ case WheelTimeline:
+ scroll ();
+ break;
+
+ case WheelScrub:
+ scrub ();
+ break;
+
+ case WheelShuttle:
+ shuttle ();
+ break;
+ }
+ }
+}
+
+void
+TranzportControlProtocol::scroll ()
+{
+ float m = 1.0;
+ if (_datawheel < WheelDirectionThreshold) {
+ m = 1.0;
+ } else {
+ m = -1.0;
+ }
+ switch(wheel_increment) {
+ case WheelIncrScreen: ScrollTimeline (0.2*m); break;
+ case WheelIncrSlave:
+ case WheelIncrSample:
+ case WheelIncrBeat:
+ case WheelIncrBar:
+ case WheelIncrSecond:
+ case WheelIncrMinute:
+ default: break; // other modes unimplemented as yet
+ }
+}
+
+void
+TranzportControlProtocol::scrub ()
+{
+ float speed;
+ struct timeval now;
+ struct timeval delta;
+ int dir;
+
+ gettimeofday (&now, 0);
+
+ if (_datawheel < WheelDirectionThreshold) {
+ dir = 1;
+ } else {
+ dir = -1;
+ }
+
+ if (dir != last_wheel_dir) {
+ /* changed direction, start over */
+ speed = 0.1f;
+ } else {
+ if (timerisset (&last_wheel_motion)) {
+
+ timersub (&now, &last_wheel_motion, &delta);
+
+ /* 10 clicks per second => speed == 1.0 */
+
+ speed = 100000.0f / (delta.tv_sec * 1000000 + delta.tv_usec);
+
+ } else {
+
+ /* start at half-speed and see where we go from there */
+
+ speed = 0.5f;
+ }
+ }
+
+ last_wheel_motion = now;
+ last_wheel_dir = dir;
+
+ set_transport_speed (speed * dir);
+}
+
+void
+TranzportControlProtocol::shuttle ()
+{
+ if (_datawheel < WheelDirectionThreshold) {
+ if (session->transport_speed() < 0) {
+ session->request_transport_speed (1.0);
+ } else {
+ session->request_transport_speed (session->transport_speed() + 0.1);
+ }
+ } else {
+ if (session->transport_speed() > 0) {
+ session->request_transport_speed (-1.0);
+ } else {
+ session->request_transport_speed (session->transport_speed() - 0.1);
+ }
+ }
+}
diff --git a/libs/surfaces/tranzport/wheel_modes.cc b/libs/surfaces/tranzport/wheel_modes.cc
new file mode 100644
index 0000000000..06b3ae03b3
--- /dev/null
+++ b/libs/surfaces/tranzport/wheel_modes.cc
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2006 Paul Davis
+ * Copyright (C) 2007 Michael Taht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+#include <cmath>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <float.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#if HAVE_TRANZPORT_KERNEL_DRIVER
+#include <fcntl.h>
+#include <poll.h>
+#endif
+
+#include <pbd/pthread_utils.h>
+
+#include <ardour/route.h>
+#include <ardour/audio_track.h>
+#include <ardour/session.h>
+#include <ardour/tempo.h>
+#include <ardour/location.h>
+#include <ardour/dB.h>
+
+#include <tranzport_control_protocol.h>
+
+using namespace ARDOUR;
+using namespace std;
+using namespace sigc;
+using namespace PBD;
+
+#include "i18n.h"
+
+#include <pbd/abstract_ui.cc>
+
+void
+TranzportControlProtocol::next_wheel_shift_mode ()
+{
+switch (wheel_shift_mode) {
+ case WheelShiftGain:
+ wheel_shift_mode = WheelShiftPan;
+ break;
+ case WheelShiftPan:
+ wheel_shift_mode = WheelShiftMaster;
+ break;
+ case WheelShiftMaster:
+ wheel_shift_mode = WheelShiftGain;
+ break;
+ case WheelShiftMarker: // Not done yet, disabled
+ wheel_shift_mode = WheelShiftGain;
+ break;
+ }
+
+ show_wheel_mode ();
+}
+
+void
+TranzportControlProtocol::next_wheel_mode ()
+{
+ switch (wheel_mode) {
+ case WheelTimeline:
+ wheel_mode = WheelScrub;
+ break;
+ case WheelScrub:
+ wheel_mode = WheelShuttle;
+ break;
+ case WheelShuttle:
+ wheel_mode = WheelTimeline;
+ }
+
+ show_wheel_mode ();
+}
+
+void
+TranzportControlProtocol::show_wheel_mode ()
+{
+ string text;
+
+ // if(session->transport_speed() != 0) {
+ // if session-transport_speed() < 1.0) show_big_bar/beat
+ // if ? greater. dont
+
+ if(session->transport_speed() != 0) {
+ show_mini_meter();
+ } else {
+
+ switch (wheel_mode) {
+ case WheelTimeline:
+ text = "Time";
+ break;
+ case WheelScrub:
+ text = "Scrb";
+ break;
+ case WheelShuttle:
+ text = "Shtl";
+ break;
+ }
+
+ switch (wheel_shift_mode) {
+ case WheelShiftGain:
+ text += ":Gain";
+ break;
+
+ case WheelShiftPan:
+ text += ":Pan ";
+ break;
+
+ case WheelShiftMaster:
+ text += ":Mstr";
+ break;
+
+ case WheelShiftMarker:
+ text += ":Mrkr";
+ break;
+ }
+
+ print (1, 0, text.c_str());
+ }
+}
diff --git a/manual/Makefile b/manual/Makefile
new file mode 100644
index 0000000000..76965262c2
--- /dev/null
+++ b/manual/Makefile
@@ -0,0 +1,68 @@
+
+DOCNAME = ardour_manual
+
+# Default values, only set if not set in book Makefile
+OUTDIR ?= tmp
+XMLFILE ?= xml/$(DOCNAME).xml
+XSLFILE ?= xsl/html.xsl
+CSSFILE ?= $(DOCNAME).css
+XSLTPROC ?= xsltproc
+#PWD = $(shell pwd)
+
+help::
+ @echo " The Following is a list of supported build targets:"
+ @echo
+ @echo " html:"
+ @echo " Build HTML version of ardour manual."
+ @echo
+ @echo " test:"
+ @echo " Validate DocBook XML source."
+ @echo
+ @echo " format:"
+ @echo " Format DocBook XML source using xmlformat."
+ @echo
+ @echo " clean:"
+ @echo " Remove temporary files."
+ @echo
+
+# xsltproc -output option gives I/O errors because??, so
+# just move the html to the output directory
+html:: clean
+ # creating output directory
+ -@mkdir $(OUTDIR)
+ # generating html
+ LANG=en_US.UTF-8 $(XSLTPROC) -xinclude $(XSLFILE) $(XMLFILE)
+ # copy html files to output directory
+ -@mv *.html $(OUTDIR)
+ # copy css file to output directory
+ -@cp css/$(CSSFILE) $(OUTDIR)/$(CSSFILE)
+ # copy the image files to the output directory
+ -@cp -r images $(OUTDIR)/images
+
+.PHONY : html
+
+test::
+ # validating book
+ xmllint --noout --postvalid --xinclude $(XMLFILE)
+
+.PHONY : test
+
+format:: test
+ @for file in `find xml/*.xml`; \
+ do xmlformat/xmlformat.pl --in-place --backup .bak \
+ --config-file xmlformat/xmlformat-ardour.conf $$file; \
+ done
+
+.PHONY : format
+
+clean::
+ @rm -rf $(OUTDIR)
+
+.PHONY : clean
+
+upload: html
+ cd tmp && tar cf - . | bzip2 > ../man.tar.bz2
+ scp man.tar.bz2 las@ardour.org:ardour.org
+
+.PHONY : upload
+
diff --git a/manual/catalog.xml b/manual/catalog.xml
new file mode 100644
index 0000000000..b605a109d2
--- /dev/null
+++ b/manual/catalog.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<!DOCTYPE catalog
+ PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
+ "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+ <rewriteSystem
+ systemIdStartString="/usr/share/sgml/docbook/"
+ rewritePrefix="/path/to/docbook/" />
+</catalog>
+
+<!--
+see http://www.sagehill.net/docbookxsl/Catalogs.html
+
+usage with xsltproc:
+XML_CATALOG_FILES="catalog.xml" make html
+-->
+
diff --git a/manual/config/dbhelper.vim b/manual/config/dbhelper.vim
new file mode 100644
index 0000000000..08f3581a1c
--- /dev/null
+++ b/manual/config/dbhelper.vim
@@ -0,0 +1,123 @@
+" Tim Mayberry's .vimrc mappings for use with DocBook 4.3. This has been
+" revised from Vivek Venugopalan's .vimrc which was revised from Dan York's .vimrc
+" Revised: August 23, 2006
+" Used with vim 7.0
+" email : mojofunk@gmail.com
+
+" MAPPINGS
+" Like the .vimrc file shown at http://www.vim.org/ I decided to
+" start all my mappings with a comma. Since I do pretty much all
+" my work in DocBook, I just started with the letter after the
+" comma for a DB tag, rather than using something like 'd' to
+" indicate it was a DB tag (i.e. ',dp' instead of ',p'). If you
+" want to use other mappings, you may want to change this.
+" My mappings are currently primarily for easy of entering DB
+" tags. I haven't yet gotten into changing existing text with mappings.
+
+" A side effect of using the comma for mappings is that when you type
+" a comma in vim, it will now pause and wait for input. If you just hit
+" the spacebar, you should see a regular old comma appear.
+
+" Note: 'imap' = a mapping for 'insert' mode of vim
+" All of these commands work ONLY when you are in Insert mode
+
+" <CR> will put a line return in the file. This is purely my style of
+" entering certain DocBook tags. You may wish to remove some.
+
+" After typing the DocBook tag, many of these macros then switch to
+" vim command mode, reposition the cursor to where I want it to be,
+" and then re-inter insert mode. You may wish to change where it ends.
+
+let mapleader = ","
+
+" header and setup info for a book
+imap<leader>dtbk <!DOCTYPE BOOK PUBLIC "-//OASIS//DTD DocBook V4.2//EN">
+imap<leader>bk <book><CR><bookinfo><CR><title></title><CR><author><CR><firstname></firstname><CR><surname></surname><CR></author><CR><address><email></email></address><CR><copyright><CR><year></year><CR><holder></holder><CR></copyright><CR><revhistory><CR></revhistory><CR></bookinfo><CR><CR></book><esc>12k$bba
+"Internal subset declaration
+imap<leader>et <!ENTITY TODO-key "TODO-value"><CR>
+imap<leader>rev <revision><CR><revnumber></revnumber><CR><date></date><CR><authorinitials></authorinitials><CR><revremark></revremark><CR></revision><esc>4k$bba
+
+"header and setup info for an article.
+imap<leader>dtart <!DOCTYPE ARTICLE PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
+imap<leader>art <article><CR><title></title><CR><CR><artheader><CR><CR><author><CR><firstname></firstname><CR><surname></surname><CR><affiliation><CR><address><email></email></address></affiliation><CR></author><CR><CR><revhistory><CR></revhistory><CR><CR></artheader><CR><abstract><CR><indexterm><CR><primary></primary><CR></indexterm><CR><para><CR><para><CR></abstract><CR><CR></article><esc>16k$bba
+
+"Paragraph formatting
+imap<leader>p <para><CR></para><esc>k$a
+
+" character formatting
+imap<leader>em <emphasis></emphasis><esc>bba
+imap<leader>es <emphasis role="strong"></emphasis><esc>bbla
+
+"Special characters
+imap<leader>> &gt;
+imap<leader>< &lt;
+
+" links
+imap<leader>ul <ulink url=""></ulink><esc>bb3la
+imap<leader>lk <link linkend=""></link><esc>bb3la
+imap<leader>x <xref linkend=""/><esc>bla
+
+" lists
+" note that '<leader>l2' was created solely to fit into<leader>il and<leader>ol
+imap<leader>li <listitem><CR><para><CR></para><CR></listitem><esc>kk$a
+imap<leader>l2 <listitem><CR><para><CR></para><CR></listitem>
+imap<leader>il <itemizedlist><CR><leader>l2<CR></itemizedlist><esc>kkk$a
+imap<leader>ol <orderedlist><CR><leader>l2<CR></orderedlist><esc>kkk$a
+imap<leader>ve <varlistentry><CR><term></term><CR><leader>l2<CR></varlistentry>
+imap<leader>vl <variablelist><CR><title></title><CR><leader>ve<CR></variablelist>
+
+" sections
+imap<leader>sn <section id=""><CR><title></title><CR><para><CR></para><CR></section><esc>kkkk$bla
+"imap<leader>s1 <sect1 id=""><CR><title></title><CR><para><CR></para><CR></sect1><esc>kkkk$bla
+"imap<leader>s2 <sect2 id=""><CR><title></title><CR><para><CR></para><CR></sect2><esc>kkkk$bla
+"imap<leader>s3 <sect3 id=""><CR><title></title><CR><para><CR></para><CR></sect3><esc>kkkk$bla
+imap<leader>ch <chapter id=""><CR><title></title><CR><para><CR></para><CR></chapter><esc>kkkk$bla
+
+" media related
+imap<leader>fig <figure><CR><title></title><CR></figure><esc>k$bba
+imap<leader>img <mediaobject><CR><imageobject><CR><imagedata fileref=""/><CR></imageobject><CR></mediaobject><esc>kk$bla
+imap<leader>oi <objectinfo><CR></objectinfo><esc>k$a
+
+" other objects
+imap<leader>ti <title></title><esc>bba
+imap<leader>fo <footnote><CR><para><CR></para><CR></footnote><esc>kk$a
+imap<leader>sb <sidebar><CR><title></title><CR><para></para><CR></sidebar>
+imap<leader>co <!-- --><esc>bhi
+imap<leader>qt <blockquote><CR><attribution></attribution><CR><literallayout><CR></literallayout><CR></blockquote>
+imap<leader>ge <glossentry id=""><CR><glossterm></glossterm><CR><glossdef><CR><para><CR></para><CR></glossdef><CR></glossentry><esc>6k$bla
+imap<leader>gt <glossterm linkend=""></glossterm><esc>bb3la
+imap<leader>gs <glossseealso></glossseealso><esc>bba
+imap<leader>l <literal></literal><esc>bba
+
+" admonitions
+imap<leader>no <note><CR><para></para><CR></note><esc>k$bba
+imap<leader>tp <tip><CR><para></para><CR></tip><esc>k$bba
+imap<leader>imp <important><CR><para></para><CR></important><esc>k$bba
+"imap<leader>ca <caution><CR><para></para><CR></caution><esc>k$bba
+imap<leader>w <warning><CR><para></para><CR></warning><esc>k$bba
+
+" computer stuff
+imap<leader>app <application></application><esc>bba
+imap<leader>cm <command></command><esc>bba
+imap<leader>sc <screen><CR></screen><esc>k$a
+imap<leader>fn <filename></filename><esc>bba
+imap<leader>gb <guibutton></guibutton><esc>bba
+imap<leader>gl <guilabel></guilabel><esc>bba
+imap<leader>gm <guimenuitem></guimenuitem><esc>bba
+imap<leader>mb <mousebutton></mousebutton><esc>bba
+imap<leader>mc <menuchoice><guimenu></guimenu><guisubmenu></guisubmenu></menuchoice><esc>8ba
+imap<leader>kc <keycombo><keycap></keycap><keycap></keycap></keycombo><esc>8ba
+imap<leader>kk <keycap></keycap><esc>bba
+
+imap<leader>row <row><CR><entry><CR></entry><CR></row><esc>kk$a
+imap<leader>en <entry><CR></entry><esc>k$a
+
+" examples
+imap<leader>ex <example id=""><CR><title></title><CR></example><ESC>$kkba
+
+"For preparing FAQs
+imap<leader>faq <article class=faq><CR><title>Frequently asked questions</title><CR><CR><articleinfo><CR><CR><author><CR><firstname></firstname><CR><surname></surname><CR><affiliation><CR><address><email></email></address></affiliation><CR></author><CR><CR><revhistory><CR></revhistory><CR><CR></articleinfo><CR><abstract><CR><indexterm><CR><primary></primary><CR></indexterm><CR><para><CR><para><CR></abstract><CR><CR><qandaset><CR><qandadiv><CR><title></title><CR><qandaentry><CR><question><CR><para></para><CR></question><CR><answer><CR><para></para><CR></answer><CR></qandaentry><CR><qandadiv><CR><qandaset><CR><CR></article><esc>16k$bba
+
+imap<leader>qd <qandaset><CR><qandadiv><CR><title></title><CR><qandaentry><CR><question><CR><para></para><CR></question><CR><answer><CR><para></para><CR></answer><CR></qandaentry><CR><qandadiv><esc>9k$bba
+
+imap<leader>qa <qandaentry><CR><question><CR><para></para><CR></question><CR><answer><CR><para></para><CR></answer><CR></qandaentry><esc>5k$bba
diff --git a/manual/css/ardour_manual.css b/manual/css/ardour_manual.css
new file mode 100644
index 0000000000..95da19334c
--- /dev/null
+++ b/manual/css/ardour_manual.css
@@ -0,0 +1,208 @@
+
+body {
+ background-color: white;
+ margin:0 auto;
+ font-family: "Bitstream Vera Sans","Lucida Grande", "Luxi Sans", verdana, "Trebuchet MS", helvetica,verdana,arial,sans-serif;
+ font-size:9pt;
+ max-width:55em;
+ padding:2em;
+ color:#333;
+ line-height:150%;
+}
+
+/* Links */
+
+/* these colors need work */
+
+a:link {
+ color:#7f83a4;
+}
+
+/* This is too light */
+a:visited {
+ color:#adabc8;
+}
+
+div.longdesc-link {
+ color:#999;
+ float:right;
+}
+
+/* Lists */
+
+dt {
+ font-weight:bold;
+}
+
+dd {
+ margin:0em;
+ margin-left:2em;
+ padding-top:0em;
+}
+
+/* Images */
+
+img {
+ display:block;
+ margin: 1.5em;
+}
+
+
+.screen {
+ background-color:#d5d1b9;
+ color:#333;
+}
+
+pre,code {
+ padding:.3em 1em;
+ font-size:0.9em;
+ font-family:"Bitstream vera mono",monospace;
+}
+
+pre {
+ display:block;
+ overflow:auto;
+}
+
+code {
+ white-space:nowrap;
+ background-color:#bbb;
+ color:#222;
+}
+
+.command,
+.filename,
+.literal,
+.option {
+ font-weight:bold;
+}
+
+/* Admonitions */
+div.note,
+div.tip,
+div.important,
+div.caution,
+div.warning {
+ background: #27272b url(images/admon-bg.png) top left repeat;
+ color:white;
+ padding:1.0em;
+ margin-bottom:1.5em;
+}
+
+div.note h2, div.note p,
+div.tip h2,div.tip p,
+div.caution h2,div.caution p,
+div.warning h2,div.warning p,
+div.important h2,div.important p {
+ padding:0em;
+ margin:0em;
+ padding-left:46px;
+}
+
+div.note .title,
+div.tip .title,
+div.important .title,
+div.caution .title,
+div.warning .title {
+ background-color:transparent;
+ background-position:top left;
+ background-repeat:no-repeat;
+ height:42px;
+ font-size:1.3em;
+ color: white;
+}
+
+div.note h2 {
+ background-image:url(images/tango-icons/note.png)
+}
+
+div.tip h2 {
+ background-image:url(images/tango-icons/tip.png)
+}
+
+div.caution h2 {
+ background-image:url(images/tango-icons/caution.png)
+}
+
+div.warning h2 {
+ background-image:url(images/tango-icons/warning.png)
+}
+
+div.important h2 {
+ background-image:url(images/tango-icons/important.png)
+}
+
+/* Tables */
+
+table {
+ width:100%;
+ border-right:1px solid #aaa;
+ border-collapse:collapse;
+ border-top:1px solid #aaa;
+ border-left:1px solid #aaa;
+ border-bottom:1px solid #aaa;
+}
+
+table th {
+ padding:.2em .5em;
+}
+
+table td {
+ padding:.10em .5em;
+}
+
+table,td,th {
+ border-color:#777 !important;
+}
+
+/* Headings */
+
+
+h1,h2,h3,h4,h5,h6 {
+ /* this color is too purpley */
+ color:#565690;
+ line-height:130%;
+ margin-top:0em;
+ font-family:"Luxi Sans","Bitstream Vera Sans","Lucida Grande","Trebuchet MS",helvetica,verdana,arial,sans-serif;
+ background-color:transparent;
+ }
+
+h1 {
+ background: #555555 url(images/title-bg.png) top left repeat;
+ line-height:1.6em;
+ color:#eff3f0;
+ font-size:2em;
+ padding:1.5em;
+}
+
+h2 {
+ font-size:1.6em;
+}
+
+h3 {
+ font-size:1.1em;
+ padding-top:1em;
+}
+
+h5.formalpara {
+ font-size:1em;
+ margin-top:2em;
+}
+
+/* Status */
+
+.ardour-draft {
+ background: white url(./images/watermark-draft.png) top left repeat;
+}
+
+/* remove table border from navigation...ugh */
+
+.navheader table, .navheader table td {
+ border:0px none;
+ border-collapse:collapse;
+}
+
+.navfooter table, .navfooter table td {
+ border:0px none;
+ border-collapse:collapse;
+}
diff --git a/manual/images/add_track_bus.png b/manual/images/add_track_bus.png
new file mode 100644
index 0000000000..8dfab00a81
--- /dev/null
+++ b/manual/images/add_track_bus.png
Binary files differ
diff --git a/manual/images/admon-bg.png b/manual/images/admon-bg.png
new file mode 100644
index 0000000000..37406fab53
--- /dev/null
+++ b/manual/images/admon-bg.png
Binary files differ
diff --git a/manual/images/con1.jpg b/manual/images/con1.jpg
new file mode 100644
index 0000000000..8b3d0a7541
--- /dev/null
+++ b/manual/images/con1.jpg
Binary files differ
diff --git a/manual/images/con2.jpg b/manual/images/con2.jpg
new file mode 100644
index 0000000000..03cd368f46
--- /dev/null
+++ b/manual/images/con2.jpg
Binary files differ
diff --git a/manual/images/internalhigheroverlap.png b/manual/images/internalhigheroverlap.png
new file mode 100644
index 0000000000..50ad2b17bc
--- /dev/null
+++ b/manual/images/internalhigheroverlap.png
Binary files differ
diff --git a/manual/images/internalloweroverlap.png b/manual/images/internalloweroverlap.png
new file mode 100644
index 0000000000..32c16b514f
--- /dev/null
+++ b/manual/images/internalloweroverlap.png
Binary files differ
diff --git a/manual/images/ladspa.jpg b/manual/images/ladspa.jpg
new file mode 100644
index 0000000000..680b18c497
--- /dev/null
+++ b/manual/images/ladspa.jpg
Binary files differ
diff --git a/manual/images/manual_style.svg b/manual/images/manual_style.svg
new file mode 100644
index 0000000000..86f03add79
--- /dev/null
+++ b/manual/images/manual_style.svg
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docbase="/home/timbyr/devel/ardour/svn/trunk/manual"
+ sodipodi:docname="ardour-brand.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.50389632"
+ inkscape:cx="561.43067"
+ inkscape:cy="641.45043"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="898"
+ inkscape:window-height="619"
+ inkscape:window-x="113"
+ inkscape:window-y="25" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <text
+ xml:space="preserve"
+ style="font-size:78.99777222px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="128.04803"
+ y="108.97908"
+ id="text1872"><tspan
+ sodipodi:role="line"
+ x="128.04803"
+ y="108.97908"
+ id="tspan2797">Ardour Style</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:53.98735046px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="207.30774"
+ y="638.5484"
+ id="text1876"><tspan
+ sodipodi:role="line"
+ x="207.30774"
+ y="638.5484"
+ id="tspan1884">Color Palette</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:62.71745682px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="280.23593"
+ y="235.28851"
+ id="text5438"><tspan
+ sodipodi:role="line"
+ id="tspan5440"
+ x="280.23593"
+ y="235.28851">Fonts?</tspan></text>
+ <rect
+ style="opacity:1;fill:black;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect6347"
+ width="304.3186"
+ height="134.66357"
+ x="60"
+ y="677.36218" />
+ <rect
+ style="opacity:1;fill:#adabc8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2772"
+ width="50.002544"
+ height="51.012703"
+ x="269.99744"
+ y="721.30762" />
+ <rect
+ y="721.3111"
+ x="206.13791"
+ height="51.005806"
+ width="50.953224"
+ id="rect2770"
+ style="opacity:1;fill:#7f83a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ y="721.30762"
+ x="143.22905"
+ height="51.012703"
+ width="50.002544"
+ id="rect2774"
+ style="opacity:1;fill:#565690;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ style="opacity:1;fill:#f3f3d2;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect5460"
+ width="49.692257"
+ height="51.275845"
+ x="79.999985"
+ y="721.17609" />
+ <rect
+ style="opacity:1;fill:#d5d1b9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2768"
+ width="325"
+ height="135"
+ x="365"
+ y="677.36218" />
+ <rect
+ style="opacity:1;fill:#555;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect7236"
+ width="75.380852"
+ height="71.096375"
+ x="380"
+ y="711.26581" />
+ <rect
+ style="opacity:1;fill:#7f83a4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect1888"
+ width="50.953224"
+ height="51.005806"
+ x="549.52209"
+ y="721.3111" />
+ <rect
+ y="721.30762"
+ x="609.99744"
+ height="51.012703"
+ width="50.002544"
+ id="rect4551"
+ style="opacity:1;fill:#adabc8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ style="opacity:1;fill:#565690;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7.0999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3662"
+ width="50.002544"
+ height="51.012703"
+ x="489.99747"
+ y="721.30762" />
+ <text
+ xml:space="preserve"
+ style="font-size:77.09712982px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="501.05905"
+ y="710.0827"
+ id="text2776"
+ transform="scale(1.105424,0.90463)"><tspan
+ sodipodi:role="line"
+ id="tspan2778"
+ x="501.05905"
+ y="710.0827">?</tspan></text>
+ </g>
+</svg>
diff --git a/manual/images/matrixmixer.png b/manual/images/matrixmixer.png
new file mode 100644
index 0000000000..2d63efe426
--- /dev/null
+++ b/manual/images/matrixmixer.png
Binary files differ
diff --git a/manual/images/midiopts.jpg b/manual/images/midiopts.jpg
new file mode 100644
index 0000000000..08e49c7a1e
--- /dev/null
+++ b/manual/images/midiopts.jpg
Binary files differ
diff --git a/manual/images/mixer.png b/manual/images/mixer.png
new file mode 100644
index 0000000000..ace8901125
--- /dev/null
+++ b/manual/images/mixer.png
Binary files differ
diff --git a/manual/images/mixer_strip_name_button_popup.png b/manual/images/mixer_strip_name_button_popup.png
new file mode 100644
index 0000000000..6092cece90
--- /dev/null
+++ b/manual/images/mixer_strip_name_button_popup.png
Binary files differ
diff --git a/manual/images/mixerstrip.png b/manual/images/mixerstrip.png
new file mode 100644
index 0000000000..1121b2d698
--- /dev/null
+++ b/manual/images/mixerstrip.png
Binary files differ
diff --git a/manual/images/new_session_advanced_tab.png b/manual/images/new_session_advanced_tab.png
new file mode 100644
index 0000000000..6fa5c93148
--- /dev/null
+++ b/manual/images/new_session_advanced_tab.png
Binary files differ
diff --git a/manual/images/new_session_select_directory.png b/manual/images/new_session_select_directory.png
new file mode 100644
index 0000000000..d6897484db
--- /dev/null
+++ b/manual/images/new_session_select_directory.png
Binary files differ
diff --git a/manual/images/overlapearlyhigher.png b/manual/images/overlapearlyhigher.png
new file mode 100644
index 0000000000..5223e09b40
--- /dev/null
+++ b/manual/images/overlapearlyhigher.png
Binary files differ
diff --git a/manual/images/overlaplaterhigher.png b/manual/images/overlaplaterhigher.png
new file mode 100644
index 0000000000..5b7bd13b59
--- /dev/null
+++ b/manual/images/overlaplaterhigher.png
Binary files differ
diff --git a/manual/images/pluginmenu.jpg b/manual/images/pluginmenu.jpg
new file mode 100644
index 0000000000..fd14de04fb
--- /dev/null
+++ b/manual/images/pluginmenu.jpg
Binary files differ
diff --git a/manual/images/plugins.jpg b/manual/images/plugins.jpg
new file mode 100644
index 0000000000..4c19f7d6e3
--- /dev/null
+++ b/manual/images/plugins.jpg
Binary files differ
diff --git a/manual/images/qjackctl.png b/manual/images/qjackctl.png
new file mode 100644
index 0000000000..bcdef4becc
--- /dev/null
+++ b/manual/images/qjackctl.png
Binary files differ
diff --git a/manual/images/qjopt.jpg b/manual/images/qjopt.jpg
new file mode 100644
index 0000000000..1d68393c0c
--- /dev/null
+++ b/manual/images/qjopt.jpg
Binary files differ
diff --git a/manual/images/qjopts.jpg b/manual/images/qjopts.jpg
new file mode 100644
index 0000000000..efe8b9aba9
--- /dev/null
+++ b/manual/images/qjopts.jpg
Binary files differ
diff --git a/manual/images/qjpatch.jpg b/manual/images/qjpatch.jpg
new file mode 100644
index 0000000000..a6a45ee968
--- /dev/null
+++ b/manual/images/qjpatch.jpg
Binary files differ
diff --git a/manual/images/save_session_dialog.png b/manual/images/save_session_dialog.png
new file mode 100644
index 0000000000..3af28d24b9
--- /dev/null
+++ b/manual/images/save_session_dialog.png
Binary files differ
diff --git a/manual/images/save_template_dialog.png b/manual/images/save_template_dialog.png
new file mode 100644
index 0000000000..1266f8b932
--- /dev/null
+++ b/manual/images/save_template_dialog.png
Binary files differ
diff --git a/manual/images/session_control.png b/manual/images/session_control.png
new file mode 100644
index 0000000000..adba5f66c1
--- /dev/null
+++ b/manual/images/session_control.png
Binary files differ
diff --git a/manual/images/signal_flow.png b/manual/images/signal_flow.png
new file mode 100644
index 0000000000..35fdcbada3
--- /dev/null
+++ b/manual/images/signal_flow.png
Binary files differ
diff --git a/manual/images/tango-icons/COPYING b/manual/images/tango-icons/COPYING
new file mode 100644
index 0000000000..e709d0c050
--- /dev/null
+++ b/manual/images/tango-icons/COPYING
@@ -0,0 +1,67 @@
+Creative Commons Attribution-ShareAlike 2.5 License Agreement
+
+CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE.
+
+License
+
+THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+
+BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
+
+1. Definitions
+
+ 1. "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.
+ 2. "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License.
+ 3. "Licensor" means the individual or entity that offers the Work under the terms of this License.
+ 4. "Original Author" means the individual or entity who created the Work.
+ 5. "Work" means the copyrightable work of authorship offered under the terms of this License.
+ 6. "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
+ 7. "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.
+
+2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.
+
+3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:
+
+ 1. to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works;
+ 2. to create and reproduce Derivative Works;
+ 3. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works;
+ 4. to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works.
+ 5.
+
+ For the avoidance of doubt, where the work is a musical composition:
+ 1. Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work.
+ 2. Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to collect, whether individually or via a music rights society or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions).
+ 6. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor waives the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions).
+
+The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved.
+
+4. Restrictions.The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:
+
+ 1. You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(c), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(c), as requested.
+ 2. You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License.
+ 3. If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit.
+
+5. Representations, Warranties and Disclaimer
+
+UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+
+6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. Termination
+
+ 1. This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
+ 2. Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.
+
+8. Miscellaneous
+
+ 1. Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
+ 2. Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
+ 3. If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
+ 4. No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
+ 5. This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.
+
+Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor.
+
+Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, neither party will use the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time.
+
+Creative Commons may be contacted at http://creativecommons.org/.
diff --git a/manual/images/tango-icons/accessories-text-editor.svg b/manual/images/tango-icons/accessories-text-editor.svg
new file mode 100644
index 0000000000..aa7188eb2d
--- /dev/null
+++ b/manual/images/tango-icons/accessories-text-editor.svg
@@ -0,0 +1,552 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ width="48px"
+ height="48px"
+ id="svg11300"
+ sodipodi:version="0.32"
+ inkscape:version="0.43+devel"
+ sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/apps"
+ sodipodi:docname="accessories-text-editor.svg">
+ <defs
+ id="defs3">
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient6719"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5060">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop5062" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5064" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient6717"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ id="linearGradient5048">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop5050" />
+ <stop
+ id="stop5056"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5052" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5048"
+ id="linearGradient6715"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+ x1="302.85715"
+ y1="366.64789"
+ x2="302.85715"
+ y2="609.50507" />
+ <linearGradient
+ id="linearGradient2994">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop2996" />
+ <stop
+ style="stop-color:#c9c9c9;stop-opacity:1;"
+ offset="1"
+ id="stop2998" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2984">
+ <stop
+ style="stop-color:#e7e2b8;stop-opacity:1;"
+ offset="0"
+ id="stop2986" />
+ <stop
+ style="stop-color:#e7e2b8;stop-opacity:0;"
+ offset="1"
+ id="stop2988" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2974">
+ <stop
+ style="stop-color:#c1c1c1;stop-opacity:1;"
+ offset="0"
+ id="stop2976" />
+ <stop
+ style="stop-color:#acacac;stop-opacity:1;"
+ offset="1"
+ id="stop2978" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2966">
+ <stop
+ style="stop-color:#ffd1d1;stop-opacity:1;"
+ offset="0"
+ id="stop2968" />
+ <stop
+ id="stop3006"
+ offset="0.5"
+ style="stop-color:#ff1d1d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#6f0000;stop-opacity:1;"
+ offset="1"
+ id="stop2970" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2919">
+ <stop
+ style="stop-color:#a3a4a0;stop-opacity:1;"
+ offset="0"
+ id="stop2921" />
+ <stop
+ style="stop-color:#888a85;stop-opacity:1;"
+ offset="1"
+ id="stop2923" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2873">
+ <stop
+ style="stop-color:#939393;stop-opacity:1;"
+ offset="0"
+ id="stop2875" />
+ <stop
+ style="stop-color:#424242;stop-opacity:1;"
+ offset="1"
+ id="stop2877" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2865">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop2867" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop2869" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2855">
+ <stop
+ style="stop-color:#dfdfdf;stop-opacity:1;"
+ offset="0"
+ id="stop2857" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop2859" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2855"
+ id="linearGradient2861"
+ x1="21.043484"
+ y1="42.83337"
+ x2="14.283642"
+ y2="6.8333683"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.137871,0.000000,0.000000,1.000000,-2.660884,0.000000)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2865"
+ id="radialGradient2871"
+ cx="23.5625"
+ cy="40.4375"
+ fx="23.5625"
+ fy="40.4375"
+ r="19.5625"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,0.348243,0.000000,26.35543)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2873"
+ id="linearGradient2879"
+ x1="26.612417"
+ y1="28.083368"
+ x2="26.228401"
+ y2="42.83337"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2919"
+ id="linearGradient2925"
+ x1="6"
+ y1="7.5624999"
+ x2="40.984375"
+ y2="7.5624999"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2966"
+ id="linearGradient2972"
+ x1="48.90625"
+ y1="17.376184"
+ x2="50.988335"
+ y2="22.250591"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-5.669292,0.000000)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2974"
+ id="linearGradient2980"
+ x1="46"
+ y1="19.8125"
+ x2="47.6875"
+ y2="22.625"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-5.669292,0.000000)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2984"
+ id="radialGradient2990"
+ cx="29.053354"
+ cy="27.640751"
+ fx="29.053354"
+ fy="27.640751"
+ r="3.2408544"
+ gradientTransform="matrix(2.923565,-3.911409e-24,2.471769e-23,2.029717,-61.55532,-27.88417)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2994"
+ id="linearGradient3000"
+ x1="25.71875"
+ y1="31.046875"
+ x2="25.514589"
+ y2="30.703125"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(-5.825542,0.125000)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2865"
+ id="radialGradient3010"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,0.348243,1.439818e-16,26.35543)"
+ cx="23.5625"
+ cy="40.4375"
+ fx="23.5625"
+ fy="40.4375"
+ r="19.5625" />
+ </defs>
+ <sodipodi:namedview
+ stroke="#c4a000"
+ fill="#edd400"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="14.928934"
+ inkscape:cy="7.6822472"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="872"
+ inkscape:window-height="659"
+ inkscape:window-x="195"
+ inkscape:window-y="221" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+ <dc:title>Text Editor</dc:title>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ transform="matrix(2.417561e-2,0,0,2.086758e-2,45.12765,40.1536)"
+ id="g6707">
+ <rect
+ style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect6709"
+ width="1339.6335"
+ height="478.35718"
+ x="-1559.2523"
+ y="-150.69685" />
+ <path
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+ id="path6711"
+ sodipodi:nodetypes="cccc" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path6713"
+ d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <path
+ style="color:#000000;fill:url(#linearGradient2861);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2879);stroke-width:0.99999982;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 7.1638699,4.5063726 L 39.813122,4.5063726 C 40.575699,4.5063726 41.189615,5.0388241 41.189615,5.7002099 C 41.189615,5.7002099 43.590945,39.868907 43.590945,39.868907 C 43.590945,39.868907 43.603403,42.216529 43.603403,42.216529 C 43.603403,42.877915 42.989488,43.410366 42.226911,43.410366 L 4.750081,43.410366 C 3.9875042,43.410366 3.3735887,42.877915 3.3735887,42.216529 L 3.3624173,40.049613 L 5.7873775,5.7002099 C 5.7873775,5.0388241 6.4012931,4.5063726 7.1638699,4.5063726 z "
+ id="rect1975"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ transform="matrix(0.616613,0.000000,0.000000,0.440367,10.61425,13.94266)"
+ d="M 43.125 40.4375 A 19.5625 6.8125 0 1 1 4,40.4375 A 19.5625 6.8125 0 1 1 43.125 40.4375 z"
+ sodipodi:ry="6.8125"
+ sodipodi:rx="19.5625"
+ sodipodi:cy="40.4375"
+ sodipodi:cx="23.5625"
+ id="path3008"
+ style="opacity:0.31578944;color:#000000;fill:url(#radialGradient3010);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ sodipodi:type="arc" />
+ <rect
+ style="opacity:1;color:#000000;fill:#a4a4a4;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2851"
+ width="39.048077"
+ height="3.0714951"
+ x="3.9770372"
+ y="39.868271"
+ rx="0.67937863"
+ ry="0.67937863" />
+ <path
+ style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 3.9267507,40.442796 C 3.9267507,40.442796 4.0776125,39.912466 4.6307727,39.868272 L 42.195375,39.868272 C 42.949684,39.868272 42.999971,40.619573 42.999971,40.619573 C 42.999971,40.619573 43.02357,39 41.7161,39 L 5.3042159,39 C 4.2984702,39.088388 3.9267507,39.779883 3.9267507,40.442796 z "
+ id="path2853"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient2925);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 6.25,5.7343749 L 6,10.125 C 6,10.125 6.3125,8.9999999 7,8.9999999 L 40.125,8.9999999 C 40.828125,8.9843749 40.859375,9.3124999 40.984375,9.8281249 C 40.984375,9.8281249 40.734375,5.9531249 40.734375,5.9531249 C 40.703125,5.4062499 40.515625,4.9999999 39.953125,4.9999999 L 7.0625,4.9999999 C 6.609375,4.9999999 6.296875,5.3437499 6.25,5.7343749 z "
+ id="path2915"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ id="path2917"
+ d="M 7.8126474,5.5404503 L 38.944983,5.5404503 C 39.66702,5.5404503 40.2483,5.3883462 40.2483,6.014572 C 40.2483,6.014572 42.521973,39.023077 42.521973,39.023077 C 42.521973,39.023077 42.622156,41.732033 42.622156,41.732033 C 42.622156,42.358259 42.48282,42.376269 41.760782,42.376269 L 4.8620444,42.376269 C 4.4493662,42.376269 4.4426114,42.269871 4.4426114,41.864615 L 4.4320338,39.194177 L 6.7280807,6.045822 C 6.7280807,5.4195962 7.09061,5.5404503 7.8126474,5.5404503 z "
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999946;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;opacity:0.43859649" />
+ <g
+ id="g2950">
+ <rect
+ ry="1"
+ rx="1"
+ y="2.5"
+ x="8.5"
+ height="5"
+ width="2"
+ id="rect2899"
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2901"
+ width="2"
+ height="5"
+ x="12.5"
+ y="2.5"
+ rx="1"
+ ry="1" />
+ <rect
+ ry="1"
+ rx="1"
+ y="2.5"
+ x="16.5"
+ height="5"
+ width="2"
+ id="rect2903"
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2905"
+ width="2"
+ height="5"
+ x="20.5"
+ y="2.5"
+ rx="1"
+ ry="1" />
+ <rect
+ ry="1"
+ rx="1"
+ y="2.5"
+ x="24.5"
+ height="5"
+ width="2"
+ id="rect2907"
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2909"
+ width="2"
+ height="5"
+ x="28.5"
+ y="2.5"
+ rx="1"
+ ry="1" />
+ <rect
+ ry="1"
+ rx="1"
+ y="2.5"
+ x="32.5"
+ height="5"
+ width="2"
+ id="rect2911"
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:1;color:#000000;fill:#fce94f;fill-opacity:1;fill-rule:evenodd;stroke:#886f00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2913"
+ width="2"
+ height="5"
+ x="36.5"
+ y="2.5"
+ rx="1"
+ ry="1" />
+ </g>
+ <g
+ id="g2941">
+ <rect
+ y="12"
+ x="9"
+ height="1"
+ width="29"
+ id="rect2927"
+ style="opacity:0.28070175;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2929"
+ width="29"
+ height="1"
+ x="9"
+ y="14.981792" />
+ <rect
+ y="18.003939"
+ x="9"
+ height="1"
+ width="13"
+ id="rect2931"
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2933"
+ width="29"
+ height="1"
+ x="9"
+ y="22.985731" />
+ <rect
+ y="26.007877"
+ x="9"
+ height="1"
+ width="29"
+ id="rect2935"
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <rect
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect2937"
+ width="29"
+ height="1"
+ x="9"
+ y="29.030024" />
+ <rect
+ y="32.05217"
+ x="9"
+ height="1"
+ width="8"
+ id="rect2939"
+ style="opacity:0.28070176;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <path
+ style="opacity:1;color:#000000;fill:#cb9022;fill-opacity:1;fill-rule:evenodd;stroke:#5c410c;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 17.34116,32.5 L 22.96616,26.875 L 43.059909,17.125 C 46.309909,15.875 48.247409,20.5 45.372409,22.125 L 25.34116,31.5 L 17.34116,32.5 z "
+ id="path2960"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ sodipodi:nodetypes="czcczcc"
+ id="path2964"
+ d="M 38.330708,20 C 38.330708,20 39.768208,20.09375 40.330708,21.34375 C 40.910201,22.631511 40.330708,24 40.330708,24 L 45.361958,21.53125 C 45.361958,21.53125 46.81399,20.649883 46.018208,18.6875 C 45.233296,16.751923 43.330708,17.53125 43.330708,17.53125 L 38.330708,20 z "
+ style="opacity:1;color:#000000;fill:url(#linearGradient2972);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient2980);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 38.330708,20 C 38.330708,20 39.768208,20.09375 40.330708,21.34375 C 40.910201,22.631511 40.330708,24 40.330708,24 L 42.330708,23 C 42.330708,23 43.15774,21.681133 42.549458,20.3125 C 41.924458,18.90625 40.330708,19 40.330708,19 L 38.330708,20 z "
+ id="path2962"
+ sodipodi:nodetypes="czcczcc" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#radialGradient2990);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 18.768208,31.78125 L 23.268208,27.28125 C 24.768208,28.09375 25.549458,29.4375 25.143208,31 L 18.768208,31.78125 z "
+ id="path2982"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="opacity:1;color:#000000;fill:url(#linearGradient3000);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 20.111958,30.375 L 18.486958,31.96875 L 20.830708,31.65625 C 21.049458,30.9375 20.643208,30.59375 20.111958,30.375 z "
+ id="path2992"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="opacity:1;color:#000000;fill:#ffffff;fill-opacity:0.36363639;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 23.268208,27.25 L 24.830708,28.5 L 40.218048,21.18133 C 39.773616,20.325286 38.976281,20.096733 38.314669,20.019068 L 23.268208,27.25 z "
+ id="path3002"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:1;color:#000000;fill:#000000;fill-opacity:0.36363639;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 25.143208,31.0625 L 25.330708,30.3125 L 40.561798,23.1829 C 40.561798,23.1829 40.451638,23.796527 40.345919,23.93225 L 25.143208,31.0625 z "
+ id="path3004"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+</svg>
diff --git a/manual/images/tango-icons/dialog-information.svg b/manual/images/tango-icons/dialog-information.svg
new file mode 100644
index 0000000000..1e957ccc3a
--- /dev/null
+++ b/manual/images/tango-icons/dialog-information.svg
@@ -0,0 +1,1145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ sodipodi:docname="dialog-information.svg"
+ sodipodi:docbase="/home/garrett/Source/tango-icon-theme/scalable/status"
+ inkscape:version="0.43+devel"
+ sodipodi:version="0.32"
+ id="svg19655"
+ height="48px"
+ width="48px"
+ inkscape:export-filename="/home/jimmac/Desktop/poing.png"
+ inkscape:export-xdpi="392.72742"
+ inkscape:export-ydpi="392.72742">
+ <defs
+ id="defs3">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3300">
+ <stop
+ style="stop-color:#4c4c28;stop-opacity:1;"
+ offset="0"
+ id="stop3302" />
+ <stop
+ style="stop-color:#4c4c28;stop-opacity:0;"
+ offset="1"
+ id="stop3304" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3311">
+ <stop
+ id="stop3313"
+ offset="0"
+ style="stop-color:#d6d7a5;stop-opacity:1;" />
+ <stop
+ id="stop3315"
+ offset="1.0000000"
+ style="stop-color:#8e8f6d;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3265">
+ <stop
+ id="stop3267"
+ offset="0"
+ style="stop-color:#929470;stop-opacity:1;" />
+ <stop
+ style="stop-color:#60614a;stop-opacity:1.0000000;"
+ offset="0.26470590"
+ id="stop3269" />
+ <stop
+ id="stop3271"
+ offset="0.63235295"
+ style="stop-color:#f3f5ba;stop-opacity:1.0000000;" />
+ <stop
+ id="stop3273"
+ offset="1.0000000"
+ style="stop-color:#929470;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3175"
+ inkscape:collect="always">
+ <stop
+ id="stop3177"
+ offset="0"
+ style="stop-color:#f1f3ff;stop-opacity:1;" />
+ <stop
+ id="stop3179"
+ offset="1"
+ style="stop-color:#f1f3ff;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2399">
+ <stop
+ style="stop-color:#929470;stop-opacity:1;"
+ offset="0"
+ id="stop2401" />
+ <stop
+ id="stop2407"
+ offset="0.26470590"
+ style="stop-color:#fcffc1;stop-opacity:1.0000000;" />
+ <stop
+ style="stop-color:#f3f5ba;stop-opacity:1.0000000;"
+ offset="0.63235295"
+ id="stop2409" />
+ <stop
+ style="stop-color:#929470;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop2403" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient6339">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop6341" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop6343" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20428">
+ <stop
+ id="stop20430"
+ offset="0.0000000"
+ style="stop-color:#a3a3a3;stop-opacity:1.0000000;" />
+ <stop
+ id="stop20432"
+ offset="1"
+ style="stop-color:#b5b5b5;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20393">
+ <stop
+ id="stop20395"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.44117647;"
+ offset="0.41176471"
+ id="stop2427" />
+ <stop
+ id="stop20397"
+ offset="1.0000000"
+ style="stop-color:#000000;stop-opacity:0.48039216;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient20210">
+ <stop
+ id="stop20212"
+ offset="0.0000000"
+ style="stop-color:#000000;stop-opacity:0.51546389;" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.14432989;"
+ offset="0.55172414"
+ id="stop20218" />
+ <stop
+ id="stop20214"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ fy="11.4873"
+ fx="17.8335"
+ r="22.7093"
+ cy="11.4873"
+ cx="17.8335"
+ id="aigrd7">
+ <stop
+ id="stop19512"
+ style="stop-color:#ffffff;stop-opacity:0.17525773;"
+ offset="0.0000000" />
+ <stop
+ id="stop19514"
+ style="stop-color:#709ac8;stop-opacity:1.0000000;"
+ offset="0.88200003" />
+ <stop
+ id="stop19516"
+ style="stop-color:#6f96dd;stop-opacity:1.0000000;"
+ offset="1.0000000" />
+ </radialGradient>
+ <linearGradient
+ y2="43.165"
+ x2="26.4785"
+ y1="43.165"
+ x1="23.124"
+ gradientUnits="userSpaceOnUse"
+ id="aigrd1">
+ <stop
+ id="stop19415"
+ style="stop-color:#686868"
+ offset="5.618000e-003" />
+ <stop
+ id="stop19417"
+ style="stop-color:#777777"
+ offset="3.012137e-002" />
+ <stop
+ id="stop19419"
+ style="stop-color:#929292"
+ offset="8.366583e-002" />
+ <stop
+ id="stop19421"
+ style="stop-color:#A7A7A7"
+ offset="0.1422" />
+ <stop
+ id="stop19423"
+ style="stop-color:#B6B6B6"
+ offset="0.2074" />
+ <stop
+ id="stop19425"
+ style="stop-color:#BEBEBE"
+ offset="0.2846" />
+ <stop
+ id="stop19427"
+ style="stop-color:#C1C1C1"
+ offset="0.4045" />
+ <stop
+ id="stop19429"
+ style="stop-color:#BCBCBC"
+ offset="0.4962" />
+ <stop
+ id="stop19431"
+ style="stop-color:#ADADAD"
+ offset="0.6057" />
+ <stop
+ id="stop19433"
+ style="stop-color:#959595"
+ offset="0.7245" />
+ <stop
+ id="stop19435"
+ style="stop-color:#747474"
+ offset="0.8497" />
+ <stop
+ id="stop19437"
+ style="stop-color:#494949"
+ offset="0.9789" />
+ <stop
+ id="stop19439"
+ style="stop-color:#414141"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient19894"
+ gradientUnits="userSpaceOnUse"
+ x1="18.995100"
+ y1="37.226601"
+ x2="30.169901"
+ y2="37.226601">
+ <stop
+ offset="5.618000e-003"
+ style="stop-color:#A3A349"
+ id="stop19896" />
+ <stop
+ offset="2.078677e-002"
+ style="stop-color:#ACAC54"
+ id="stop19898" />
+ <stop
+ offset="6.600059e-002"
+ style="stop-color:#C1C172"
+ id="stop19900" />
+ <stop
+ offset="0.1148"
+ style="stop-color:#D4D68E"
+ id="stop19902" />
+ <stop
+ offset="0.1677"
+ style="stop-color:#E2E4A6"
+ id="stop19904" />
+ <stop
+ offset="0.2265"
+ style="stop-color:#EDF0B8"
+ id="stop19906" />
+ <stop
+ offset="0.2963"
+ style="stop-color:#F3F6C3"
+ id="stop19908" />
+ <stop
+ offset="0.4045"
+ style="stop-color:#F5F8C7"
+ id="stop19910" />
+ <stop
+ offset="0.5239"
+ style="stop-color:#EEF0BE"
+ id="stop19912" />
+ <stop
+ offset="0.6666"
+ style="stop-color:#DBDDA9"
+ id="stop19914" />
+ <stop
+ offset="0.8211"
+ style="stop-color:#BEBD88"
+ id="stop19916" />
+ <stop
+ offset="0.9832"
+ style="stop-color:#989564"
+ id="stop19918" />
+ <stop
+ offset="1"
+ style="stop-color:#949160"
+ id="stop19920" />
+ </linearGradient>
+ <linearGradient
+ gradientTransform="matrix(1.639127,0,0,1.639127,-15.97035,-29.79355)"
+ y2="43.165"
+ x2="26.4785"
+ y1="43.165"
+ x1="23.124"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient20109"
+ xlink:href="#aigrd1"
+ inkscape:collect="always" />
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ r="7.8289826"
+ fy="74.209934"
+ fx="14.772334"
+ cy="74.209934"
+ cx="14.772334"
+ gradientTransform="scale(1.764278,0.566804)"
+ id="radialGradient20216"
+ xlink:href="#linearGradient20210"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.726292"
+ x2="32.096882"
+ y1="10.061084"
+ x1="16.998856"
+ gradientTransform="matrix(1.140494,0.000000,0.000000,0.926002,0.272330,-3.247170)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7708"
+ xlink:href="#linearGradient6339"
+ inkscape:collect="always" />
+ <radialGradient
+ r="33.934090"
+ fy="29.869318"
+ fx="68.137589"
+ cy="29.869318"
+ cx="68.137589"
+ gradientTransform="matrix(0.551290,1.265592e-16,-1.355720e-16,0.766034,-10.48701,3.514312)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7720"
+ xlink:href="#aigrd7"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="3.8557322"
+ x2="-5.2517161"
+ y1="16.651863"
+ x1="37.940434"
+ gradientTransform="matrix(0.894129,0.000000,0.000000,0.985230,1.515981,2.449800e-2)"
+ id="linearGradient3181"
+ xlink:href="#linearGradient3175"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20393"
+ id="linearGradient1700"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6293,0,0,1.589068,50.68808,3.804378)"
+ x1="30.620375"
+ y1="10.313651"
+ x2="32.166080"
+ y2="18.162935" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20393"
+ id="linearGradient1702"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6293,0,0,1.589068,1.411612,3.929378)"
+ x1="30.620375"
+ y1="10.313651"
+ x2="32.166080"
+ y2="18.162935" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20428"
+ id="linearGradient1704"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.985083,0,0,0.503757,1.786612,4.554378)"
+ x1="14.637301"
+ y1="31.504122"
+ x2="9.3648205"
+ y2="32.250980" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient1725"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.026450,0.974232)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient1727"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.026450,0.974232)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient1729"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.026450,0.974232)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient1731"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.026450,0.974232)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3311"
+ id="linearGradient2516"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.603440,0.000000,0.000000,0.549396,0.614167,2.449800e-2)"
+ x1="17.879995"
+ y1="55.362793"
+ x2="11.906206"
+ y2="54.863026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3265"
+ id="linearGradient2518"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.905728,-4.386156e-2,0.189510,-0.963437,0.614167,2.449800e-2)"
+ x1="-29.007195"
+ y1="-29.799353"
+ x2="-37.641232"
+ y2="-29.598314" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient2522"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.618682,-0.132027,6.262726e-2,0.741184,31.12021,8.300410)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient2524"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.618682,-0.132027,6.262726e-2,0.741184,31.12021,8.300410)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient2529"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.566621,2.988977e-2,-0.118557,0.656541,36.18544,20.08311)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient2531"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.566621,2.988977e-2,-0.118557,0.656541,36.18544,20.08311)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3300"
+ id="linearGradient3306"
+ gradientTransform="scale(1.002656,0.997352)"
+ x1="24.613028"
+ y1="31.146202"
+ x2="24.613028"
+ y2="26.739624"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3311"
+ id="linearGradient3127"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.60344,0,0,0.549396,0.614167,2.4498e-2)"
+ x1="17.879995"
+ y1="55.362793"
+ x2="11.906206"
+ y2="54.863026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3265"
+ id="linearGradient3129"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.905728,-4.386156e-2,0.18951,-0.963437,0.614167,2.4498e-2)"
+ x1="-29.007195"
+ y1="-29.799353"
+ x2="-37.641232"
+ y2="-29.598314" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd7"
+ id="radialGradient3131"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.55129,1.265592e-16,-1.35572e-16,0.766034,-10.48701,3.514312)"
+ cx="68.137589"
+ cy="29.869318"
+ fx="68.137589"
+ fy="29.869318"
+ r="33.934090" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6339"
+ id="linearGradient3133"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.140494,0,0,0.926002,0.27233,-3.24717)"
+ x1="16.998856"
+ y1="10.061084"
+ x2="32.096882"
+ y2="36.726292" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3175"
+ id="linearGradient3135"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.894129,0,0,0.98523,1.515981,2.4498e-2)"
+ x1="37.940434"
+ y1="16.651863"
+ x2="-5.2517161"
+ y2="3.8557322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3311"
+ id="linearGradient3157"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.60344,0,0,0.549396,0.614167,2.4498e-2)"
+ x1="17.879995"
+ y1="55.362793"
+ x2="11.906206"
+ y2="54.863026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3265"
+ id="linearGradient3159"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.905728,-4.386156e-2,0.18951,-0.963437,0.614167,2.4498e-2)"
+ x1="-29.007195"
+ y1="-29.799353"
+ x2="-37.641232"
+ y2="-29.598314" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd7"
+ id="radialGradient3161"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.55129,1.265592e-16,-1.35572e-16,0.766034,-10.48701,3.514312)"
+ cx="68.137589"
+ cy="29.869318"
+ fx="68.137589"
+ fy="29.869318"
+ r="33.934090" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3175"
+ id="linearGradient3163"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.894129,0,0,0.98523,1.515981,2.4498e-2)"
+ x1="37.940434"
+ y1="16.651863"
+ x2="-5.2517161"
+ y2="3.8557322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20393"
+ id="linearGradient3165"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6293,0,0,1.589068,50.68808,3.804378)"
+ x1="30.620375"
+ y1="10.313651"
+ x2="32.166080"
+ y2="18.162935" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20393"
+ id="linearGradient3167"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6293,0,0,1.589068,1.411612,3.929378)"
+ x1="30.620375"
+ y1="10.313651"
+ x2="32.166080"
+ y2="18.162935" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20428"
+ id="linearGradient3169"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.985083,0,0,0.503757,1.786612,4.554378)"
+ x1="14.637301"
+ y1="31.504122"
+ x2="9.3648205"
+ y2="32.250980" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6339"
+ id="linearGradient3171"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.140494,0,0,0.926002,0.27233,-3.24717)"
+ x1="16.998856"
+ y1="10.061084"
+ x2="32.096882"
+ y2="36.726292" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3300"
+ id="linearGradient3185"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.002656,0.997352)"
+ x1="24.613028"
+ y1="31.146202"
+ x2="24.613028"
+ y2="26.739624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient3187"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.566621,2.988977e-2,-0.118557,0.656541,36.18544,20.08311)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient3189"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.566621,2.988977e-2,-0.118557,0.656541,36.18544,20.08311)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient3191"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.02645,0.974232)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient3193"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.02645,0.974232)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient3195"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.02645,0.974232)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient3197"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.02645,0.974232)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient3199"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.618682,-0.132027,6.262726e-2,0.741184,31.12021,8.30041)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient3201"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.618682,-0.132027,6.262726e-2,0.741184,31.12021,8.30041)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd1"
+ id="linearGradient4100"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.639127,0,0,1.639127,-15.97035,-29.79355)"
+ x1="23.124"
+ y1="43.165"
+ x2="26.4785"
+ y2="43.165" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3300"
+ id="linearGradient4102"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.002656,0.997352)"
+ x1="24.613028"
+ y1="31.146202"
+ x2="24.613028"
+ y2="26.739624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient4104"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.566621,2.988977e-2,-0.118557,0.656541,36.18544,20.08311)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient4106"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.566621,2.988977e-2,-0.118557,0.656541,36.18544,20.08311)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient4108"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.02645,0.974232)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient4110"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.02645,0.974232)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient4112"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.02645,0.974232)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient4114"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.02645,0.974232)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient19894"
+ id="linearGradient4116"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.618682,-0.132027,6.262726e-2,0.741184,31.12021,8.30041)"
+ x1="-22.874170"
+ y1="38.675991"
+ x2="-4.3908315"
+ y2="38.675991" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2399"
+ id="linearGradient4118"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.618682,-0.132027,6.262726e-2,0.741184,31.12021,8.30041)"
+ x1="-10.480865"
+ y1="39.033951"
+ x2="-23.851389"
+ y2="39.142845" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3311"
+ id="linearGradient4120"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.60344,0,0,0.549396,0.614167,2.4498e-2)"
+ x1="17.879995"
+ y1="55.362793"
+ x2="11.906206"
+ y2="54.863026" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3265"
+ id="linearGradient4122"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.905728,-4.386156e-2,0.18951,-0.963437,0.614167,2.4498e-2)"
+ x1="-29.007195"
+ y1="-29.799353"
+ x2="-37.641232"
+ y2="-29.598314" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd7"
+ id="radialGradient4124"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.55129,1.265592e-16,-1.35572e-16,0.766034,-10.48701,3.514312)"
+ cx="68.137589"
+ cy="29.869318"
+ fx="68.137589"
+ fy="29.869318"
+ r="33.934090" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3175"
+ id="linearGradient4126"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.894129,0,0,0.98523,1.515981,2.4498e-2)"
+ x1="37.940434"
+ y1="16.651863"
+ x2="-5.2517161"
+ y2="3.8557322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20393"
+ id="linearGradient4128"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.6293,0,0,1.589068,50.68808,3.804378)"
+ x1="30.620375"
+ y1="10.313651"
+ x2="32.166080"
+ y2="18.162935" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20393"
+ id="linearGradient4130"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.6293,0,0,1.589068,1.411612,3.929378)"
+ x1="30.620375"
+ y1="10.313651"
+ x2="32.166080"
+ y2="18.162935" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient20428"
+ id="linearGradient4132"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.985083,0,0,0.503757,1.786612,4.554378)"
+ x1="14.637301"
+ y1="31.504122"
+ x2="9.3648205"
+ y2="32.250980" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6339"
+ id="linearGradient4134"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.140494,0,0,0.926002,0.27233,-3.24717)"
+ x1="16.998856"
+ y1="10.061084"
+ x2="32.096882"
+ y2="36.726292" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-y="91"
+ inkscape:window-x="146"
+ inkscape:window-height="922"
+ inkscape:window-width="1060"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ showgrid="true"
+ inkscape:current-layer="layer1"
+ inkscape:cy="19.729332"
+ inkscape:cx="29.03294"
+ inkscape:zoom="1"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="0.55294118"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:showpageshadow="false"
+ gridempspacing="4" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Info</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>dialog</rdf:li>
+ <rdf:li>info</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Garrett LeSage</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1"
+ id="layer1">
+ <path
+ transform="matrix(1.197183,0,0,1.098591,-6.201582,-3.209507)"
+ d="M 39.875 42.0625 A 13.8125 4.4375 0 1 1 12.25,42.0625 A 13.8125 4.4375 0 1 1 39.875 42.0625 z"
+ sodipodi:ry="4.4375"
+ sodipodi:rx="13.8125"
+ sodipodi:cy="42.0625"
+ sodipodi:cx="26.0625"
+ id="path20208"
+ style="color:#000000;fill:url(#radialGradient20216);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;opacity:0.8"
+ sodipodi:type="arc"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true" />
+ <g
+ id="g4076"
+ transform="translate(0,1)"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true">
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ transform="matrix(1.075823,0,0,0.937493,-2.551335,3.047213)"
+ id="path19509"
+ d="M 21.893504,38.885945 L 21.893504,40.36116 C 21.893504,41.836375 23.204807,43.147679 24.680022,43.147679 C 26.155237,43.147679 27.466539,41.836375 27.466539,40.36116 L 27.466539,38.885945 L 21.893504,38.885945 z "
+ style="fill:url(#linearGradient4100);fill-rule:nonzero;stroke:#565656;stroke-miterlimit:4;stroke-opacity:1" />
+ <g
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ transform="matrix(0.989073,0,0,0.993556,-0.408739,7.920479e-3)"
+ id="g3173">
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ sodipodi:nodetypes="cccccccscccccccs"
+ id="path3209"
+ d="M 24.511725,27.668867 C 21.208844,27.660897 17.463275,28.632054 19.492913,30.467931 C 18.98969,30.670934 18.270371,31.124313 18.355167,32.185222 C 18.401983,32.739286 18.989243,33.079394 19.79236,33.32911 C 18.881908,33.967722 18.302581,34.642557 18.355167,35.264921 C 18.401438,35.812525 18.976334,36.187531 19.76303,36.43814 C 18.875519,37.069403 18.303301,37.760121 18.355167,38.373951 C 18.434436,39.312088 20.457743,40.362928 24.838928,40.2419 C 27.993329,40.155914 30.776913,39.590514 30.996599,38.373951 C 31.082862,37.896248 30.691907,37.450531 30.087355,37.05408 C 30.539926,36.597918 30.85698,36.135242 30.820616,35.704878 C 30.774128,35.154694 30.205993,34.781923 29.412754,34.53166 C 30.300265,33.900397 30.872482,33.209679 30.820616,32.595849 C 30.774128,32.045664 30.205993,31.702225 29.412754,31.45196 C 30.310848,30.817288 30.872816,30.133928 30.820616,29.516149 C 30.762593,28.829446 27.61599,27.676358 24.511725,27.668867 z "
+ style="color:#000000;fill:#aeae57;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4102);stroke-width:2.01752925;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ sodipodi:nodetypes="csccc"
+ id="path3183"
+ d="M 30.920208,38.329767 C 30.700522,39.546331 27.591422,40.232861 22.615132,39.983673 C 19.463507,39.825856 19.283163,38.944055 19.502848,37.727491 C 19.722534,36.510926 22.458318,35.65848 25.609509,35.824708 C 28.7607,35.990936 31.139893,37.113203 30.920208,38.329767 z "
+ style="color:#000000;fill:url(#linearGradient4104);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4106);stroke-width:0.08906282;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ sodipodi:type="arc"
+ style="color:#000000;fill:url(#linearGradient4108);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4110);stroke-width:0.13035245;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path1603"
+ sodipodi:cx="-13.87697"
+ sodipodi:cy="27.228739"
+ sodipodi:rx="10.341436"
+ sodipodi:ry="3.2703688"
+ d="M -3.5355339 27.228739 A 10.341436 3.2703688 0 1 1 -24.218407,27.228739 A 10.341436 3.2703688 0 1 1 -3.5355339 27.228739 z"
+ transform="matrix(0.60274,-0.128625,6.428372e-2,0.760788,31.12021,14.49141)" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ transform="matrix(0.60274,-0.128625,6.428372e-2,0.760788,31.12021,11.39591)"
+ d="M -3.5355339 27.228739 A 10.341436 3.2703688 0 1 1 -24.218407,27.228739 A 10.341436 3.2703688 0 1 1 -3.5355339 27.228739 z"
+ sodipodi:ry="3.2703688"
+ sodipodi:rx="10.341436"
+ sodipodi:cy="27.228739"
+ sodipodi:cx="-13.87697"
+ id="path2364"
+ style="color:#000000;fill:url(#linearGradient4112);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4114);stroke-width:0.13035245;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ sodipodi:type="arc" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ sodipodi:nodetypes="cccss"
+ id="path2366"
+ d="M 30.698087,29.636386 C 30.698087,31.014688 28.157326,32.55444 24.716601,33.288693 C 21.275876,34.022945 18.38922,33.50421 18.273172,32.130802 C 18.157124,30.757395 20.509679,29.155466 23.952388,28.968827 C 27.422379,28.780711 30.698087,28.924901 30.698087,29.636386 z "
+ style="color:#000000;fill:url(#linearGradient4116);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4118);stroke-width:0.08906286;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ transform="matrix(0.335464,0,0,0.335464,11.74678,27.2261)"
+ d="M 31 22.375 A 3.25 3.25 0 1 1 24.5,22.375 A 3.25 3.25 0 1 1 31 22.375 z"
+ sodipodi:ry="3.25"
+ sodipodi:rx="3.25"
+ sodipodi:cy="22.375"
+ sodipodi:cx="27.75"
+ id="path20372"
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ sodipodi:type="arc" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ sodipodi:nodetypes="cscc"
+ id="path3241"
+ d="M 19.342183,33.378865 C 22.736592,33.883533 26.320992,33.346192 29.214315,31.470807 C 30.025582,30.944962 30.147604,30.343945 30.520921,29.873844 C 29.09679,31.000705 25.494982,34.035625 19.342183,33.378865 z "
+ style="fill:#000000;fill-opacity:0.23391807;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ sodipodi:type="arc"
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="path2435"
+ sodipodi:cx="27.75"
+ sodipodi:cy="22.375"
+ sodipodi:rx="3.25"
+ sodipodi:ry="3.25"
+ d="M 31 22.375 A 3.25 3.25 0 1 1 24.5,22.375 A 3.25 3.25 0 1 1 31 22.375 z"
+ transform="matrix(0.335464,0,0,0.335464,11.74678,30.23376)" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ sodipodi:nodetypes="cscc"
+ id="path3237"
+ d="M 19.466621,39.517838 C 22.86103,40.022506 26.44543,39.485165 29.338753,37.60978 C 30.15002,37.083935 30.272043,36.482919 30.645359,36.012817 C 29.221228,37.139678 25.61942,40.174598 19.466621,39.517838 z "
+ style="fill:#000000;fill-opacity:0.23391807;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ style="fill:#000000;fill-opacity:0.23391807;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 19.487361,36.406872 C 22.88177,36.91154 26.46617,36.374199 29.359492,34.498814 C 30.17076,33.972969 30.292782,33.371953 30.666099,32.901851 C 29.241968,34.028712 25.64016,37.063632 19.487361,36.406872 z "
+ id="path3239"
+ sodipodi:nodetypes="cscc" />
+ </g>
+ <g
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ transform="translate(-0.988797,0)"
+ id="g3146">
+ <g
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ id="g3141">
+ <path
+ transform="matrix(0.954439,0,0,0.989869,1.433222,0.639881)"
+ sodipodi:nodetypes="csscs"
+ id="path3243"
+ d="M 18.87103,29.628128 C 18.87103,28.836695 20.445135,27.889988 24.419234,27.942972 C 28.101154,27.992059 30.526608,28.83866 30.526608,30.105404 C 30.526608,31.345281 27.307242,32.174416 23.874677,32.008188 C 20.442113,31.84196 18.87103,30.868005 18.87103,29.628128 z "
+ style="color:#000000;fill:url(#linearGradient4120);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4122);stroke-width:0.09083303;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true" />
+ <path
+ transform="matrix(0.954439,0,0,0.989869,1.433222,0.639881)"
+ sodipodi:nodetypes="csssssc"
+ id="path6305"
+ d="M 24.680021,0.8622936 C 16.858005,0.8622936 10.506261,6.8372628 10.506261,14.195288 C 10.506261,21.737851 16.247826,22.573217 16.247826,25.352995 C 16.247826,28.619061 19.614103,32.322687 25.149309,32.188995 C 31.035159,32.046835 33.464182,28.825655 33.464182,25.352995 C 33.464182,22.384064 38.853781,22.304889 38.853781,14.195288 C 38.853781,6.8372628 32.502038,0.8622936 24.680021,0.8622936 z "
+ style="color:#000000;fill:url(#radialGradient4124);fill-opacity:1;fill-rule:nonzero;stroke:#616471;stroke-width:1.01595449;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true" />
+ <path
+ transform="matrix(0.954439,0,0,0.989869,1.433222,0.639881)"
+ style="color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4126);stroke-width:0.94685698;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 24.680021,1.9277146 C 17.389999,1.9277146 11.470252,7.4963123 11.470252,14.353901 C 11.470252,21.383476 16.82132,22.162027 16.82132,24.752746 C 16.82132,27.79668 19.958648,31.248413 25.117392,31.123813 C 30.602931,30.991321 32.866751,27.989222 32.866751,24.752746 C 32.866751,21.98574 37.889791,21.911948 37.889791,14.353901 C 37.889791,7.4963123 31.970044,1.9277146 24.680021,1.9277146 z "
+ id="path2429"
+ sodipodi:nodetypes="csssssc"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true" />
+ </g>
+ <g
+ id="g1695"
+ transform="matrix(0.9375,0,0,0.926938,0.569221,0.25176)"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true">
+ <path
+ style="fill:url(#linearGradient4128);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4"
+ d="M 31.947292,19.22274 C 32.260034,19.326988 32.468529,19.63973 32.364281,19.952471 L 28.507134,31.523913 C 28.402887,31.836655 28.090145,32.045149 27.777403,31.940902 C 27.464662,31.836655 27.256168,31.523913 27.360415,31.211172 L 31.217562,19.63973 C 31.321809,19.326988 31.634551,19.118493 31.947292,19.22274 z "
+ id="path1691"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true" />
+ <path
+ id="path19612"
+ d="M 20.152404,19.34774 C 19.839662,19.451988 19.631167,19.76473 19.735415,20.077471 L 23.592562,31.648913 C 23.696809,31.961655 24.009551,32.170149 24.322293,32.065902 C 24.635034,31.961655 24.843528,31.648913 24.739281,31.336172 L 20.882134,19.76473 C 20.777887,19.451988 20.465145,19.243493 20.152404,19.34774 z "
+ style="fill:url(#linearGradient4130);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-miterlimit:4"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4132);stroke-width:0.21454535;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
+ d="M 20.255362,19.273128 C 20.009452,19.315194 19.816806,19.507772 19.774653,19.753667 C 19.732499,19.999562 19.850004,20.245309 20.067862,20.366878 C 20.067862,20.366878 21.910084,21.447747 24.317862,21.991878 C 26.72564,22.536009 29.806763,22.571305 32.130362,20.304378 C 32.305608,20.165345 32.386854,19.938963 32.340007,19.720224 C 32.29316,19.501485 32.126325,19.328233 31.909509,19.273168 C 31.692693,19.218103 31.463406,19.290751 31.317862,19.460628 C 29.367326,21.36359 26.773024,21.36522 24.567862,20.866878 C 22.3627,20.368536 20.661612,19.366878 20.661612,19.366878 C 20.542178,19.287089 20.397682,19.253744 20.255362,19.273128 z "
+ id="path19614"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true" />
+ </g>
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ style="opacity:0.5977654;color:#000000;fill:url(#linearGradient4134);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.98750001;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M 25.001158,3.5644322 C 18.737608,3.5644322 13.655359,7.5900329 13.655359,12.547843 C 13.655359,14.527956 14.632918,16.261758 16.006008,17.747035 C 17.558672,18.378895 19.249827,18.832941 21.114752,18.832941 C 27.378302,18.832941 32.460549,14.807341 32.460551,9.849528 C 32.460551,7.857476 31.466744,6.1074629 30.07856,4.6174331 C 28.533139,3.9930601 26.854241,3.5644321 25.001158,3.5644322 z "
+ id="path6334"
+ transform="matrix(0.954439,0,0,0.989869,1.433222,0.639881)" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/manual/images/tango-icons/dialog-warning.svg b/manual/images/tango-icons/dialog-warning.svg
new file mode 100644
index 0000000000..51f7ff34ab
--- /dev/null
+++ b/manual/images/tango-icons/dialog-warning.svg
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48px"
+ height="48px"
+ id="svg1377"
+ sodipodi:version="0.32"
+ inkscape:version="0.43+devel"
+ sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/status"
+ sodipodi:docname="dialog-warning.svg">
+ <defs
+ id="defs1379">
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient6719"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5060">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop5062" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5064" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient6717"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ id="linearGradient5048">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop5050" />
+ <stop
+ id="stop5056"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5052" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5048"
+ id="linearGradient6715"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+ x1="302.85715"
+ y1="366.64789"
+ x2="302.85715"
+ y2="609.50507" />
+ <linearGradient
+ y2="56.0523"
+ x2="47.3197"
+ y1="11.1133"
+ x1="4.1914"
+ gradientUnits="userSpaceOnUse"
+ id="aigrd1">
+ <stop
+ id="stop6490"
+ style="stop-color:#D4D4D4"
+ offset="0" />
+ <stop
+ id="stop6492"
+ style="stop-color:#E2E2E2"
+ offset="0.3982" />
+ <stop
+ id="stop6494"
+ style="stop-color:#FFFFFF"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ y2="56.0523"
+ x2="47.3197"
+ y1="11.1133"
+ x1="4.1914"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7451"
+ xlink:href="#aigrd1"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient4126"
+ inkscape:collect="always">
+ <stop
+ id="stop4128"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop4130"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ r="17.142857"
+ fy="40.000000"
+ fx="23.857143"
+ cy="40.000000"
+ cx="23.857143"
+ gradientTransform="matrix(1,0,0,0.5,2.139286e-14,20)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7449"
+ xlink:href="#linearGradient4126"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6525"
+ id="linearGradient5250"
+ x1="8.5469341"
+ y1="30.281681"
+ x2="30.85088"
+ y2="48.301884"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.899009,0,0,0.934235,1.875108,1.193645)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd1"
+ id="linearGradient3922"
+ gradientUnits="userSpaceOnUse"
+ x1="4.1914"
+ y1="11.1133"
+ x2="47.3197"
+ y2="56.0523" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6525"
+ id="linearGradient3924"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.899009,0,0,0.934235,1.875108,1.193645)"
+ x1="8.5469341"
+ y1="30.281681"
+ x2="30.85088"
+ y2="48.301884" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6525"
+ id="linearGradient3933"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.899009,0,0,0.934235,1.875108,1.193645)"
+ x1="8.5469341"
+ y1="30.281681"
+ x2="30.85088"
+ y2="48.301884" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd1"
+ id="linearGradient3935"
+ gradientUnits="userSpaceOnUse"
+ x1="4.1914"
+ y1="11.1133"
+ x2="47.3197"
+ y2="56.0523" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#aigrd1"
+ id="linearGradient3946"
+ gradientUnits="userSpaceOnUse"
+ x1="4.1914"
+ y1="11.1133"
+ x2="47.3197"
+ y2="56.0523" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6525"
+ id="linearGradient3948"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.899009,0,0,0.934235,1.875108,1.193645)"
+ x1="8.5469341"
+ y1="30.281681"
+ x2="30.85088"
+ y2="48.301884" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="14.757891"
+ inkscape:cx="24"
+ inkscape:cy="24"
+ inkscape:current-layer="g7435"
+ showgrid="true"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:window-width="1105"
+ inkscape:window-height="1084"
+ inkscape:window-x="157"
+ inkscape:window-y="16"
+ gridempspacing="4" />
+ <metadata
+ id="metadata1382">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Dialog Warning</dc:title>
+ <dc:date>2005-10-14</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Andreas Nilsson</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Jakub Steiner, Garrett LeSage</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>dialog</rdf:li>
+ <rdf:li>warning</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ transform="matrix(1.566667,0.000000,0.000000,1.566667,-8.925566,-23.94764)"
+ id="g7435">
+ <g
+ style="display:inline"
+ transform="matrix(1.444074e-2,0,0,1.331973e-2,33.38871,40.40337)"
+ id="g6707">
+ <rect
+ style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect6709"
+ width="1339.6335"
+ height="478.35718"
+ x="-1559.2523"
+ y="-150.69685" />
+ <path
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+ id="path6711"
+ sodipodi:nodetypes="cccc" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path6713"
+ d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <g
+ id="g3937"
+ transform="matrix(1,0,4.537846e-3,1,-0.138907,-1.394718e-15)"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true">
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ transform="matrix(1,0,-8.726683e-3,1,0.328074,1.276596)"
+ id="path6485"
+ d="M 33.282781,38.644744 L 22.407791,18.394765 C 22.095292,17.832266 21.532792,17.519767 20.907793,17.519767 C 20.282793,17.519767 19.720294,17.894765 19.407795,18.457265 L 8.7828048,38.707245 C 8.5328048,39.207244 8.5328048,39.894744 8.8453048,40.394743 C 9.1578038,40.894743 9.6578038,41.144742 10.282804,41.144742 L 31.782782,41.144742 C 32.407781,41.144742 32.97028,40.832243 33.220281,40.332243 C 33.53278,39.832243 33.53278,39.207244 33.282781,38.644744 z "
+ style="fill:#cc0000;fill-rule:nonzero;stroke:#9f0000;stroke-width:0.6382978;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ id="g6487"
+ transform="matrix(0.625,0,-5.534934e-3,0.634254,6.164053,15.76055)"
+ style="fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4">
+ <linearGradient
+ y2="56.052299"
+ x2="47.319698"
+ y1="11.1133"
+ x1="4.1914001"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient6525">
+ <stop
+ id="stop6529"
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0" />
+ <stop
+ id="stop6531"
+ style="stop-color:#ffffff;stop-opacity:0.34020618;"
+ offset="1" />
+ </linearGradient>
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ id="path6496"
+ d="M 9.5,37.6 C 9.2,38.1 9.5,38.5 10,38.5 L 38.2,38.5 C 38.7,38.5 39,38.1 38.7,37.6 L 24.4,11 C 24.1,10.5 23.7,10.5 23.5,11 L 9.5,37.6 z "
+ style="fill:url(#linearGradient3946);stroke:none" />
+ </g>
+ <path
+ inkscape:r_cy="true"
+ inkscape:r_cx="true"
+ transform="matrix(1,0,-8.726683e-3,1,0.318277,1.276596)"
+ sodipodi:nodetypes="ccsccscccc"
+ id="path1325"
+ d="M 32.323106,38.183905 L 22.150271,19.265666 C 21.71698,18.45069 21.561698,18.189213 20.908406,18.189213 C 20.346525,18.189213 20.054127,18.57002 19.651305,19.339291 L 9.7489285,38.242296 C 9.1737649,39.303588 9.1128238,39.580228 9.3937644,40.047345 C 9.6747034,40.514462 10.032797,40.48902 11.356441,40.519491 L 30.974593,40.519491 C 32.206825,40.534726 32.483988,40.440837 32.70874,39.97372 C 32.989681,39.506602 32.867799,39.136 32.323106,38.183905 z "
+ style="opacity:0.5;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3948);stroke-width:0.63829792;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ style="fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4"
+ transform="matrix(0.555088,0,0,0.555052,7.749711,17.80196)"
+ id="g6498"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true">
+ <path
+ style="stroke:none"
+ d="M 23.9,36.5 C 22.6,36.5 21.6,35.5 21.6,34.2 C 21.6,32.8 22.5,31.9 23.9,31.9 C 25.3,31.9 26.1,32.8 26.2,34.2 C 26.2,35.5 25.3,36.5 23.9,36.5 L 23.9,36.5 z M 22.5,30.6 L 21.9,19.1 L 25.9,19.1 L 25.3,30.6 L 22.4,30.6 L 22.5,30.6 z "
+ id="path6500"
+ inkscape:r_cx="true"
+ inkscape:r_cy="true" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/manual/images/tango-icons/emblem-important.svg b/manual/images/tango-icons/emblem-important.svg
new file mode 100644
index 0000000000..835d6fcc96
--- /dev/null
+++ b/manual/images/tango-icons/emblem-important.svg
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48px"
+ height="48px"
+ id="svg1800"
+ sodipodi:version="0.32"
+ inkscape:version="0.43+devel"
+ sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/emblems"
+ sodipodi:docname="emblem-important.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs3">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3101">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3103" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3105" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3101"
+ id="radialGradient3107"
+ cx="17.3125"
+ cy="25.53125"
+ fx="17.3125"
+ fy="25.53125"
+ r="9.6875"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,0.351613,1.292803e-15,16.55413)"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ fill="#edd400"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.20392157"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="66.140367"
+ inkscape:cy="14.79073"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="872"
+ inkscape:window-height="891"
+ inkscape:window-x="370"
+ inkscape:window-y="110" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+ <dc:title>Emblem Important</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>emblem</rdf:li>
+ <rdf:li>photos</rdf:li>
+ <rdf:li>pictures</rdf:li>
+ <rdf:li>raw</rdf:li>
+ <rdf:li>jpeg</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Notice" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/Attribution" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://web.resource.org/cc/ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.40909091;color:#000000;fill:url(#radialGradient3107);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.1053395;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+ id="path3099"
+ sodipodi:cx="17.312500"
+ sodipodi:cy="25.531250"
+ sodipodi:rx="9.6875000"
+ sodipodi:ry="3.4062500"
+ d="M 27.000000 25.531250 A 9.6875000 3.4062500 0 1 1 7.6250000,25.531250 A 9.6875000 3.4062500 0 1 1 27.000000 25.531250 z"
+ transform="matrix(2.182912,0.000000,0.000000,2.182912,-13.50372,-14.35012)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1.0000000;fill:#f57900;fill-opacity:1.0000000;fill-rule:nonzero;stroke:#914900;stroke-width:0.98214942;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path1650"
+ sodipodi:cx="24.130018"
+ sodipodi:cy="23.428040"
+ sodipodi:rx="22.008699"
+ sodipodi:ry="21.213203"
+ d="M 46.138718 23.428040 A 22.008699 21.213203 0 1 1 2.1213188,23.428040 A 22.008699 21.213203 0 1 1 46.138718 23.428040 z"
+ transform="matrix(0.944630,0.000000,0.000000,0.980053,1.504174,-1.556912)" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1.0000000;fill:none;fill-opacity:1.0000000;fill-rule:nonzero;stroke:#fcaf3e;stroke-width:0.98214942;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path3392"
+ sodipodi:cx="24.130018"
+ sodipodi:cy="23.428040"
+ sodipodi:rx="22.008699"
+ sodipodi:ry="21.213203"
+ d="M 46.138718 23.428040 A 22.008699 21.213203 0 1 1 2.1213188,23.428040 A 22.008699 21.213203 0 1 1 46.138718 23.428040 z"
+ transform="matrix(0.914086,0.000000,0.000000,0.948364,2.380576,-0.905815)" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1224999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 21.464926,10.373268 C 21.336952,10.373268 21.230316,10.547762 21.230316,10.757175 L 22.295085,25.197999 C 22.295085,25.407412 22.401721,25.581906 22.529695,25.581907 C 22.529695,25.581907 23.370516,25.593810 24.063684,25.581907 C 24.292022,25.577986 24.361898,25.602219 24.568998,25.581907 C 25.262166,25.593810 26.102987,25.581907 26.102987,25.581907 C 26.230961,25.581907 26.337597,25.407412 26.337597,25.197999 L 27.402366,10.757175 C 27.402366,10.547762 27.295730,10.402799 27.167755,10.402799 L 24.587044,10.402799 C 24.577532,10.400862 24.578842,10.373268 24.568998,10.373268 L 21.464926,10.373268 z "
+ id="rect1872" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:1.0000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.1224999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ id="path2062"
+ sodipodi:cx="-16.437500"
+ sodipodi:cy="34.062500"
+ sodipodi:rx="4.5625000"
+ sodipodi:ry="3.8125000"
+ d="M -11.875000 34.062500 A 4.5625000 3.8125000 0 1 1 -21.000000,34.062500 A 4.5625000 3.8125000 0 1 1 -11.875000 34.062500 z"
+ transform="matrix(0.504864,0.000000,0.000000,0.604182,32.65935,9.608845)" />
+ <path
+ style="fill:#fffeff;fill-opacity:0.21390374;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
+ d="M 43.676426,20.476780 C 43.676426,31.307396 37.624257,16.170581 25.001688,20.863168 C 12.279172,25.592912 4.4350535,31.307396 4.4350535,20.476780 C 4.4350535,9.6461627 13.225120,0.85609769 24.055740,0.85609769 C 34.886359,0.85609769 43.676426,9.6461627 43.676426,20.476780 z "
+ id="path3068"
+ sodipodi:nodetypes="czssc" />
+ </g>
+</svg>
diff --git a/manual/images/tango-icons/important.png b/manual/images/tango-icons/important.png
new file mode 100644
index 0000000000..6bdddcbe35
--- /dev/null
+++ b/manual/images/tango-icons/important.png
Binary files differ
diff --git a/manual/images/tango-icons/note.png b/manual/images/tango-icons/note.png
new file mode 100644
index 0000000000..45c3643877
--- /dev/null
+++ b/manual/images/tango-icons/note.png
Binary files differ
diff --git a/manual/images/tango-icons/tip.png b/manual/images/tango-icons/tip.png
new file mode 100644
index 0000000000..98d249a3be
--- /dev/null
+++ b/manual/images/tango-icons/tip.png
Binary files differ
diff --git a/manual/images/tango-icons/warning.png b/manual/images/tango-icons/warning.png
new file mode 100644
index 0000000000..cee66db38a
--- /dev/null
+++ b/manual/images/tango-icons/warning.png
Binary files differ
diff --git a/manual/images/title-bg.png b/manual/images/title-bg.png
new file mode 100644
index 0000000000..00fc7ed920
--- /dev/null
+++ b/manual/images/title-bg.png
Binary files differ
diff --git a/manual/images/track_name_field.png b/manual/images/track_name_field.png
new file mode 100644
index 0000000000..8cf02b9941
--- /dev/null
+++ b/manual/images/track_name_field.png
Binary files differ
diff --git a/manual/images/transctls.jpg b/manual/images/transctls.jpg
new file mode 100644
index 0000000000..695c593176
--- /dev/null
+++ b/manual/images/transctls.jpg
Binary files differ
diff --git a/manual/images/watermark-draft.png b/manual/images/watermark-draft.png
new file mode 100644
index 0000000000..b4fffd2bad
--- /dev/null
+++ b/manual/images/watermark-draft.png
Binary files differ
diff --git a/manual/templates/chapter_template.xml b/manual/templates/chapter_template.xml
new file mode 100644
index 0000000000..ea286543c3
--- /dev/null
+++ b/manual/templates/chapter_template.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!ENTITY % BOOK_ENTITIES SYSTEM "./entities.ent">
+%BOOK_ENTITIES;
+
+]>
+
+<chapter id="ch-template">
+
+ <title>Chapter Template</title>
+ <subtitle>Subtitle</subtitle>
+
+ <section>
+ <title>Section</title>
+
+ </section>
+
+ <!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+
+</chapter>
diff --git a/manual/templates/section_template.xml b/manual/templates/section_template.xml
new file mode 100644
index 0000000000..e5cb7ae34d
--- /dev/null
+++ b/manual/templates/section_template.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!ENTITY % BOOK_ENTITIES SYSTEM "./entities.ent">
+%BOOK_ENTITIES;
+
+]>
+
+<section id="sn-template">
+
+ <title>Section Template</title>
+ <subtitle>Subtitle</subtitle>
+
+ <para>
+ A paragraph
+ </para>
+
+ <!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+
+</section>
diff --git a/manual/xml/adding_tracks.xml b/manual/xml/adding_tracks.xml
new file mode 100644
index 0000000000..999c65959a
--- /dev/null
+++ b/manual/xml/adding_tracks.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-adding-tracks">
+ <title>Adding Tracks</title>
+ <para>
+ To add a new Track or Bus activate the New Track Dialog
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <menuchoice> <guimenu>Session</guimenu> <guisubmenu>Add
+ Track/Bus</guisubmenu> </menuchoice>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/add_track_bus.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ In the Add Tracks dialog, choose whether you wish to add a new Track or
+ a new Bus.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Enter the number of new tracks/busses you want to add.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Choose the I/O configuration of the tracks/busses you are adding using
+ the clickbox.
+ </para>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/advanced_editing.xml b/manual/xml/advanced_editing.xml
new file mode 100644
index 0000000000..980f333d5c
--- /dev/null
+++ b/manual/xml/advanced_editing.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-advanced-editing">
+ <title>Advanced Editing</title>
+ <para>
+ This section of the manual covers various editing techniques that go
+ beyond basic cutting/trimming/rearranging of regions in a playlist.
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="working_with_crossfades.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="working_with_layers.xml" />
+</chapter>
diff --git a/manual/xml/ardour_basics.xml b/manual/xml/ardour_basics.xml
new file mode 100644
index 0000000000..d936f317f5
--- /dev/null
+++ b/manual/xml/ardour_basics.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-ardour-basics">
+ <title>Ardour Basics</title>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="sessions.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="jack.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="main_windows.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_window.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mixer_window.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="tracks_and_busses.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="clocks.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="other_windows.xml" />
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</chapter>
diff --git a/manual/xml/ardour_manual.xml b/manual/xml/ardour_manual.xml
new file mode 100644
index 0000000000..abbed68e2d
--- /dev/null
+++ b/manual/xml/ardour_manual.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Entities -->
+
+]>
+
+<book id="bk-ardour-manual">
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="book_info.xml" />
+
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="preface.xml" />
+ -->
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="introduction.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="ardour_basics.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="using_existing_audio.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="basic_editing.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="advanced_editing.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="exporting.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mixing.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="recording.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="synchronization.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="control_surfaces.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="known_issues.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="glossary.xml" />
+
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="contributing_to_the_manual.xml" />
+</book>
diff --git a/manual/xml/automation.xml b/manual/xml/automation.xml
new file mode 100644
index 0000000000..0f19d0720e
--- /dev/null
+++ b/manual/xml/automation.xml
@@ -0,0 +1,223 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-automation">
+ <title>Automation</title>
+ <para>
+ This chapter will explain how to use Ardour's automation facilities to
+ make editing and mixing your sessions more productive.
+ </para>
+
+ <section id="what-is-automation">
+ <title> What is automation? </title>
+ <para>
+ Automation refers to Ardour's ability to remember changes you made to
+ various parameters in the session, and at what point along the
+ timeline playback had reached when you made them. Later, Ardour can
+ make these changes happen automatically at the same point on the
+ timeline, thus leaving your hands free to do something else. A typical
+ practice when using automation is to work on one or two tracks while
+ leaving others alone, recording the edits/changes. Once satisfied with
+ the track(s), you can move on to adjust other tracks. As the overall
+ mix changes, you can return to earlier tracks and adjust their
+ existing automation.
+ </para>
+ </section>
+
+ <section id="what-can-be-automated">
+ <title> What can be automated? </title>
+ <para>
+ You can automate all changes to track/bus gain control, panning
+ (currently only for stereo output) and all plugin parameters. Future
+ versions of Ardour will allow automation of mute/solo controls,
+ non-stereo panning, and send gain levels.
+ </para>
+ </section>
+
+ <section id="automation-modes">
+ <title> Automation Modes </title>
+ <para>
+ Each parameter that can be automated has a button available to control
+ its state of automation. Each button can be used to put the parameter
+ into one of 4 possible automation states:
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term>Off</term>
+ <listitem>
+ <para>
+ No changes to the parameter are recorded, and any existing
+ automation for the parameter is ignored. This is the default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Play</term>
+ <listitem>
+ <para>
+ Existing automation data controls the value of the parameter,
+ and graphical/hardware editing of the value is disabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Write</term>
+ <listitem>
+ <para>
+ All changes to the parameter are recorded as new automation
+ data, overwriting any existing data for that point in time.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Touch</term>
+ <listitem>
+ <para>
+ Existing automation data controls the value of the parameter,
+ but new changes to the parameter are recorded, overwriting any
+ existing data for that point in time.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="basic-automation-recording">
+ <title> Basic Automation Recording </title>
+ <section id="automation-recording-gain-and-pan">
+ <title> Gain and Pan </title>
+ <para>
+ Each track/bus has two automation control buttons for gain and pan
+ in its mixer strip. For each track/bus that you wish to automate,
+ click on the relevant automation button. From the popup menu that
+ appears (showing all automation states) choose
+ <guibutton>Record</guibutton> . As long as the automation state
+ remains in "Record", then any changes you make to gain or pan for
+ that track/bus will be recorded.
+ </para>
+ </section>
+
+ <section id="automation-recording-plugin-parameters">
+ <title> Plugin Parameters </title>
+ <para>
+ Many plugins have many parameters that you might wish to play while
+ recording gain automation, so Ardour offers independent control of
+ recording changes to these parameters. You can access the controls
+ in either of two ways:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ open the plugin's editor window, and click on the appropriate
+ automation control button. From the menu that pops up, choose
+ <guibutton>Record</guibutton>
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ make the automation track for this parameter visible (see
+ plugin_automation_tracks on how to do this), and click on the
+ automation control button in the track controls. From the menu
+ that pops up, choose <guibutton>Record</guibutton> .
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ To record edits to the parameter, click on the appropriate
+ <guibutton>arec</guibutton> button. As long as the button stays
+ pressed, all edits to that parameter will be recorded.
+ </para>
+ </section>
+ </section>
+
+ <section id="basic-automation-playback">
+ <title> Basic Automation Playback </title>
+ <section id="automation-playback-gain-and-pan">
+ <title> Gain and Pan </title>
+ <para>
+ Each track/bus has two automation control buttons for gain and pan
+ in its mixer strip. For each track/bus where you want existing
+ automation data to control gain and/or panning, click on the
+ relevant automation button. From the popup menu that appears
+ (showing all automation states) choose
+ <guimenuitem>Play</guimenuitem>. As long as the automation state
+ remains in <guimenuitem>Play</guimenuitem>, you can no longer
+ control the gain and/or panning from the graphical user interface or
+ an external hardware control surface.
+ </para>
+ </section>
+
+ <section id="automation-playback-plugin-parameters">
+ <title> Plugin Parameters </title>
+ <para>
+ For each plugin parameter you want controlled by automation data,
+ you need to activate automation playback which can be done in one of
+ two ways:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ open the plugin's editor window, and click on the appropriate
+ automation control button, and choose
+ <guimenuitem>Play</guimenuitem> from the menu that pops up.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ make the automation track for this parameter visible (see
+ plugin_automation_tracks on how to do this), and click on the
+ automation control button in the track controls. Choose
+ <guimenuitem>Play</guimenuitem> from the menu that pops up.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ You also need to enable automation playback for the plugin itself.
+ This needs to be done in the plugin's editor window by clicking on
+ the automation button in the upper right corner. Without this step,
+ the individual parameter buttons will not enable automation
+ playback.
+ </para>
+
+ <para>
+ The plugin automation button also allows you to globally disable
+ automation control of all parameters by unsetting it (clicking it so
+ that it is no longer "pressed"). This leaves the individual
+ automation control buttons in whatever state they were already in,
+ but it stops the use of automation data for all parameters. This can
+ be useful if you have a hardware control surface, and have
+ automation-playback-enabled several parameters. You can override the
+ automation playback settings and manually control parameter values
+ from the control surface without having to click on each parameter's
+ automation control button individually.
+ </para>
+ </section>
+ </section>
+
+ <section id="editing-automation-data">
+ <title> Editing Automation Data </title>
+ <para>
+ The editor window can display all automation data for a track. Each
+ type of automation data is shown in its own "track" to make it easy to
+ see the data, and to edit it.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/basic_editing.xml b/manual/xml/basic_editing.xml
new file mode 100644
index 0000000000..4f19157b61
--- /dev/null
+++ b/manual/xml/basic_editing.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-basic-editing">
+ <title>Basic Editing</title>
+ <para>
+ Once you have recorded or imported the material that will make up a
+ session/piece/composition, it will generally become time to
+ <emphasis>edit</emphasis> it. You can add/remove material at any time,
+ and/or modify the mix if you desire. But editing tends to be a distinct
+ focus during the "middle" part of working on an arrangement, and has its
+ own particular set of tools and approaches. This section of the manual
+ covers the editing tools you will probably use all the time; see
+ <xref linkend="ch-advanced-editing"/> for coverage of more specialized
+ tools and techniques.
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editing_concepts.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="working_with_playlists.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="working_with_ranges.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="working_with_regions.xml" />
+</chapter>
diff --git a/manual/xml/basic_recording.xml b/manual/xml/basic_recording.xml
new file mode 100644
index 0000000000..ba40c96ebc
--- /dev/null
+++ b/manual/xml/basic_recording.xml
@@ -0,0 +1,273 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<!-- XXX This needs a fair amount of work-->
+
+<section id="sn-basic-recording">
+ <title>Basic Recording</title>
+ <para>
+ Recording audio is theoretically a very simple process. You have to make
+ essentially 2 decisions: what are you going to record, and how many
+ channels will you be recording, then press a couple of buttons and
+ you're recording.
+ </para>
+
+ <para>
+ Unfortunately, most recording also requires monitoring&mdash;providing
+ some way to hear what you are recording as you record it, possibly with
+ existing recorded material as well. Monitoring in Ardour is very
+ flexible, but with flexibility comes complexity. If you want to try to
+ skip ahead and record without reading about monitoring, you are welcome
+ to do so. Ardour attempts to use reasonable defaults for monitoring, but
+ the variety of hardware setups make it impossible to pick one default
+ that will work for everyone.
+ </para>
+
+ <para>
+ For this reason, you are strongly recommended to spend a few minutes
+ understanding <xref linkend="sn-monitoring"/>, because otherwise you're
+ going to get very confused and possibly irritated.
+ </para>
+
+ <section id="recording-a-single-track">
+ <title>Recording a single audio track</title>
+ <para>
+ These steps can all be taken directly within the Editor window,
+ although most of them can also be done via Mixer window if you prefer.
+ </para>
+ </section>
+
+ <section id="setting-up-a-new-track-for-recording">
+ <title>Setting up a new track for recording</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ Choose <menuchoice> <guimenu>Session</guimenu> <guisubmenu>Add
+ Track/Bus</guisubmenu> </menuchoice>. This will popup a dialog
+ allowing you to choose how many tracks to add, and what basic I/O
+ configuration the track will have (mono, stereo, etc.). You can
+ change I/O configurations for tracks at any time.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Make the editor's dedicated mixer strip visible by clicking on the
+ <guibutton>Editor Mixer</guibutton> button located at the left end
+ of the transport bar.
+ <note>
+ <para>
+ In Ardour2, there is no <guibutton>Editor Mixer</guibutton>
+ button, but you can make the mixer strip visible by selecting
+ <menuchoice> <guimenu>View</guimenu> <guisubmenu>Show Editor
+ Mixer</guisubmenu> </menuchoice>, or by pressing
+ <keycombo><keycap>Shift</keycap><keycap>E</keycap></keycombo>
+ on the keyboard.
+ </para>
+ </note>
+ </para>
+ </listitem>
+ </orderedlist>
+ <section id="selecting-record-source">
+ <title>Selecting the source to record</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ Check the input configuration for the new track. Click on its
+ control area. A mixer strip appears in the editor for this
+ track. Click on the <guibutton>Input</guibutton> button near the
+ top of the strip, and select <guimenuitem>Edit</guimenuitem>
+ from the menu. The standard I/O dialog pops up to let you
+ connect the track to whichever JACK port you want to record
+ from.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Rename the track. This is an important step in helping you make
+ sense of your session, because track names are used when naming
+ newly created regions.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Click on the track's record-enable button to record enable the
+ track. You can use the <guibutton>r</guibutton> button in the
+ track control area or the <guibutton>record</guibutton> button
+ of the mixer strip. The button will turn pink.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Adjust the output level of the sound source to the a level where
+ the loudest input drives the meter in the mixer strip close to,
+ but not over, 0dB. The mixer strip will show the incoming signal
+ level, along with peak indicators
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If you are using software monitoring, adjust the output volume
+ and possibly panning if desired. These settings do not affect
+ the recorded material.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ Check the output configuration for the new track. Click on the
+ <guibutton>Output</guibutton> button near the bottom of the strip,
+ and select <guimenuitem>Edit</guimenuitem> from the menu. Make sure
+ the track's output is connected as you intend.
+ </para>
+
+ <note>
+ <para>
+ by default (and when not using a session template that works
+ otherwise) mono tracks have mono outputs, meaning that you cannot
+ pan them.
+ </para>
+ </note>
+ </section>
+ </section>
+
+ <section id="to-record-to-the-new-audio-track">
+ <title>To record to the new audio track</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ If necessary, setup the session's default meter and tempo by on
+ the initial meter and tempo markers.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If desired, enable the click track in the transport bar.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Click on the <guimenuitem>Record</guimenuitem> button of the
+ transport window, which will start to flash.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ When you are ready to record, click the
+ <guibutton>Play</guibutton> button in the transport window.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ When you have finished recording, click the
+ <guibutton>Stop</guibutton> button in the transport window.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If desired, click the track's record-enable button to disengage
+ record-enable for this track.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ The audio you recorded will be written to a new audio file stored on
+ one of your disks. In the editor, a new region will appear in the
+ track display area and also in the region list display.
+ </para>
+ </section>
+
+ <section id="to-playback-the-new-audio-track">
+ <title>To play back the new audio track</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ Press the <keycap>Home</keycap> key (or
+ <keycombo><keycap>Ctrl</keycap><keycap>A</keycap></keycombo>) to
+ return the playhead to the start of the track
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ In the transport bar click on the <guibutton>Play</guibutton>
+ button, or press the <keycap>spacebar</keycap>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Adjust the track's volume as necessary, using either the mixer
+ strip in the editor, or the corresponding strip in the mixer
+ window.
+ </para>
+ </listitem>
+ </orderedlist>
+ </section>
+
+ <section id="cancelling-a-take">
+ <title>Cancelling a take</title>
+ <para></para>
+ </section>
+
+ <section id="recording-multiple-tracks">
+ <title>Recording multiple tracks</title>
+ <para>
+ Multiple tracks can easily be recorded simultaneously by
+ record-enabling each track you would like to record.
+ </para>
+ </section>
+
+ <section id="recording-additional-takes">
+ <title>Recording additional takes</title>
+ <para></para>
+ </section>
+
+ <section id="appending-new-material">
+ <title>Appending new material</title>
+ <para></para>
+ </section>
+
+ <section id="recording-into-a-new-playlist">
+ <title>Recording into a new playlist</title>
+ <para>
+ There is a <guibutton>p</guibutton> button in the track controls. If
+ you press it and select <guimenuitem>new playlist</guimenuitem>, the
+ contents will be cleared, allowing you to construct a new arrangement
+ of recordings. You can recall your playlist later by using the same
+ button and selecting <guimenuitem>select...</guimenuitem>. This will
+ open a window displaying all the playlists you have recorded on that
+ track. Select the one you want and proceed. Playlists from other
+ tracks can also be selected.. in fact you can have the same playlist
+ on two different tracks if you feel it necessary.
+ </para>
+ </section>
+
+ <section id="punch-recording">
+ <title>Punch Recording</title>
+ <para>
+ You can automate the portion of a track to be recorded using the punch
+ functions. This is most often implemented when a portion of a
+ particular take is problematic but an adjacent portion is good. In
+ order to punch record, the punch range must be set.
+ </para>
+ </section>
+
+ <section id="loop-recording">
+ <title>Loop Recording</title>
+ <para></para>
+ </section>
+
+ <section id="setting-punch-loop-points">
+ <title>Setting Punch/Loop Points</title>
+ <para></para>
+ </section>
+
+ <section id="using-pre-and-post-roll">
+ <title>Using Pre- and Post-Roll</title>
+ <para></para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/bcf2000.xml b/manual/xml/bcf2000.xml
new file mode 100644
index 0000000000..64c1b2f246
--- /dev/null
+++ b/manual/xml/bcf2000.xml
@@ -0,0 +1,671 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-bcf2000">
+ <title>Using a BCF2000</title>
+ <para>
+ This will walk you through the process of configuring and using a
+ <ulink url="http://www.behringer.com/BCF2000/index.cfm">Behringer
+ BCF2000 MIDI control surface</ulink> , or BCF, with Ardour. This should
+ also work with the
+ <ulink url="http://www.behringer.com/BCR2000/index.cfm">BCR2000</ulink>,
+ but has not been tested.
+ </para>
+
+ <section id="bcf2000-connecting-device">
+ <title>Connecting Device</title>
+ <para>
+ It's assumed that your USB ports are functional under Linux. The
+ easiest way to tell if you've got a functional link is to simply
+ connect the BCF2000 to your computer with a USB cable, connect the
+ power, and turn it on. You should see the USB MODE light come on in
+ the upper right corner of the BCF. If that's not on, you'll need to
+ figure out how to make your <ulink url="http://www.linux-usb.org/">USB
+ port work under Linux.</ulink>
+ </para>
+
+ <para>
+ If the USB MODE light is on, doublecheck that Linux knows of the
+ device.
+ </para>
+<screen>
+xtc:~% aconnect -o
+client 64: 'M Audio Delta 1010 MIDI - Rawmidi 0' [type=kernel]
+ 0 'M Audio Delta 1010 MIDI'
+client 72: 'BCF2000 - Rawmidi 1' [type=kernel]
+ 0 'BCF2000 MIDI 1 '
+</screen>
+ </section>
+
+ <section id="updating-firmware">
+ <title> Firmware Updating (v1.07) </title>
+ <para>
+ The first thing you're likely to have to do is update the firmware in
+ the unit. This is a relatively painless process.
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Download the firmware from Behringers
+ <ulink url="http://www.behringer.com/05_support/bc_download/bc_downloads.cfm">downloads
+ page</ulink>. There will be a
+ <ulink url="http://www.behringer.com/BCF2000/bcf2000_107.zip">zip
+ file</ulink> available which should be downloaded. (This example
+ uses version 1.07 of the firmware, the latest available at the
+ time of this writing. There may be a newer version available now.)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Unzip the file you downloaded. You'll typically extract 2 files, a
+ PDF file with release notes and an SYX file, which is the firmware
+ update.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Find the system device of the BCF
+ </para>
+<screen>
+xtc:~% cat /proc/asound/cards
+0 [M1010 ]: ICE1712 - M Audio Delta 1010
+ M Audio Delta 1010 at 0xdf80, irq
+2 [BCF2000 ]: USB-Audio - BCF2000
+ BEHRINGER BCF2000 at usb-00:1d.1-2, full speed
+</screen>
+ </listitem>
+ </orderedlist>
+ <para>
+ In this case there are 2 devices. The number at the left indicates the
+ card number. The BCF is almost certain, then, to use the device
+ <filename>/dev/snd/midiCnD0</filename> where <emphasis>n</emphasis> is
+ the card number, in this case, 2.
+ </para>
+
+ <para>
+ Write the firmware to the BCF with the command
+ </para>
+<screen>
+cat bcf2000_1-07.syx > /dev/snd/midiC2D0
+</screen>
+ <important>
+ <para>
+ Make sure you use the actual device you determined in the previous
+ step
+ </para>
+ </important>
+
+ <para>
+ The BCF display will show a whirling figure-8 animation and count up
+ to 18. Once the whirling stops, you should turn off the BCF, count to
+ 5, then turn it on again. You should then see the version number of
+ the upgraded firmware displayed for a few seconds as the BCF starts.
+ </para>
+ </section>
+
+ <section id="bcf2000-connecting-to-ardour">
+ <title> Connecting to Ardour </title>
+ <para>
+ After starting Ardour, it's important to connect the MIDI device ports
+ of Ardour and the BCF together so that they will communicate with each
+ other. There are a few ways to do this.
+ </para>
+
+ <section id="bcf2000-connecting-with-qjackctl">
+ <title> With qjackctl </title>
+ <para>
+ If you use the program <application>qjackctl</application> to
+ control JACK, there's an easy way to connect Ardour to the BCF. Run
+ qjackctl, and click on the <guibutton>Connect</guibutton> button in
+ the main qjackctl window. This will bring up the Connection window.
+ You should see at least 2 items listed, the BCF and Ardour:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/con1.jpg"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Connect the BCF output to the Ardour input, and vice versa:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/con2.jpg"/>
+ </imageobject>
+ </mediaobject>
+ <section id="bcf2000-automating-qjackctl-connection">
+ <title> Automating the qjackctl connection </title>
+ <para>
+ You can set qjackctl to automatically make the MIDI connections
+ (and others) by using the Patchbay feature in qjackctl. Start
+ qjackctl and Ardour, and make the MIDI connections as shown above.
+ Click on the <guibutton>Patchbay</guibutton> button, then click on
+ <guibutton>New</guibutton>. Qjackctl will ask if you want to
+ create a patchbay definition as a snapshot of all actual client
+ connections. Clicking on <guibutton>Yes</guibutton> will bring in
+ a set of all ports available.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/qjpatch.jpg"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Make sure you've got both connections as described above, and
+ click <guibutton>Save...</guibutton> and choose a filename. Once
+ this is saved, you can close the patchbay.
+ </para>
+
+ <para>
+ Next, click on the qjackctl <guibutton>Setup</guibutton> button,
+ then click on the <guibutton>Options</guibutton> tab.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/qjopts.jpg"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Click on <guibutton>Activate patchbay persistence</guibutton> and
+ use the filename you used to save the patchbay above. The patchbay
+ connections will now be made after qjackctl starts up the clients.
+ </para>
+ </section>
+ </section>
+
+ <section id="bcf2000-connecting-from-command-line">
+ <title> From the command line </title>
+ <para>
+ The command <command>aconnect</command>, which is the ALSA sequencer
+ connection manager, can do the job of connecting the BCF to Ardour.
+ First find the numbers of the MIDI device ports for the two:
+ </para>
+<screen>
+xtc:~% aconnect -o
+client 64: 'M Audio Delta 1010 MIDI - Rawmidi 0' [type=kernel]
+ 0 'M Audio Delta 1010 MIDI'
+client 80: 'BCF2000 - Rawmidi 2' [type=kernel]
+ 0 'BCF2000 MIDI 1 '
+client 129: 'ardour' [type=user]
+ 0 'seq '
+</screen>
+ <para>
+ Here, the BCF is 80, and Ardour is 129. The proper connections can
+ be made between the two with two commands:
+ </para>
+<screen>
+xtc:~% aconnect 80:0 129:0
+xtc:~% aconnect 129:0 80:0
+</screen>
+ </section>
+
+ <section id="bcf2000-automatic-midi-connection">
+ <title> Automating the MIDI connection from the command line </title>
+ <para>
+ It's sometimes handy to start Ardour from the command line. I found
+ it irritating to have Ardour come up, and then have to manually make
+ the connections for the BCF. This was quickly solved by the
+ following script, which starts Ardour, finds the proper MIDI device
+ ports, and connects them:
+ </para>
+<screen>
+#!/bin/ksh
+# /usr/local/bin/start_ardour.sh
+#
+# April 17, 2005 - Joe Hartley (jh@brainiac.com)
+# A quick script to start Ardour and then make the MIDI connections between
+# the BCF2000 and Ardour.
+
+# start Ardour and give it a little time before setting the MIDI connections
+nohup /usr/bin/ardour &amp;
+sleep 3
+
+# Set the IDs - note that they'll both end with a colon
+BCF_ID=$(aconnect -o | grep BCF2000 | grep client | awk '{print $2}')
+ARD_ID=$(aconnect -o | grep ardour | awk '{print $2}')
+
+aconnect "$BCF_ID"0 "$ARD_ID"0
+aconnect "$ARD_ID"0 "$BCF_ID"0
+</screen>
+ <para>
+ As an alternative to the patchbay in qjackctl, you could have it run
+ this script to start Ardour and make the MIDI connections. Click the
+ <guibutton>Setup</guibutton> button and choose the
+ <guibutton>Options</guibutton> tab. Enable the <guibutton>Execute
+ script after Startup</guibutton> option, and change the line to call
+ the <filename>start_ardour.sh</filename> script. In this example, I
+ change directories to the drive I record to so new sessions will
+ open there by default before I run the script.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="qjopt.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </section>
+ </section>
+
+ <section id="bcf2000-programming">
+ <title> Programming the BCF2000 for effective use </title>
+ <para>
+ One problem that I ran into with the BCF2000 was that none of the
+ factory presets really did what I needed to control Ardour. I had a
+ modest set of things I wanted to use the BCF to control for a track:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Volume
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Panning
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Mute, solo and rec-enable
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Transport (play, stop, ffwd, rewind)
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Preset 2 (P2), the Simple Mixer, was almost there, but I could not map
+ the mute, solo and rec-enable controls in Ardour to a pushbutton on
+ the BCF. This was because in P2, the buttons sent a Program Change
+ signal, but Ardour expects a Control Change signal. This required
+ re-programming the BCF a bit. Here's a list of the controls and what I
+ mapped them to send:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Rotary knobs 1 through 8, when pressed: CC33 through CC40
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ First row of buttons: CC65 through CC72
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ second row of buttons: CC73 through CC80
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Here's a quick walkthrough to program the controls on the BCF. First
+ we'll do the rotary knobs:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Hold down the EDIT button and press the rotary control. The
+ display will show b1.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Turn the rotary control labeled "TYPE" until the display reads
+ "CC".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Turn the rotary control labeled "PAR" until the display reads
+ "33".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Turn the rotary control labeled "MODE" until the display reads "t
+ on".
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Press the EXIT button.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ Continue to program the other rotary controls in the same way,
+ incrementing the value set by the "PAR" control by 1 each time. This
+ will set the CC parameter for the second knob to 34, the third knob to
+ 35, and so on.
+ </para>
+
+ <para>
+ The steps are the same for the two rows of pushbuttons under the
+ rotary knobs. The CC values for the first row of buttons run from 65
+ to 72, and from 73 to 80 for the second row.
+ </para>
+
+ <para>
+ Finally, you need to store these changes so that they'll be kept even
+ when the BCF has its power cycled.
+ <orderedlist>
+ <listitem>
+ <para>
+ Press the STORE button. Its LED will start to flash.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select a different preset number if you wish with the left and
+ right PRESET buttons.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Press STORE again to write the settings to an empty preset. If
+ you want to overwrite an existing preset, press STORE twice. You
+ can cancel the store at any time by pressing EXIT.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>
+ Your BCF2000 is now ready to control Ardour!
+ </para>
+
+ <section id="bcf2000-preconfigured-preset-file">
+ <title> Preconfigured Preset File </title>
+ <para>
+ Here is a <ulink url="http://zappa.brainiac.com/preset1.syx">saved
+ preset file</ulink>, which has the definitions described above. You
+ can use <command>amidi</command> to load this into the BCF as
+ <xref linkend="bcf2000-loading-a-preset"/>.
+ </para>
+ </section>
+ </section>
+
+ <section id="bcf2000-mapping-ardour-controls">
+ <title> Mapping Ardour controls to the BCF2000 </title>
+ <para>
+ The final step to control surface Nirvana is to map the controls in
+ Ardour to the knobs, buttons and faders on the BCF.
+ </para>
+
+ <para>
+ Before you can map things properly, you'll need to set the MIDI
+ options within Ardour. In the Editor window of Ardour, choose
+ <menuchoice> <guimenu>Windows</guimenu> <guisubmenu>Options
+ Editor</guisubmenu> </menuchoice>. Make sure the seq device is online,
+ and make sure <guibutton>MTC</guibutton>, <guibutton>MMC</guibutton>
+ and <guibutton>MIDI Parameter Control</guibutton> is set for the seq
+ device. Also make sure that the 4 boxes below are checked:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <guibutton>MMC control</guibutton>
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <guibutton>MIDI parameter control</guibutton>
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <guibutton>Send MMC</guibutton>
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <guibutton>Send MIDI parameter feedback</guibutton>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/midiopts.jpg"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Now you're ready to do the actual mapping. This is a pretty simple
+ process, all controlled with a <keycombo><keycap>Ctrl</keycap>
+ <mousebutton>Button2</mousebutton> </keycombo> click. This will pop up
+ a little window which says <guilabel>operate MIDI controller
+ now</guilabel>. Simply press the BCF button (or move the slider) that
+ you want to have control the Ardour function.
+ </para>
+
+ <section id="bcf2000-example">
+ <title>Example</title>
+ <para>
+ We want to map the Master fader in Ardour to the first slider on the
+ BCF. Hold down the <keycap>Ctrl</keycap> key on your keyboard, and
+ click with <mousebutton>Button2</mousebutton> on the Master fader in
+ Ardour. You should see the <guilabel>operate MIDI controller
+ now</guilabel>. Move the first slider on the BCF up or down a bit.
+ The window should disappear, and you should see the master fader
+ move up and down as you move the slider on the BCF. If that works,
+ move the fader in Ardour with your mouse. You should see the slider
+ on the BCF move up and down in tandem with the Master fader!
+ </para>
+
+ <para>
+ If the "operate MIDI controller now" window does not go away, there
+ is no connection between Ardour and the BCF. Make sure you've
+ properly connected the two as outlined in the Connecting to Ardour
+ section.
+ </para>
+ </section>
+
+ <section id="bcf2000-transport-controls">
+ <title> Transport Controls </title>
+ <para>
+ The 4 buttons in the lower right corner are already mapped in Preset
+ 2 to the MMC transport controls Home (or rewind to the beginning of
+ the session), Fast Forward, Stop and Play, as shown here.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/transctls.jpg"/>
+ </imageobject>
+ </mediaobject>
+ </section>
+ </section>
+
+ <section id="bcf2000-saving-and-loading-presets">
+ <title> Saving and Loading Presets </title>
+ <para>
+ After beating my head against a wall trying to get various programs
+ that handle SysEx messages to do what I wanted, I realized that once
+ again, the simplest way for me to do this the first time through is
+ from the command line. <glossterm linkend="gt-alsa">ALSA</glossterm>
+ provides the perfect tool for saving and loading files:
+ <command>amidi</command>
+ </para>
+
+ <para>
+ First, use <command>amidi</command> to list the available ports:
+ </para>
+<screen>
+xtc:~% amidi -l
+Device Name
+hw:0,0 M Audio Delta 1010 MIDI
+hw:2,0,0 BCF2000 MIDI 1
+</screen>
+ <para>
+ There's the BCF, at port hw:2 (we can ignore everything after the
+ first number after the colon). We'll tell amidi to use this port with
+ the -p option
+ </para>
+
+ <section id="bcf2000-saving-a-preset">
+ <title> Saving a Preset </title>
+ <para>
+ There's 2 parts to saving a preset: telling the BCF to send the
+ data, and telling the computer to accept it.
+ </para>
+
+ <section id="bcf2000-recieving-the-data">
+ <title> Receiving the Data </title>
+ <para>
+ Run <command>amidi</command>, using the <option>-p</option> option
+ to specify the port, and the <option>-r</option> option to receive
+ the date into.
+ </para>
+<screen>
+xtc:~% amidi -p hw:2 -r preset1.syx
+</screen>
+ <para>
+ The system will collect data from the MIDI port now until it's
+ told to stop with a
+ <keycombo><keycap>Ctrl</keycap><keycap>C</keycap> </keycombo> so
+ it's time to send some data.
+ </para>
+ </section>
+
+ <section id="bcf2000-sending-the-data">
+ <title> Sending the Data </title>
+ <para>
+ To send the MIDI data for the current preset to the computer, hold
+ down the Edit key on the BCF and press the Store button. They
+ should both stay lit and the display should read
+<screen>
+ EG
+</screen>
+ . This is the Global Edit mode.
+ </para>
+
+ <para>
+ You can choose whether to send the current preset's data or the
+ data for all 32 presets by turning the Mode knob, #6, and
+ selecting either
+<screen>
+ All
+</screen>
+ or
+<screen>
+ SnGl
+</screen>
+ . When ready to send the data, press knob 6. The display on the
+ BCF will circle around while it's sending data, and return to
+<screen>
+ EG
+</screen>
+ when complete. At this point,
+ <keycombo><keycap>Ctrl</keycap><keycap>C</keycap> </keycombo> out
+ of amidi. You'll see a report on the amount of data read:
+ </para>
+<screen>
+xtc:~% amidi -p hw:2 -r preset1.syx
+13169 bytes read
+
+xtc:~% ls -l preset1.syx
+-rw-r--r-- 1 jh jh 13169 May 1 22:14 preset1.syx
+</screen>
+ <para>
+ The data for the preset is now saved in the file
+ <filename>preset1.syx</filename>. Press Exit on the BCF to exit
+ the Global Edit mode.
+ </para>
+ </section>
+ </section>
+
+ <section id="bcf2000-loading-a-preset">
+ <title> Loading a Preset </title>
+ <para>
+ Loading a .syx file, such as the one saved above, is very simple.
+ First, select the preset on the BCF to choose the preset to
+ overwrite. Then call <command>amidi</command> using the
+ <option>-s</option> option instead of <option>-r</option> to send a
+ file.
+ </para>
+<screen>
+xtc:~% amidi -p hw:2 -s preset1.syx
+</screen>
+ <para>
+ There will be a quick left-to-right flash of the encoder LEDs along
+ the top of the BCF, followed by the display circling around until
+ the data is loaded. It will then display the preset number again.
+ </para>
+
+ <para>
+ The preset is now loaded with the settings from the file. They are
+ only active as long as the preset is not changed. If you go to
+ another preset and back to the one you loaded, all the changes will
+ have disappeared. To save the settings,
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Press the STORE button. Its LED will start to flash.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select a different preset number if you wish with the left and
+ right PRESET buttons.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Press STORE again to write the settings to an empty preset. If
+ you want to overwrite an existing preset, press STORE twice. You
+ can cancel the store at any time by pressing EXIT.
+ </para>
+ </listitem>
+ </orderedlist>
+ </section>
+ </section>
+
+ <section id="bcf2000-bcedit">
+ <title> Using BCEdit </title>
+ <para>
+ The tool provided by Behringer to manage presets and other things on
+ the BCF is the Java program
+ <ulink url="http://www.behringer.com/05_support/bc_download/bc_downloads.cfm">BCEdit</ulink>.
+ This program will start up under Linux provided the correct version of
+ Java is used. I've found that
+ <ulink url="http://java.sun.com/j2se/1.5.0/download.jsp">JRE 5.0
+ Update 2</ulink> starts up correctly, but earlier versions of 5.0 will
+ not.
+ <ulink url="http://behringer-en.custhelp.com/cgi-bin/behringer_en.cfg/php/enduser/std_alp.php?sm=2">The
+ Behringer support page</ulink> says that the "editor software was
+ originally developed under J2SE-1_4_2_05". I tested it with
+ J2RE1.4.2_08 and BCEdit started, but was unable to see the BCF when
+ the "Scan" button was pressed. Running under JRE_1.5.0_02, pressing
+ the "Scan" button found the BCF, and I was able to load presets from
+ the BCF to BCEdit, but when I simply renamed the preset and tried to
+ write it back to the BCF, I got a Timeout Error while sending "$rev
+ F1" in the application.
+ </para>
+
+ <para>
+ At this point, I don't consider <application>BCEdit</application> to
+ be fully usable under Linux yet.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/behringer_ddx3216.xml b/manual/xml/behringer_ddx3216.xml
new file mode 100644
index 0000000000..697498f9a5
--- /dev/null
+++ b/manual/xml/behringer_ddx3216.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-behringer-ddx3216">
+ <title>Behringer DDX3216</title>
+ <para>
+ The Behringer DDX3216 isn't actually a dedicated control surface, it is
+ a digital mixer. However it does have the capability to control ardour
+ using it's faders and the pan pots, through it's midi I/O. Unfortunately
+ for some bizzare reason, the protocol for mute toggling changes on the
+ Behringer and is not compatible with ardour. Most commonly you would
+ setup ardour so the mixer and panning was reflected by the Behringer,
+ however you can control other elements of ardour such as plugin
+ controls/automation. This can potentially save a lot of time given you
+ can control a lot more than just one level at a time, as opposed to one
+ when using a mouse. The DDX3216 can also receive MTC (MIDI Time Code)
+ from ardour and control ardours transport via MMC (Midi Machine
+ Control), making it a very useful go between for any other external
+ devices that can also receive MTC. On top of that, any other software
+ synced to JACK will be controlled via the DDX3216 as well!
+ </para>
+
+ <para>
+ The setup is quite simple as follows:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ On the DDX3216 select the MMC/MIDI button. Press the Previous/Next
+ buttons to move to the RX/TX page. Make sure that you have both RX
+ and TX selected for 'Control Change', and TX selected for 'Machine
+ Control'. Under the menu 'RX/TX Only', make sure Fader and Pan is
+ selected.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ To receive MTC do the following. Press the Previous button to get to
+ the Setup page. Select MTC as your source. Make sure the receive
+ channel is set to OMNI so it will listen on all channels, and the
+ MMC device is set to 7F (all). Save a new Preset on the DDX3216,
+ something like MMC/MTC.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Connect your midi in and out cables to your sound card, and to the
+ Behringer DDX3216. Start <application>qjackctl</application>, and
+ then start ardour. In qjackctl go to the connections dialog, and
+ select the <guilabel>midi</guilabel> tab. Select the Midi output on
+ the left window and the ardour input on the right window, and press
+ connect. Select the ardour output on the left window and the midi
+ input on the right window, and press connect.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ I suggest making a template in ardour so you don't have to do these
+ following steps each time. Load a new session with your desired
+ amount of tracks (I used 16). Go to menu <menuchoice>
+ <guimenu>Windows</guimenu> <guisubmenu>Options Editor</guisubmenu>
+ </menuchoice> and select the <guilabel>MIDI</guilabel> tab. Select
+ all the options and make sure the midi port you have connected to in
+ qjackctl is 'online'.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Open the mixer window
+ (<keycombo><keycap>Alt</keycap><keycap>M</keycap></keycombo>) and
+ then hold down <keycap>Ctrl</keycap> and click the middle button of
+ your mouse, on the fader control for track 1. A dialog will appear
+ over the fader asking you to <literal>operate MIDI control
+ now</literal>. Move the fader on the Behringer that you want to
+ control track 1 ardour fader - and whalla! I use fader 17 (fader 1
+ in page 2) as it isn't used for analog inputs and saves confusion.
+ Now do the same thing for the panning, ctrl and middle click on the
+ pan control in ardour, and move the pan pot on the DDX3216. Repeat
+ the Step for as many tracks as you have. Then save the template as
+ 'MIDI controlled' or something similar. Next time you create a
+ session, select this template from the drop down list and you are
+ ready to cruise.
+ </para>
+
+ <para>
+ Remember you can assign the DDX3216 pan pots or even faders if you
+ want, to the plugin controls, send levels, inserts etc etc.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ You can also operate the ardour transport and have ardour transmit
+ MTC back to your DDX3216 (it is only capable of receiving timecode,
+ not transmitting it). Go to the ardour menu
+ <menuchoice><guimenu>Windows</guimenu><guisubmenu>Option
+ Editor</guisubmenu></menuchoice> and the <guilabel>Sync</guilabel>
+ Tab. Set <guimenuitem>Positional Sync</guimenuitem> to Sync with
+ Jack. Select <guimenuitem>Send MTC</guimenuitem> and
+ <guimenuitem>Jack time master</guimenuitem>. Set your SMPTE to the
+ appropriate frame rate for your region (PAL - 25 frames, NTSC 30
+ frames/drop frames). On the DDX3216 in the MMC/MIDI screen, select
+ the <guilabel>Machine Control</guilabel> Tab and you can now press
+ play and watch ardour begin playback, and the time code start
+ rolling! Of course if you have hydrogen/rosegarden/muse/whatever
+ also running, then they will begin with ardour as well.
+ </para>
+ </listitem>
+ </orderedlist>
+ <note>
+ <para>
+ With ardour set to sync with JACK you cannot rewind from the transport
+ control, because JACK does not support global varispeed. If you are
+ just working with ardour and nothing else, then you can change the
+ Sync option to internal. You also will want to enable the -12dB gain
+ reduction for ff/rew in the <guilabel>Misc</guilabel> tab for sanity
+ reasons.
+ </para>
+ </note>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/book_info.xml b/manual/xml/book_info.xml
new file mode 100644
index 0000000000..06e4cbfb05
--- /dev/null
+++ b/manual/xml/book_info.xml
@@ -0,0 +1,43 @@
+<?xml version='1.0'?>
+
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!ENTITY % BOOK_ENTITIES SYSTEM "./entities.ent">
+%BOOK_ENTITIES;
+
+]>
+
+<bookinfo>
+ <title>Ardour Manual</title>
+ <issuenum>1.0</issuenum>
+ <productnumber>2.0</productnumber>
+ <abstract>
+ <para>
+ This is the manual for &ARDOUR_NAME;, a digital audio workstation for
+ Linux and MacOSX. This manual is jointly created and edited by the
+ &ARDOUR_NAME; community. It may be published in paper format at some
+ time in the future.
+ </para>
+ </abstract>
+ <isbn>
+ N/A
+ </isbn>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/ardourlogo.png"/>
+ </imageobject>
+ </mediaobject>
+ <publisher>
+ <publishername>
+ <inlinemediaobject>
+ <imageobject>
+ <imagedata fileref="images/ardour-title.png" />
+ </imageobject>
+ </inlinemediaobject>
+ </publishername>
+ </publisher>
+ <copyright>
+ <year>&YEAR;</year>
+ <holder>&COPYRIGHT_HOLDER;</holder>
+ </copyright>
+</bookinfo>
diff --git a/manual/xml/cleaning_up_a_session.xml b/manual/xml/cleaning_up_a_session.xml
new file mode 100644
index 0000000000..9a5e3d9bc9
--- /dev/null
+++ b/manual/xml/cleaning_up_a_session.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-cleaning-up-a-session">
+ <title>Cleaning up a Session</title>
+ <para>
+ placeholder text: needs editing and references to menu items
+ </para>
+
+ <para>
+ Cleanup looks for audio files that were recorded by ardour for this
+ session, but are no longer in use. "In use" means "present in any
+ playlist in any snapshot of the session". If you have unused playlists
+ (e.g. alternate takes) cleanup will volunteer to delete them for you.
+ then it will search all snapshots (including the one you are working
+ with), and move all unused captured audio files into the "dead_sounds"
+ directory within the session. At this point, you could still potentially
+ get material that was "cleaned up" back, though its quite tricky to do.
+ </para>
+
+ <para>
+ It is advisable, even <emphasis>firmly recommended</emphasis> that after
+ this cleanup step, you save the session, exit ardour and restart. This
+ will enable you to confirm that the session still works as expected. If
+ all goes well (and it should), you can then do the 2nd phase cleanup,
+ which will remove the files from the <filename>dead_sounds</filename>
+ directory (at which point, the material is not recoverable without
+ backups on your part).
+ </para>
+
+ <para>
+ Note that the presence of snapshots can cause user confusion, as in "why
+ didn’t cleanup do anything?" The answer is frequently that there are
+ all capture audio files are in use in this snapshot or in others.
+ </para>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/clocks.xml b/manual/xml/clocks.xml
new file mode 100644
index 0000000000..aa3ba8fd6b
--- /dev/null
+++ b/manual/xml/clocks.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-clocks">
+ <title>Clocks</title>
+ <para>
+ There are several clock displays in the user interface for Ardour:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Primary transport clock
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Secondary transport clock
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Nudge clock
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Region position and length clocks
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ SMPTE offset clock
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ and more. All of these clocks provide the same operations and can be
+ used in the same way.
+ </para>
+
+ <section id="clock-operations">
+ <title>Clock Operations</title>
+ <section id="changing-clock-mode">
+ <title> Changing Clock Mode </title>
+ <para>
+ All clocks can be used in any one of 5 modes:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ SMPTE time
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ BBT time
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Audio frames
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Minutes:Seconds
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Off
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ To change clock modes, simply ContextClick on the clock, and select
+ the desired mode from the popup menu.
+ </para>
+ </section>
+
+ <section id="editing-clock-values">
+ <title> Editing Clock Values </title>
+ <para></para>
+ </section>
+ </section>
+<!--
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+-->
+</section>
diff --git a/manual/xml/closing_a_session.xml b/manual/xml/closing_a_session.xml
new file mode 100644
index 0000000000..4a1449761c
--- /dev/null
+++ b/manual/xml/closing_a_session.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-closing-a-session">
+ <title>Closing a Session</title>
+ <para>
+ Ardour only allows you to work on one session at a time (although your
+ computer may be able to run multiple instances of Ardour at one time).
+ This means that to work on a different session than the current one, you
+ will be forced to close the current session. You can either
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <menuchoice> <guimenu>Session</guimenu>
+ <guisubmenu>Close</guisubmenu> </menuchoice> will close the current
+ session.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <menuchoice> <guimenu>Session</guimenu>
+ <guisubmenu>Open</guisubmenu> </menuchoice> will prompt you for the
+ name of a session to work on, and will then close the current
+ session.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <menuchoice> <guimenu>Session</guimenu> <guisubmenu>New</guisubmenu>
+ </menuchoice> will open the New Session dialog to collect
+ configuration information for the new session, and will then close
+ the current session.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Whenever a session is closed but has been modified since last saved, the
+ Save dialog will appear.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/save_session_dialog.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ You have three options when this dialog appears:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Save the session before closing it
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Close the session without saving it
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Do not close the session
+ </para>
+ </listitem>
+ </orderedlist>
+ <note>
+ <para>
+ If you choose the final option, whatever operation initiated the
+ closing of the session will be stopped. For example, if you were
+ loading a new session while working on an existing one, no new session
+ will be loaded.
+ </para>
+ </note>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/configuring_usb_device_access.xml b/manual/xml/configuring_usb_device_access.xml
new file mode 100644
index 0000000000..88781b018b
--- /dev/null
+++ b/manual/xml/configuring_usb_device_access.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-configuring-usb-device-access">
+ <title>Configuring USB device access (Linux only)</title>
+ <para>
+ Linux is by default a multi-user system, so it has to have a policy to
+ determine who can access various devices. This includes those that can
+ be plugged into to a USB port.
+ </para>
+
+ <para>
+ For devices known to the operating system (which these days includes
+ most digital cameras, scanners, MIDI interfaces etc.), a logged-in user
+ will be granted access automatically. However, for devices that the OS
+ doesn't recognize (even if there is software on it that can use it),
+ this is not the case. It is possible to configure Linux to reverse this
+ policy and grant all users access to all devices, but this is not
+ recommended for security reasons.
+ </para>
+
+ <section id="usb-access-tranzport">
+ <title>Configuring Access to a Frontier Design Tranzport</title>
+ <para>
+ Using the Tranzport on Linux requires a couple of extra steps to
+ enable non-administrative users to access the device.
+ </para>
+
+ <para>
+ First, you need to login as the administrative user ("root"). Then put
+ the following into a new file called
+ <filename>/etc/hotplug/usb/tranzport</filename>
+ </para>
+<screen>
+#!/bin/sh
+
+if [ $ACTION = "add" ] &amp;&amp; [ -f $DEVICE ] ; then
+ chmod 0666 $DEVICE
+fi
+exit 0
+</screen>
+ <para>
+ Then make sure that the file is executable by running
+ </para>
+<screen>
+chmod +x /etc/hotplug/usb/tranzport
+</screen>
+ <para>
+ Second, edit the file <filename>/etc/hotplug/usb.usermap</filename> by
+ adding the following 2 lines to the end of it (make sure that the 2nd
+ line is not split across multiple lines, even though it is very long):
+ </para>
+<screen>
+# Frontier Design Tranzport
+tranzport 0x0000 0x165b 0x8101 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x00000000
+</screen>
+ <para>
+ After doing these steps, the next time you plugin your Tranzport it
+ will be accessible to you as a regular user.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/contributing_to_the_manual.xml b/manual/xml/contributing_to_the_manual.xml
new file mode 100644
index 0000000000..7a74f94365
--- /dev/null
+++ b/manual/xml/contributing_to_the_manual.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<appendix id="ap-contributing-to-the-manual" label="A" status="ardour-draft"><title>Contributing to the Manual</title>
+ <para>
+ A paragraph
+ </para>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</appendix>
diff --git a/manual/xml/control_surfaces.xml b/manual/xml/control_surfaces.xml
new file mode 100644
index 0000000000..3d9bdd2069
--- /dev/null
+++ b/manual/xml/control_surfaces.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-control-surfaces">
+ <title>Using Control Surfaces</title>
+ <para>
+ You can use a variety of different control surfaces with Ardour. We
+ anticipate full support for a new class of control surfaces (those using
+ the Mackie Control protocol) by the mid-summer of 2006, possibly
+ earlier.
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="behringer_ddx3216.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="bcf2000.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="frontier_design_tranzport.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="generic_midi_control_surface.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="configuring_usb_device_access.xml" />
+</chapter>
diff --git a/manual/xml/creating_a_new_session.xml b/manual/xml/creating_a_new_session.xml
new file mode 100644
index 0000000000..d969f04d78
--- /dev/null
+++ b/manual/xml/creating_a_new_session.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-creating-a-new-session">
+ <title>Creating a new Session</title>
+ <para>
+ The first step in starting a new project with Ardour is to create a new
+ session. When you do this, Ardour creates a new folder named after your
+ session, and stores differents kinds of files and subfolders within it.
+ The two most important subfolders are <filename>sounds</filename> which
+ contains all the audio recorded or imported for the session and
+ <filename>automation</filename> which contains automation data for
+ various parts of the session.
+ </para>
+
+ <para>
+ When you start ardour without specifying an existing session, it
+ automatically brings up the new session dialog. If you want to create a
+ new session at other times, choose <menuchoice>
+ <guimenu>Session</guimenu> <guisubmenu>New Session</guisubmenu>
+ </menuchoice>.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/session_control.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Enter a name for the new session. You can use any characters you like as
+ part of the name, but you should know that more or less anything other
+ than alphabetic and numeric characters will be converted to underscores
+ to form the name of the session folder.
+ </para>
+
+ <para>
+ Next, choose where you want to store the new session folder. If its not
+ in your current working folder, click on the browse button to expand the
+ file selector, and then navigate to your desired location.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/new_session_select_directory.png"/>
+ </imageobject>
+ </mediaobject>
+ <section id="new-session-io">
+ <title>Input and Output Configuration</title>
+ <para>
+ Next, configure the basic IO setup for the session. You have several
+ choices here, and doing nothing is one of them. This will give you a
+ session that includes:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ a stereo master bus with its outputs connected to the first two
+ outputs of your audio interface
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ all new track will have their outputs sent to the master bus
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ all new track inputs will be connected to Ardour’s best guess at
+ the relevant input of your audio interface.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ However, if you want more control over this, click on the expander
+ next to <guilabel>Advanced options</guilabel> label to show the full
+ set of options:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/new_session_advanced_tab.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ There are two options available for track input configuration:
+ autoconnect or manual. If you select autoconnect (the default) then
+ new tracks will be connected to an input of your audio interface. If
+ you select manual, it will be up to you to configure the input for
+ each track.
+ </para>
+
+ <para>
+ For output, the first two choices are whether to have control and
+ master outs. Most DAWs assume the presence of master outs, and few (if
+ any) offer control outs.
+ </para>
+
+ <section id="new-session-master-outs">
+ <title>Master Outputs</title>
+ <para>
+ A Master out is a bus to which all (or most) tracks and other busses
+ send their output. It provides a convenient single point of control
+ for the output of ardour, and is a typical location for global
+ effects. Because of this, using master outs is enabled by default,
+ and the master out bus is setup to be stereo (2 inputs, 2 outputs).
+ However, if you are feeding Ardour’s output through a hardware
+ mixing console, you may not want master outs. In such cases, disable
+ them by clicking on the radio button next to “Use master outsâ€.
+ Alternatively, you may want some other channel configuration for the
+ master output (for example, 8 channel surround sound). Select this
+ by using the clickbox (see clickboxes) next to the radio button.
+ </para>
+ </section>
+
+ <section id="new-session-control-outs">
+ <title>Control Outputs</title>
+ <para>
+ Control outs are unusual for DAWs, but because Ardour is designed to
+ be as flexible as possible, and in particular is intended to be
+ useful as a live mixer, they are included here. Using control outs
+ provides you with a dedicated bus to which all tracks have an
+ additional output connection. As well as feeding their regular
+ outputs, they send data to the control outs as well. In an
+ unadjusted session, this means that the control outs carry the same
+ signal as the master outs. However, once you start soloing tracks,
+ the control outs will carry only soloed tracks while the master outs
+ continue to carry the entire mix. A typical use of control outs is
+ when doing live stage work. The mix engineer will be listening to
+ the control outs, and can therefore solo tracks without affecting
+ the signal being sent to the master outs (the main speakers).
+ </para>
+ </section>
+ </section>
+</section>
diff --git a/manual/xml/default_track_names.xml b/manual/xml/default_track_names.xml
new file mode 100644
index 0000000000..e16d152e4b
--- /dev/null
+++ b/manual/xml/default_track_names.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="default-track-names">
+ <title>Default Track Names</title>
+ <para>
+ When a track is added to the session it is given a default name based on
+ the Track type. For example, the first audio track that is added to the
+ session will be given the name <literal>Audio 1</literal> and the first
+ bus will be called <literal>Bus 1</literal> and any subsequently added
+ tracks will be consecutively numbered.
+ </para>
+
+ <para>
+ Track names determine the names of the files created when recording to a
+ track so it is suggested that meaningful names are given to tracks, see
+ <xref linkend="renaming-tracks"/>
+ </para>
+</section>
diff --git a/manual/xml/editing_concepts.xml b/manual/xml/editing_concepts.xml
new file mode 100644
index 0000000000..c73bb00c2a
--- /dev/null
+++ b/manual/xml/editing_concepts.xml
@@ -0,0 +1,341 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editing-concepts">
+ <title>Editing Concepts</title>
+ <para>
+ In Ardour, "editing" describes the process of
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ making modifications to playlists. Recall that
+ <glossterm linkend="gt-playlist">playlists</glossterm> are nothing
+ more than lists of
+ <glossterm linkend="gt-region">regions</glossterm> arranged over
+ time.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ recording/modifying automation data
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="editing-cut-copy-paste">
+ <title> Cut/Copy/Paste </title>
+ <para></para>
+ </section>
+
+ <section id="sn-snap-settings">
+ <title>Snap Settings</title>
+ <para>
+ By default, when you move objects around, they move freely. There
+ <emphasis>is</emphasis> a "granularity" to the motion, but it is a
+ single audio frame (so typically on the order of 1/48000'th or
+ 1/96000'th of a second), and at most zoom levels it will not be
+ apparent in any way.
+ </para>
+
+ <para>
+ However, this is not always the way you want to move some kinds of
+ objects. If you are working with structured compositions that utilize
+ traditional concepts of bars, beats, rythmn and so forth, you will
+ often want to move regions so that that they always align to specific
+ periodic time points that correspond to the start of a bar, or a beat
+ etc. If you are working on a movie soundtrack, you may prefer to have
+ regions always align to SMPTE frames, or perhaps even to whole
+ seconds.
+ </para>
+
+ <para>
+ Ardour provides a wide variety of "snap" settings. If any but "None"
+ is selected, they define a grid of timepoints which will be used to
+ "snap" object positions as they are dragged. The grid can be regular
+ (as is the case if you choose "Beats", for example), or it can be
+ completely irregular (if you choose "Marks", for example). It can even
+ consist of a <emphasis>single</emphasis> timepoint (if you choose
+ "Edit cursor", for example).
+ </para>
+
+ <variablelist>
+ <title> Possible Snap Settings </title>
+ <varlistentry>
+ <term><guilabel>None</guilabel></term>
+ <listitem>
+ <para>
+ no alignment used at all
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> CD Frames</guilabel></term>
+ <listitem>
+ <para>
+ align to 1/75th of a second intervals, as defined by the
+ "Redbook" Audio CD standards
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> SMPTE Frames</guilabel></term>
+ <listitem>
+ <para>
+ align to whatever the current SMPTE frame interval is (defined
+ in the options editor)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> SMPTE Seconds</guilabel></term>
+ <listitem>
+ <para>
+ align to whole seconds, adjusted to account for any SMPTE start
+ offset
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> SMPTE Minutes</guilabel></term>
+ <listitem>
+ <para>
+ align to whole minutes, adjust to account for any SMPTE start
+ offset
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Seconds</guilabel></term>
+ <listitem>
+ <para>
+ align to whole seconds
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Minutes</guilabel></term>
+ <listitem>
+ <para>
+ align to whole minutes
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Beats/32</guilabel></term>
+ <listitem>
+ <para>
+ align to 1/32 divisions of the beat
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Beats/16</guilabel></term>
+ <listitem>
+ <para>
+ align to 1/16 divisions of the beat
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Beats/8</guilabel></term>
+ <listitem>
+ <para>
+ align to 1/8 divisions of the beat
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Beats/4</guilabel></term>
+ <listitem>
+ <para>
+ align to 1/4 divisions of the beat
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Beats/3</guilabel></term>
+ <listitem>
+ <para>
+ align to 1/3 divisions of the beat
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Beats</guilabel></term>
+ <listitem>
+ <para>
+ align to beats
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Bars</guilabel></term>
+ <listitem>
+ <para>
+ align to the start of bars
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Marks</guilabel></term>
+ <listitem>
+ <para>
+ align to the nearest mark of some kind
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Edit Cursor</guilabel></term>
+ <listitem>
+ <para>
+ align to the current position of the edit cursor
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Region starts</guilabel></term>
+ <listitem>
+ <para>
+ align to the nearest start of a region in the (first) selected
+ track
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Region ends</guilabel></term>
+ <listitem>
+ <para>
+ align to the nearest end of a region in the (first) selected
+ track
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Region syncs</guilabel></term>
+ <listitem>
+ <para>
+ align to the nearest region sync point in the (first) selected
+ track
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel> Region bounds </guilabel></term>
+ <listitem>
+ <para>
+ align to the nearest region start or end in the (first) selected
+ track
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <section id="changing-snap-settings">
+ <title> To change snap settings </title>
+ <para>
+ Move the mouse pointer to the toolbar panel of the editor window.
+ Click on the "expansion arrow" of the "Snap setting" chooser. This
+ will popup a list of available snap settings. If necessary, scroll
+ down to see your desired choice. Click on your choice in the list to
+ dismiss it and make Ardour switch to the new setting.
+ </para>
+
+ <note>
+ <para>
+ Changing snap settings has <emphasis>no</emphasis> effect on the
+ position of any existing region. Its effect is only on objects
+ being moved.
+ </para>
+ </note>
+ <tip>
+ <para>
+ The snap setting also affects moving the playhead, the edit
+ cursor, loop/punch and location markers, and dragging/moving range
+ selections.
+ </para>
+ </tip>
+ </section>
+
+ <section id="snap-mode">
+ <title> Snap Mode </title>
+ <para>
+ There are two subtly different ways in which the snap setting can
+ affect region motion:
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term>normal snap mode</term>
+ <listitem>
+ <para>
+ regions can only be moved to positions defined by the snap
+ setting. It is not possible to move them to intermediate
+ positions.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>magnetic snap mode</term>
+ <listitem>
+ <para>
+ regions can still be moved to positions not defined by the
+ setting, but they "stick" to the timepoints that are when
+ dragged across them. Imagine that the timepoints and the
+ regions are magnetic - or just try it and see.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ However, you can press the <emphasis>snap modifier</emphasis> key
+ while dragging, and the snap setting will be ignored. By default,
+ this is the key on your keyboard that generates
+ <emphasis>Mod3</emphasis> , but you can modify this from the
+ <emphasis>Options Editor</emphasis> keyboard tab.
+ </para>
+ </section>
+
+ <section id="changing-snap-mode">
+ <title> To change snap mode </title>
+ <para>
+ Move the mouse pointer to the toolbar panel of the editor window.
+ Click on the "expansion arrow" of the "Snap mode" chooser. This will
+ popup a list of available snap settings. If necessary, scroll down
+ to see your desired choice. Click on your choice in the list to
+ dismiss it and make Ardour switch to the new setting.
+ </para>
+ </section>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_aligning_key_bindings.xml b/manual/xml/editor_aligning_key_bindings.xml
new file mode 100644
index 0000000000..8a6c677272
--- /dev/null
+++ b/manual/xml/editor_aligning_key_bindings.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-aligning-key-bindings">
+ <title>Aligning</title>
+ <table id="tbl-editor-aligning-key-bindings">
+ <title>Editor Aligning Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>a</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ relative alignment of region sync points or starts
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Meta</keycap><keycap>a</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ absolute alignment of region sync points or starts
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><keycap>a</keycap>
+ </keycombo>
+ </entry>
+
+ <entry>
+ relative alignment of region ends
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>Meta</keycap><keycap>a</keycap>
+ </keycombo>
+ </entry>
+
+ <entry>
+ align region ends
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_canvas_key_bindings.xml b/manual/xml/editor_canvas_key_bindings.xml
new file mode 100644
index 0000000000..e9b3eb4d08
--- /dev/null
+++ b/manual/xml/editor_canvas_key_bindings.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-canvas-key-bindings">
+ <title>Changing What's Visible</title>
+ <table id="tbl-editor-canvas-key-bindings">
+ <title>Editor Canvas Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>left arrow</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move editor timeline earlier
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>b</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move editor timeline earlier
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>right arrow</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move editor timeline later
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>f</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move editor timeline later
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Page_Up</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ scroll track display up
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Page_Down</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ scroll track display down
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Up arrow</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ step track display up
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Down arrow</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ step track display down
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_edit_cursor_position_key_bindings.xml b/manual/xml/editor_edit_cursor_position_key_bindings.xml
new file mode 100644
index 0000000000..1190e3efa7
--- /dev/null
+++ b/manual/xml/editor_edit_cursor_position_key_bindings.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-edit-cursor-key-bindings">
+ <title>Moving the Edit Cursor</title>
+ <table id="tbl-editor-edit-position-key-bindings">
+ <title>Edit Cursor Position Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>e</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ position edit cursor at mouse pointer
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>Return</keycap>
+ </keycombo>
+ </entry>
+
+ <entry>
+ move edit cursor to playhead
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>[</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move edit cursor to earlier region start
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>[</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move edit cursor to earlier region end
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>]</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move edit cursor to next region start
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>]</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move edit cursor to next region end
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>&#8221;&#8221;&#8217;</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move edit cursor to next region sync
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>;</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ moved edit cursor to previous region sync
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>F1</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move edit cursor to start of range selection (if defined)
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>F2</keycap></keycombo>
+ </entry>
+
+ <entry>
+ move edit cursor to end of range selection (if defined)
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_locations_marks_key_bindings.xml b/manual/xml/editor_locations_marks_key_bindings.xml
new file mode 100644
index 0000000000..d83c446578
--- /dev/null
+++ b/manual/xml/editor_locations_marks_key_bindings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-location-marks-key-bindings">
+ <title>Locations and Marks</title>
+ <table id="tbl-editor-locations-marks-key-bindings">
+ <title>Locations and Marks Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>Enter</keycap> </keycombo> (keypad)
+ </entry>
+
+ <entry>
+ create a new marker at the playhead location
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Keypad &gt;</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move playhead to next marker
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Keypad &lt;</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move playhead to previous marker
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_miscellaneous_key_bindings.xml b/manual/xml/editor_miscellaneous_key_bindings.xml
new file mode 100644
index 0000000000..1fd40d13ea
--- /dev/null
+++ b/manual/xml/editor_miscellaneous_key_bindings.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-miscellaneous-key-bindings">
+ <title>Miscellaneous</title>
+ <table id="tbl-editor-miscellaneous-key-bindings">
+ <title>Miscellaneous Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>l</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ toggle auto loop
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>f</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ toggle follow playhead
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_nudging_key_bindings.xml b/manual/xml/editor_nudging_key_bindings.xml
new file mode 100644
index 0000000000..8c0560d0b8
--- /dev/null
+++ b/manual/xml/editor_nudging_key_bindings.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-nudging-key-bindings">
+ <title>Nudging Key Bindings</title>
+ <table id="tbl-editor-nudging-key-bindings">
+ <title>Nudging Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>+</keycap> </keycombo> (keypad)
+ </entry>
+
+ <entry>
+ nudge forward
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>+</keycap> </keycombo>
+ (keypad)
+ </entry>
+
+ <entry>
+ nudge next forward
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>-</keycap> </keycombo> (keypad)
+ </entry>
+
+ <entry>
+ nudge backward
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>-</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ nudge next backward
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_play_position_key_bindings.xml b/manual/xml/editor_play_position_key_bindings.xml
new file mode 100644
index 0000000000..52024cbb59
--- /dev/null
+++ b/manual/xml/editor_play_position_key_bindings.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-play-position-key-bindings">
+ <title>Moving the Playhead</title>
+ <table id="tbl-editor-play-position-key-bindings">
+ <title>Play Position Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>p</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ position playhead at mouse pointer
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Return</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move playhead to edit cursor
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Tab</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move playhead to later region start
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>Tab</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move playhead to later region end
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>`</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move playhead to earlier region start
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>`</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ move playhead to next mark
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>|</keycap> </keycombo> (keypad)
+ </entry>
+
+ <entry>
+ move playhead to previous mark
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>l</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ center screen around playhead
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>g</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ goto
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_range_operations_key_bindings.xml b/manual/xml/editor_range_operations_key_bindings.xml
new file mode 100644
index 0000000000..111de889de
--- /dev/null
+++ b/manual/xml/editor_range_operations_key_bindings.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-range-operations-key-bindings">
+ <title>Range Operations</title>
+ <table id="tbl-editor-range-operations-key-bindings">
+ <title>Range Operations Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>Keypad Down arrow</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ begin range definition while transport rolls
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Keypad Up arrow</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ end range definition while transport rolls
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap><keycap>Tab</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ extend range to end of region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><keycap>Tab</keycap>
+ </keycombo>
+ </entry>
+
+ <entry>
+ extend range to start of region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Meta</keycap><keycap>s</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ duplicate range
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_region_operations_key_bindings.xml b/manual/xml/editor_region_operations_key_bindings.xml
new file mode 100644
index 0000000000..e830c2c338
--- /dev/null
+++ b/manual/xml/editor_region_operations_key_bindings.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-region-operation-key-bindings">
+ <title>Region Operations Key Bindings</title>
+ <table id="tbl-editor-region-operation-key-bindings">
+ <title>Region Operation Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>s</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ split region(s) at mouse
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>s</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ split region(s) at edit cursor
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Insert</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ insert selected region (from region list)
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Meta</keycap><keycap>d</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ duplicate region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>r</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ reverse region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>n</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ normalize region
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_standard_editing_key_bindings.xml b/manual/xml/editor_standard_editing_key_bindings.xml
new file mode 100644
index 0000000000..d8f23899ec
--- /dev/null
+++ b/manual/xml/editor_standard_editing_key_bindings.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-standard-editing-key-bindings">
+ <title>Standard Editing</title>
+ <table id="tbl-editor-standard-editing-key-bindings">
+ <title>Editor Standard Editing Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>z</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ undo
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>r</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ redo
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>x</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ cut
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Delete</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ cut
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>c</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ copy
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>v</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ paste
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_window.xml b/manual/xml/editor_window.xml
new file mode 100644
index 0000000000..8f56afaa2e
--- /dev/null
+++ b/manual/xml/editor_window.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-window">
+ <title>The Editor</title>
+ <para>
+ Ardour provides two ways of viewing a session: the Editor and the Mixer.
+ The Editor shows the session by representing tracks as horizontal
+ timeline displays, with material within the tracks (audio, MIDI, video,
+ automation data, etc.) arranged along the horizontal (time) axis. The
+ Mixer shows the session by representing tracks as mixer strips, with
+ controls for gain, record enable, soloing and so forth. More abstractly,
+ the Editor represents the time based aspects of a session, whereas the
+ Mixer represents the signal flow.
+ </para>
+
+ <para>
+ However, it is quite possible to control the signal flow aspects from
+ within the Editor as well, without the comprehensive overview that the
+ Mixer provides. For some sessions, especially during the early stages of
+ a session, the Editor may be the only window you need to use.
+ </para>
+
+ <section id="editor-window-layout">
+ <title>Editor Window Layout</title>
+ <para>
+ Lets survey the basic layout of the editor window:
+ </para>
+
+ <para>
+ The transport controls are in a tearoff window at the top of the
+ editor, and are described in transport_window.
+ </para>
+ </section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_window_controls.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_window_track_list.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_window_group_list.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_window_region_list.xml" />
+ <section id="editor-window-chunk-list">
+ <title>Chunk List</title>
+ <para>
+ Below the region list is the Chunk List, which provides a visual list
+ of all "chunks". Chunks are collections (possibly discontiguous) of
+ sections.
+ </para>
+ </section>
+
+ <section id="editor-window-track-display">
+ <title>Track Display</title>
+ <para>
+ This is the main area within the editor. Each track or bus is
+ represented by a horizontal "stripe", with a set of controls on the
+ left side, with the timeline above them all.
+ </para>
+ </section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_window_timeline.xml" />
+ <section id="editor-window-track-controls">
+ <title>Track Controls</title>
+ <para>
+ Each track has a set of controls on its left side. Which controls are
+ present varies depending on the type of track (audio, bus, automation,
+ MIDI, etc.). Every track type has a "hide" button marked with a cross.
+ Click on this to hide the track.
+ </para>
+ </section>
+
+ <section id="editor-window-track-views">
+ <title>Track Views</title>
+ <para>
+ This is where all editing takes place. The track views contain region
+ objects, curve control points, lines and other items that can be
+ added, removed, copied, cut and pasted. See editing_basics for more
+ information on editing.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_window_controls.xml b/manual/xml/editor_window_controls.xml
new file mode 100644
index 0000000000..092a4ce6b7
--- /dev/null
+++ b/manual/xml/editor_window_controls.xml
@@ -0,0 +1,345 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="editor-window-controls">
+ <title>Editor Controls</title>
+ <para>
+ The editor controls are in a tearoff window, which you can use in the
+ usual way.
+ </para>
+
+ <section id="editor-edit-cursor-clock">
+ <title>Edit cursor clock</title>
+ <para>
+ This clock shows the current position of the edit cursor. You can edit
+ the position using the clock if you wish.
+ </para>
+ </section>
+
+ <section id="editor-zoom-buttons">
+ <title>Zoom buttons</title>
+ <para>
+ The zoom buttons allow you to see more ("zoom out") or less ("zoom
+ in") of the session timeline in the track display area. Click on the
+ zoom out button to zoom out, and the zoom in button to zoom in.
+ </para>
+ </section>
+
+ <section id="editor-zoom-range-clock">
+ <title>Zoom range clock</title>
+ <para>
+ The zoom range clock shows the current duration of the timeline that
+ is visible in the track display area. It does not indicate the
+ location of the visible section of the timeline, only its length. You
+ can zoom in and out by editing this clock directly, which may be
+ useful if you want to see a precise duration within the editor.
+ </para>
+ </section>
+
+ <section id="editor-zoom-selectors">
+ <title>Zoom selectors</title>
+ <para>
+ The two zoom select buttons allow you to go to the maximum and minimum
+ zoom levels with a single button click. The "1:1" button zooms all the
+ way into single sample level, where each pixel on the screen
+ represents a single sample. The "whole session button" zooms out to
+ show the entire session in the track display area.
+ </para>
+ </section>
+
+ <section id="editor-zoom-focus-control">
+ <title>Zoom focus control</title>
+ <para>
+ When zooming, there is always a change in what is displayed in the
+ track display area. However, one position in the display will continue
+ to correspond to the same point in the timeline, and there are several
+ choices of how to define that point. The default behaviour is to keep
+ the left edge of the track display area constant. If it was at a
+ position 1:12:14 into the session timeline before zooming, then it
+ will continue to be at that position after zooming. Other points in
+ the display that you can ensure are in the same position while zooming
+ include the right edge of the track display, the center of the track
+ display, the playhead and the edit cursor. Whichever of these is
+ selected is known as the current zoom focus.
+ </para>
+
+ <para>
+ To change the current zoom focus, click on the combo box to see the
+ list of available choices. Click on the zoom focus you wish to use.
+ The list of choices will disappear, and the new zoom focus choice will
+ be in effect.
+ </para>
+ </section>
+
+ <section id="editor-snap-control">
+ <title>Snap control</title>
+ <para>
+ When moving objects around in the track display area, you have the
+ choice of moving them freely or having their positions be limited to
+ certain points along the timeline. This applies to region, the
+ playhead, the edit cursor, curve control points and markers, among
+ others. If you want the positions of objects to be limited, then you
+ can choose from several different possibilities. We call this "snap
+ to" because when moving objects around with the mouse, they appear to
+ "snap to" various positions.
+ </para>
+
+ <para>
+ The most obvious source of "snap to" positions is the tempo map, but
+ ardour offers many different possibilities:
+ </para>
+
+ <table id="tbl-snap-control">
+ <title>Snap Control</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Snap Option" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Snap Option
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ BBT
+ </entry>
+
+ <entry>
+ you can select 64th,32nd,16th,8th,quarter and whole beat
+ positions, as well as beat triplets and whole bars (measures).
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Region beginnings
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Region ends
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Region sync points
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Region boundaries
+ </entry>
+
+ <entry>
+ (combines regions beginnings and ends)
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Marks
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Edit Cursor
+ </entry>
+
+ <entry>
+ a single snap-to point. This is useful when aligning several
+ objects at the same point. Set the edit cursor to the desired
+ position, then select this snap setting, and then move the
+ objects, which will immediately snap to the chosen position.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="editor-edit-mode-control">
+ <title>Edit mode control</title>
+ <para>
+ When moving regions around in a track, it is sometimes desirable to
+ leave spaces between regions and sometimes to force regions to always
+ be placed directly next to their neighbours. Which is more appropriate
+ depends a lot on the nature of the project and the regions themselves.
+ </para>
+
+ <para>
+ By default, Ardour uses slide mode which allows you to freely place
+ regions in a track (subject to the current snap setting, of course).
+ If you cut part of region, an empty space will remain where the part
+ you removed used to be. If you move a region along the timeline, it
+ will move independently of other regions, and will stay wherever you
+ place it.
+ </para>
+
+ <para>
+ If you are editing a session and require behaviour where regions are
+ forced to always to be directly adjacent, you can switch to splice
+ maybe. In this mode, cutting part of region will cause all later
+ regions in the track to move up (earlier) the timeline so that there
+ is no intervening space between them. Moving a region will cause other
+ regions to move around so that the moved region fits "between" them.
+ </para>
+ </section>
+
+ <section id="editor-window-nudge-buttons">
+ <title>Nudge buttons</title>
+ <para>
+ Sometimes when editing its nice to be able to move objects by
+ predefined amounts rather than just positioning them freely or using
+ snap-to. This kind of motion is called nudging. At the present time,
+ only the playhead, playlists and regions can be nudged. The distance
+ an object is nudged is set by the nudge clock (see below).
+ </para>
+
+ <para>
+ To nudge one or more regions forward by 1 second, first edit the nudge
+ clock so that it specifies that time. Then select the region(s) by
+ clicking on them, and finally click the nudge forward button.
+ </para>
+
+ <para>
+ Nudging backwards is identical to nudging forwards, except that you
+ should click on the nudge backwards button.
+ </para>
+
+ <para>
+ To nudge a playlist forward or backwards, first set the nudge clock to
+ the desired nudge distance. Then in the track that is using the
+ playlist. Choose Nudge Nudge entire track fwd or Nudge nudge entire
+ track bwd as desired.
+ </para>
+
+ <para>
+ You can also nudge all regions in the playlist positioned after (later
+ than) the edit cursor. To do this, follow the steps for nudging the
+ playlist, but choose Nudge nudge track after edit cursor fwd or Nudge
+ nudge track after edit cursor bwd, as appropriate.
+ </para>
+ </section>
+
+ <section id="editor-window-nudge-clock">
+ <title>Nudge clock</title>
+ <para>
+ You can edit the clock value to alter the distance that
+ regions/playlists will be nudged. (see <xref linkend="sn-clocks"/> for
+ instructions).
+ </para>
+ </section>
+
+ <section id="editor-window-tool-selector">
+ <title>Tool Selector</title>
+ <para>
+ The editor tool selector is in a tearoff window, and contains a series
+ of buttons used to select what the mouse (and often the keyboard) will
+ do when editing tracks. The tools include:
+ </para>
+
+ <table id="tbl-editor-window-mouse-modes">
+ <title>Snap Control</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Snap Option" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Mode
+ </entry>
+
+ <entry>
+ Description
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ object
+ </entry>
+
+ <entry>
+ <para>
+ Left-clicking Object will place the mouse in object mode.
+ When in object mode, the mouse pointer appears as a hand
+ whenever it is over the track canvas or the rulers. The
+ mouse can now be used to select and perform operations on
+ objects such as regions, markers etc.
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ range
+ </entry>
+
+ <entry>
+ <para>
+ Left-clicking Range will place the mouse in range mode. When
+ in range mode, the mouse pointer appears as a vertical line
+ whenever it is over the track canvas or the rulers. The
+ mouse will now be able to select a point or range of time.
+ Time ranges can be selected over one or several tracks.
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ gain
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ zoom
+ </entry>
+
+ <entry>
+ <para>
+ Left-clicking Zoom will place the mouse in zoom mode. When
+ in zoom mode, the mouse pointer appears as a magnifying
+ glass whenever it is over the track canvas or the rulers.
+ This mode is used to zoom the display to any range that is
+ subsequently set using the mouse.
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ timefx
+ </entry>
+
+ <entry>
+ <para>
+ Left-clicking Timefx will place the mouse in timefx mode.
+ When in timefx mode, the mouse pointer appears as a
+ distinctive 'expanding' illustration whenever it is over the
+ track canvas or the rulers. This mode is used to resize
+ regions using a timestretch algorithm.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+</section>
diff --git a/manual/xml/editor_window_group_list.xml b/manual/xml/editor_window_group_list.xml
new file mode 100644
index 0000000000..42b645c282
--- /dev/null
+++ b/manual/xml/editor_window_group_list.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="editor-window-edit-group-list">
+ <title>Edit Group List</title>
+ <para>
+ Below the track list is the edit group list, which lists all edit groups
+ for the session, including a default group called &#8220;all&#8221;. To
+ the left of each group name is a checkbox which indicates whether or not
+ the group is active (a checkmark means its active). Click on the
+ checkbox to change the active status of an edit group.
+ </para>
+
+ <para>
+ The edit group list can also be used to toggle the visibility of all
+ members of the group. Visible edit groups are displayed in cyan, hidden
+ ones in orange. Click on the name of the edit group to toggle its
+ visibility. Note that an edit group can be visible and yet have hidden
+ member tracks, and vice versa.
+ </para>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_window_key_bindings.xml b/manual/xml/editor_window_key_bindings.xml
new file mode 100644
index 0000000000..a96ed75222
--- /dev/null
+++ b/manual/xml/editor_window_key_bindings.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-tool-selection-key-bindings">
+ <title>Tool Selection</title>
+ <table id="tbl-tool-selection-key-bindings">
+ <title>Tool Selection Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>r</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Select Range mode
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>g</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Select Gain mode
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>o</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Select Object mode
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>t</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Select TimeFX mode
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>z</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Select Zoom mode
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_window_region_list.xml b/manual/xml/editor_window_region_list.xml
new file mode 100644
index 0000000000..7c7990e1da
--- /dev/null
+++ b/manual/xml/editor_window_region_list.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="editor-window-region-list">
+ <title>Region List</title>
+ <para>
+ To the right of the track display is the region list, which uses a tree
+ display to show all regions in the session. There are sections in the
+ region list, &#8220;Captured&#8221; and &#8220;External&#8221;.
+ &#8220;Captured&#8221; contains all regions that were either recorded by
+ Ardour or imported as native audio files. &#8220;External&#8221;contains
+ regions created using audio files external to Ardour (from a sample
+ library, for example).
+ </para>
+
+ <section id="region-list-organization">
+ <title>Organization of the region list</title>
+ <para>
+ In both sections of the region list, any regions containing multiple
+ channels will have its name followed by &#8220;[N]&#8221; where N is a
+ number indicating the number of channels. Any region that ends in
+ &#8220;-N&#8221;, where N is a number, is a region that describes an
+ entire audio file. Any region that ends in &#8220;.N&#8221; is a
+ region that describes part of an audio file. Any subtree within the
+ region list can be hidden or displayed by clicking on the box left of
+ its name.
+ </para>
+
+ <para>
+ Within the Captured part of the tree, each track is represented by its
+ own subtree (strictly speaking, its not each track but each playlist
+ that is represented). Within that subtree is an entry for each take
+ recorded for that track. Remember that each take is stored as one and
+ audio files (strictly, one per channel). Within the take tree is an
+ entry for each region created from that take.
+ </para>
+
+ <para>
+ Within the External part of the tree, there is a subtree for each
+ audio file embedded into the session. Within that subtree are entries
+ for each region created from that audio file.
+ </para>
+ </section>
+
+ <section id="region-list-operations">
+ <title>Region list operations</title>
+ <para>
+ Click on the box to the left of the name of part of the tree to
+ hide/show that part of the subtree.
+ </para>
+
+ <para>
+ Click the name of a region and then drag it to the track display area
+ to insert a region into a track.
+ </para>
+
+ <para>
+ Click on the title bar of the region list to display a menu allowing
+ you to
+ </para>
+
+ <table id="tbl-region-list-operations-menu">
+ <title>Region List Context Menu</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Snap Option" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Menu Item
+ </entry>
+
+ <entry>
+ Description
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ Find
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Show/Hide All
+ </entry>
+
+ <entry>
+ <para>
+ fully expand or collapse the region list
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Sort
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Display Automatic Regions normally,
+ </entry>
+
+ <entry>
+ Ardour does not display regions created as a result of a side
+ effect of user actions. If this option is selected, all
+ regions will be included in the region list.
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Import audio files
+ </entry>
+
+ <entry>
+ <para>
+ copy (and if necessary convert) audio files into the
+ session. See Importing for more details.
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Embed audio file
+ </entry>
+
+ <entry>
+ <para>
+ embed external audio files into the session. No new files
+ are created, and no format conversion is done. See
+ [[editing:Embedding]] for more details.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_window_timeline.xml b/manual/xml/editor_window_timeline.xml
new file mode 100644
index 0000000000..f9352aa7ef
--- /dev/null
+++ b/manual/xml/editor_window_timeline.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="editor-window-timeline">
+ <title>Timeline</title>
+ <para>
+ At the top of the track display area is the timeline display. This
+ consists of a number of rulers, a meter track, a tempo track and the
+ marker display.
+ </para>
+
+ <para>
+ The available rulers include:
+ </para>
+
+ <table id="tbl-rulers">
+ <title>Ruler Types</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Ruler Type" colwidth="1"/>
+ <colspec colnum="2" colname="Description" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Ruler Type
+ </entry>
+
+ <entry>
+ Description
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ Frames
+ </entry>
+
+ <entry>
+ this ruler measures audio frames. The number of audio frames per
+ second depends on the sample rate in use.
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ SMPTE
+ </entry>
+
+ <entry>
+ this ruler displays SMPTE timecode. The SMPTE format (25fps,
+ 30fps, drop frame etc) is selected in the Options Editor
+ option_editor.
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ Min:Sec
+ </entry>
+
+ <entry>
+ this ruler displays time in minutes+seconds, measured since the
+ start of the session.
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ BBT
+ </entry>
+
+ <entry>
+ <para>
+ (Bars,Beats,Ticks) this ruler displays positions based on the
+ tempo map.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ To show or hide one or more of the rulers, click on the area to the left
+ of their names. A menu will popup that has a check item for each
+ available ruler. Click on the name of the ruler to toggle its
+ visibility.
+ </para>
+
+ <para>
+ The tempo and meter tracks display the tempo map for the session. The
+ tempo track contains 1 or more tempo change points, with a default tempo
+ of 120 beats per minute. The meter track contains 1 or more meter change
+ points, with an initial default meter of 4/4.
+ </para>
+
+ <para>
+ on a tempo/meter change point to edit it. Click in the tempo/meter track
+ to add a new change point. Click and drag on a change point to move it.
+ on a tempo/meter change point to remove it.
+ </para>
+
+ <para>
+ There is more information on using the timeline in editing_basics.
+ </para>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_window_track_list.xml b/manual/xml/editor_window_track_list.xml
new file mode 100644
index 0000000000..9ede6fa82e
--- /dev/null
+++ b/manual/xml/editor_window_track_list.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="editor-window-track-list">
+ <title>Track List</title>
+ <para>
+ To the left of the track area is the track list, which lists all tracks
+ and busses in the session. Tracks/Busses that are visible have their
+ names displayed in cyan, while hidden ones have their names displayed in
+ orange.
+ </para>
+
+ <para>
+ Click on the name of a track/bus to toggle its visibility in the editor.
+ Click and drag the name to reorder the track display area.
+ </para>
+
+ <para>
+ You can click on the title bar of the track list to display a menu that
+ allows you to:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Hide all
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Show all
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Hide all tracks
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Show all tracks
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Hide all busses
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Show all busses
+ </para>
+ </listitem>
+ </itemizedlist>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/editor_zoom_key_bindings.xml b/manual/xml/editor_zoom_key_bindings.xml
new file mode 100644
index 0000000000..b8afa14bfe
--- /dev/null
+++ b/manual/xml/editor_zoom_key_bindings.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-editor-zoom-key-bindings">
+ <title>Zoom Key Bindings</title>
+ <table id="tbl-editor-zoom-key-bindings">
+ <title>Editor Zoom Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>=</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ zoom in on timeline
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>-</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ zoom out on timeline
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Z</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ switch zoom focus to playhead
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/entities.ent b/manual/xml/entities.ent
new file mode 100644
index 0000000000..f21530b9f4
--- /dev/null
+++ b/manual/xml/entities.ent
@@ -0,0 +1,11 @@
+<!ENTITY YEAR "2007">
+<!ENTITY BOOKNAME "Ardour Reference Guide">
+<!ENTITY BOOKVERSION "0.01"> <!-- change version here -->
+<!ENTITY BOOKDATE "2007-01-13"> <!-- change revision date here -->
+<!ENTITY BOOKID "&BOOKNAME;-&BOOKVERSION; (&BOOKDATE;)">
+
+<!ENTITY ARDOUR_NAME "ardour">
+<!ENTITY ARDOUR_VERSION "2.0">
+<!ENTITY ARDOUR_COMMAND "<command>ardour-&ARDOUR_VERSION;</command>">
+<!ENTITY ARDOUR_APPLICATION "<application>&ARDOUR_NAME;</application>">
+<!ENTITY COPYRIGHT_HOLDER "&ARDOUR_NAME; Foundation">
diff --git a/manual/xml/exporting.xml b/manual/xml/exporting.xml
new file mode 100644
index 0000000000..fb34fb30f5
--- /dev/null
+++ b/manual/xml/exporting.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-exporting">
+ <title>Exporting</title>
+ <para>
+ This section covers ways to get your session converted into various
+ formats for use by other software or systems.
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="exporting_to_cd.xml" />
+</chapter>
diff --git a/manual/xml/exporting_to_cd.xml b/manual/xml/exporting_to_cd.xml
new file mode 100644
index 0000000000..2042e29c2e
--- /dev/null
+++ b/manual/xml/exporting_to_cd.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-exporting-to-cd">
+ <sectioninfo>
+ <authorgroup>
+ <author>
+ <personname>
+ <firstname>Nick</firstname>
+ <surname>Mainsbridge</surname>
+ </personname>
+ </author>
+ </authorgroup>
+ </sectioninfo>
+ <title>Exporting to CD</title>
+ <section id="table-of-contents">
+ <title>Table of Contents </title>
+ <para>
+ A Table of Contents is a description of the data stored on a medium.
+ In the case of audio Cds, the TOC comes in the form of PQ data which
+ is intermingled with the audio data whaen the CD is burnt. Because PQ
+ data isn't part of 'normal' audio file formats such as wav or aiff,
+ this information must be stored in a separate file on your computer (a
+ CUE or TOC file) ready for use by your CD burning software which will
+ combine the two.
+ </para>
+
+ <para>
+ At the moment, Ardour can export TOC and CUE files containing the
+ red-book related fields Track, Index, ISRC, SCMS and Preemphasis. The
+ CD-TEXT fields TITLE, COMPOSER, PERFORMER and disc title are also
+ supported.
+ </para>
+
+ <para>
+ Range markers in Ardour can be 'promoted' to become CD tracks in the
+ locations window. Marks (point markers) can be promoted to be CD
+ Indexes in the same window. All TOC/CUE export operations hinge on
+ this.
+ </para>
+
+ <para>
+ Assuming you have several songs on your timeline laid out so that
+ their spacing and level is 'correct' as you hear it, you should then
+ set ranges that represent the start and end points of each track,
+ These will become the start and end points on your CD. The start times
+ are all rounded down to the previous CD frame (Of which there are
+ 75/second) on export, so if you want to hear the exact point that your
+ CD player will start from, select 'CD frames' as your snap setting
+ while you do this. If you want track indexes (nobody does, but they're
+ there), set a location marker for each desired index.
+ </para>
+
+ <para>
+ The locations dialog is useful here, as you can just 'go' to a point
+ to audition the exact position of a marker/range.
+ </para>
+ </section>
+
+ <section id="pregap">
+ <title> Pregap </title>
+ <para>
+ A word about pregap:
+ </para>
+
+ <para>
+ A 'normal' redbook CD should have a blank (digital black) space of 2
+ seconds before the first modulation called the pregap. Ideally, your
+ first song will have been placed at 2 seconds when you began, but you
+ can always drag the whole collection of songs to the right position
+ fairly easily at this point.
+ </para>
+
+ <para>
+ Also, note that this 2 second rule can be fun to break. You can make
+ the pregap as long as you like.. even hide whole songs in there. The
+ player will still play track one when the disc is inserted. Only those
+ listeners with the urge to rewind beyond the beginning will find your
+ hidden song/dog bark. Also keep in mind that there is a pregap for
+ each song. It starts where the previous song ends. In other words, if
+ you leave a gap in the ranges between songs 2 &amp; 3, that gap will
+ only play for those listening through the entire CD. Anyone skipping
+ directly to 3 will miss your secret 'long' intro.
+ </para>
+
+ <para>
+ After setting a non-overlapping range for each track (overlapping CD
+ tracks are removed on export, from left to right, as are indexes that
+ aren't inside a track), open the locations window and make your ranges
+ into track markers by clicking the CD button. Fill in whatever
+ information you feel is necessary in the boxes below. Unused fields
+ will be ignored as far as the exported TOC/CUE file is concerned.
+ </para>
+
+ <para>
+ CD-TEXT track titles are taken from the range's name. The CD-TEXT
+ title of the CD is taken from the session name (i should have told you
+ that first, right?).
+ </para>
+
+ <note>
+ <para>
+ Pre-emphasis is there for those strange types that use it (they also
+ use track indexes). You almost certainly don't want pre-emphasis. A
+ valid ISRC is all capitals, 12 characters.
+ </para>
+ </note>
+ </section>
+
+ <section id="cue-files">
+ <title> Cue Files </title>
+ <para>
+ Cue files have no notion of 'the end'. Its a drag. They think the end
+ of the file is the end of the last track. If you want to use CUE
+ files, you have to make sure that the session end marker is snapped to
+ CD frames (before you export, of course), or else use the -pad option
+ when you burn.
+ </para>
+ </section>
+
+ <section id="export-the-session">
+ <title> Export The Session </title>
+ <para>
+ Now export the session to a file (16bit 44.1kHz for CD), selecting
+ your preferred cuefile type (TOC or CUE). The TOC/CUE file is written
+ to the same directory as your audio file, and has the same name, only
+ with '.toc' or '.cue' appended. Usually you will only be selecting the
+ two master outputs to export, with output 1 always being 'left'. The
+ export is post fader and panner. Don't assume that the sound will be
+ identical after you have truncated/dithered to 16 bits. It can be
+ worthwhile to experiment with different dither settings when making
+ your export.
+ </para>
+
+ <para>
+ To check out the details without burning
+ </para>
+<screen>
+cdrdao show-toc blah.wav.toc
+</screen>
+ <para>
+ to correct a problem, make your changes, then use the 'export toc file
+ only' option. If you have to change the session end marker, you'll
+ have to re-export your audio file.
+ </para>
+
+ <para>
+ To burn
+ </para>
+<screen>
+cdrdao write /home/britney/globalsmash.wav.toc
+</screen>
+ <para>
+ One last thing:
+ </para>
+
+ <para>
+ If you don't make any CD Track ranges and export a TOC/CUE file, the
+ entire session is treated as one track with no pregap. Indexes, if
+ present, will be honoured.
+ </para>
+ </section>
+
+ <section id="ddp-support">
+ <title>FAQ </title>
+ <para>
+ Why no DDP? ( http://www.dcainc.com/products/ddp/ )
+ </para>
+
+ <para>
+ A: DCA have been kind enough to get in touch. Hopefully they will
+ allow a GPL implementaton soon.
+ </para>
+ </section>
+
+ <section id="catalog-numbers">
+ <title>What about catalog numbers for the CD?</title>
+ <para>
+ A: coming eventually.. we need a tab for session-wide variables like
+ these. where to put it? in the export dialog or the options menu?
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/formatting_conventions.xml b/manual/xml/formatting_conventions.xml
new file mode 100644
index 0000000000..3908a53480
--- /dev/null
+++ b/manual/xml/formatting_conventions.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-formatting-conventions">
+ <title>Formatting Conventions</title>
+ <section id="typography">
+ <title>Typography</title>
+ <para>
+ This manual uses a few conventions to indicate key commands, menu
+ choices and other user interactions:
+ </para>
+
+ <para>
+ Key commands such as <keycombo><keycap>Ctrl</keycap><keycap>a</keycap>
+ </keycombo> mean "Hold down the Ctrl key and press the 'a' key". New
+ and important terms are written like this.
+ </para>
+
+ <para>
+ The names of on-screen buttons are shown like this
+ <guibutton>Button</guibutton>
+ </para>
+
+ <para>
+ The name of a menu item is shown like <guimenuitem>This</guimenuitem>,
+ and nested menu items will appear like <menuchoice>
+ <guimenu>Menu</guimenu> <guisubmenu>Sub Menu</guisubmenu>
+ </menuchoice>
+ </para>
+ </section>
+
+ <section id="admonitions">
+ <title>Admonitions</title>
+ <para>
+ Admonitions are set apart from the main text and are meant to draw
+ your attention to pieces of information. In the order of how critical
+ the information is to you, these items are marked as follows:
+ </para>
+
+ <note>
+ <title>Note</title>
+ <para>
+ A note is typically information that you need to understand the
+ behavior of Ardour.
+ </para>
+ </note>
+ <tip><title>Tip</title>
+ <para>
+ A tip is typically an alternative way of performing a task.
+ </para>
+ </tip>
+ <important>
+ <title>Important</title>
+ <para>
+ The important admonition is used to draw attention to parts of the
+ interface that may be overlooked or certain settings that are vital
+ in determining the behaviour of ardour.
+ </para>
+ </important>
+
+ <warning>
+ <title>Warning</title>
+ <para>
+ The warning admonition is used where an action may result in
+ consequences that are unintended or permanent such as changes to the
+ session that can not be undone or the removal of files.
+ </para>
+ </warning>
+ </section>
+
+ <section id="mouse-buttons">
+ <title>Mouse Buttons</title>
+ <para>
+ You might be used to terms like "right mouse button", "left mouse
+ button" etc. These are widely used, but they can be very confusing for
+ left-handed people, or people using mice with many buttons arranged in
+ an unconventional way. Ardour is typically used with mice equipped
+ with at least 3 buttons that can be remapped for left- and
+ right-handed users, making it hard to unambiguously define "left" and
+ "right" in a useful way.
+ </para>
+
+ <para>
+ If you are right-handed and use a conventional mouse, then
+ <mousebutton>Button1</mousebutton> corresponds to "left mouse button",
+ <mousebutton>Button2</mousebutton> to "middle mouse button" and
+ <mousebutton>Button3</mousebutton> to "right mouse button". Otherwise,
+ the numbered button nomenclature refers to the same button numbers as
+ defined by your X Window configuration.
+ </para>
+
+ <para>
+ If you see instructions to use <keycombo><keycap>Ctrl</keycap>
+ <mousebutton>Button1</mousebutton> </keycombo> , it means "Hold down
+ the <keycap>Ctrl</keycap> key and click
+ <mousebutton>Button1</mousebutton> ".
+ </para>
+ </section>
+
+ <section id="select-choose">
+ <title>Select/Choose</title>
+ <para>
+ In conventional English, "select" and "choose" are often used as
+ synonyms. In this manual, we use them to mean quite different things:
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term>Select</term>
+ <listitem>
+ <para>
+ When you select something, it will stay selected. Putting a
+ check-mark in a box, for example, would be referred to as
+ "selecting" that box. This is also true for menu items that
+ enable or disable options ("select Big Clock from the Windows
+ menu", for example) and various editing functions.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Choose</term>
+ <listitem>
+ <para>
+ "Choosing" involves clicking or using the keyboard to accomplish
+ a one-time action. A command to save the current session might
+ be described as, "Choose Save from the Session menu.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/frontier_design_tranzport.xml b/manual/xml/frontier_design_tranzport.xml
new file mode 100644
index 0000000000..675999f17b
--- /dev/null
+++ b/manual/xml/frontier_design_tranzport.xml
@@ -0,0 +1,558 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-frontier-design-tranzport">
+ <title>Using a Frontier Design Tranzport</title>
+ <section id="tranzport-configuration">
+ <title>Enabling a Tranzport</title>
+ <para>
+ Ardour 2.0 can currently use a single Tranzport controller. Ensure
+ that the device is plugged into a functional USB port. On Linux you
+ will need to <link linkend="sn-configuring-usb-device-access">take
+ steps</link> to ensure that non-administrative users can access the
+ device. Note that this feature is <emphasis>not</emphasis> available
+ in Ardour 0.99.x.
+ </para>
+
+ <para>
+ In the Options menu, navigate into the Control Surfaces submenu. Click
+ on the "Tranzport" option to enable use of the control surface within
+ Ardour. To disable it, click on this item a second time.
+ </para>
+ </section>
+
+ <section id="tranzport-buttons-and-wheel-functions">
+ <title>Tranzport Buttons and Datawheel functions</title>
+ <table id="tbl-tranzport-functions">
+ <title>Tranzport Functions</title>
+ <tgroup cols = "3">
+ <colspec colnum="1" colname = "Key Binding" colwidth = "1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key
+ </entry>
+
+ <entry>
+ Normal Click
+ </entry>
+
+ <entry>
+ Shift Click
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>
+ REW
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Rewind
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Go to start
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ FFWD
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Fast forward
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Go to end
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ STOP
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Stop
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Enter *
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ PLAY
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Play
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Save
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ RECORD
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Record
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+ </row>
+
+ <row>
+ <entry></entry>
+
+ <entry></entry>
+
+ <entry></entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ PREV
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Go to previous marker
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Zoom full
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ ADD
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Add marker at current location
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ NEXT
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Go to next marker
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Select normal, scrub or shuttle mode
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry></entry>
+
+ <entry></entry>
+
+ <entry></entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ IN
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+
+ <entry>
+ <para>
+ Zoom In
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ OUT
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+
+ <entry>
+ <para>
+ Zoom Out
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ PUNCH
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ LOOP
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+
+ <entry>
+ <para>
+ Select gain/pan/master level mode
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry></entry>
+
+ <entry></entry>
+
+ <entry></entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ &lt; TRACK
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Previous track
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ TRACK &gt;
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Next track
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ REC
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Toggle track's record enable on/off
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Clear all track record arming
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ MUTE
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Toggle track's mute status on/off
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Clear all mutes
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ SOLO
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Toggle track's solo status on/off
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Clear all solos
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ UNDO
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Undo
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ Redo
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry></entry>
+
+ <entry></entry>
+
+ <entry></entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ DATA WHEEL
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ scroll timeline, scrub or shuttle
+ </para>
+ </entry>
+
+ <entry>
+ <para>
+ adjust track gain, track pan or master gain
+ </para>
+ </entry>
+ </row>
+
+ <row>
+ <entry></entry>
+
+ <entry></entry>
+
+ <entry></entry>
+ </row>
+
+ <row>
+ <entry>
+ <para>
+ FOOTSWITCH
+ </para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+
+ <entry>
+ <para></para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="tranzport-normal-scrub-shuttle-modes">
+ <title>Normal, Scrub and Shuttle Modes</title>
+ <para>
+ In Ardour, the Tranzport in has 3 different modes of operation termed
+ "timeline", "scrub" and "shuttle".
+ </para>
+
+ <variablelist>
+ <title>Tranzport Modes of Operation</title>
+ <varlistentry>
+ <term>Timeline</term>
+ <listitem>
+ <para>
+ the data wheel scrolls the timeline in the editor window back
+ and forth.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Scrub</term>
+ <listitem>
+ <para>
+ the data wheel is used to scrub audio data back and forth.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Shuttle</term>
+ <listitem>
+ <para>
+ the data wheel is used to control varispeed playback. Turning
+ the data wheel clockwise increases the playback speed in a
+ forward direction. Counter-clockwise decreases the speed and
+ will reverse playback. Shuttle mode as several important
+ features:
+ <itemizedlist>
+ <listitem>
+ <para>
+ While in Shuttle mode the actual playback speed will be
+ displayed in the top right corner of the LCD as a
+ percentage of real-time, ie. +100% is normal playback
+ speed.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Press STOP to automatically set the Shuttle speed to 0%.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Press PLAY to automatically set the Shuttle speed to
+ +100%.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Press and hold SHIFT to momentarily toggle the TranzPort
+ into Scrub mode. Releasing the SHIFT button will return to
+ Shuttle mode at 0% speed. This combination of functions is
+ very useful for quickly moving through an audio track and
+ accurately locating points hit points.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Pressing ADD will drop a marker at the current location
+ and exit Shuttle mode
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/general_key_bindings.xml b/manual/xml/general_key_bindings.xml
new file mode 100644
index 0000000000..edf77ad113
--- /dev/null
+++ b/manual/xml/general_key_bindings.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-general-key-bindings">
+ <title>General Key Bindings</title>
+ <table id="tbl-general-key-bindings">
+ <title>General Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum = "1" colname = "Key Binding" colwidth = "1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>w</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Closes any non-error dialog windows
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>e</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Raise the Editor Window
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>m</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Toggle display of the locations window
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>c</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Toggle display of the options editor
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>t</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Add a track or bus
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>s</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Save the session
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>q</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Quit
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>u</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Starts a prefix entry sequence
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>m</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ Toggle sending MIDI feedback
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/generic_midi_control_surface.xml b/manual/xml/generic_midi_control_surface.xml
new file mode 100644
index 0000000000..675d8948a9
--- /dev/null
+++ b/manual/xml/generic_midi_control_surface.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-generic-midi-control-surface">
+ <title>Using a Generic MIDI control surface</title>
+ <para>
+ To be completed. Applies only to Ardour 2.
+ </para>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/generic_mouse_actions.xml b/manual/xml/generic_mouse_actions.xml
new file mode 100644
index 0000000000..fdc26d4e6c
--- /dev/null
+++ b/manual/xml/generic_mouse_actions.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="generic-mouse-actions">
+ <title>Generic Mouse Actions</title>
+ <table id="tbl-generic-mouse-actions">
+ <title>Range Operations Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <mousebutton>Button3</mousebutton> click
+ </entry>
+
+ <entry>
+ Show context menu for clicked-upon item
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ "Delete" click ( <keycombo><keycap>Shift</keycap>
+ <mousebutton>Button3</mousebutton> </keycombo> )
+ </entry>
+
+ <entry>
+ Remove clicked upon item
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ "Edit" click
+ (<keycombo><keycap>Ctrl</keycap><mousebutton>Button3</mousebutton></keycombo>)
+ </entry>
+
+ <entry>
+ Edit clicked upon item (if possible)
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ "snap modifier" (<keycap>Mod3</keycap>)
+ </entry>
+
+ <entry>
+ allow continuous dragging when snap-to is selected
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ These generic mouse actions can be changed from the options window
+ </para>
+</section>
diff --git a/manual/xml/glossary.xml b/manual/xml/glossary.xml
new file mode 100644
index 0000000000..e07b2c462a
--- /dev/null
+++ b/manual/xml/glossary.xml
@@ -0,0 +1,304 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE glossary PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<glossary>
+ <title>Ardour Glossary</title>
+ <glossdiv>
+ <title>A</title>
+ <glossentry id="gt-alsa">
+ <glossterm><acronym>ALSA</acronym></glossterm>
+ <glossdef>
+ <para>
+ Abbreviation for Advanced Linux Sound Architecture. ALSA provides
+ audio and MIDI functionality to the Linux operating system.
+ </para>
+ <para>
+ <ulink url="http://www.alsa-project.org"/>
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-audio-track">
+ <glossterm>Audio Track</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-auditioner">
+ <glossterm>Auditioner</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>B</title>
+ <glossentry id="gt-bus">
+ <glossterm>Bus</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-bus-track">
+ <glossterm>Bus Track</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>C</title>
+ <glossentry id="gt-crossfade">
+ <glossterm>Crossfade</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>D</title>
+ <glossentry id="gt-daw">
+ <glossterm><acronym>DAW</acronym></glossterm>
+ <glossdef>
+ <para>
+ Abbreviation of Digital Audio Workstation. Some reasonable
+ definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-destructive-recording">
+ <glossterm>Destructive Recording</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>E</title>
+ <glossentry id="gt-embed">
+ <glossterm>Embed</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>H</title>
+ <glossentry id="gt-hdr">
+ <glossterm><acronym>HDR</acronym></glossterm>
+ <glossdef>
+ <para>
+ Short for Hard Disk Recorder. Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>I</title>
+ <glossentry id="gt-insert">
+ <glossterm>Insert</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>J</title>
+ <glossentry id="gt-jack">
+ <glossterm><acronym>JACK</acronym></glossterm>
+ <glossdef>
+ <para>
+ Initialism of Jack Audio Connection Kit. Some reasonable
+ definition here.
+ </para>
+ <para>
+ <ulink url="http://jackaudio.org"/>
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>L</title>
+ <glossentry id="gt-ladpsa">
+ <glossterm><acronym>LADSPA</acronym> </glossterm>
+ <glossdef>
+ <para>
+ Abbreviation of Linux Audio Developers Simple Plugin API. Some
+ reasonable definition here.
+ </para>
+ <para>
+ <ulink url="http://ladspa.org"/>
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>M</title>
+ <glossentry id="gt-midi">
+ <glossterm><acronym>MIDI</acronym> </glossterm>
+ <glossdef>
+ <para>
+ Abbreviation for Musical Instrument Digital Interface. Some
+ reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>P</title>
+ <glossentry id="gt-playlist">
+ <glossterm>Playlist</glossterm>
+ <glossdef>
+ <para>
+ some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-plugin">
+ <glossterm>plugin</glossterm>
+ <glossdef>
+ <para>
+ some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-posix">
+ <glossterm><acronym>POSIX</acronym></glossterm>
+ <glossdef>
+ <para>
+ POSIX stands for Portable Operating System Interface for uniX.
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>R</title>
+ <glossentry id="gt-region">
+ <glossterm>Region</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-redirect">
+ <glossterm>Redirect</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>S</title>
+ <glossentry id="gt-send">
+ <glossterm>Send</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-session">
+ <glossterm>Session</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-session-template">
+ <glossterm>Session Template</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ <glossseealso otherterm="gt-session"/>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-submixing">
+ <glossterm>Submixing</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>T</title>
+ <glossentry id="gt-tape-track">
+ <glossterm>Tape Track</glossterm>
+ <glossdef>
+ <para>
+ Some Reasonable definition here.
+ </para>
+ <glossseealso otherterm="gt-track"/>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="gt-track">
+ <glossterm>Track</glossterm>
+ <glossdef>
+ <para>
+ Some reasonable definition here.
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+
+ <glossdiv>
+ <title>V</title>
+ <glossentry id="gt-vst">
+ <glossterm><acronym>VST</acronym></glossterm>
+ <glossdef>
+ <para>
+ Short for Virtual Studio Technology
+ </para>
+ </glossdef>
+ </glossentry>
+ </glossdiv>
+</glossary>
diff --git a/manual/xml/introduction.xml b/manual/xml/introduction.xml
new file mode 100644
index 0000000000..27c14636d7
--- /dev/null
+++ b/manual/xml/introduction.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-introduction">
+ <title>Introduction</title>
+ <para>
+ Welcome to Ardour. Ardour is a powerful digital audio workstation that
+ gives you everything you need to record, edit, mix, and arrange
+ professional audio.
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="formatting_conventions.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="midi_configuration.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="user_interface_conventions.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="what_is_different_about_ardour.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="why_is_it_called_ardour.xml" />
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</chapter>
diff --git a/manual/xml/jack.xml b/manual/xml/jack.xml
new file mode 100644
index 0000000000..8798a45686
--- /dev/null
+++ b/manual/xml/jack.xml
@@ -0,0 +1,292 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-configuring-jack">
+ <title>Getting Audio In, Out and Around Your Computer</title>
+ <para>
+ Before you can begin to use Ardour, you will need to get the audio
+ input/output capabilities of your system working and properly
+ configured. There are two aspects to this process: getting your audio
+ interface (soundcard) working, and configuring it to work with the Jack
+ Audio Connection Kit (<ulink url="http://jackaudio.org/">JACK</ulink>).
+ </para>
+
+ <section id="sn-jack">
+ <title>JACK</title>
+ <para>
+ It is extremely important to understand that Ardour does not interact
+ directly with your audio interface when it is running. Instead, all of
+ the audio data signals that Ardour receives and generates are sent to
+ and from JACK, a piece of software that routes audio data between an
+ audio interface and audio applications, in real time.
+ </para>
+
+ <para>
+ Traditionally, most of the audio sources that you would want to
+ record, as well as a lot of the more significant effects processing,
+ existed outside the computer. Consequently one of the biggest issues
+ in integrating a computer into the operation of the studio is how to
+ move audio data in and out of the computer.
+ </para>
+
+ <para>
+ However, it is becoming increasingly common for studios to use audio
+ sources and effects processing that are comprised completely of
+ software, quite often running on the same machine as an audio
+ sequencer or digital audio workstation (DAW). A new problem arises in
+ such situations, because moving audio in and out of the DAW no longer
+ involves your hardware audio interface. Instead, data has to be moved
+ from one piece of software to another, preferably with the same kind
+ of sample synchronisation you’d have in a properly configured
+ digital hardware system. This is a problem that has been solved at
+ least a couple of times (ReWire from PropellerHeads and DirectConnect
+ from Digidesign are the two most common examples), but JACK is a new
+ design developed as an open source software project, and is thusly
+ available for anyone to use, learn from, extend, *fix or modify.
+ </para>
+
+ <para>
+ New users may not initially realize that by using Jack, their computer
+ becomes an extremely flexible and powerful audio tool - especially
+ with Ardour acting as the ’heart’ of the system.
+ </para>
+ </section>
+
+ <section id="getting-audio-working">
+ <title>Getting Your Audio Interface Working</title>
+ <note>
+ <para>
+ Although Ardour runs on OS X as well as Linux, this documentation
+ describes only a Linux (ALSA) system. The issues faced on OS X tend
+ to be entirely different, and are centered mostly on JACK. There are
+ also alternative audio device driver families for Linux but they are
+ also not discussed here.
+ </para>
+ </note>
+
+ <para>
+ Getting your audio interface working can be the hardest part of
+ setting your computer up to run Ardour, or it could be one of the
+ easiest. The level of difficulty you will face depends on the type of
+ audio interface ("soundcard") you are using, the operating system
+ version you are using, and your own understanding of how it all works.
+ </para>
+
+ <para>
+ In an ideal world, your computer already has a working audio
+ interface, and all you need do is to start up qjackctl and run JACK.
+ You can determine if you face this ideal situation by doing a few
+ simple tests on your machine. The most obvious test is whether
+ you’ve already heard audio coming out of your computer. If you are
+ in this situation, you can skip ahead to
+ <xref linkend="selecting-capture-source"/>.
+ </para>
+ </section>
+
+ <section id="checking-for-an-audio-interface">
+ <title>Checking For an Audio Interface</title>
+ <para>
+ If you’ve never tried to play audio on your computer before, you
+ should use a basic playback program such as play, aplay or possibly
+ xmms. Find an audio file on your machine (<command>locate
+ .wav</command> may help here), and try to play it. There are several
+ possibilities:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ You may get an error from the program
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ You may hear nothing
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ You may hear something, but its too quiet
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ you may hear something from the wrong loudspeakers.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="selecting-capture-source">
+ <title>Selecting Capture Source</title>
+ <para>
+ Many audio interfaces, particularly the cheaper varieties that are
+ often found built into computers, have ways to plug in both
+ microphones and instruments or other audio equipment to be recorded.
+ This immediately poses a question: how does Ardour (or any software)
+ know which signal to record, the one coming into the microphone input,
+ or the one arriving at the "line in" socket? The same question arises
+ also for "high-end" audio interfaces, though in different ways.
+ </para>
+
+ <para>
+ The short answer is: Ardour doesn’t. Instead, this is a choice you
+ have to make using a program a program that understands how to control
+ the mixing hardware on the audio interface. Linux/ALSA has a number of
+ such programs: alsamixer, gamix, aumix, kmix are just a few of them.
+ Each of them offers you a way to select which of the possible
+ recordable signals will be used for as the "capture source". How you
+ select the preferred signal varies from program to program, so you
+ will have to consult the help documentation for whichever program you
+ choose to use.
+ </para>
+
+ <para>
+ There are also a few programs that offer ways to control just one
+ particular kind of audio interface. For example, the
+ <application>hdspmixer</application> program offers control over the
+ very powerful matrix mixer present on several RME audio interface.
+ <application>envy24ctrl</application> does the same for a number of
+ interfaces built around the common ice1712/envy24 chipset, found in
+ devices from M-Audio, Terratec and others. Please note that this quite
+ similar to the situation for Windows and MacOS users, where each audio
+ interface often comes with its own control program that allows certain
+ critical configuration choices to be made.
+ </para>
+
+ <section id="problems-with-input-signal">
+ <title>"I don’t get any signal when I record …"</title>
+ <para>
+ The most common problem for first-time audio users on Linux is to
+ try to record something and get no signal at all, or alternatively,
+ a very low signal. The low signal problem typically arises from one
+ or more of the following issues:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ a microphone input plugged into the "line in" socket of the
+ interface. The signal levels delivered by microphones are very
+ small, and require amplification before they can be used by most
+ audio circuitry. In professional recording studios, this is done
+ using a dedicated box called a "pre-amplifier". If your audio
+ interface has a "mic input" socket, then it has its own
+ pre-amplifier built in, although its probably not a very good
+ one. If you make the mistake of plugging a microphone into the
+ "line in" socket, you will get either an inaudible or very quiet
+ signal.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ the wrong capture source selected in the audio interface’s
+ hardware mixer (see above)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ the "capture" gain level in the audio interface’s hardware
+ mixer is turned down too low. You will need to use a hardware
+ mixer application (as described above) to increase this.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <note>
+ <para>
+ You will notice in the mixer strip for each track in ardour that
+ you can change the selection of the monitoring source between
+ input/pre/post. Adjusting the fader while watching the ’input’
+ levels will NOT have any affect on the levels. As mentioned above,
+ ardour is dependent on external mixer settings for a source level.
+ </para>
+ </note>
+ </section>
+ </section>
+
+ <section id="monitoring-choices">
+ <title>Monitoring Choices</title>
+ <para>
+ Its unfortunate that we have to raise this issue at a point in the
+ manual where you, the reader, may not even knoiw what "monitoring"
+ means. However, it is such an absolutely critical aspect of using any
+ digital audio workstation that we need to at least cover the basics
+ here. The only people who don’t need to care about monitoring are
+ those who will never use ardour to record a live performance (even on
+ performed using a software synthesizer).
+ </para>
+
+ <para>
+ Monitoring is the term we use to describe listening to what ardour is
+ recording. If you are playing a guitar and recording it with ardour,
+ you can probably hear the guitar’s own sound, but there are many
+ situations where relying on the sound of the instrument is completely
+ inadequate. For example, with an electronic instrument, there is no
+ sound until the electrical signal that it generates has been processed
+ by an amplifier and fed to a loudspeaker. But if Ardour is recording
+ the instrument’s signal, what is responsible for sending it to the
+ amp+loudspeakers? It can get a lot more complex than that: if you are
+ recording multiple performers at the same time, each performer needs
+ to hear their own playing/singing, but they also probably need to hear
+ some of their colleagues’ sound as well. You might be overdubbing
+ yourself - playing a new line on an instrument while listening to
+ tracks you’ve already recorded - how do you hear the new material as
+ well as the existing stuff?
+ </para>
+
+ <para>
+ Well, hopefully, you’re convinced that there are some questions to
+ be dealt with surrounding monitoring, see
+ <xref linkend="sn-monitoring"/> for more in depth information.
+ </para>
+ </section>
+
+ <section id="using-multiple-soundcards">
+ <title>Can I use multiple soundcards</title>
+ <para>
+ There are really lots of great reasons why you should not even attempt
+ to do this. But seriously, save your money for a while and buy
+ yourself a properly designed multichannel soundcard.
+ </para>
+ </section>
+
+ <section id="qjackctl">
+ <title>Qjackctl</title>
+ <para>
+ JACK itself does not come with graphical user interface - to start
+ JACK and control it you need to have access to a command line and a
+ basic knowledge of Unix-like operating systems. However,
+ <ulink url="http://qjackctl.sourceforge.net/">qjackctl</ulink> is a
+ wonderful application that wraps JACK up with a graphical interface
+ that is both nice to look at and useful at same time. qjackctl is the
+ recommended way of using JACK.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/qjackctl.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ You should be able to start qjackctl from the “application menuâ€
+ of your system, typically found on the panel/appbar/dock or whatever
+ its called that lives at the top/bottom/left/right of your screen.
+ </para>
+
+ <para>
+ [ need screenshot of GNOME/KDE/OSX menus here ]
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/key_bindings.xml b/manual/xml/key_bindings.xml
new file mode 100644
index 0000000000..f3b50810a7
--- /dev/null
+++ b/manual/xml/key_bindings.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-and-keyboard-bindings">
+ <title>Mouse and Keyboard Bindings</title>
+ <section id="sn-key-bindings">
+ <title>Key Bindings</title>
+ <para>
+ Note that all keyboard bindings can be changed in either the system or
+ the user's Ardour configuration file
+ (<filename>$HOME/.ardour/ardour.rc</filename>).
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="general_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="transport_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mixer_window_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_window_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_play_position_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_edit_cursor_position_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_canvas_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_zoom_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_aligning_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_standard_editing_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_range_operations_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_nudging_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_region_operations_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_locations_marks_key_bindings.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="editor_miscellaneous_key_bindings.xml" />
+ </section>
+
+ <section id="sn-mouse-operations">
+ <title>Mouse Operations</title>
+ <para>
+ Note that the definition of the "Delete" and "Edit" clicks can be
+ redefined by the user, either in their Ardour configuration file
+ (<filename>$HOME/.ardour/ardour.rc</filename>) or using the Options
+ Editor (Keyboard+Mouse tab).
+ </para>
+
+ <para>
+ You might wonder why we say Button1 ? Here is an
+<!--
+ <a href="/manual/intro/formatting#Mouse Buttons">explanation</a>.
+ -->
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="generic_mouse_actions.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_wheel_actions.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_object_mode.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_region_gain_mode.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_range_mode.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_zoom_mode.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_ruler.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_mixer_controls.xml" />
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/known_issues.xml b/manual/xml/known_issues.xml
new file mode 100644
index 0000000000..0cdeedd087
--- /dev/null
+++ b/manual/xml/known_issues.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="sn-problems-bugs-known-issues">
+ <title>Problems, Bugs and Known Issues</title>
+ <section id="known-issues">
+ <title> Known Issues </title>
+ <para>
+ This section documents known issues with the all versions of Ardour up
+ to and including 1.0. It is not a replacement for our
+ <ulink url="http://tracker.ardour.org/">bug tracking system</ulink>,
+ but instead summarizes some known issues that are likely to be
+ encountered by users and are not in the process of being fixed.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ creating 3rd level feedback loops (e.g. bus 1 feeds bus 2 feeds
+ bus 3; bus 3 feeds bus 1) may prevent a session from loading
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ ardour's interpretation of "beats per minute" is different from
+ most other programs and from convention. 1 "beat" is whatever the
+ meter in effect defines. Thus, 120 bpm in a 4/4 meter is 120
+ quarter notes per minute; 120 bpm in a 3/8 meter is 120 eighth
+ notes per minute.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ copying or cut-n-pasting two (or more) regions that have a
+ crossfade between them to a new location or a new track does not
+ copy the crossfade. Until a future version of Ardour changes this,
+ you are advised to do region editing first, and create crossfades
+ second.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ it is not possible to create pan automation control points using
+ the mouse for stereo (or higher channel count) tracks and busses.
+ you can create automation for these configurations by recording
+ panning motion, and you can edit the data using the mouse.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ when importing an audio file directly into a track, there are no
+ choices for the quality level of any necessary sample rate
+ conversion. On any system that Ardour is running on, there is
+ almost certainly a utility called
+ <command>sndfile-resample</command> which uses the same sample
+ rate conversion library as Ardour. This utility offers a great
+ deal of control over the sample rate conversion process, including
+ quality levels. Ardour uses the "best" quality internally. If you
+ want a different quality, you can use this tool to produce a
+ rate-converted file at the correct speed, and then import that
+ into Ardour.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ when timestretch is used to alter the length of a region, any
+ region-specific gain envelope is lost. The new region has the
+ default unity gain throughout its duration.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ if you overdub on a playlist in an area containing cross-fades,
+ the cross-fades will still be audible in spite of the newly
+ overdubbed material being "on top" of them. Workaround is to mute
+ or remove the crossfades before overdubbing. As a corollary to
+ this, creating crossfades that span other crossfades will not work
+ correctly in this version of Ardour.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</chapter>
diff --git a/manual/xml/main_windows.xml b/manual/xml/main_windows.xml
new file mode 100644
index 0000000000..56d6a17d2b
--- /dev/null
+++ b/manual/xml/main_windows.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-main-windows">
+ <title>Windows</title>
+ <para>
+ When Ardour starts without a session, there is just a single window
+ visible which we call the editor. However, the program has many more
+ windows that can be displayed for various purposes:
+ </para>
+
+ <note>
+ <para>
+ All Ardour windows have their WMCLASS property set to 'ardour', so
+ that you can configure your window manager to handle them in a certain
+ way if you wish to.
+ </para>
+ </note>
+
+ <section id="editor-window-summary">
+ <title>Editor Window</title>
+ <para>
+ This is the primary Ardour window. It contains the main menubar, plus
+ several tear-off windows, and the editor itself.
+ </para>
+ </section>
+
+ <section id="transport-bar-summary">
+ <title>Transport Bar Window</title>
+ <para>
+ This window provides complete control over all of Ardour's transport
+ functionality. it is initially attached to the editor window, but can
+ be torn off and kept as an independent window if you prefer.
+ </para>
+ </section>
+
+ <section id="mixer-window-summary">
+ <title>Mixer Window</title>
+ <para>
+ This window will be displayed automatically whenever a Session is
+ loaded, and provides a representation of the Session that is modelled
+ on a mixing console. Each track and bus has its own Mixer Strip, and
+ there are also various lists for things like Mix Groups.
+ </para>
+
+ <para>
+ A more precise way to think about the difference between the editor
+ and the mixer is that the editor is primarily for controlling the time
+ flow of the Session, whereas the mixer is primarily for controlling
+ the signal flow.
+ </para>
+ </section>
+
+ <section id="location-and-marker-display-window-summary">
+ <title>Location and Marker Display Window</title>
+ <para>
+ This window is used to display, edit and set various Locations and
+ markers within a Session.
+ </para>
+ </section>
+
+ <section id="options-editor-window-summary">
+ <title>Options Editor Window</title>
+ <para>
+ This window is used to set the many global and per-session options for
+ Ardour.
+ </para>
+ </section>
+
+ <section id="track-bus-inspector-window-summary">
+ <title>Track/Bus Inspector Window</title>
+ <para>
+ This optional window provides a single point of control for
+ configuring all I/O and processing for every track and bus. It doesn't
+ provide anything not offered by other windows, but it does group
+ several things together in one place. You may prefer to use or not use
+ this window.
+ </para>
+ </section>
+
+ <section id="big-clock-window-summary">
+ <title>Big Clock Window</title>
+ <para>
+ This optional window provides a display of the playhead position in a
+ large font, readable from some distance. it can be useful when using
+ Ardour to record yourself and you need or want to keep track of time.
+ </para>
+ </section>
+</section>
diff --git a/manual/xml/midi_configuration.xml b/manual/xml/midi_configuration.xml
new file mode 100644
index 0000000000..32eb2c71d1
--- /dev/null
+++ b/manual/xml/midi_configuration.xml
@@ -0,0 +1,299 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-midi-configuration">
+ <title>Midi Configuration</title>
+ <para>
+ Although at this time Ardour does not support
+ <glossterm linkend="gt-midi">MIDI</glossterm> sequencing, it does
+ support a fairly rich set of interactions via MIDI with other devices.
+ In particular:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Ardour can function as MIDI Time Code (MTC) master or slave
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Ardour can control or be controlled by other devices using MIDI
+ Machine Control (MMC)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Ardour can bind all gain faders, panners, mute/solo/rec-enable
+ buttons and all plugin parameters to be controlled by MIDI
+ Continuous Controller (CC) or Note On/Off messages.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Ardour can send MIDI "feedback" whenever gain, pan or plugin state
+ changes, so that external motorized control surfaces can reflect
+ parameter changes caused by automation etc.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="specifying-midi-ports">
+ <title>Specifying MIDI ports</title>
+ <para>
+ Ardour does not attempt to discover what MIDI ports exist on your
+ system. This is a complex issue, and on systems like Linux and OS X
+ that permit virtual ports to be created at any time, it is not trivial
+ to get right (although future versions of Ardour may try).
+ </para>
+
+ <para>
+ Instead, the MIDI ports that are available for Ardour to use are
+ defined in your <filename>ardour.rc</filename> file. These port
+ definitions are not session specific, on the assumption that your
+ system's MIDI hardware probably doesn't change much from session to
+ session. The default version of this file contains a single port that
+ can be used for inter-application MIDI routing as well as MIDI I/O to
+ whatever physical MIDI ports might be available on your computer. In
+ many cases, you will not need to change them.
+ </para>
+
+ <para>
+ When you first use Ardour, the
+<!--
+ xlink linkend="files_and_environment"
+ -->
+ <filename>ardour.rc</filename> file that you will have contains a
+ single port definition. It defines a port that is almost guaranteed to
+ be usable on your system ((Linux/ALSA users may need to ensure that
+ the <filename>snd-seq</filename> kernel module gets loaded - many
+ distributions do not do this by default)). This port is a "virtual
+ port" it isn't actually a hardware MIDI port, but instead is a
+ software port that can be connected to other software ports or to
+ whatever hardware MIDI ports you have (see
+ <xref linkend="midi-making-connections"/>).
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+ <section id="defining-additional-midi-ports">
+ <title>Defining additional MIDI ports</title>
+ <para>
+ To define additional ports, find the line in
+ <filename>ardour.rc</filename> that looks roughly like this:
+ </para>
+<screen>
+&lt;MIDI-port tag="hw:0" device="/dev/snd/midiC1D0" type="alsa/raw" mode="duplex"/&gt;
+ </screen>
+ <para>
+ On OSX/CoreMIDI it would look more like:
+ </para>
+<screen width="50">
+&lt;MIDI-port tag="coremidi" device="ardour" type="coremidi" mode="duplex"/&gt;
+ </screen>
+ <para>
+ You can then add another line right after it that looks similar but
+ contains a different port definition.
+ </para>
+
+ <para>
+ You will see there are 4 pieces of information required to define a
+ MIDI port for use within Ardour. Your port definition
+ </para>
+
+ <section id="midi-tag">
+ <title>Tag</title>
+ <para>
+ This is just a name of your own choosing. It is how the port will be
+ referred to within Ardour. You could use a name that describes what
+ is plugged into the port (e.g. "1600x", "Novation"), or a name that
+ describes the computer device/system that provides the port (e.g.
+ "HDSP", "Sequencer"), or a whimsical name of your own choice (e.g.
+ "bowtie", "merlin").
+ </para>
+ </section>
+
+ <section id="midi-type">
+ <title>Type</title>
+ <para>
+ This is an operating system specific identifier that defines what
+ kind of port this is. It can be set to one of three values:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>alsa/raw</literal> - the port corresponds to a physical
+ MIDI port that is accessed directly without involving the ALSA
+ MIDI routing subsystem.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <literal>alsa/sequencer</literal> - the port is a virtual port
+ that can send and receive MIDI data via the ALSA MIDI routing
+ subsystem.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <literal>coremidi</literal> - the port is a virtual port that
+ can send and receive MIDI data via the CoreMidi
+ inter-application MIDI routing subsystem.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="midi-device">
+ <title>Device</title>
+ <para>
+ This is an operating specific and MIDI subsystem-specific name that
+ actually identifies the device to be used for MIDI I/O.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ for a raw ALSA hardware port, it is the name of the device file
+ corresponding to the hardware MIDI port. A typical value might
+ be <filename>/dev/snd/midiC0D0/</filename>.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ for an ALSA sequencer port, it is an arbitrary name for the port
+ that will appear as part of the ALSA MIDI routing system
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ for a CoreMIDI port, it is an arbitrary name for the port that
+ will appear as in any CoreMIDI port selection dialogs.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="midi-mode">
+ <title>Mode</title>
+ <para>
+ This specifies whether the port is available for input, output or
+ both:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>read</literal> - the port is available for input only
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <literal>write</literal> - the port is available for output only
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <literal>duplex</literal> - the port is available for input and
+ output
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ You should probably always use <literal>duplex</literal> here. It is
+ rare to need to open a port for unidirectional communication only.
+ </para>
+ </section>
+ </section>
+
+ <section id="midi-removing-ports">
+ <title>Removing Midi Ports</title>
+ <para>
+ To remove a MIDI port, simply delete the line in your
+ <filename>ardour.rc</filename> file that defines it.
+ </para>
+ </section>
+
+ <section id="midi-making-connections">
+ <title>Making Connections</title>
+ <para>
+ If you use actual physical hardware MIDI ports, then establishing
+ connections to other MIDI equipment is simply a matter of connecting
+ cables correctly. However, if you use "virtual ports" such as those
+ offered by the ALSA router/sequencer or CoreMIDI, making connections
+ is slightly more involved.
+ </para>
+
+ <para>
+ Ardour does not come with any way of establishing MIDI connections
+ from/to other software MIDI ports. This is a difficult task to get
+ right, and Ardour may offer something in the future. For now, you need
+ to use an external tool that is dedicated to this purpose, much the
+ same way you would use a patchbay (audio/MIDI) with physical
+ equipment.
+ </para>
+
+ <section id="midi-connections-alsa">
+ <title>Linux/ALSA</title>
+ <para>
+ <application>qjackctl</application> (the same program that is
+ recommended for controlling JACK) also includes an excellent MIDI
+ connection manager. You could also use command line tools such as
+ <application>aconnect</application>.
+ </para>
+ </section>
+
+ <section id="midi-connection-osx">
+ <title>OSX/CoreMIDI</title>
+ <para>
+ On OSX/CoreMIDI you need to connect the MIDI ports with a patchbay
+ tool such as the excellent MIDI Patchbay from
+ <ulink url="http://pete.yandell.com/software/">Pete Yandell</ulink>
+ </para>
+ </section>
+ </section>
+
+ <section id="midi-using-midi-ports">
+ <title>Using MIDI ports</title>
+ <para>
+ Each port that is defined in <filename>ardour.rc</filename> can be
+ used for any of the following functions:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ MTC input and output
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ MMC input and output
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ MIDI CC/Note input and output
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+</section>
diff --git a/manual/xml/mixer_strip_list.xml b/manual/xml/mixer_strip_list.xml
new file mode 100644
index 0000000000..ca72916e85
--- /dev/null
+++ b/manual/xml/mixer_strip_list.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="mixer-window-strip-list">
+ <title> Strip List </title>
+ <para>
+ The Strip List provides a simple interface to the layout of the mixer
+ strips on the mixer. Mixer strips on the mixer have two possible states
+ - visible and hidden. Mixer strips can also be placed in any order on
+ the mixer. Rearranging the order of the mixer strips has no effect on
+ the signal flow of the session. The names of all tracks in your session
+ are listed in their current order. Hidden mixer strips are darker in
+ colour than visible ones. A single left click on a track name will
+ remove the track's mixer strip from the mixer, and changing the colour
+ of the item on the strip list. This action has no effect on signal flow.
+ Dragging a track name vertically with the left mouse button will
+ rearrange the mixer to reflect the order selected when the mouse button
+ is released. Clicking the word "Strip" at the top of the strip list will
+ open a drop-down list of shortcuts to actions that change the strip list
+ (and consequently the state of the mixer).
+ </para>
+
+ <variablelist>
+ <title>Strip List Context Menu</title>
+ <varlistentry>
+ <term><guimenuitem>show all</guimenuitem></term>
+ <listitem>
+ <para>
+ sets all hidden mixer strips to the visible state
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>hide all</guimenuitem></term>
+ <listitem>
+ <para>
+ sets all visible mixer strips to the hidden state.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>show all AudioTrack Mixer Strips</guimenuitem></term>
+ <listitem>
+ <para>
+ sets all hidden mixer strips that are audio tracks to the visible
+ state
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>hide all AudioTrack Mixer Strips</guimenuitem></term>
+ <listitem>
+ <para>
+ sets all visible mixer strips that are audio tracks to the hidden
+ state.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>show all AudioBus Mixer Strips</guimenuitem></term>
+ <listitem>
+ <para>
+ sets all hidden mixer strips that are audio buses to the visible
+ state
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>hide all AudioBus Mixer Strips</guimenuitem></term>
+ <listitem>
+ <para>
+ sets all visible mixer strips that are audio buses to the hidden
+ state.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ At the bottom right of the strip list, a square box provides a method
+ for resizing the pane. Holding down the left mouse button while dragging
+ the square vertically will move the lower border of the strip list.
+ </para>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mixer_strips.xml b/manual/xml/mixer_strips.xml
new file mode 100644
index 0000000000..b381ced49a
--- /dev/null
+++ b/manual/xml/mixer_strips.xml
@@ -0,0 +1,519 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<!-- XXX lots to do on this page -->
+
+<section id="mixer-strips">
+ <title>Mixer Strips</title>
+ <para>
+ Each track and bus is represented in the mixer window by a
+ <emphasis>mixer strip</emphasis> that contains various controls related
+ to signal flow. There are two places in Ardour in which you can see
+ mixer strips. The mixer window is the obvious one (and the one we deal
+ with here), but you can also view a single mixer strip in the editor
+ window by clicking the <guibutton>editor mixer</guibutton> button.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/mixerstrip.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ this image needs replacing with labels and better resolution The mixer
+ strip for a bus is essentially identical to the one for an audio track,
+ but it is missing certain controls that make no sense - you cannot
+ record into a bus, so there is no record enable button, for example.
+ </para>
+
+ <para>
+ The mixer strips are designed to visually model signal flow. The input
+ button selects the input of the track that this mixer strip monitors.
+ The outputs of the track (the 'tape recorder') are 'hard-wired' to the
+ inputs of the mixer strip. Think of the input to the strip starting at
+ the polarity switch, flowing down through the prefader
+ inserts/plugins/sends section, through the gain fader, past the
+ postfader inserts/plugins/sends section, the panner, and out through the
+ output selector. In the case of a bus, there is no 'tape machine'
+ inserted between the input selector and the actual input of the strip,
+ but the signal flow is identical otherwise.
+ </para>
+
+ <section id="mixer-strip-narrow-strip-button">
+ <title>Narrow Mixer Strip Button</title>
+ <para>
+ the button on the top left of the mixer strip is labelled with two
+ arrows separated by a line. Left clicking this button will reduce the
+ horizontal size of the mixer strip. Clicking it again will restore the
+ previous size. The first click also has the effect of shortening the
+ names of controls. Plugin lists become very small in this mode,
+ however more faders are accessible without scrolling. Your needs may
+ vary, hence the existence of this button.
+ </para>
+ </section>
+
+ <section id="mixer-strip-hide-button">
+ <title>Hide Button</title>
+ <para>
+ The button opposite the <emphasis>Narrow Mixer Strip Button</emphasis>
+ hides the mixer strip from view. this button has no effect on signal
+ flow or muting. When a mixer strip is hidden, it's entry in the strips
+ list is darkened. To restore the mixer strip to the visible state,
+ click it's entry in the strip list with the left mouse button.
+ </para>
+ </section>
+
+ <section id="mixer-strip-track-name">
+ <title>Track Name</title>
+ <para>
+ The track name displays the current name of the track as displayed in
+ the editor window. right-clicking on the name brings up a drop-down
+ menu that allows you to rename, activate, deactivate and remove the
+ track. Selecting <guimenuitem>Rename</guimenuitem> opens a new window
+ displaying the name of the track. to change it, type your change and
+ press ok. to leave it unaltered, press cancel. Selecting
+ <guimenuitem>remove</guimenuitem> opens a new window asking for
+ confirmation of your track removal request. removing a track removes
+ that track from the project. If the playlist used by the removed track
+ is not used by any other track, it will also be removed.
+ </para>
+ </section>
+
+ <section id="mixer-strip-group-button">
+ <title>Group Button</title>
+ <para>
+ The group button displays the name of the currently selected mix
+ group. if no group is selected, it will read no group. when clicked, a
+ drop-down menu appears which lists the current mixer groups, along
+ with the option no group. if a group is selected, any fader movement
+ on one of the group member faders will be translated to the other
+ members of the group.
+ </para>
+ </section>
+
+ <section id="mixer-strip-input-selector">
+ <title>Input Selector</title>
+ <para>
+ The input selector allows you to assign hardware or software inputs to
+ the track that this mixer strip monitors. clicking on the input box
+ makes a drop-down menu appear which lists ready-made combinations of
+ jack ports, along with the options disconnect and edit. You can either
+ select a preset hardware input combination from the drop-down list, or
+ select <guimenuitem>edit</guimenuitem> to open the input selector
+ window which allows finer control, such as changing the number of
+ inputs to the track or using software devices as inputs. For more
+ information on this window, see <xref linkend="sn-other-windows"/>.
+ <guibutton>Disconnect</guibutton> removes all input assignments while
+ leaving the number of ports untouched.
+ </para>
+ </section>
+
+ <section id="mixer-strip-polarity-button">
+ <title>Polarity Button</title>
+ <para>
+ The polarity button, when pressed, inverts the phase of the signal as
+ it leaves the track and enters the mixer strip. it has no effect on
+ the signal being recorded to disk. It has no effect on the timing of
+ the signal, either.
+ </para>
+ </section>
+
+ <section id="mixer-strip-solo-button">
+ <title>Solo Button</title>
+ <para>
+ The solo button puts the mixer strip in solo mode. the solo indicator
+ in the editor window will flash if any mixer strip is set to solo, and
+ only those tracks that are set in solo will be routed through the
+ system.
+ </para>
+ </section>
+
+ <section id="mixer-strip-mute-button">
+ <title>Mute Button</title>
+ <para>
+ The mute button mutes the output of the mixer strip.
+ </para>
+ </section>
+
+ <section id="mixer-strip-track-speed-control">
+ <title>Track Speed Control</title>
+ <para>
+ The track speed allows a varispeed setting to be applied to the track.
+ a setting of <literal>1.0</literal> corresponds to the normal playback
+ speed of the session. a setting of <literal>0.5</literal> will play at
+ half normal playback speed. when altered, the track will be redrawn to
+ reflect the new position of the audio resulting from the speed change.
+ The Track Speed Control has three decimal places of precision. A left
+ or right click on the displayed number will raise or lower the track
+ speed by 0.1%. when the speed is not exactly 1, the display will be
+ coloured red. Hovering over the displayed number will allow you to use
+ the mouse wheel to set the desired speed. A middle click on the
+ displayed number will return the speed to exactly 1.
+ </para>
+
+ <para></para>
+ </section>
+
+ <section id="mixer-strip-record-enable-button">
+ <title>Record Enable Button</title>
+ <para>
+ The record enable button arms the track for recording. pressing this
+ will change the way you monitor and meter the selected input signal
+ depending on the state of the monitoring settings in the options
+ editor, as well as the auto input setting in the editor.
+ </para>
+ </section>
+
+ <section id="mixer-strip-automation-mode-buttons">
+ <title>Automation Mode Buttons</title>
+ <para>
+ The automation mode buttons allow you to select a fader or pan
+ automation mode from a drop-down list. see
+ <xref linkend="sn-automation"/> for more information about automation
+ modes.
+ </para>
+ </section>
+
+ <section id="mixer-strip-redirect-boxes">
+ <title>Redirect Boxes</title>
+ <para>
+ These dark areas above and below the fader allow you to place inserts,
+ sends and plugins into the signal path before and after the fader
+ respectively. you may also easily reorder them whilst playing.
+ collectively, the objects that belong in these boxes are called
+ redirects. If there are redirects present in the channel, they can be
+ reordered by dragging them vertically. because plugins and inserts can
+ have different numbers of inputs to outputs, sometimes you may reach a
+ situation where the inputs and outputs cannot be all connected
+ sensibly. in this case, your reordering change will be disallowed by
+ the program.
+ </para>
+
+ <para>
+ Right clicking within the dark area will bring up a drop-down menu
+ which allows you to manipulate the redirects in various ways.
+ </para>
+
+ <variablelist>
+ <title>Redirect Boxes</title>
+ <varlistentry>
+ <term><guimenuitem>new plugin</guimenuitem></term>
+ <listitem>
+ <para>
+ selecting new plugin will open a dialog which lists the plugins
+ available on your system. selecting a plugin which is compatible
+ with the number of streams in the channel at that point will
+ result in the plugin being placed in the redirect box in an
+ inactive state. this is indicated by the brackets around the
+ plugin name. double-clicking the plugin name will bring up a
+ window that allows you to control the parameters of the plugin
+ statically (including bypass) or using automation. all plugins
+ that report their latency are time-compensated automatically in
+ ardour.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>new insert</guimenuitem></term>
+ <listitem>
+ <para>
+ places at least two new jack ports at that point in the mixer
+ strip (one input, one output). these ports will then be
+ available to any jack client (including Ardour itself), allowing
+ another program (or channels within another program) to be
+ inserted across the channel. hardware ports may also, of course,
+ be used, allowing the insertion of outboard equipment. the
+ insert will then appear in the redirect box in brackets
+ indicating that it is inactive. to activate or deactivate an
+ insert, right-click on it and select activate. double-clicking
+ on the insert will bring up a dialog which allows to to assign
+ its inputs and outputs to other jack ports.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>new send</guimenuitem></term>
+ <listitem>
+ <para>
+ selecting new send will first bring up a dialog box that enables
+ you to select the number of outputs the send has, along with the
+ destination of each output. closing this dialog will reveal the
+ name of the send in brackets, indicating that it is inactive. to
+ activate the send, right click on it and select Activate.
+ double-clicking on the send brings up the previous dialog, which
+ will now include a fader which is provided for level control.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>clear</guimenuitem></term>
+ <listitem>
+ <para>
+ selecting clear in the menu removes all redirects from the mixer
+ strip (pre and post fader). you can remove an individual
+ redirect by holding the shift key and right clicking it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>cut</guimenuitem>, <guimenuitem>copy</guimenuitem>, <guimenuitem>paste</guimenuitem></term>
+ <listitem>
+ <para>
+ these items allow you to cut, copy and paste plugins, including
+ their current settings, between Redirect Boxes.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>rename</guimenuitem></term>
+ <listitem>
+ <para>
+ selecting rename will bring up a dialog displaying the name of
+ the selected redirect. change the name by typing into the text
+ area and pressing ok.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>select all/deselect all</guimenuitem></term>
+ <listitem>
+ <para>
+ these two options select or deselect all plugins in the channel.
+ this could be used, for instance, in preparation to copy all
+ plugins from a channel to another one, along with the current
+ settings.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>activate/deactivate</guimenuitem></term>
+ <listitem>
+ <para>
+ selecting either of these will activate or deactivate the
+ currently selected redirect(s) respectively. deactivate is the
+ equivalent of <guimenuitem>bypass</guimenuitem>.
+ </para>
+
+ <note>
+ <para>
+ note that you can bypass a plugin from it's parameter window
+ as well as from here.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>activate all/deactivate all</guimenuitem></term>
+ <listitem>
+ <para>
+ selecting either of these will activate or deactivate all
+ redirect(s) in the mixer strip respectively. deactivate is the
+ equivalent of <guimenuitem>bypass</guimenuitem> if you're a
+ plugin.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guimenuitem>edit</guimenuitem></term>
+ <listitem>
+ <para>
+ selecting edit brings up the controls relevent to the selected
+ redirect. this is the equivalent to holding control and
+ right-clicking on a redirect. note that the right click method
+ will not bring up the controls of the selected redirect, only
+ the one beneath the mouse pointer.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="mixer-strip-pre-post-input-button">
+ <title>Pre/Post/Input Button</title>
+ <para>
+ This button cycles between three metering modes, which determine which
+ signal is fed to the meters. the modes are pre-fader (the signal at
+ the input to the fader), post-fader and input (the level at the track
+ input). left clicking cycles through the three modes one step at a
+ time, while middle-clicking alternates between the current setting and
+ the setting two steps ahead. this allows one-click direct a/b
+ comparison between all available monitoring points.
+ </para>
+ </section>
+
+ <section id="mixer-strip-gain-display">
+ <title>Gain Display</title>
+ <para>
+ this control displays the current gain of the fader to the nearest
+ 0.1dB. left clicking on the value will lower the gain by an amount
+ dependent upon the fader position the graduations become smaller as
+ the fader nears 0dB gain. right clicking increases the gain by the
+ same amount. middle clicking resets the gain to 0dB.
+ </para>
+ </section>
+
+ <section id="mixer-strip-unit-selector">
+ <title>Unit Selector</title>
+ <para>
+ Right clicking on the meter bars allows you to select the range of
+ signal levels displayed by the meters. the selected range will be
+ displayed as a column of numbers next to the meter. /*XXX this feature
+ is currently not working*/ Gain Level Display
+ </para>
+ </section>
+
+ <section id="mixer-strip-peak-meter">
+ <title>Peak Meter</title>
+ <para>
+ This control displays the highest peak since the last peak meter
+ reset. Resetting the peak meter is achieved by left-clicking the
+ displayed number. The peak meter monitors the signal selected by the
+ <emphasis>Pre/Post/Input Button</emphasis> .. the same signal as the
+ meters. It should be noted here that 0dBfs corresponds a value equal
+ to the maximum input or output level of your audio hardware,
+ independent of it's bit depth.
+ </para>
+ </section>
+
+ <section id="mixer-strip-gain-fader">
+ <title>Gain Fader</title>
+ <para>
+ The fader changes the signal level within the mixer strip before the
+ post-fader plugins, which are before the output ports. 6dB of gain is
+ allowed. there are several shortcuts available for the fader. Using
+ the scroll wheel of your mouse while hovering above the fader will
+ coarsely change its position. Holding the control key whilst mouse
+ wheeling will give you finer control. Holding the shift key and
+ clicking the fader will reset it to unity gain. Holding control and
+ pressing the middle mouse button whilst over the fader will allow you
+ to bind a midi control to it, provided you have an available midi
+ device set in the options menu.
+ </para>
+ </section>
+
+ <section id="mixer-strip-meters">
+ <title>Meters</title>
+ <para>
+ The number of meters displayed next to the fader is dependent on the
+ number of inputs or outputs the channel has, whichever is greater. The
+ meters provide a colour-graduated scale from -50 dBfs to +6dBfs. They
+ display the instantaneous value of the signal at the monitoring point
+ selected by the Pre/Post/Input button. 0dBfs corresponds a value equal
+ to the maximum input or output level of your audio hardware,
+ independent of it's bit depth. Exceeding 0dBfs does not correspond to
+ running out of headroom within the mixer, or in any signal path
+ subsequent to that point within the Jack server. It merely means that
+ if that signal is connected directly to a hardware port whose
+ resolution is less than the 32-bit floating point resolution that
+ Ardour uses (i.e. a soundcard), then that port will exceed it's
+ maximum output level, resulting in distortion. hitting 0dB within the
+ mixer (or any point in the Jack server) means that you have
+ approximately 100dB of headroom remaining. as it is unlikely that you
+ will reach this point, it is not represented in any special way by the
+ meter. Naturally, if the input is selected as the monitoring point for
+ the meter, exceeding 0dBfs means that the input of your a/d converter
+ has clipped.
+ </para>
+ </section>
+
+ <section id="mixer-strip-panner">
+ <title>Panner</title>
+ <para>
+ The panner in Ardour is actually two panners. Because any mixer strip
+ in Ardour can route any number of streams of audio anywhere, the idea
+ of panning can be a complex one. To allow for the current
+ stereo-centric mainstream world as well as the multi-speaker
+ experimental one, one of two styles of panner will appear here
+ depending on the number of outputs the channel strip has. In the
+ simple case of mono channel input / stereo output, a single panner
+ will be present. The current pan position is represented by a dot (the
+ dot is the audio stream) which lies between the letters 'L' and 'R',
+ which represent the left and right outputs respectively. To change the
+ panning position of the stream, move the mouse while holding down the
+ left mouse button. the dot will follow your mouse pointer. To
+ introduce sudden changes to the pan setting, place the mouse pointer
+ over the desired position and click the middle mouse button. The pan
+ control will immediately snap to the mouse pointer position. The
+ panner may be bypassed by right-clicking the control and selecting
+ <guimenuitem>bypass</guimenuitem> from the drop-down menu. The panner
+ will immediately be bypassed. The increased level you notice when the
+ panner is bypassed is due to the way panning works. It is not a bug.
+ <emphasis>XXX what gain law is used in the panner?</emphasis>
+ </para>
+
+ <para>
+ In the case of a stereo input / stereo output combination, two panning
+ controls will appear, one corresponding to each audio stream. You can
+ <emphasis>link</emphasis> the controls together in two different ways
+ in this situation, using the direction arrows next to the
+ <guibutton>link</guibutton> button. Panners can be linked to travel
+ either in opposite directions or to maintain a consistent stereo width
+ across the travel of the control. These two modes are represented by
+ the orientation of the two arrows next to the
+ <guibutton>link</guibutton> button, which point in either the same or
+ opposite directions. The <guibutton>link</guibutton> button must be
+ engaged before you can change the <emphasis>link</emphasis> mode. To
+ link all the panners in a mixer strip, left-click the
+ <guibutton>link</guibutton> button, then select the desired link mode
+ by pressing the button marked with arrows.
+ </para>
+
+ <para>
+ Let's get a little more complicated by adding another output to the
+ mixer strip. From this point onwards, the panning positions are
+ represented with numbered dots on a square field. Orange dots
+ represent the outputs, and the numbered dots represent the streams.
+ the position of the outputs change according to the number of outputs
+ in the strip. This happens in order to allow the most useful
+ arrangement of the available space. At some point, adding an output
+ will cause the outputs to line up from the top left of the panning
+ square towards the centre. this is to allow for the 'multi-speaker big
+ sweep' to occur - where the sound is panned from speaker to speaker
+ around the room in sequence.
+ </para>
+
+ <para>
+ Don't forget that you can bypass the panner by right clicking and
+ selecting <guimenuitem>bypass</guimenuitem> from the drop-down menu.
+ this may simplify your multi-speaker setup, as often in this type of
+ project panning between all speakers or outputs is not required on all
+ tracks.
+ </para>
+ </section>
+
+ <section id="mixer-strip-output-selector">
+ <title>Output Selector</title>
+ <para>
+ The output selector allows you to assign the outputs of each mixer
+ strip. left-clicking the output selector causes a ready-made list of
+ output ports to appear in a drop-down menu, along with edit and
+ disconnect options. Selecting <guimenuitem>Edit</guimenuitem> will
+ allow you to change the number of outputs the channel has, as well as
+ select software and hardware ports to route signals to. For more
+ information on the window that appears when you select this option,
+ see the <xref linkend="sn-other-windows"/>.
+ <guimenuitem>Disconnect</guimenuitem> will leave the number of output
+ ports unchanged, but remove all assignments to output ports.
+ </para>
+ </section>
+
+ <section id="mixer-strip-scratch-pad">
+ <title>Scratch Pad</title>
+ <para>
+ This is the text area below the <guibutton>output</guibutton> button.
+ it allows you to enter any notes that you feel may be relevant to that
+ track. The notes are stored when you save the session.
+ </para>
+ </section>
+</section>
diff --git a/manual/xml/mixer_window.xml b/manual/xml/mixer_window.xml
new file mode 100644
index 0000000000..8346773ee8
--- /dev/null
+++ b/manual/xml/mixer_window.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mixer-window">
+ <title>The Mixer</title>
+ <para>
+ The mixer window provides a view of the session that mimics a
+ traditional hardware mixing console. Rather than focusing on the
+ arranging of regions along a timeline, the mixer is designed to allow
+ you to manipulate the signal flow elements of a session - gain control,
+ plugins, bussing and so forth.
+ </para>
+
+ <para>
+ The left area of the mixer contains three small vertical panes which
+ allow various operations to be made on the larger area, which of course
+ represents a mixing console.
+ </para>
+
+ <para>
+ The lines that outline the three smaller panes all have a small square
+ near their vertices. This square can be used to resize the four panes
+ that form the mixer window. Dragging each of these squares with the left
+ mouse button will move the border.
+ </para>
+
+ <section id="mixer-window-layout">
+ <title>Mixer Window Layout</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/mixer.png"/>
+ </imageobject>
+ </mediaobject>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mixer_strips.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mixer_strip_list.xml" />
+ <section id="mixer-window-group-list">
+ <title> Group List </title>
+ <para>
+ The group list pane provides an interface to create and control the
+ state of the mix groups present on the mixer. Mix groups provide a
+ method of linking faders together, so that a movement on one fader
+ will translate to all the other faders in the group.
+ </para>
+
+ <para>
+ A new session will contail one group, called all. This preset group
+ refers to all mixer strips?? <emphasis>what is 'all' doing
+ here?</emphasis> Any new groups you create will be listed in this
+ pane. Left clicking the <guibutton>Mix Groups</guibutton> button
+ will open a window titled <literal>Name for a new mix
+ group</literal>, which contains a dark text area. Enter a name for
+ your new mix group in the text area. Left clicking
+ <guibutton>cancel</guibutton> will close the <literal>Name for a new
+ mix group</literal> window. The group list will be unaffected. Left
+ clicking <guibutton>OK</guibutton> will create a new mix group. The
+ new group will be listed in the group list pane with an empty box
+ next to it's name. All mixer strips will now contain the name of the
+ new group in their <guibutton>group</guibutton> button. Selecting
+ the new group in a mixer strip will assign control of that channel's
+ gain fader to the selected group, but <emphasis>only if the group is
+ active</emphasis>. Left clicking the box next to the group name will
+ activate the group.
+ </para>
+
+ <para>
+ At the bottom right of the group list, a square box provides a
+ method for resizing the pane. Holding down the left mouse button
+ while dragging the square vertically will move the lower border of
+ the group list.
+ </para>
+ </section>
+
+ <section id="mixer-window-snapshot-list">
+ <title> Snapshot List </title>
+ <para>
+ Track Name Group Button Input Selector Solo Button Mute Button
+ Polarity Button Track Speed Control Record Enable Button Automation
+ Record Button Automation Playback Button Pre/Post Button Gain
+ Display Unit Selector Gain Level Display Peak Meter Gain Fader
+ Meters Output Selector
+ </para>
+ </section>
+ </section>
+</section>
diff --git a/manual/xml/mixer_window_key_bindings.xml b/manual/xml/mixer_window_key_bindings.xml
new file mode 100644
index 0000000000..b207203585
--- /dev/null
+++ b/manual/xml/mixer_window_key_bindings.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mixer-window-key-bindings">
+ <title>Mixer window key bindings</title>
+ <table id="tbl-mixer-window-key-bindings">
+ <title>Mixer Window Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>right arrow</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ fast forward/faster
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap><keycap>right
+ arrow</keycap><keycap>space</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ rapid fast forward
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>right arrow</keycap>
+ </keycombo>
+ </entry>
+
+ <entry>
+ slow fast forward
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>left arrow</keycap> </keycombo>
+ </entry>
+
+ <entry>
+ rewind/faster
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap><keycap>left arrow</keycap>
+ </keycombo>
+ </entry>
+
+ <entry>
+ rapid rewind
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>left arrow</keycap>
+ </keycombo>
+ </entry>
+
+ <entry>
+ slow rewind
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mixing.xml b/manual/xml/mixing.xml
new file mode 100644
index 0000000000..6f181cb4e6
--- /dev/null
+++ b/manual/xml/mixing.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-mixing">
+ <title>Mixing</title>
+ <para>
+ Placeholder for an intro to mixing
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="automation.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="plugins.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="vst_plugins.xml" />
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</chapter>
diff --git a/manual/xml/monitoring.xml b/manual/xml/monitoring.xml
new file mode 100644
index 0000000000..8479e16b8a
--- /dev/null
+++ b/manual/xml/monitoring.xml
@@ -0,0 +1,203 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-monitoring">
+ <title>Monitoring</title>
+ <para>
+ If you are recording an acoustic instrument or voice with no
+ pre-existing recorded material as an accompaniment, then you probably
+ don't need to worry about monitoring. Just make sure you've made the
+ right <link linkend="sn-jack">connections</link> and you should be ready
+ to record without reading this section.
+ </para>
+
+ <para>
+ However, if a musician is playing an instrument (it doesn't matter what
+ kind) while listening to some pre-existing material, then it is
+ important that some mechanism exists to allow her to hear both her own
+ playing and the accompaniment. The same is true in a slightly different
+ way if the instrument makes no sound until the electrical signal it
+ creates has been amplified and fed to some loudspeakers. Listening to
+ the performance in this way is called monitoring.
+ </para>
+
+ <para>
+ So, if you are recording an electrical or software instrument/signal,
+ and/or the musician wants to listen to existing material while
+ performing, then you need to ensure that signal routing is setup to
+ allow monitoring. You have 2 basic choices:
+ </para>
+
+ <section id="hardware-monitoring">
+ <title>Hardware Monitoring</title>
+ <para>
+ Hardware monitoring uses the capabilities of your audio interface to
+ route an incoming signal (e.g. someone playing a guitar into a
+ microphone) to an output connection (for example, the speaker outputs,
+ or a dedicated analog monitoring stereo pair). Most audio interfaces
+ can do this, but how you get them to do so, and what else they can do
+ varies greatly. We can divide audio interfaces into 3 general
+ categories:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ relatively simple, typically stereo, devices that allow the signal
+ being recorded to be routed back to the main outputs (most
+ "consumer" audio interfaces fit this description, along with
+ anything that provides an "AC97-compliant CODEC")
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ multichannel devices that allow a given input channel to be routed
+ back to its corresponding output channel (the main example is the
+ RME Digi9652)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ multichannel devices that allow any input channel, along with any
+ playback channel, to be routed to any output channel (the RME HDSP
+ and various interfaces based on the envy24/ice1712 chipsets, such
+ as the M-Audio Delta 1010, EZ-8 and various Terratec cards)
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="monitoring-consumer-audio-interfaces">
+ <title>"Consumer" audio interfaces and monitoring</title>
+ <para>
+ For interfaces in the first category, there is no standard method of
+ getting the signal routing correct. The variations in the wiring of
+ hardware mixing chips, and the capabilities of those chips, means
+ that you will have to get familiar with a hardware mixer control
+ program and the details of your audio interface. In the simple
+ cases, simply increasing the level named "Line In" or "Mic" in the
+ hardware mixer control program will suffice. But this is not a
+ general rule, because there is no general rule.
+ </para>
+
+ <para>
+ The following diagram shows a fairly typical AC97-based audio
+ interface schematic:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/simplemixer.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Notice:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ there are multiple input connections, but only one can be used
+ as the capture source
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ it is (normally) possible to route the input signals back to the
+ outputs, and independently control the gain for this "monitored"
+ signal
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ it may or may not be possible to choose the playback stream as
+ the capture stream
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="monitoring-prosumer-audio-interfaces">
+ <title>High end "prosumer" interfaces and monitoring</title>
+ <para>
+ For the only interface in the second category, the RME Digi9652
+ ("Hammerfall"), the direct monitoring facilities are simplistic but
+ useful in some circumstances. They are best controlled using
+ <emphasis>JACK hardware monitoring</emphasis>.
+ </para>
+
+ <para>
+ When using one of the interfaces in the third category, most people
+ find it useful to use hardware monitoring, but prefer to control it
+ using a dedicated hardware mixer control program. If you have an RME
+ HDSP system, then <command>hdspmixer</command> is the relevant
+ program. For interfaces based on the envy24/ice1712/ice1724
+ chipsets, such as the Delta1010, Terratecs and others,
+ <command>envy24ctl</command> is the right choice. Both programs
+ offer access to very powerful matrix mixers that permit many
+ different variations on signal routing, for both incoming signals
+ and the signals being played back by the computer. You will need to
+ spend some time working with these programs to grasp their potential
+ and their usage in different situations.
+ </para>
+
+ <para>
+ The following diagram gives a partial view of the monitoring
+ schemantics for this class of audio interface. Each input can be
+ routed back to any output, and each such routing has its own gain
+ control. The diagram only shows the routings for "in1" to avoid
+ becoming completely incomprehensible.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/matrixmixer.png"/>
+ </imageobject>
+ </mediaobject>
+ </section>
+ </section>
+
+ <section id="jack-hardware-monitoring">
+ <title>JACK hardware monitoring</title>
+ <para></para>
+ </section>
+
+ <section id="software-monitoring">
+ <title>Software monitoring</title>
+ <para>
+ Much simpler than hardware monitoring is "software monitoring". This
+ means that any incoming signal (say, through a Line In connector) is
+ delivered to software (such as Ardour) which can then deliver it back
+ to any output it chooses, possibly having subjected it to various
+ processing beforehand. The software can also mix signals together
+ before delivering them back to the output. The fact that software
+ monitoring can blend together incoming audio with pre-recorded
+ material while adjusting for latency and other factors is the big plus
+ for this method. The major downside is latency. There will always be a
+ delay between the signal arriving at your audio interface inputs and
+ it re-emerging from the outputs, and if this delay is too long, it can
+ cause problems for the performer who is listening. They will sense a
+ delay between pressing a key/pulling the bow/hitting the drum etc. and
+ hearing the sound it produces.
+ </para>
+
+ <para>
+ However, if your system is capable of low latency audio, its likely
+ that you can use software monitoring effectively if it suits your
+ goals.
+ </para>
+ </section>
+
+ <section id="controlling-monitoring-within-ardour">
+ <title>Controlling monitoring choices within Ardour</title>
+ <para></para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mouse_operations.xml b/manual/xml/mouse_operations.xml
new file mode 100644
index 0000000000..b1e06eacec
--- /dev/null
+++ b/manual/xml/mouse_operations.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-operations">
+ <title>Mouse Operations</title>
+ <para>
+ Note that the definition of the "Delete" and "Edit" clicks can be
+ redefined by the user, either in their Ardour configuration file
+ (<filename>$HOME/.ardour/ardour.rc</filename>) or using the Options
+ Editor (Keyboard+Mouse tab).
+ </para>
+
+ <para>
+ You might wonder why we say Button1 ? Here is an
+<!--
+ <a href="/manual/intro/formatting#Mouse Buttons">explanation</a>.
+ -->
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="generic_mouse_actions.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_wheel_actions.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_object_mode.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_region_gain_mode.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_range_mode.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_zoom_mode.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_ruler.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="mouse_operations_mixer_controls.xml" />
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mouse_operations_mixer_controls.xml b/manual/xml/mouse_operations_mixer_controls.xml
new file mode 100644
index 0000000000..d2e42c44a4
--- /dev/null
+++ b/manual/xml/mouse_operations_mixer_controls.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-operations-mixer-controls">
+ <title>Mixer Controls</title>
+ <table id="tbl-solo-mute-rec-buttons">
+ <title>Solo, Mute and Rec enable buttons</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> click
+ </entry>
+
+ <entry>
+ toggle for the track (or the entire mix group when the group is
+ active)
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button2</mousebutton> click
+ </entry>
+
+ <entry>
+ momentary switch
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ toggle for the entire mix group when the group is not active
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ toggle for all the tracks and busses
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button2</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ learn MIDI control
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table id="tbl-solo-buttons">
+ <title>Solo Buttons Only</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap><mousebutton>Button1</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ toggle "lock" of current solo state ("solo safe")
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>Alt</keycap><mousebutton>Button1</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ solo only this track or active group, unsolo all others
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table id="tbl-faders">
+ <title>Faders</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ Button1 drag
+ </entry>
+
+ <entry>
+ operate fader
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>
+ drag
+ </entry>
+
+ <entry>
+ finer control
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>
+ drag
+ </entry>
+
+ <entry>
+ finest control
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap><mousebutton>Button1</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ reset fader
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button2</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ learn MIDI control
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mouse_operations_object_mode.xml b/manual/xml/mouse_operations_object_mode.xml
new file mode 100644
index 0000000000..59b96f8cb3
--- /dev/null
+++ b/manual/xml/mouse_operations_object_mode.xml
@@ -0,0 +1,334 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-operations-object-mode">
+ <title>Object Mode</title>
+ <section id="sn-object-mode-region-operations">
+ <title>Region Operations</title>
+ <para>
+ A region has several areas in its on-screen representation:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ the waveform (the majority of the region's display area, normally)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ the trim bar (the colored bar below the waveform)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ the name (in the trim bar, text)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ the fade handles (small squares that default to the upper left +
+ right corners)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ the fade shape (filled or empty curves representing fade in + fade
+ out)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ the gain envelope (hidden by default)
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Mouse operations on each area will do different things.
+ </para>
+
+ <table id="tbl-object-mode-region-operations">
+ <title>Region Operations</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ Button1 click on waveform
+ </entry>
+
+ <entry>
+ select region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap>
+ <mousebutton>Button1</mousebutton> </keycombo> click
+ </entry>
+
+ <entry>
+ add region to selection, or deselect it if selected
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag on "empty space"
+ </entry>
+
+ <entry>
+ rubber-band selection of regions
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>Alt</keycap>
+ <mousebutton>Button1</mousebutton> </keycombo> drag on region
+ </entry>
+
+ <entry>
+ rubber-band selection of regions
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> click in trim bar
+ </entry>
+
+ <entry>
+ set start of region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button2</mousebutton> click in trim bar
+ </entry>
+
+ <entry>
+ set end of region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag near ends of trim bar
+ </entry>
+
+ <entry>
+ adjust start/end of region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap>
+ <mousebutton>Button1</mousebutton> </keycombo> drag in trim
+ bar
+ </entry>
+
+ <entry>
+ move audio inside region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag
+ </entry>
+
+ <entry>
+ move region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap>
+ <mousebutton>Button1</mousebutton> </keycombo> drag
+ </entry>
+
+ <entry>
+ copy region and move copy
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button2</mousebutton> drag
+ </entry>
+
+ <entry>
+ fixed time move (for transfer to other tracks)
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap>
+ <mousebutton>Button2</mousebutton> </keycombo> drag
+ </entry>
+
+ <entry>
+ fixed time copy+move
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap>
+ <mousebutton>Button2</mousebutton> </keycombo> click
+ </entry>
+
+ <entry>
+ raise region
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><keycap>Shift</keycap>
+ <mousebutton>Button2</mousebutton> </keycombo> click
+ </entry>
+
+ <entry>
+ lower region
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+
+ <section id="object-mode-automation-operations">
+ <title>Automation Operations</title>
+ <para>
+ In general Button2-drag will do a constrained drag: control points
+ will stay at the same position in time if dragged up and down and they
+ will stay at the same value if dragged sideways.
+ </para>
+
+ <table id="tbl-object-mode-automation-operations">
+ <title>Region Operations</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> click in automation track
+ </entry>
+
+ <entry>
+ add a new control point to the line
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag in an automation track
+ </entry>
+
+ <entry>
+ rubber-band select control points
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag on control point
+ </entry>
+
+ <entry>
+ move control point
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag on line
+ </entry>
+
+ <entry>
+ move line segment vertically
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button2</mousebutton> drag on control-point
+ </entry>
+
+ <entry>
+ constrained adjustment
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>
+ drag on control point
+ </entry>
+
+ <entry>
+ move control point+all later points move with the same time
+ displacement
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button2</mousebutton></keycombo>
+ drag on control point
+ </entry>
+
+ <entry>
+ constrained move control point + move all later points with
+ the same time displacement
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mouse_operations_range_mode.xml b/manual/xml/mouse_operations_range_mode.xml
new file mode 100644
index 0000000000..3ed66cb93d
--- /dev/null
+++ b/manual/xml/mouse_operations_range_mode.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-operations-range-mode">
+ <title>Range Mode</title>
+ <table id="tbl-range-mode">
+ <title>Range Operations</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag outside of a range
+ </entry>
+
+ <entry>
+ define a range
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag on range handles
+ </entry>
+
+ <entry>
+ change start/end of a range
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap>
+ <mousebutton>Button1</mousebutton> </keycombo> drag
+ </entry>
+
+ <entry>
+ define an additional range
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button2</mousebutton> click on another track
+ </entry>
+
+ <entry>
+ move range to another track
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap><mousebutton>Button1</mousebutton></keycombo>
+ click on another track
+ </entry>
+
+ <entry>
+ extend range to another track
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>
+ drag
+ </entry>
+
+ <entry>
+ move continuous part of range
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap><mousebutton>Button1</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ seperate range into a new region
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mouse_operations_region_gain_mode.xml b/manual/xml/mouse_operations_region_gain_mode.xml
new file mode 100644
index 0000000000..7883bb4ce0
--- /dev/null
+++ b/manual/xml/mouse_operations_region_gain_mode.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-operations-region-gain-mode">
+ <title>Region Gain Mode</title>
+ <table id="tbl-region-gain-mode">
+ <title>Region Gain Envelope Operations</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> click
+ </entry>
+
+ <entry>
+ add a new control point to the gain envelope
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag on control point
+ </entry>
+
+ <entry>
+ move control point
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag on line
+ </entry>
+
+ <entry>
+ move line segment
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>
+ drag on control point
+ </entry>
+
+ <entry>
+ move control point+all later points
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mouse_operations_ruler.xml b/manual/xml/mouse_operations_ruler.xml
new file mode 100644
index 0000000000..09b05850b1
--- /dev/null
+++ b/manual/xml/mouse_operations_ruler.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-operations-ruler">
+ <title>Ruler Operations</title>
+ <table id="tbl-marks-locations">
+ <title>Marks, Locations</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> click in marker, tempo, meter
+ ruler
+ </entry>
+
+ <entry>
+ create a new marker
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag on a marker
+ </entry>
+
+ <entry>
+ move marker
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>
+ drag on loop or punch mark
+ </entry>
+
+ <entry>
+ move both ends of range at once
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><mousebutton>Button1</mousebutton></keycombo>
+ click in marker
+ </entry>
+
+ <entry>
+ hide marker but do not remove it
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table id="tbl-punch-loop-ranges">
+ <title>Punch/Loop Ranges</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag
+ </entry>
+
+ <entry>
+ define a new punch or loop range
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ other operations as for marks and locations above
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mouse_operations_zoom_mode.xml b/manual/xml/mouse_operations_zoom_mode.xml
new file mode 100644
index 0000000000..765c049432
--- /dev/null
+++ b/manual/xml/mouse_operations_zoom_mode.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-operations-zoom-mode">
+ <title>Zoom Mode</title>
+ <table id="tbl-zoom-mode">
+ <title>Zoom Operations</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> drag
+ </entry>
+
+ <entry>
+ define the new visible area
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button1</mousebutton> click
+ </entry>
+
+ <entry>
+ zoom in
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <mousebutton>Button2</mousebutton> click
+ </entry>
+
+ <entry>
+ zoom out
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button2</mousebutton></keycombo>
+ click
+ </entry>
+
+ <entry>
+ zoom to session
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/mouse_wheel_actions.xml b/manual/xml/mouse_wheel_actions.xml
new file mode 100644
index 0000000000..c750031af6
--- /dev/null
+++ b/manual/xml/mouse_wheel_actions.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-mouse-wheel-actions">
+ <title>Mouse Wheel Actions</title>
+ <table id="tbl-mouse-wheel-actions">
+ <title>Mouse Wheel Actions</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Mouse Action" colwidth="1"/>
+ <colspec colnum="2" colname="Result" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Mouse Action
+ </entry>
+
+ <entry>
+ Result
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ Mouse Wheel
+ </entry>
+
+ <entry>
+ scroll editor window up/down (except in Zoom mode)
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Alt</keycap> <mousebutton>Mouse
+ Wheel</mousebutton> </keycombo>
+ </entry>
+
+ <entry>
+ scroll editor window left/right
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap> <mousebutton>Mouse
+ Wheel</mousebutton> </keycombo>
+ </entry>
+
+ <entry>
+ zoom in/out
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap> <mousebutton>Mouse
+ Wheel</mousebutton> </keycombo>
+ </entry>
+
+ <entry>
+ step track height
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <note>
+ <para>
+ The mouse wheel also moves the faders and other controls. In Zoom mode
+ the mouse wheel zooms instead of scrolling the window.
+ </para>
+ </note>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/opening_a_session.xml b/manual/xml/opening_a_session.xml
new file mode 100644
index 0000000000..b717c31bc7
--- /dev/null
+++ b/manual/xml/opening_a_session.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-opening-a-session">
+ <title>Opening a Session</title>
+ <para>
+ You can open a session by either
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Choose <menuchoice> <guimenu>Session</guimenu>
+ <guisubmenu>Open</guisubmenu> </menuchoice> or press
+ <keycombo><keycap>Ctrl</keycap><keycap>O</keycap></keycombo> and
+ then use the file selector to locate the session you want to open.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ start ardour from a command line, and specify the session folder as
+ an argument.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ When specifying a session to open you can either specify the session
+ folder or the session file. If you specify the folder, Ardour will open
+ the primary session file within the folder. If you specify a session
+ file (see <xref linkend="sn-snapshots"/>), Ardour will open that
+ particular session.
+ </para>
+
+ <section id="recent-sessions">
+ <title>Recent Sessions</title>
+ <para>
+ The <menuchoice> <guimenu>Session</guimenu>
+ <guisubmenu>Recent</guisubmenu> </menuchoice> menu item will allow you
+ to navigate directly to sessions that you have worked on recently. For
+ sessions with more than one recent session file, expand the session
+ subtree by clicking on the expansion box left of the session name.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/other_windows.xml b/manual/xml/other_windows.xml
new file mode 100644
index 0000000000..d3c2069937
--- /dev/null
+++ b/manual/xml/other_windows.xml
@@ -0,0 +1,246 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-other-windows">
+ <title>Other Windows</title>
+ <para>
+ This page summarises various windows you will find in your travels
+ through Ardour that aren't available from the
+ <guimenuitem>windows</guimenuitem> menu in the editor. They aren't
+ available because they are specific to a particular object, like a mixer
+ strip, and are launched from the object itself.
+ </para>
+
+ <section id="input-output-connections-editor">
+ <title>Input/Output Connections Editor</title>
+ <para>
+ Selecting <guimenuitem>edit</guimenuitem> from the input drop-down
+ menu on a mixer strip will open this window, as will selecting
+ <guimenuitem>edit</guimenuitem> from the output button. The
+ Input/Output connections editor is one of the strangest interfaces
+ known to man. After a small amount of use, however, you will find it
+ quite natural to use. Because these two windows are identical except
+ for 'input' being transposed with 'output', we will cover the Input
+ Connections Editor here and leave it up to your imaginative self to
+ work out what it all means in the output window.
+ </para>
+
+ <para>
+ When the window opens, you will be see that it is divided into two
+ main areas marked <guilabel>Inputs</guilabel> and <guilabel>Available
+ Connections</guilabel> . A third area contains buttons marked
+ <guibutton>rescan</guibutton>, <guibutton>OK</guibutton> and
+ <guibutton>Cancel</guibutton>.
+ </para>
+
+ <para>
+ The <guilabel>Inputs</guilabel> area has two buttons marked
+ <guibutton>add input</guibutton> and <guibutton>clear
+ connections</guibutton>. The <guibutton>add input</guibutton> button
+ adds an audio stream to the mixer strip.
+ </para>
+
+ <para>
+ In other words, if you currently have a two input channel, pressing
+ <guibutton>add input</guibutton> will make it a three input channel.
+ If you subsequently record on the corresponding track, each region
+ will comprise of three channels of audio taken from the inputs you
+ have set in the area below.
+ </para>
+
+ <para>
+ Pressing <guibutton>clear connections</guibutton> will remove all
+ connections you have assigned in the area below.
+ </para>
+
+ <para>
+ Speaking of "the area below", if you've used a template to create your
+ new session with, the input fields will aready be filled in with
+ default values that are determined by the number of channels your
+ hardware supports. It should be noted that by default, inputs are
+ initially set to hardware ports, as presumably you will be recording
+ from a hardware device initially. This doesn't indicate a preference
+ on Ardour's part, as software inputs are just as valid to Ardour as
+ hardware ones.
+ </para>
+
+ <para>
+ Anyway, in "the area below", notice that one input (probably labelled
+ <literal>in 1</literal>) is a lighter colour than the other. If you
+ only have one input at the moment, press <guibutton>add
+ input</guibutton> just to see the difference. You can remove an input
+ by holding the control key while right-clicking on the input name.
+ </para>
+
+ <para>
+ The lighter coloured input is the one that will be added to when an
+ output in the <guilabel>Available connections</guilabel> area is
+ clicked. If the wrong input is highlighted, you can highlight the
+ correct one by left-clicking the text of the input name you desire.
+ </para>
+
+ <para>
+ Note that you can "mux" as many inputs together as you like when doing
+ this, they just pile up on top of the last one. Be warned, though,
+ that they are all summed at unity gain. You can reach some fairly
+ astonishing levels by doing this a lot.
+ </para>
+
+ <para>
+ If you click an output from the <guilabel>Available
+ connections</guilabel> area, the connection is added to that input's
+ list, the connection is made active, and the next input is made a
+ lighter colour, indicating that it is ready to accept your selection.
+ This makes it a simple matter to assign many connections rapidly. The
+ transport does not have to be stopped to change inputs or outputs (or
+ anything, really) in Ardour.
+ </para>
+
+ <para>
+ Removing assignments is achieved by left-clicking the relevant output
+ in the <guilabel>inputs</guilabel> area. As with most objects in
+ Ardour, you can also remove an assignment by holding the shift key
+ while right-clicking it.
+ </para>
+
+ <para>
+ The Available connections area lists all available connections, sorted
+ into tabs which represent their associated hardware or software ports.
+ The front tab is always <literal>alsa_pcm</literal>. this represents
+ the physical ports on your computer. It should contain as many ports
+ as hour hardware has inputs.
+ </para>
+
+ <para>
+ The next tab is Ardour. This tab lists all the connections that Ardour
+ has available, including inserts and sends. If you have some other
+ Jack aware programs running, they will be given tabs in this area
+ which will correspond to their Jack output ports.
+ </para>
+
+ <para>
+ The <guibutton>rescan</guibutton> button searches for any new
+ available outputs. It may be necessary to use it if you have started a
+ Jack application after you open the window.
+ </para>
+
+ <para>
+ The <guibutton>Cancel</guibutton> button closes the window
+ <emphasis>XXX what really happens?</emphasis> , as does the
+ <guibutton>OK</guibutton> button.
+ </para>
+ </section>
+
+ <section id="ladspa-plugin-window">
+ <title>The LADSPA Plugin Window</title>
+ <para>
+ This window opens when you double-left-click or control right-click a
+ plugin on a mixer strip. It allows you to adjust, store and automate
+ the controls presented by any LADSPA plugin. Because LADSPA plugins do
+ not contain graphical interface information, this window adapts itself
+ to suit the various controls presented by the plugin. The advantage of
+ this system is that each plugin appears consistently within Ardour.
+ The disadvantage is that with a few plugins, the controls seem to be
+ laid out in a haphazard fashion. This is not usually the case,
+ however.
+ </para>
+
+ <para>
+ Each plugin window will have a <guibutton>bypass</guibutton> switch in
+ the top left. Whenever you add a plugin, it's initial state will be
+ bypass. The button will be red and appear depressed. To activate the
+ plugin, press the <guibutton>bypass</guibutton> button. you should
+ immediately hear the plugin inserted in the signal path. All plugins
+ that report their latency are automatically time compensated
+ sample-accurately.
+ </para>
+
+ <para>
+ To the left of the bypass switch you will see the name of the plugin,
+ the author and the number of inputs and outputs that the plugin makes
+ use of. To the right will be a text entry area, a list selector and a
+ <guibutton>Save</guibutton> button. To save a combination of settings,
+ press the <guibutton>Save</guibutton> button. A window will appear
+ asking for the name of the preset. Enter a name, press
+ <guibutton>OK</guibutton>, and your new preset will appear on the list
+ of saved settings.
+ </para>
+
+ <para>
+ To restore a saved preset, select it from the list. The settings
+ should immediately be restored as you release the mouse button.
+ </para>
+
+ <para>
+ The rest of the window consists of sliders and buttons which represent
+ the various controls available for the plugin. To move a slider, left
+ click it and slide the mouse horizontally over the range of the
+ control. You can see the numeric value and the bar change as you move
+ the mouse. You can also press the control key while moving for finer
+ adjustments.
+ </para>
+
+ <para>
+ Next to each control is an automation mode button. The default state
+ is <guimenuitem>off</guimenuitem>. To write automation information,
+ press the button and select <guimenuitem>write</guimenuitem> from the
+ drop-down list. After engaging the transport, movement of the control
+ will be recorded for playback when the <guimenuitem>play</guimenuitem>
+ automation mode is selected. <guimenuitem>Touch</guimenuitem> mode
+ automatically switches from <guimenuitem>play</guimenuitem> to
+ <guimenuitem>write</guimenuitem> as the control is first selected with
+ the mouse button and released, respectively. The automation data is
+ accessible from the editor window, along with the other automation
+ data for the track.
+ </para>
+ </section>
+
+ <section id="export-window">
+ <title>The Export Window</title>
+ <para>
+ The export window appears when either <guimenuitem>export session to
+ audiofile</guimenuitem> or <guimenuitem>export range to
+ audiofile</guimenuitem> have been selected from the session menu. This
+ window enables an audio file to be rendered from either the master bus
+ or individual tracks in freewheel mode. A large range of audio file
+ formats are supported, as is the ability to export a CUE or TOC file
+ representing any CD index or track markers you may have in the
+ session. Bit depth reduction can be performed with three types of
+ dither, or no dither.
+ </para>
+ </section>
+
+ <section id="crossfade-editor-window">
+ <title>The Crossfade Editor Window</title>
+ <para>
+ The crossfade editor will appear whenever you select <menuchoice>
+ <guimenu>crossfade</guimenu> <guisubmenu>edit</guisubmenu>
+ </menuchoice> from any active or inactive crossfade in the editor
+ window. This window allows you to customise the default crossfade that
+ is automatically applied when two regions overlap. Provision is made
+ for auditioning different elements of the crossfade, or the crossfade
+ as a whole.
+ </para>
+ </section>
+
+ <section id="locations-window">
+ <title>the Locations Window</title>
+ <para>
+ The locations window provides a means to locate to and define points
+ and ranges in your session. Points and ranges may also be 'promoted'
+ to be CD Index or CD Track markers, respectively. Once promoted, they
+ may be exported to a standard T.O.C. or CUE file along with the
+ exported audio using the export window. The locations window will
+ appear when <menuchoice> <guimenu>windows</guimenu>
+ <guisubmenu>locations</guisubmenu> </menuchoice> is selected from the
+ editor window.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/plugins.xml b/manual/xml/plugins.xml
new file mode 100644
index 0000000000..033217e41b
--- /dev/null
+++ b/manual/xml/plugins.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-plugins">
+ <title>Using Plugins</title>
+ <para>
+ Using Plugins in ardour is easy and fun!
+ </para>
+
+ <para>
+ Fortunately for us, there's
+ <ulink url="http://ladspa.org">LADSPA!!</ulink> Ladspa stands for
+ <emphasis>L</emphasis>inux <emphasis>A</emphasis>udio
+ <emphasis>D</emphasis>evelopers <emphasis>S</emphasis>imple
+ <emphasis>P</emphasis>lugin <emphasis>A</emphasis> PI, and there is a
+ great suite of Free plugins maintained by Steve Harris at
+ <ulink url="http://plugin.org.uk">plugin.org.uk</ulink>.
+ </para>
+
+ <para>
+ Once you have the plugins installed, restart Ardour (don't forget to
+ save!) and open up the mixer window. See the black rectangle about 3/4
+ of the way down the mixer strip? That's the sends list. Think of a mixer
+ strip as a signal path. Follow the signal as it flows from the top down
+ through inputs, varispeed settings, volume controls, plugins and sends,
+ pan control and then output. Right-click on the empty sends list and
+ select <guimenuitem>New Plugin</guimenuitem> from the popup menu.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/pluginmenu.jpg"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ You'll be presented with a list of available LADSPA plugins. experiment
+ and choose the one that's right for you. I really like the VyNil effect.
+ It creates an old worn out vynil record sound.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/ladspa.jpg"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ In the screenshot below, you will find a bouquet of various LADSPA
+ plugins. aaahhh... le mot juste...
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/plugins.jpg"/>
+ </imageobject>
+ </mediaobject>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/preface.xml b/manual/xml/preface.xml
new file mode 100644
index 0000000000..ce364faeeb
--- /dev/null
+++ b/manual/xml/preface.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<preface id="sn-preface"><title>Preface</title>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="formatting_conventions.xml" />
+ -->
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</preface>
diff --git a/manual/xml/recording.xml b/manual/xml/recording.xml
new file mode 100644
index 0000000000..6b3feb6112
--- /dev/null
+++ b/manual/xml/recording.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-recording">
+ <title>Recording</title>
+ <para>
+ This section covers the main points of recording audio into an Ardour
+ session.
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="basic_recording.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="monitoring.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="setting_up_to_record.xml" />
+</chapter>
diff --git a/manual/xml/renaming_tracks.xml b/manual/xml/renaming_tracks.xml
new file mode 100644
index 0000000000..22aa34e72b
--- /dev/null
+++ b/manual/xml/renaming_tracks.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="renaming-tracks">
+ <title>Renaming Tracks</title>
+ <para>
+ Tracks can be renamed from within the
+ <link linkend="sn-editor-window">Editor Window</link> or the
+ <link linkend="sn-mixer-window">Mixer Window</link>.
+ </para>
+
+ <para>
+ To change the name of a track in the Editor Window click within the
+ track name field in the <link linkend="track-controls">Track
+ Controls</link>, enter the new track name and press the
+ <keycap>Enter</keycap> key to confirm the change.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/track_name_field.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ If you decide not to rename a track after already changing the content
+ of the track name field but before confirming the change pressing the
+ <keycap>ESC</keycap> key will restore the original track name.
+ </para>
+ <tip>
+ <para>
+ Several tracks can be renamed quickly in sequence by using the
+ <keycap>Tab</keycap> key to move the focus between the track name
+ fields.
+ </para>
+ </tip>
+ <para>
+ To change the name of a track in Mixer Window click on the track name
+ button and choose <guimenuitem>Rename</guimenuitem> from the pop-up
+ menu.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/mixer_strip_name_button_popup.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ A dialog will then appear allowing you to rename the track, input the
+ new name and press <keycap>Enter</keycap> or click
+ <guimenuitem>Rename</guimenuitem> to confirm the name change.
+ </para>
+
+ <warning>
+ <para>
+ Changes to track names cannot be undone.
+ </para>
+ </warning>
+</section>
diff --git a/manual/xml/saving_a_session.xml b/manual/xml/saving_a_session.xml
new file mode 100644
index 0000000000..b430a90256
--- /dev/null
+++ b/manual/xml/saving_a_session.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-saving-a-session">
+ <title>Saving a Session</title>
+ <para>
+ Ardour will save your session every time you add a new track/bus, and
+ after every capture. Saving regularly at other times will help ensure
+ that your work is preserved on your disk drive.
+ </para>
+
+ <section id="save-the-session-file">
+ <title>Save the Session File</title>
+ <para>
+ Choose <menuchoice> <guimenu>Session</guimenu>
+ <guisubmenu>Save</guisubmenu> </menuchoice> to save the changes that
+ have been made to the session.
+ </para>
+
+ <warning>
+ <para>
+ Saving a session writes a new session in place of the old one, and
+ it cannot be undone.
+ </para>
+ </warning>
+ </section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="snapshots.xml" />
+</section>
diff --git a/manual/xml/sessions.xml b/manual/xml/sessions.xml
new file mode 100644
index 0000000000..a9e31f5790
--- /dev/null
+++ b/manual/xml/sessions.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-sessions">
+ <title>Sessions</title>
+ <para>
+ This chapter covers the basics of starting a new project with Ardour,
+ including how to set up a session.
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="starting_up_your_system.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="creating_a_new_session.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="adding_tracks.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="opening_a_session.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="saving_a_session.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="templates.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="closing_a_session.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="cleaning_up_a_session.xml" />
+</section>
diff --git a/manual/xml/setting_up_to_record.xml b/manual/xml/setting_up_to_record.xml
new file mode 100644
index 0000000000..88b94bd816
--- /dev/null
+++ b/manual/xml/setting_up_to_record.xml
@@ -0,0 +1,235 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-setting-up-to-record">
+ <title>Setting Up To Record</title>
+ <para>
+ This page needs massive work
+ </para>
+
+ <para>
+ It is very important that you check your system is connected and
+ configured correctly before attempting to record. See Hardware
+ Installation for more information on this topic.
+ </para>
+
+ <section id="setup-connections">
+ <title>Connections</title>
+ <para></para>
+ </section>
+
+ <section id="setup-levels">
+ <title>Levels</title>
+ <para></para>
+ </section>
+
+ <section id="setup-clipping">
+ <title>Clipping</title>
+ <para></para>
+ </section>
+
+ <section id="record-enabling-tracks">
+ <title>Record Enabling Tracks</title>
+ <para></para>
+ </section>
+
+ <section id="setup-monitoring">
+ <title>Monitoring</title>
+ <para></para>
+ </section>
+
+ <section id="setup-hardware-monitoring">
+ <title>Hardware Monitoring</title>
+ <para></para>
+ </section>
+
+ <section id="setup-software-monitoring">
+ <title>Software Monitoring</title>
+ <para></para>
+ </section>
+
+ <section id="setup-latency">
+ <title>Latency</title>
+ <para></para>
+ </section>
+
+ <section id="setup-external-monitoring">
+ <title>External Monitoring</title>
+ <para></para>
+ </section>
+
+ <section id="setup-auto-input">
+ <title>Auto-Input</title>
+ <para></para>
+ </section>
+
+ <section id="setup-track-naming">
+ <title>Track Naming</title>
+ <para></para>
+ </section>
+
+ <section id="setup-default-names">
+ <title>Default names</title>
+ <para></para>
+ </section>
+
+ <section id="disk-allocation">
+ <title> Disk Allocation </title>
+ <para>
+ It is of course possible to use Ardour on a single-disk system, but
+ you are more likely to have performance problems this way.
+ </para>
+
+ <para>
+ If you have more than one disk available, we highly recommend using
+ one "system" disk and one or more "audio" disks.
+ </para>
+
+ <section id="using-the-system-disk">
+ <title>Using the system disk </title>
+ <para>
+ The "system" disk is the main disk on which your operating system
+ and (usually) all your installed software reside.
+ </para>
+
+ <para>
+ If you have any other disks available, it is usually
+ <emphasis>not</emphasis> advisable to put your Ardour session and
+ all its soundfiles on the main system disk. The reason is that this
+ disk may be used at any time by the OS or other programs and, if
+ Ardour is trying to play a large amount of disk data at that moment,
+ in the worst case this can cause Ardour's playback to stop
+ completely. (insert screenshot of error dialog here)
+ </para>
+
+ <para>
+ Even so, if you have only two disks (the system disk and your audio
+ disk), it is possible that a large session will reach the
+ performance limits of a single dedicated audio disk. In this case,
+ it may be better to put some audio data on the system disk as
+ described in the Soft RAID section below.
+ </para>
+ </section>
+
+ <section id="using-multiple-disks">
+ <title> Using Multiple Disks </title>
+ <section id="hardware-raid">
+ <title>Hardware RAID</title>
+ <para>
+ You can of course use a normal RAID disk array to spread data
+ across multiple disks. This is beyond the scope of this manual.
+ </para>
+ </section>
+
+ <section id="soft-raid-path">
+ <title>Ardour's "Soft" RAID Path</title>
+ <para>
+ It is possible to spread the resources for your Ardour session
+ across multiple disks. This can increase the number of tracks or
+ regions you can work with at once.
+ </para>
+
+ <para>
+ There is no reason to do this if your computer has only one disk.
+ </para>
+
+ <para>
+ To use the "soft RAID" feature, manually create a new directory on
+ another disk. Open the Options Editor window. Click on the
+ Paths/Files tab. In the "session RAID path" text box, you will see
+ that the default value is the path to the directory where your
+ current session lives. But this Session RAID Path can actually be
+ a colon-separated list of directories. To add your new directory
+ to this list, type a single colon after the existing Session RAID
+ Path, followed by the full path to the new directory. Ardour will
+ now record new tracks to either directory. (question: how does
+ ardour decide which files go where?)
+ </para>
+
+ <para>
+ You can squeeze some more disk performance out of an existing
+ session by following the above procedure, then manually moving
+ some files from the
+ <code>sounds/</code>
+ subdirectory of the existing session into a
+ <code>sounds/</code>
+ subdirectory of your new directory. Be very careful when doing
+ this! If you accidentally delete these sound files, Ardour cannot
+ magically fix it for you.
+ </para>
+
+ <note>
+ <para>
+ If you use the "soft" RAID feature described above, take care to
+ remember this when making and restoring session backups! You
+ will not be happy if you forget to back up one of your data
+ directories; and restoring a backup won't work if you don't make
+ sure that the "Session RAID Path" setting corresponds to the
+ directories where you actually put the restored files.
+ </para>
+ </note>
+ </section>
+ </section>
+ </section>
+
+ <section id="recording-modes">
+ <title> Recording modes </title>
+ <section id="destructive-recording">
+ <title> destructive recording </title>
+ <para>
+ When creating tracks, there are 2 different options: Normal tracks
+ and Tape tracks. Tape tracks implement a "destructive" style of
+ recording that is useful when you will be making multiple recordings
+ to the same track, and you don't want to keep a separate "region" on
+ disk for each take. There is no undo function (yet) and there is no
+ way to edit a tape track (yet). So what is this good for? Well,
+ consider the case where you are doing a final mixdown of a project.
+ You could record-enable two Tape tracks, and send the master bus
+ output to these tracks. Every time you play through a section of the
+ project, the resulting mix will be recorded onto the continuous tape
+ track. Once you reach the end of the project, you can send the
+ resultant wav file directly to the next production step. There is no
+ "rendering" step required. The utility of this increases when you
+ are using an outboard, automated mixer. This type of recording is
+ very common on a film dubbing stage.
+ </para>
+ </section>
+ </section>
+
+ <section id="setup-loop-recording">
+ <title>loop recording</title>
+ <para></para>
+ </section>
+
+ <section id="setup-punch-recording">
+ <title>Punch Recording</title>
+ <para></para>
+ </section>
+
+ <section id="recording-with-a-click-track">
+ <title>Recording with a Click track</title>
+ <para></para>
+ </section>
+
+ <section id="the-click-track">
+ <title>The Click Track</title>
+ <para>
+ Enabling the click Routing the click Specifying click sounds Default
+ Meter Default Tempo
+ </para>
+ </section>
+
+ <section id="tempo">
+ <title>Tempo</title>
+ <para>
+ manual tempo tap tempo
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/snapshots.xml b/manual/xml/snapshots.xml
new file mode 100644
index 0000000000..dcb3d38b61
--- /dev/null
+++ b/manual/xml/snapshots.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-snapshots">
+ <title>Snapshots</title>
+ <para>
+ Choose <menuchoice> <guimenu>Session</guimenu>
+ <guisubmenu>Snapshot</guisubmenu> </menuchoice> to store the current
+ state of the session without overwriting the primary session file. The
+ snapshot dialog will appear, and you can (optionally) enter a name for
+ the snapshot. The default name is based on the current time.
+ </para>
+
+ <para>
+ IMAGE
+ </para>
+<!--
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/snapshot_dialog.png"/>
+ </imageobject>
+ </mediaobject>
+ -->
+ <para>
+ A snapshot is nothing more than a new session file. It still references
+ the same audio and automation data as the primary session file.
+ </para>
+
+ <note>
+ <para>
+ Saving a snapshot does not change the status of the current session.
+ It does not change what will happen when you choose <menuchoice>
+ <guimenu>Session</guimenu> <guisubmenu>Save</guisubmenu> </menuchoice>
+ at a later time. Note that a snapshot is not a new session.
+ </para>
+ </note>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/starting_up_your_system.xml b/manual/xml/starting_up_your_system.xml
new file mode 100644
index 0000000000..684edb20b8
--- /dev/null
+++ b/manual/xml/starting_up_your_system.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-starting-up-your-system">
+ <title>Starting up your system</title>
+ <para>
+ In order for Ardour to be able to do anything at all, you need JACK to
+ be running. See <xref linkend="sn-configuring-jack"/> for more details
+ on how to start and configure JACK.
+ </para>
+</section>
diff --git a/manual/xml/synchronization.xml b/manual/xml/synchronization.xml
new file mode 100644
index 0000000000..5c626feba8
--- /dev/null
+++ b/manual/xml/synchronization.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-synchronization">
+ <title>Synchronization</title>
+ <para>
+ This section covers techniques and strategies for running Ardour in sync
+ with other hardware and software.
+ </para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="synchronization_concepts.xml" />
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="video_synchronization_via_mtc.xml" />
+</chapter>
diff --git a/manual/xml/synchronization_concepts.xml b/manual/xml/synchronization_concepts.xml
new file mode 100644
index 0000000000..0947baf340
--- /dev/null
+++ b/manual/xml/synchronization_concepts.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-synchronization_concepts">
+ <title>Synchronization Concepts</title>
+ <para>
+ As soon as you start handling audio on more than one device, it is
+ important to understand and to think about
+ <emphasis>synchronization</emphasis> : how to get the devices to have
+ the same sense of time and speed.
+ </para>
+
+ <para>
+ However, there are two fundamentally different kinds of synchronization:
+ </para>
+
+ <section id="sample-clock">
+ <title>Sample Clock</title>
+ <para>
+ As outlined in the <emphasis>introductory concepts</emphasis> section,
+ digital audio is created by taking a "sample" of an analog signal
+ level on a periodic basis, say 48000 times per seconds (the "sample
+ rate"). A dedicated clock (the "sample clock") ((actually, an
+ oscillating crystal, but technology people call such things clocks))
+ "ticks" at that rate, and every time it does, a new sample is
+ measured. The way the clock is used to convert digital audio back to
+ an analog signal (i.e. to be sent to some loudspeakers) is more
+ complex, but the clock is still an absolutely fundamental part of the
+ mechanism.
+ </para>
+
+ <para>
+ Whenever you connect two digital audio devices together in order to
+ move audio data from one to the other, you <emphasis>must ensure they
+ share the same sample clock</emphasis> . Why is this necessary? The
+ oscillating crystals used for the sample clock are generally very
+ stable (they always tick at the same speed), but there are always
+ minute differences in the speed that any two clocks tick at. When used
+ by themselves, this makes no difference, but connect two digital audio
+ devices together and these minute differences will eventually
+ accumulate over time. Eventually, one of the devices will be trying to
+ read a sample "in the middle" of the other device's tick, and the
+ result is a small click or pop in the audio stream.
+ </para>
+ </section>
+
+ <section id="timeline-sync">
+ <title>Timeline Sync</title>
+ <para>
+ The concept of a timeline comes up over and over again when working
+ with a digital audio workstation, and also with video editing systems.
+ By "timeline" we mean nothing more than some way to define a "name"
+ for the point where certain sounds (and/or visual images) occur. When
+ you work in Ardour's editor window, the rulers near the top provide
+ one or more timelines in different units. You can look at the editor
+ window and say "this sound starts at 1 minute 32 seconds" or "this
+ tracks fades out starting at bar 13 beat 22".
+ </para>
+
+ <para>
+ But what happens when you want to share a timeline between two
+ different devices? For example, you may want to run a hardware video
+ editor in conjunction with ardour, and always have the visual and
+ audio playback be at the same point "in time". How do they each know
+ what "in time" means? How do they know where the other one is? A
+ mechanism for answering these questions provides <emphasis>timeline
+ synchronization</emphasis> .
+ </para>
+
+ <para>
+ Timeline synchronization is entirely different from sample clock
+ synchronization. Two devices can share a sample clock, but never use
+ timeline information. Two devices can be sharing timeline information,
+ but run on different sample clocks - they might not even have sample
+ clocks if they are analog devices.
+ </para>
+ </section>
+
+ <section id="word-clock">
+ <title>Word Clock</title>
+ <para>
+ "Word Clock" is the name given to a signal used to distribute the
+ "ticks" of a sample clock to multiple devices. Most digital audio
+ devices that are intended for professional use have a word clock
+ connector and a way to tell the device to use either its internal
+ sample clock (for standalone use), or to use the word clock signal as
+ the sample clock. Because of the electrical characteristics of the
+ signal, it is very important that any length of cable used to
+ distribute word clock is "terminated" with a 75 ohm resistor at both
+ ends. Unfortunately, some devices include this terminator themselves,
+ some contain a switchable resistor and some do not. Worse still, the
+ user manuals for many devices do not provide any information on their
+ termination configuration. It is often necessary to ask the
+ manufacturer in cases where it is not made very obvious from marking
+ near the word clock connectors on the device.
+ </para>
+ </section>
+
+ <section id="timecode">
+ <title>Timecode</title>
+ <para>
+ "Timecode" is a signal that contains positional or "timeline"
+ information. There are several different kinds of timecode signal, but
+ by far the most important is known as SMPTE. Its name is an acronym
+ for the Society for Motion Picture T?? Engineering, and timecode is
+ just one of the standards they defined, but its the most well known.
+ Because of its origins in the film/video world, SMPTE is very centered
+ on the time units that matter to film/video editors. The base unit is
+ called a "frame" and corresponds to a single still image in a film or
+ video. There are typically on the order of 20-30 frames per second, so
+ the actual resolution of SMPTE timecode is not very good compared to
+ audio-based units where there are tens of thousands of "frames" per
+ second.
+ </para>
+ </section>
+
+ <section id="SMPTE">
+ <title>SMPTE</title>
+ <para>
+ SMPTE defines time using a combinations of hours, minutes, seconds,
+ frames and subframes, combined with the frame rate. In a film/video
+ environment, SMPTE is typically stored on the film/video media, and
+ sent from the device used to play it. There are different ways of
+ storing it on the media - you may come across terms like LTR and VTC -
+ but the crucial idea to grasp is that the film/video has a timecode
+ signal "stamped" into it, so that it is always possible to determine
+ "what time it is" when any given image is visible.
+ </para>
+
+ <para>
+ SMPTE timecode is sent from one system to another as an analog audio
+ signal. You could listen to it if you wanted to, though it sounds like
+ a generally screeching and unpleasant noise. What the SMPTE standard
+ defines is a way to encode and decode the
+ hrs:mins:secs:frames:subframes time into or from this audio signal.
+ </para>
+ </section>
+
+ <section id="mtc">
+ <title>MTC</title>
+ <para>
+ The other very common form of timecode is known as "MTC" (MIDI Time
+ Code). However, MTC is actually nothing more than a different way to
+ transmit SMPTE timecode. It uses the exact same units as SMPTE
+ timecode, but rather than send the signal as audio MTC defines a
+ transmission method that uses a MIDI cabable and a data protocol. MTC
+ consumes a measurable, but small, percentage of the available
+ bandwidth on a MIDI cable (on the order of 2-3%). Most of the time, it
+ is wise to use a single cable for MTC and MMC (MIDI Machine Control)
+ and not share it with "musical" MIDI data (the kind that an instrument
+ would send while being played).
+ </para>
+ </section>
+
+ <section id="jack-transport">
+ <title>JACK Transport</title>
+ <para>
+ For Ardour and other programs that use <emphasis>JACK</emphasis>,
+ there is another method of doing timeline synchronization that is not
+ based on SMPTE or MTC.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/templates.xml b/manual/xml/templates.xml
new file mode 100644
index 0000000000..0b39eb7d77
--- /dev/null
+++ b/manual/xml/templates.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-templates">
+ <title>Session Templates</title>
+ <para>
+ Ardour allows you to create templates that specify the number of tracks
+ and busses, the I/O configuration and other aspects of the session. When
+ creating a new session, you can specify a template and it will be
+ created to match the template settings. To create a template, you will
+ need to be working on an existing session. Make sure that the session is
+ setup to in exactly the way you would like the template to be. Choose
+ <menuchoice> <guimenu>Session</guimenu> <guisubmenu>Save
+ Template</guisubmenu> </menuchoice>.
+ </para>
+
+ <para>
+ To open the Save Template dialog enter a name for the template and click
+ <guibutton>Save</guibutton> or
+ <keycombo><keycap>Ctrl</keycap><keycap>S</keycap></keycombo> to store
+ the template using the current session configuration. Templates are
+ basically session files without any audio data references. They are
+ stored in your <filename>.ardour</filename> folder.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/save_template_dialog.png"/>
+ </imageobject>
+ </mediaobject>
+ <section id="sn-using-a-template">
+ <title>Using a template</title>
+ <para>
+ When opening a new session, instead of leaving the <guibutton>New
+ setup</guibutton> button selected in the New Session dialog, click the
+ <guibutton>Use template</guibutton> button, and then click on the name
+ of the template you would like to use. Note that this option does not
+ appear until you have saved at least one template.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/tracks_and_busses.xml b/manual/xml/tracks_and_busses.xml
new file mode 100644
index 0000000000..d008a64864
--- /dev/null
+++ b/manual/xml/tracks_and_busses.xml
@@ -0,0 +1,323 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-tracks-and-busses">
+ <title>Tracks and Busses</title>
+ <para>
+ This chapter covers basic management of tracks. Tracks are probably the
+ most important objects in Ardour. They represent the fundamental way to
+ playback and record audio, MIDI, and image data.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/signal_flow.png"/>
+ </imageobject>
+ </mediaobject>
+ <section id="creating-tracks">
+ <title>Creating Tracks</title>
+ <para>
+ Tracks may be added to the session at any time.
+ </para>
+ <orderedlist><title>Creating a new Track</title>
+ <listitem>
+ <para>
+ Choose <menuchoice> <guimenu>Session</guimenu> <guisubmenu>Add
+ Track/Bus</guisubmenu> </menuchoice>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ add_track.ps Add Track Dialog
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ In the Add Tracks dialog, choose whether you wish to add a new
+ Track or a new Bus.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Enter the number of new tracks/busses you want to add.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Choose the I/O configuration of the tracks/busses you are adding
+ using the clickbox.
+ </para>
+ </listitem>
+ </orderedlist>
+ </section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="renaming_tracks.xml" />
+ <section id="deleting-tracks">
+ <title>Deleting Tracks</title>
+ <para>
+ Deleting a track is permanent operation that cannot be undone.
+ However, since the audio, MIDI, automation and other data associated
+ with the track will remain as part of the session, and the actual
+ playlist(s) that were in use by the track are still available. for use
+ by other tracks. As a result, although inadvertently deleting a track
+ is inconvenient, it doesn't result in any significant loss of
+ information.
+ </para>
+
+ <section id="deleting-a-track">
+ <title>deleting a track</title>
+ <para>
+ Click on the name of the track you want to delete. From the menu
+ that appears, select <guimenuitem>Remove</guimenuitem>. A
+ confirmation dialog will appear to ensure that you really meant to
+ remove the track.
+ </para>
+ </section>
+ </section>
+
+ <section id="hiding-tracks">
+ <title>Hiding Tracks</title>
+ <para>
+ The track list on the left edge of the Editor and Mixer can be used to
+ hide or show specific tracks in either or both of those two windows.
+ To hide a track, click to on the tracks name in the relevant track
+ list. To show a track, click on its name in the track list. Visible
+ tracks have their names shown in cyan, hidden ones in orange.
+ </para>
+
+ <para>
+ You can also hide any track by clicking its hide button
+ (images/hidebutton.ps).
+ </para>
+
+ <para>
+ Hiding a track in the Editor has no effect on its visibility in the
+ Mixer, and vice versa. Hiding a track in one or both windows does not
+ affect the playback of that track's material.
+ </para>
+ </section>
+
+ <section id="track-visibility">
+ <title>Track Visibility</title>
+ <section id="showing-all-tracks">
+ <title>Showing all Tracks</title>
+ <para>
+ Click on the titlebar of the track list of the Editor or Mixer. From
+ the menu that appears, select "Show All"
+ </para>
+ </section>
+
+ <section id="hiding-all-tracks">
+ <title>Hiding all Tracks</title>
+ <para>
+ Click on the titlebar of the track list of the Editor or Mixer. From
+ the menu that appears, select "Hiding All".
+ </para>
+ </section>
+
+ <section id="showing-classes-of-tracks">
+ <title>Showing certain classes of tracks</title>
+ <para>
+ Click on the titlebar of the track list of the Editor or Mixer. From
+ the menu that appears, select "Show All Audio Tracks", or "Show all
+ Busses" as appropriate.
+ </para>
+ </section>
+
+ <section id="hiding-classes-of-tracks">
+ <title>Hiding certain classes of tracks</title>
+ <para>
+ Click on the titlebar of the track list of the Editor or Mixer. From
+ the menu that appears, select "Hide All Audio Tracks", or "Hide all
+ Busses" as appropriate.
+ </para>
+ </section>
+
+ <section id="reordering-tracks">
+ <title>Reordering Tracks</title>
+ <para>
+ Tracks may be reordered by clicking on their name in one of the
+ track lists and dragging it to a new position in the list. Note that
+ the order of tracks in the editor is totally independent of their
+ order in the mixer.
+ </para>
+ </section>
+ </section>
+
+ <section id="io-configuration">
+ <title>I/O Configuration</title>
+ <para></para>
+ </section>
+
+ <section id="soloing-tracks">
+ <title>Soloing Tracks</title>
+ <para>
+ "Soloing" a track refers to changing some aspect of the signal flow
+ through Ardour that makes it possible to listen to one (or just a few)
+ tracks at a time. It is often done during mixing and mastering to help
+ an audio engineer listen carefully to parts of the mix.
+ </para>
+
+ <para>
+ Tracks may be soloed at any time. When one or more tracks are soloed,
+ all non-soloedntracks will no longer be audible.
+ </para>
+
+ <para>
+ Soloing tracks does not affect the solo status of busses, nor vice
+ versa. That is, soloing a track leaves all busses audible and soloing
+ a track leaves all tracks "audible". You may not actually be able to
+ hear the "audible" material if it is routed through a non-soloed bus.
+ </para>
+
+ <para>
+ This design is intended to allow FX busses and master outs to be
+ useful even when soloing. Soloing is made significantly more complex
+ by the presence of control outs (see control_outs_soloing for more
+ details on soloing with control outs).
+ </para>
+
+ <section id="rude-solo-light">
+ <title>Rude Solo Light</title>
+ <para>
+ Whenever one or more tracks are soloed, the "rude solo light" in the
+ transport window will flash. You can cancel any current solos by
+ clicking on the "rude solo light".
+ </para>
+ </section>
+
+ <section id="solo-modes">
+ <title>Solo modes</title>
+ <para>
+ Ardour has two solo modes.
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term>solo latch</term>
+ <listitem>
+ <para>
+ soloing a track adds it to the set of soloed tracks, so you
+ may have any number of soloed tracks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>solo unlatch</term>
+ <listitem>
+ <para>
+ soloing a track unsolos any other soloed track, so you can
+ have only one soloed track at a time.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="changing-solo-mode">
+ <title>Changing Solo Mode</title>
+ <para>
+ To change the solo mode, goto the Options editor (options_editor)
+ and view the <guilabel>Misc</guilabel> tab.
+ </para>
+ </section>
+
+ <section id="soloing-a-track">
+ <title>Soloing a Track</title>
+ <para>
+ To toggle the solo state of a track, click on the solo button in
+ either the mixer strip for the track or the track controls section
+ in the editor.
+ </para>
+
+ <para>
+ To toggle the solo state of all tracks in an edit or mix group, use
+ Ctrl1 on the solo button of a track in the group. If you do this in
+ the Editor, the edit group will be used; in the Mixer, the mix group
+ will be used.
+ </para>
+
+ <para>
+ To toggle the solo state of all tracks, use
+ <keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><mousebutton>Button1</mousebutton></keycombo>
+ on a track solo button.
+ </para>
+ </section>
+
+ <section id="solo-safe">
+ <title>Solo safe</title>
+ <para>
+ To protect a track's current solo status, use Shift1 on that track's
+ solo button. The color of the button will change to a pale blue to
+ indicate "solo safe" status. No changes to the solo state for that
+ track are possible until "solo safe" has been unset for the track.
+ </para>
+ </section>
+
+ <section id="momentary-solo">
+ <title>Momentary solo</title>
+ <para>
+ Use 2 on a track's solo button to solo the track for as long as the
+ mouse button is pressed.
+ </para>
+ </section>
+ </section>
+
+ <section id="track-display-size">
+ <title>Track Display Size</title>
+ <para>
+ In the editor window, tracks always extend across the full extent of
+ the track display area, but they can have varying heights. In the
+ mixer window, tracks always from the top to the bottom of the mixer
+ (as strips), but they can have varying widths.
+ </para>
+
+ <section id="changing-editor-track-height">
+ <title>Changing editor track height</title>
+ <para></para>
+ </section>
+
+ <section id="changing-mixer-track-width">
+ <title>Changing mixer track width</title>
+ <para></para>
+ </section>
+ </section>
+
+ <section id="track-groups">
+ <title>Grouping Tracks</title>
+ <section id="creating-a-track-group">
+ <title>Creating a Group</title>
+ <para></para>
+ </section>
+
+ <section id="renaming-track-group">
+ <title>Renaming a Group</title>
+ <para></para>
+ </section>
+
+ <section id="changing-members-of-a-track-group">
+ <title>Changing members of a group</title>
+ <para></para>
+ </section>
+
+ <section id="deleting-a-track-group">
+ <title>Deleting a Group</title>
+ <para></para>
+ </section>
+ </section>
+
+ <section id="track-controls">
+ <title>Track Controls</title>
+ <para></para>
+ </section>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="default_track_names.xml" />
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/transport_key_bindings.xml b/manual/xml/transport_key_bindings.xml
new file mode 100644
index 0000000000..c2a3954b19
--- /dev/null
+++ b/manual/xml/transport_key_bindings.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-transport-key-bindings">
+ <title>Transport Key Bindings</title>
+ <table id="tbl-transport-key-bindings">
+ <title>Transport Key Bindings</title>
+ <tgroup cols = "2">
+ <colspec colnum="1" colname="Key Binding" colwidth="1"/>
+ <colspec colnum="2" colname="Action" colwidth= "2"/>
+ <thead>
+ <row>
+ <entry>
+ Key Binding
+ </entry>
+
+ <entry>
+ Action
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <keycombo><keycap>space</keycap></keycombo>
+ </entry>
+
+ <entry>
+ Toggle transport motion
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><keycap>space</keycap></keycombo>
+ </entry>
+
+ <entry>
+ Raise the Editor Window
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Shift</keycap><keycap>r</keycap></keycombo>
+ </entry>
+
+ <entry>
+ Toggle transport record-enable state
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>Home</keycap></keycombo>
+ </entry>
+
+ <entry>
+ Move playhead to start
+ </entry>
+ </row>
+
+ <row>
+ <entry>
+ <keycombo><keycap>End</keycap></keycombo>
+ </entry>
+
+ <entry>
+ Move playhead to end
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/user_interface_conventions.xml b/manual/xml/user_interface_conventions.xml
new file mode 100644
index 0000000000..61f80ad6ba
--- /dev/null
+++ b/manual/xml/user_interface_conventions.xml
@@ -0,0 +1,183 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-user-interface-conventions">
+ <title>Interface Basics</title>
+ <para>
+ Although Ardour has a fairly conventional graphical user interface,
+ there are a few elements that are unique to it and are probably new to
+ you. This chapter provides a guide to using these aspects of the
+ interface.
+ </para>
+
+ <section id="interface-mouse-clicks">
+ <title>Mouse Clicks</title>
+ <section id="interface-click">
+ <title>Click</title>
+ <para>
+ When we say "click on" without specifying a mouse button, we mean
+ use <mousebutton>Button1</mousebutton> to click on a user interface
+ element (button, fader, menu, etc).
+ </para>
+ </section>
+
+ <section id="interface-context-click">
+ <title>Context Click</title>
+ <para>
+ As in most graphical user interfaces today, a "context click"
+ (<mousebutton>Button3</mousebutton>) in many parts of the user
+ interface will popup a context-specific menu, allowing you to set
+ parameters or carry out operations. There are a lot of examples of
+ this, but trying it on an audio region, a mixer mute button and a
+ mixer strip name will show the general idea.
+ </para>
+ </section>
+
+ <section id="interface-delete-edit-click">
+ <title>Delete &amp; Edit Click</title>
+ <para>
+ There are two additional mouse/key combinations that you should be
+ familiar and comfortable with. They are called "delete click" and
+ "edit click", and by default they consist
+ <keycombo><keycap>Shift</keycap><mousebutton>Button3</mousebutton></keycombo>
+ click and
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button3</mousebutton></keycombo>
+ click respectively. A delete click on most objects within Ardour's
+ editor will delete that object. This includes regions, markers,
+ curve control points and so on. An edit click on the any of the same
+ kind of objects will pop up an editor dialog for that object.
+ </para>
+ </section>
+ </section>
+
+ <section id="interface-clocks">
+ <title>Clocks</title>
+ <para>
+ There are several clocks in Ardour's user interface, some of them
+ visible all the time, others in windows that are only shown by
+ request. All these clocks are identical to each other in their
+ functionality, although some can be edited by the user and some are
+ for display only.
+ </para>
+
+ <para>
+ Context clicking on a clock brings up a menu that allows you to modify
+ the display mode of that clock. The choices are:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Audio Frames
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ BBT (Bars,Beats,Ticks - musical tempo &amp; meter based time)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ SMPTE
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Min:Sec
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Each clock mode has a number of different fields. For example, SMPTE
+ has hours, minutes, seconds, and video frames.
+ </para>
+
+ <para>
+ To edit the value of a particular clock, click in the leftmost field
+ you want to modify. You can then enter a new value for that field
+ using numeric keys, along with '.' where appropriate. Editing will
+ move the next field of the clock after you have entered the maximum
+ number of digits for a field. To move to the next field before this
+ press Tab. To finish editing, either press <keycap>Return</keycap> or
+ use the <keycap>Tab</keycap> key to advance through all remaining
+ fields.
+ </para>
+ </section>
+
+ <section id="interface-bar-controllers">
+ <title>Bar Controllers</title>
+ <para>
+ Bar controllers were inspired by a comment made by "Larry the O" in
+ Electronic Musician in 2001.
+ </para>
+
+ <para>
+ A bar controller is a user interface element that works rather
+ differently than any standard element found in most programs. They are
+ used to provide a combined method of displaying and modifying a
+ parameter.
+ </para>
+
+ <para>
+ To graphically edit the value of the parameter represented by a bar
+ controller, press <mousebutton>Button1</mousebutton> and drag the
+ controller left/right or up/down as appropriate. To edit the value
+ with greater precision, double click the controller and it will
+ transform into a data entry box. You can enter an exact value for the
+ parameter, or use arrow buttons to increment/decrement the displayed
+ value. When you are finished editing, the Enter or Tab keys will
+ transform the data entry box back into the normal version of the bar
+ controller.
+ </para>
+ </section>
+
+ <section id="interface-click-boxes">
+ <title>Click Boxes</title>
+ <para>
+ Click boxes were also inspired by Larry's comment.
+ </para>
+
+ <para>
+ A click box is, as its name suggests, just a part of a window you can
+ click on to change some parameter or control value.
+ </para>
+
+ <para>
+ Clicking with 3 moves the parameter to the next value, clicking with 1
+ moves to the previous value. Clicking and holding either button will
+ automatically advance through the possible values in the appropriate
+ direction.
+ </para>
+
+ <note>
+ <para>
+ we are slowly eliminating click boxes in favor of bar controllers
+ </para>
+ </note>
+ </section>
+
+ <section id="interface-panes">
+ <title>Panes</title>
+ <para>
+ Panes are user interface elements that allow you to adjust the
+ relative sizes of two sections of a window. The panes in Ardour work
+ perfectly normally but have one additional feature: a Delete-click on
+ the pane divider will completely hide one side of its two sections.
+ Which section depends on the pane, and is not user configurable, but
+ is neary always precisely what you'd want anyway. If the pane is
+ already hidden, then Delete-click (on the still-visible pane) will
+ restore it to the size it had before it was hidden.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/using_existing_audio.xml b/manual/xml/using_existing_audio.xml
new file mode 100644
index 0000000000..1aba2db49d
--- /dev/null
+++ b/manual/xml/using_existing_audio.xml
@@ -0,0 +1,442 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<chapter id="ch-using-existing-audio">
+ <title>Using Existing Audio</title>
+ <para>
+ There are two primary ways to bring data into Ardour: recording it
+ within a session from a live sound source or importing pre-existing
+ audio files. This section covers the various ways to import audio into a
+ session.
+ </para>
+
+ <section id="importing-and-embedding">
+ <title>Importing and Embedding</title>
+ <para>
+ Importing and embedding are two different methods of using existing
+ audio files on your computer (or network file system) within a
+ session. They differ in one key respect:
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term>Importing</term>
+ <listitem>
+ <para>
+ An existing audio file is copied to the session's sounds folder,
+ and is converted into the session's native format (WAVE or
+ Broadcast WAVE depending on your choice) and sample rate.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Embedding</term>
+ <listitem>
+ <para>
+ An existing audio file is used as a the source for a region, but
+ is not copied or modified in any way.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+
+ <section id="supported-external-audio-file-formats">
+ <title>Supported External Audio File Formats</title>
+ <para>
+ The list of audio file formats that Ardour can import/embed is quite
+ long. It is based on the functionality offered by libsndfile, an
+ excellent and widely used software library by Australian programmer
+ Erik de Castro Lopo. As libsndfile's capabilities expand, so will
+ Ardour's abilities to import (and export) new formats. Ogg/Vorbis (an
+ excellent, unpatented and license free audio compression format
+ similar to MP3) is planned for the near future. Currently, supported
+ formats include:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Microsoft WAV
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ SGI/Apple AIFF/AIFC
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Sun AU/Snd
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Raw (headerless)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Paris Audio File (PAF)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Commodore IFF/SVX
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Sphere/NIST WAV
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ IRCAM SF
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Creative VOC
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ SoundForge W64
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ GNU Octave MAT4.4
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Portable Voice Format
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Fasttracker 2 XI
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ HMM Tool Kit HTK
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Sample encodings supported include:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Unsigned and signed 8, 16, 24 and 32 bit PCM
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ IEEE 32 and 64 floating point
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ U-LAW
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ A-LAW
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ IMA ADPCM
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ MS ADPCM
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ GSM 6.10
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ G721/723 ADPCM
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ 12/16/24 bit DWVW
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ OK Dialogic ADPCM
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ 8/16 DPCM
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="using-audio-files">
+ <title> Using audio files as tracks or regions? </title>
+ <para>
+ When you want to use existing audio files in an Ardour session, the
+ first choice you need to make is whether you want to bring the files
+ in as tracks or as new regions. Consider the two following scenarios:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ you have an 8 track recording of existing material, with 1 audio
+ file per track
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ you have a sample library containing 500 small audio files
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ In the first case, your goal is probably to have 8 tracks (at least),
+ with each track containing a single audio file. In the second case,
+ its a lot more likely that you simply want to be able to use any of
+ the samples easily, but do not want any tracks created as a direct
+ result of the import/embed. It is very important that you understand
+ this distinction: many new users think there should be a "simple" way
+ to import existing audio without understanding that the goal of
+ importing/embedding is not always the same.
+ </para>
+
+ <para>
+ Ardour provides two different options when importing. You can
+ import/embed audio files as new tracks, or you can import/embed them
+ into the region list, where they will be available as regions to put
+ into new or existing tracks. You can also insert import/embed audio
+ files directly into an existing track.
+ </para>
+ </section>
+
+ <section id="importing-an-audio-file-as-a-new-track">
+ <title> How to import an audio file as a new track </title>
+ <para>
+ Click on the <guimenuitem>Edit</guimenuitem> item in the editor's menu
+ bar. From the popup menu that appears, choose <menuchoice>
+ <guimenu>Import</guimenu> <guisubmenu>...as new tracks</guisubmenu>
+ </menuchoice>. The Audio Library/File Chooser window will appear.
+ After you have made your selection of files to import, click the
+ button at the bottom of that window (it will say something like
+ "Import selected regions as new tracks").
+ </para>
+ </section>
+
+ <section id="embedding-an-audio-file-as-a-new-track">
+ <title> How to embed an audio file as a new track </title>
+ <section id="embedding-an-audio-file-drag-and-drop">
+ <title> Drag-n-Drop </title>
+ <para>
+ If you use a file manager such as Nautilus or Konqueror ((basically,
+ any tool that uses standard "list-of-URL's" encoding for
+ drag-n-drop)), the simplest method to import files as tracks is to
+ drag-n-drop. Select the files you want to embed in the file manager,
+ drag the selection into Ardour and drop it over an area of the
+ editor's track/arrange display where there are no tracks. The files
+ will be embedded as 1 new track per file.
+ </para>
+ </section>
+
+ <section id="embedding-audio-file-using-edit-menu">
+ <title> Edit menu </title>
+ <para>
+ Click on the <guimenuitem>Edit</guimenuitem> item in the editor's
+ menu bar. From the popup menu that appears, choose <menuchoice>
+ <guimenu>Embed</guimenu> <guisubmenu>...as new tracks</guisubmenu>
+ </menuchoice>. The Audio Library/File Chooser window will appear.
+ After you have made your selection of files to embed, click the
+ button at the bottom of that window (it will say something like
+ "Embed selected regions as new tracks"). 1 new track will be created
+ for each file.
+ </para>
+ </section>
+ </section>
+
+ <section id="importing-audio-as-a-new-region">
+ <title> Importing as a new region </title>
+ <para></para>
+ </section>
+
+ <section id="embedding-audio-as-a-new-region">
+ <title> Embedding as a new region </title>
+ <para></para>
+
+ <section id="embedding-audio-drag-and-drop">
+ <title> Drag-n-Drop </title>
+ <para></para>
+ </section>
+
+ <section id="embedding-audio-region-list-menu">
+ <title> Region List Menu </title>
+ <para></para>
+ </section>
+ </section>
+
+ <section id="how-to-import-embed">
+ <title>How to import/embed</title>
+ <para>
+ Begin by clicking on the titlebar of the region list in the editor
+ window. Select <guimenuitem>Import</guimenuitem> from the menu that
+ appears, and the Sound File Database will be displayed. See sfdb for
+ more details on using this dialog.
+ </para>
+
+ <para>
+ Once you have found and selected the files you want to import, click
+ the "Import Selected" button on the SFDB dialog. Each selected audio
+ file will be copied into the session's sounds folder, converted into
+ the session's native format and sample rate. One or more new regions
+ will be placed in the "External" section of the region list, either
+ one per channel of each file or, if "create multichannel regions" was
+ selected in the SFBD dialog, one per file.
+ </para>
+
+ <para>
+ If you use Nautilus as your file manager, you can easily import files
+ into your project by dragging them onto the desired track, then
+ releasing the mouse button. The file will then be
+ <link linkend="gt-embed">embedded</link> into your session.
+ </para>
+
+ <para>
+ At this time, no control over the conversion process is offered. If
+ sample rate conversion is required, it will be carried out at the
+ highest quality that Ardour can provide. This means that it can be
+ rather slow (many minutes to import an audio file lasting a few
+ minutes).
+ </para>
+ </section>
+
+ <section id="how-to-embed-a-file">
+ <title> How to embed a file </title>
+ <para>
+ There are two pathways for embedding an audio file into a session. One
+ is initiated from the region list, and simply creates one or more new
+ regions. The other is initiated from a specific track, and not only
+ adds regions to the region list, but also inserts them into the
+ track's playlist.
+ </para>
+
+ <section id="embedding-via-the-region-list">
+ <title>Embedding via the region list</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ click with 1 on the region list title bar.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select Import audio file from the menu that appears.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The SFDB dialog appears.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select the files you want to import
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ then click on the <guibutton>Embed Selected</guibutton> button.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ New regions are added to the External section of the region list.
+ </para>
+ </section>
+
+ <section id="embedding-from-a-track">
+ <title>Embedding from a track</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ in the track you want to add the audiofile to.The track context
+ menu will appear.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select EditInsert external sndfile from this menu. The SFDB
+ dialog appears.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Select the files you want to import
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ then click on the <guibutton>Embed Selected</guibutton> button.
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ New regions are added to the "External" section of the region list,
+ and one is inserted into the track from which the embed was started.
+ </para>
+ </section>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</chapter>
diff --git a/manual/xml/video_synchronization_via_mtc.xml b/manual/xml/video_synchronization_via_mtc.xml
new file mode 100644
index 0000000000..3b5af0113d
--- /dev/null
+++ b/manual/xml/video_synchronization_via_mtc.xml
@@ -0,0 +1,115 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-video-sync-via-mtc">
+ <title>Video Synchronization via MTC</title>
+ <note>
+ <para>
+ if you do not have any MIDI I/O available on your system, then it is
+ impossible to use MIDI Time Code.
+ </para>
+ </note>
+
+ <section id="ardour-as-mtc-master">
+ <title>Using Ardour as an MTC Master</title>
+ <para></para>
+ </section>
+
+ <section id="ardour-as-mtc-slave">
+ <title>Using Ardour as an MTC Slave</title>
+ <orderedlist>
+ <listitem>
+ <para>
+ ensure that you have defined at least one MIDI port in your
+ ardour.rc file. The default configuration includes a single port
+ that is part of the ALSA MIDI router/sequencer system.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ open the Options Editor.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ switch to the <guilabel>MIDI</guilabel> tab.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if you have more than one MIDI port, click on the button in the
+ <guilabel>MTC</guilabel> column for the port you plan where MTC
+ will be received.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if you have more than one MIDI port, then you should probably
+ click on the button in the <guilabel>MMC</guilabel> column for the
+ port you plan where MMC will be received. This is not required,
+ but many devices that send MTC also send MIDI Machine Control
+ commands and may not be able to control Ardour correctly unless
+ Ardour is also responding to MMC.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ switch to the <guilabel>Sync</guilabel> tab. Open the
+ <guilabel>Positional Sync</guilabel> selector to see the list of
+ possible sources of timeline synchronization:
+ </para>
+
+ <variablelist>
+ <title>Syncronization Options</title>
+ <varlistentry>
+ <term>Internal</term>
+ <listitem>
+ <para>
+ use Ardour's own sense of position and time
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Slave to JACK</term>
+ <listitem>
+ <para>
+ follow JACK Transport information
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Slave to MTC</term>
+ <listitem>
+ <para>
+ follow incoming MTC information
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </listitem>
+ <listitem>
+ <para>
+ choose <guimenuitem>Slave to MTC</guimenuitem>
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ To test that Ardour is now slaved, press the
+ <guibutton>Play</guibutton> button on the MTC master, or some other
+ action that will cause it to start transmitting MTC. Ardour should
+ jump to the position indicated by incoming MTC, and start playing.
+ Press <guibutton>Stop</guibutton> on the master (or do some other
+ action that will cause the master to stop sending MTC) and Ardour
+ should stop at the precise time indicated by the master.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/vst_plugins.xml b/manual/xml/vst_plugins.xml
new file mode 100644
index 0000000000..476b5fbb5d
--- /dev/null
+++ b/manual/xml/vst_plugins.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-vst-plugins">
+ <title>Using VST Plugins</title>
+ <section id="vst-why-so-hard">
+ <title>Why is this harder than it should be?</title>
+ <para>
+ The owners of VST (Steinberg Technologies, now owned by Yamaha) give
+ VST away to developers for free. Sounds great, but they do not those
+ same developers the ability to pass what they get from Steinberg on to
+ other developers.
+ </para>
+
+ <para>
+ This conflicts with the terms of the license for Ardour and several
+ software libraries used by Ardour. Steinberg have said quite often
+ that they are not opposed in principle to changing their license to
+ allow redistribution, but as of mid-summer 2006, it has not happened
+ yet.
+ </para>
+
+ <para>
+ All of this means that it is <emphasis>illegal</emphasis> for anyone
+ to distribute a binary (ready-to-run) version of Ardour with support
+ for VST plugins built in. If you want to use Ardour with VST plugins,
+ you must <emphasis>compile it yourself</emphasis>.
+ </para>
+
+ <para>
+ This is not a trivial undertaking; see our <emphasis>build
+ page</emphasis> for a full explanation even without VST support. This
+ page documents some more required steps for the build if you want to
+ include VST support.
+ </para>
+ </section>
+
+ <section id="building-ardour-with-vst-support">
+ <title>Getting a version of Ardour with VST support</title>
+ <para>
+ ... to be completed.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/what_is_different_about_ardour.xml b/manual/xml/what_is_different_about_ardour.xml
new file mode 100644
index 0000000000..ff41c30578
--- /dev/null
+++ b/manual/xml/what_is_different_about_ardour.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-what-is-different-about-ardour">
+ <title>What's Different about Ardour</title>
+ <para>
+ If you are someone who has used other audio software, particularly
+ software generally referred to as a Digital Audio Workstation (or
+ "DAW"), then there will be a number of things about Ardour that may
+ puzzle you on your initial and early encounters with the program.
+ </para>
+
+ <section id="no-default-session">
+ <title>No default session</title>
+ <para>
+ You must explicitly create a
+ <glossterm linkend="gt-session">Session</glossterm> before you can do
+ anything else, and if you choose not to use one of the provided
+ <glossterm linkend="gt-session-template">session templates</glossterm>
+ , you will also have to create
+ <glossterm linkend="gt-track">tracks</glossterm> and
+ <glossterm linkend="gt-bus">busses</glossterm> in order to record
+ and/or edit existing audio material.
+ </para>
+ </section>
+
+ <section id="where-do-plugins-and-sends-go">
+ <title>Where do plugins and sends go?</title>
+ <para>
+ Ardour doesn't have any fixed number of "slots" for
+ <glossterm linkend="gt-plugin">plugins</glossterm>, or
+ <glossterm linkend="gt-send">sends</glossterm>, or
+ <glossterm linkend="gt-insert">inserts</glossterm> : you can have as
+ many per-track as your system has the horsepower handle. The two black
+ boxes above and below the mixer strip's gain fader are
+ <glossterm linkend="gt-redirect">redirect</glossterm> lists where you
+ can add, reorder, remove and generally control plugins, sends, and
+ inserts, both pre- and post-fader.
+ </para>
+ </section>
+
+ <section id="no-builtin-eq">
+ <title>No builtin EQ</title>
+ <para>
+ Most people don't think much of the EQ's built into other DAWs.
+ Moreover, you cannot meaningfully do equalization with 3 knobs marked
+ "Lo", "Mid" and "Hi". Since good-quality EQ plugins are available for
+ no-cost on Linux, Ardour prefers to allow you to choose one which you
+ prefer. Of course, you can save your session configurations as
+ templates, so if you have a particular EQ that you prefer, you only
+ need do this once.
+ </para>
+ </section>
+
+ <section id="no-visible-send-controls">
+ <title>No visible send controls</title>
+ <para>
+ Although Ardour supports sends, there is no way to control them
+ directly from the mixer interface - you don't get a dedicated knob on
+ the mixer strip. However, if you bring up the send's own editor (for
+ example, by double-clicking on its name in the redirect list), you
+ will find a richer set of functionality than most other DAWs offer for
+ controlling the behaviour of a send.
+ </para>
+ </section>
+
+ <section id="a-smaller-set-of-tools">
+ <title>A smaller set of tools</title>
+ <para>
+ Most DAWs have evolved towards providing the so-called "smart tool"
+ which allows you to use the mouse for several different kinds of
+ operations without changing to a different tool. Ardour has taken this
+ approach from the beginning, so that the "Object" tool actually allows
+ you to carry out many different operations depending on how and where
+ the mouse is used. Ardour does not provide a destructive "pencil" tool
+ as some other DAWs do, for some fairly deep technical reasons. Needing
+ to use a "pencil" tool for waveform repair nearly always indicates a
+ problem with the setup of your session and/or recording hardware. The
+ different tools that ardour does offer include the "Object" tool which
+ has many different uses including region trimming/moving/copying,
+ automation editing, and more; a "Range" tool for defining ranges of
+ time; a "TimeFX" tool for timestretching; a "Gain" tool used
+ exclusively for editing region gain envelopes; and a "Zoom" tool to
+ manipulate temporal zoom. Many other operations are accessible via
+ context menus or <link linkend="sn-key-bindings">keyboard
+ bindings</link>
+<!--
+ a href="/manual/intro/mouse_and_keyboard">keyboard bindings/a
+ -->
+ .
+ </para>
+ </section>
+
+ <section id="no-restrictions-on-track-io-configuration">
+ <title>No restrictions on track I/O configuration</title>
+ <para>
+ Tracks and busses in ardour do not come in pre-determined
+ configurations. You can create a mono track, and convert it to a
+ stereo track at any time. You can convert it to a track with 3 inputs
+ and 7 outputs if you want, because Ardour also doesn't restrict track
+ I/O configurations to a fixed set of mono/stereo/5.1/7.1 etc. In
+ addition, because of Ardour's use of
+ <link linkend="sn-configuring-jack">JACK</link> , a track with one
+ input can actually receive data from many different locations. You can
+ also connect any track to any number of other tracks and busses. In
+ Ardour, the only difference between a track and a bus is that a track
+ plays back pre-recorded material from your disk drives and can record
+ to them. Both tracks and busses can have plugins, sends, inserts,
+ automation data and more.
+ </para>
+ </section>
+
+ <section id="your-audio-hardware-is-not-the-only-io-option">
+ <title>Your audio hardware is not the only I/O option</title>
+ <para>
+ Because Ardour uses <glossterm linkend="gt-jack">JACK</glossterm> ,
+ your session isn't limited to receiving and sending audio to and from
+ your audio interface. It can freely send and receive audio signals to
+ any other JACK application, in some cases even JACK applications
+ running on other computers. On the one hand, this makes understanding
+ the I/O options for a track or bus a little more complex than in a
+ conventional program, but it also adds incredible power to Ardour, as
+ you will see later.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/why_is_it_called_ardour.xml b/manual/xml/why_is_it_called_ardour.xml
new file mode 100644
index 0000000000..55b659958a
--- /dev/null
+++ b/manual/xml/why_is_it_called_ardour.xml
@@ -0,0 +1,222 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-why-is-it-called-ardour">
+ <title>Why is it called "Ardour" and other questions</title>
+ <section id="why-ardour">
+ <title>Why "Ardour" ?</title>
+ <para>
+ The name "Ardour" came from considerations of how to pronounce the
+ acronym <glossterm linkend="gt-hdr">HDR</glossterm> (Hard Disk
+ Recorder). The most obvious attempt sounds like a vowelless "harder"
+ and it then was then a short step to an unrelated by slightly
+ homophonic word:
+ </para>
+
+ <para>
+ <emphasis>ardour</emphasis>
+ <quote>
+ n 1: a feeling of strong eagerness (usually in favor of a person or
+ cause); "they were imbued with a revolutionary ardor"; "he felt a
+ kind of religious zeal" [syn: ardor, elan, zeal] 2: intense feeling
+ of love [syn: ardor] 3: feelings of great warmth and intensity; "he
+ spoke with great ardor" [syn: ardor, fervor, fervour, fervency,
+ fire, fervidness]
+ </quote>
+ </para>
+
+ <para>
+ Given the work required to develop Ardour, and the personality of its
+ primary author, the name seemed appropriate even without the vague
+ relationship to <glossterm linkend="gt-hdr">HDR</glossterm> .
+ </para>
+
+ <para>
+ Years later, another interpretation of "Ardour" appeared, this time
+ based on listening to non-native English speakers attempt to pronounce
+ the word. Rather than "Ardour", it became "Our DAW", which seemed
+ poetically fitting for a <glossterm linkend="gt-daw">Digital Audio
+ Workstation</glossterm> whose source code and design belongs to a
+ group of collaborators.
+ </para>
+ </section>
+
+ <section id="why-write-another-daw">
+ <title>Why write another DAW?</title>
+ <para>
+ There are already a number of excellent digital audio workstations. To
+ mention just a few: ProTools, Nuendo, Samplitude, Digital Performer,
+ Logic, Cubase (SX), Sonar, along with several less well known systems
+ such as SADIE, SAWStudio and others. Each of these programs has its
+ strengths and weaknesses, although over the last few years most of
+ them have converged on a very similar set of core features. However,
+ each of them suffers from two problems when seen from the perspective
+ of Ardour's development group:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ they do not run on Linux
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ they are not available in source code form, making modifications,
+ improvements, bugfixes by technically inclined users or their
+ friends or consultants impossible.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="why-linux-and-osx">
+ <title>Why Linux (and OS X) ?</title>
+ <para>
+ Not running on Linux is understandable, given the rather small (but
+ growing) share of the desktop market that Linux has. However, when
+ surveying the landscape of "popular operating systems", we find:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ older versions of Windows: plagued by abysmal stability and
+ appalling security
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Windows XP: finally, a version of Windows that seems stable but
+ still suffers from incredible security problems
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ OS X: an amazing piece of engineering that is excellent for audio
+ work but only runs on proprietary hardware and still lacks the
+ flexibility and adaptability of Linux.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Security matters today, and will matter more in the future as more and
+ more live or semi-live network based collaborations take place.
+ </para>
+
+ <para>
+ Let's contrast this with Linux, an operating system which:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ can stay up for months (or even years) without issues
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ is endlessly configurable down to the tiniest detail
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ is not owned by any single corporate entity, ensuring its life and
+ direction are not intertwined with that of a company (for a
+ contrary example, consider BeOS)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ is fast and efficient
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ runs on almost any computing platform ever created, including old
+ "slow" systems
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ is one of the most secure operating systems "out of the box"
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ More than anything, however, Ardour's primary author uses Linux and
+ wanted a DAW that ran there.
+ </para>
+
+ <para>
+ Having written a DAW for Linux, it turned out to be relatively easy to
+ port Ardour to OS X, mostly because of the excellent work done by the
+ JACK OS X group that ported JACK to OS X. Although OS X has a number
+ of disadvantages compared to Linux, its ease of use and its presence
+ in many studios already makes it a worthwhile platform.
+ </para>
+ </section>
+
+ <section id="why-doesnt-ardour-run-on-windows">
+ <title>Why doesn't Ardour run on Windows ?</title>
+ <para>
+ There have been several discussions about porting Ardour to Windows.
+ The obstacles are relatively few in number, but rather substantial in
+ significance. Ardour was written to run on operating systems that
+ properly and efficiently support a portable operating system standard
+ called <glossterm linkend="gt-posix">POSIX</glossterm> (endorsed by
+ the US government and many other large organizations). Linux and OS X
+ both do a good job of supporting POSIX, but Windows does not. In
+ particular, the efficiency with which Windows handles certain aspects
+ of the POSIX standard makes it very hard to port Ardour to that
+ platform. It is not impossible that we will port Ardour at some point,
+ but Windows continues to be a rather unsuitable platform for pro-audio
+ work despite the improvements that have been made to it in the last
+ few years.
+ </para>
+ </section>
+
+ <section id="need-dsp-hardware">
+ <title>Don't I need DSP hardware to run a good DAW?</title>
+ <para>
+ Please see XXX for a discussion of the merits of dedicated DSP
+ hardware.
+ </para>
+ </section>
+
+ <section id="ardour-is-complicated">
+ <title>Isn't this a really complicated program?</title>
+ <para>
+ There is no point in pretending that Ardour is a simple, easy to use
+ program. The development group has worked hard to try to make simple
+ things reasonably easy, common tasks quick, and hard and/or uncommon
+ things possible. There is no doubt that we have more to do in this
+ area, as well as polishing the user interface to improve its
+ intuitiveness and work flow characteristics. At the same time,
+ multi-track, multi-channel, non-linear, non-destructive audio editing
+ is a far from simple process. Doing it right requires not only a good
+ ear, but a solid appreciation for basic audio concepts and a robust
+ mental model/metaphor of what you are doing. Ardour is not a simple
+ "audio recorder" - you can certainly use it to record stereo (or even
+ mono) material in a single track, but the program has been designed
+ around much richer capabilities than this.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/working_with_crossfades.xml b/manual/xml/working_with_crossfades.xml
new file mode 100644
index 0000000000..412da4b844
--- /dev/null
+++ b/manual/xml/working_with_crossfades.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-working-with-crossfades">
+ <title>Working with Crossfades</title>
+ <para>
+ Whenever you arrange any two audio regions so that they overlap in any
+ way, you create the potential for a
+ <link linkend="gt-crossfade">crossfade</link> between them: a smooth
+ transition from one region to the other. Crossfades in Ardour are
+ generated in realtime, and are not stored on disk. They are objects
+ within a playlist just like regions, except that the only way to create
+ a crossfade is by overlapping two regions, and the only way to remove a
+ crossfade is to move one or both of the regions so that they no longer
+ overlap. Note that crossfades are not always audible (they can be muted
+ and unmuted at will), and can be edited in a variety of ways. We think
+ of a crossfade as consisting of an overlap between two regions, plus two
+ gain control curves that control the volume of the incoming and outgoing
+ regions during the crossfade.
+ </para>
+
+ <section id="crossfade-types">
+ <title>Types of crossfades</title>
+ <para>
+ Ardour comes with two basic kinds of crossfades, termed
+ <emphasis>short crossfades</emphasis> and <emphasis>full
+ crossfades</emphasis> . A full crossfade is a transition between two
+ regions that spans the entire overlap between them. If the overlap is
+ 2 seconds long, then the crossfade is 2 seconds long. A short
+ crossfade is a transition between two regions that lasts a fixed
+ amount of time and serves simply to avoid audio glitches at the
+ boundary of the two regions. The length of a short crossfade is a
+ session-wide parameter than can be set via the <emphasis>option
+ editor</emphasis> . The default is 15ms, and the length can vary from
+ 1 milliseconds to 0.5 seconds. In the current version of Ardour, it is
+ not possible to change the length of a short becrossfade after it has
+ been created, but it is possible to change most short crossfades to a
+ full crossfade and vice versa. Full crossfades can have their length
+ altered by changing the extent of the overlap between the two regions.
+ </para>
+
+ <para>
+ Note that even though the absolute length of the crossfade is fixed,
+ crossfades can be <emphasis>edited</emphasis> with complete freedom,
+ allowing you change the effective length of a crossfade by altering
+ the shapes of the fade in and fade out curves.
+ </para>
+ </section>
+
+ <section id="crossfade-overlaps">
+ <title>Overlaps</title>
+ <para>
+ There are several different ways to overlap two regions, and they
+ result in different kinds of crossfades being placed at the boundaries
+ of the two regions:
+ </para>
+
+ <section id="external-overlaps">
+ <title>External overlaps</title>
+ <para>
+ An "external" overlap occurs when a region starts within another
+ region, but extends beyond the other's end.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/overlaplaterhigher.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Overlaps like this will cause an xfade to be placed at the start of
+ the later region. Whether it is a full or short crossfade is
+ controlled by the current crossfade type preference. If short
+ crossfades have been chosen, the crossfade will last for the current
+ short crossfade duration; otherwise the full crossfade will last for
+ the entire overlap. The mute status of the crossfade will depend on
+ the current state of the "New crossfades are muted" setting.
+ </para>
+
+ <para>
+ In the example above, the later region is above the earlier one. It
+ is also possible to create an overlap where the earlier region is in
+ a higher layer:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/overlapearlyhigher.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ For an overlap of this type, the current crossfade type preference
+ affects the placement of the crossfade. If full crossfades have been
+ chosen, the crossfade will be placed at the start of the later
+ region and will last for the entire overlap. If short crossfades
+ have been chosen, the crossfade will start just before the end of
+ the earlier region and will last for the chosen short crossfade
+ duration. The mute status of the crossfade will depend on the
+ current state of the "New crossfades are muted" setting.
+ </para>
+ </section>
+
+ <section id="internal-overlaps">
+ <title>Internal overlaps</title>
+ <para>
+ An "internal" overlap occurs when the start and end of one region
+ both occur within the duration of another.
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/internalhigheroverlap.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Overlaps of this type will cause two short crossfades to be place at
+ the start of the later region and close to its end. Both crossfades
+ will last for the current short crossfade duration, and are created
+ in an un-muted state. These crossfades <emphasis>cannot</emphasis>
+ be converted to full crossfades. It is important to realize that the
+ purpose of these two crossfades is a little different than those
+ created for the single-ended overlap cases above. They are created
+ solely to avoid audio glitches at the transitions between the two
+ regions, and are not intended to facilitate interesting crossfades
+ between the upper and lower region.
+ </para>
+
+ <para>
+ Notice that in the example above, the shorter region is above the
+ longer one. It is also possible to create the following type of
+ overlap, where the shorter region is below the longer one:
+ </para>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/internalloweroverlap.png"/>
+ </imageobject>
+ </mediaobject>
+ <para>
+ Overlaps of this type will not cause any crossfades to be created.
+ The uppermost region will be audible throughout its duration; the
+ lowermost region will not be audible at all.
+ </para>
+ </section>
+ </section>
+
+ <section id="creating-crossfades">
+ <title>Creating Crossfades</title>
+ <para>
+ To create a crossfade between two regions, move them so that they
+ overlap. A crossfade is automatically created within the overlap
+ (possibly two, dependening on the type of overlap, as explained
+ above). Whether the crossfade is muted or not depends on two things:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ if the current crossfade type is set to "Short", the new crossfade
+ will be created in an un-muted state
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ if the current crossfade type is set to "Full", the mute status of
+ the new crossfade is controlled from the <emphasis>option
+ editor</emphasis> on the "Layers&amp;Fades" control panel. If "New
+ crossfades are unmuted", the new crossfade will be unmuted.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ A muted crossfade is not directly visible in the editor window, but
+ can be accessed by context clicking within the overlap that it relates
+ to. An unmuted crossfade has a yellow background that covers the
+ entire overlap (to make its presence obvious at all times), and a pair
+ of visible curves that show the gain control curves for the fade.
+ These curves may not be visible at a particular zoom level, especially
+ for short crossfades.
+ </para>
+ </section>
+
+ <section id="editing-crossfades">
+ <title>Editing Crossfades</title>
+ <para>
+ To carry out operations on a crossfade, context click anywhere in the
+ overlap. For the short crossfades in the "internal" overlap case, you
+ will need to zoom in until the crossfade becomes visible, and then
+ context click on it. Each crossfade under the mouse pointer (there is
+ normally only one) will appear in the context menu, and will lead to a
+ submenu offering the following options:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Mute/Unmute the crossfade
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Edit the crossfade
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ change the crossfade from short to full or vice versa
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The last option is not available for the short crossfades in the
+ "internal" overlap case.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/working_with_layers.xml b/manual/xml/working_with_layers.xml
new file mode 100644
index 0000000000..bd843ca305
--- /dev/null
+++ b/manual/xml/working_with_layers.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-working-with-layers">
+ <title>Working with layers</title>
+ <para>
+ It is possible to arrange regions in a playlist (track) so that they
+ overlap - one starts before another finishes, for example. Because of
+ this, its important that there is a clear and understandable rule for
+ what you will hear when playing back these kinds of region arrangements.
+ </para>
+
+ <para>
+ Every region in a playlist is assigned to a layer. There can only ever
+ be one region on a given layer, although rearranging the playlist
+ (track) may change which region is on which layer. At any given point
+ along the timeline, you will hear the uppermost region at that point.
+ </para>
+
+ <para>
+ Of course, nothing in digital audio is ever quite that simple, and so of
+ course there are some complications:
+ </para>
+
+ <section id="layers-crossfades">
+ <title> Crossfades </title>
+ <para>
+ Whenever two regions overlap, there is the potential for a
+ <link linkend="sn-working-with-crossfades">crossfade</link> between
+ them. If the crossfade is not muted, then you will hear the contents
+ of the crossfade during the overlap, not just the uppermost region.
+ </para>
+ </section>
+
+ <section id="region-opacity">
+ <title> Region Opacity </title>
+ <para>
+ In a perverse nod to image manipulation programs, Ardour allows you to
+ make regions transparent. By default, all regions are created opaque,
+ which means that when they are playing, no region below them are
+ audible. However, if you change the region to be transparent, the
+ region will be audible together with any regions below it. This
+ capability should probably not be abused - if you really want to mix
+ sounds together in this way, they should probably live in their own
+ tracks. Occasionally though, this can be useful trick.
+ </para>
+
+ <para>
+ To change the opacity of a region, popup the region's editor,
+ accessible by context clicking on the region. Then click on the
+ "opaque" button, turning it on or off as desired.
+ </para>
+ </section>
+
+ <section id="layering-styles">
+ <title> Layering Styles </title>
+ <para>
+ When you are recording new material for a track, its typical to want
+ to new material recorded "over" existing material in the track to be
+ what you hear on playback. For example, if you overdub part of a
+ guitar solo, you normally want the overdub to be audible, not hidden
+ by the old version that was already there. By contrast, when editing
+ using splitting/trimming/moving of regions to create a particular
+ arrangement along the timeline, many people find that they want
+ regions that start later on the timeline to be the ones that are
+ audible.
+ </para>
+
+ <para>
+ To facilitate these two contradictory desires, Ardour features three
+ different styles for assigning regions to layers.
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term>Most recently added regions are higher</term>
+ <listitem>
+ <para>
+ Use this style when recording/overdubbing new material. Edits of
+ any kind do not modify the layering.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Most recently added/moved/trimmed regions are higher</term>
+ <listitem>
+ <para>
+ Use this style when recording/overdubbing new material, but you
+ want basic edits to cause regions to rise to the top.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Later regions are higher</term>
+ <listitem>
+ <para>
+ Use this style when rearranging and editing regions.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ A new session has the layering style set to "Most recently
+ added/moved/trimmed regions are higher". To change the layering style,
+ open the <emphasis>options editor</emphasis> and select the
+ "Layers&amp;Fades" page. There is an option there to select the style
+ you want. Layering style may be changed at any time. The existing
+ layering of all playlists is not changed when changing the layering
+ model.
+ </para>
+ </section>
+
+ <section id="modifying-layering-by-hand">
+ <title> Modifying Layering By Hand </title>
+ <para>
+ If you want a particular region to be the uppermost when the current
+ layering style has put it on a lower layer, context click on the
+ region. Select the region from the menu that pops up, and in the
+ submenu that appears, choose one of "Move region to lowest layer" or
+ "Move region to upper layer". The layering for the playlist will be
+ recalculated to ensure that the region is on the layer you chose.
+ Note: these operations only have any effect if using one of the "Most
+ recently .." layer models.
+ </para>
+
+ <para>
+ You can see the precise layer a region is assigned in the popup region
+ editor, accessible by context clicking on the region.
+ </para>
+
+ <note>
+ <para>
+ At one time, Ardour offered more explicit control over the layering,
+ allowing you to move regions up or down to specific layers. This was
+ found to be problematic, confusing, and generally rendered
+ unnecessary by both of the layering styles the program now offers.
+ </para>
+ </note>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/working_with_playlists.xml b/manual/xml/working_with_playlists.xml
new file mode 100644
index 0000000000..ccf56ccc3a
--- /dev/null
+++ b/manual/xml/working_with_playlists.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-working-with-playlists">
+ <title>Working with Playlists</title>
+ <para>
+ As described earlier <link linkend="gt-playlist">playlists</link> are
+ one of the central objects in a digital audio workstation. A playlist is
+ a list of <link linkend="gt-region">regions</link> ordered in time. It
+ defines which parts of which source files should be played and when.
+ </para>
+
+ <para>
+ Each track in Ardour is really just a mechanism for taking a playlist
+ and generating the audio stream that it represents. As a result, editing
+ a track really means modifying its playlist in some way. Since a
+ playlist is a list of regions, most of the modifications involve
+ manipulating regions: their position, length and so forth. This is
+ covered in <xref linkend="sn-working-with-regions"/>. Here, we cover
+ some of the things you can do with playlists as objects in their own
+ right.
+ </para>
+
+ <section id="tracks-are-not-playlists">
+ <title> Tracks are not Playlists </title>
+ <para>
+ It is important to understand that a track is <emphasis>not</emphasis>
+ a playlist. A track is a mechanism for generating the audio stream
+ represented by the playlist and passing it through a signal processing
+ pathway. At any point in time, a track has a single playlist
+ associated with it. When the track is used to record, that playlist
+ will have one or more new regions added to it. When the track is used
+ for playback, the contents of the playlist will be heard. Old tape
+ operators will feel comfortable thinking of the playlist as the tape,
+ and the track as the tape machine.
+ </para>
+
+ <para>
+ However, you can change the playlist associated with a track at
+ (almost) any time, and even share playlists between tracks. There is
+ more on this <link linkend="playlist-operations">below</link>.
+ </para>
+ </section>
+
+ <section id="playlists-are-cheap">
+ <title> Playlists are cheap </title>
+ <para>
+ One thing you should be clear about is that playlists are cheap. They
+ don't cost anything in terms of CPU consumption, and they have very
+ minimal efforts on memory use. Don't be afraid of generating new
+ playlists whenever you want to. They are not equivalent to tracks,
+ which require extra CPU time and significant memory space, or audio
+ files, which use disk space, or to plugins that require extra CPU
+ time. If a playlist is not in use, it occupies a small amount of
+ memory, and nothing more.
+ </para>
+ </section>
+
+ <section id="playlists-as-takes">
+ <title> Playlists as "Takes" or "Virtual Tracks" </title>
+ <para>
+ If you have a background in audio engineering, then it might be
+ easiest for you to think of playlists as "takes". This isn't a
+ particularly useful analogy by itself, and it can be misleading. But
+ if you are working with music where most tracks feature single-pass
+ recordings of a single instrument, then the idea of using one playlist
+ per "take" can make life very convenient. Each time you need to record
+ another take, create a new playlist list first. You will then end up
+ with a simple way of switching back and forth between each version, or
+ even listening to several at the same time.
+ </para>
+
+ <para>
+ If you have some experience of other DAWs, then you might have come
+ across the term "virtual track", normally defined as a track that
+ isn't actually playing or doing anything, but can be mapped/assigned
+ to a "real track". This concept is functionally identical to Ardour's
+ playlists. We just like to be little more clear about what is actually
+ happening rather than mixing old and new terminology ("virtual" and
+ "track") into confusing terminology.
+ </para>
+ </section>
+
+ <section id="playlist-operations">
+ <title> Playlist Operations </title>
+ <para>
+ At this point, all operations on playlists start by clicking on the
+ playlist button (labelled <guibutton>p</guibutton>) in the control
+ area of a track in the editor. Clicking the button will popup a menu
+ with the following choices:
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term><guilabel>Current</guilabel></term>
+ <listitem>
+ <para>
+ shows the name of the current playlist used by this track
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Rename</guilabel></term>
+ <listitem>
+ <para>
+ pops up a dialog that allows the current playlist to be renamed
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>New</guilabel></term>
+ <listitem>
+ <para>
+ creates a new <emphasis>empty</emphasis> playlist, and switches
+ this track to use it
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>New Copy</guilabel></term>
+ <listitem>
+ <para>
+ creates a new playlist that is a copy of the current playlist,
+ and switches this track to use it
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Clear Current</guilabel></term>
+ <listitem>
+ <para>
+ removes all regions from the current playlist
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Select</guilabel></term>
+ <listitem>
+ <para>
+ pops up a playlist browser to manually choose which playlist
+ this track should use
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <section id="renaming-playlists">
+ <title>Renaming Playlists</title>
+ <para>
+ Playlists are created with the name of the track of which they are
+ associated, plus a version number. So, the first playlist for a
+ track called "Cowbell" will be called "Cowbell.1". This name will be
+ used to define the names of any regions added to the playlist by
+ recording. You can change the name at any time, to anything you
+ want. Ardour does not require that your playlist names are all
+ unique, but it will make your life easier if they are. Suggested
+ examples of user-assigned names for a playlist might include "Lead
+ Guitar, 2nd take", "vocals (quiet)", and "downbeat cuica". Notice
+ how these might be different from the associated track names, which
+ for these examples might be "Lead Guitar", "Vocals" and "Cuica". The
+ playlist name provides more information because it is about a
+ specific version of the material that may (or may not) end up in the
+ final version of the track.
+ </para>
+
+ <para>
+ If you are going to rename your playlists, do so before recording
+ new material to them.
+ </para>
+ </section>
+
+ <section id="selecting-playlists">
+ <title>Selecting Playlists</title>
+ <para>
+ If you click on the "Select" choice of the playlist button menu, a
+ dialog will appear that displays all playlists in a tree-structure
+ (many will be hidden). Playlists will be grouped by the track for
+ which they were created, with all those created for the current
+ track displayed. Other tracks are hidden in a collapsed tree that
+ can be expanded as you wish to find other playlists.
+ </para>
+ </section>
+
+ <section id="sharing-playlists">
+ <title>Sharing Playlists</title>
+ <para>
+ It is entirely possible to share playlists between tracks. The only
+ slightly unusual thing you may notice when sharing is that edits to
+ the playlist made in one track will magically appear in the other.
+ If you think about this for a moment, its an obvious consequence of
+ sharing.
+ </para>
+
+ <para>
+ You might not want this kind of behaviour, even though you still
+ want two tracks to use the same (or substantially the same)
+ playlist. To accomplish this, select the chosen playlist in the
+ second track, and then use <guilabel>New Copy</guilabel> to generate
+ an independent copy of it for that track. You can then edit this
+ playlist without affecting the original.
+ </para>
+ </section>
+
+ <section id="using-playlists-for-takes">
+ <title>Using playlists for takes</title>
+ <para>
+ You have several choices here. You can obviously record new takes
+ directly over an existing one, because of the non-destructive nature
+ of digital audio editing. You can also use the <guilabel>Clear
+ Current</guilabel> operation each time you want to start a new take.
+ This is a non-destructive operation that removes all existing
+ regions from the current playlist. Although you won't lose any
+ information doing this, its probably not appropriate unless the last
+ take was so awful that you want to discard it (although without the
+ finality of <emphasis>Remove Last Capture</emphasis> ). Finally, and
+ probably most useful, you can use the <guilabel>New</guilabel>
+ operation in the playlist button menu to create a new empty
+ playlist, ready for the next take. Later, you can
+ <guilabel>Select</guilabel> your way back to previous or later takes
+ as desired, either in this or some other track.
+ </para>
+ </section>
+ </section>
+</section>
diff --git a/manual/xml/working_with_ranges.xml b/manual/xml/working_with_ranges.xml
new file mode 100644
index 0000000000..f21e0f99b9
--- /dev/null
+++ b/manual/xml/working_with_ranges.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-working-with-ranges">
+ <title>Working with Ranges</title>
+ <para>
+ This section doesn't really exist it yet, but is a placeholder for the
+ following
+ </para>
+
+ <section id="bounce-range">
+ <title>Bounce Range</title>
+ <para>
+ Currently, when bouncing a range to disk, files corresponding to each
+ channel of the range's output are created. The file names begin with
+ Audio, then the track number followed by ".1." Then, a 0 or 1 is
+ added, depending on the channel. Finally, the file extension is added.
+ The file type is determined by the native format selection in the
+ options editor (the Paths/Files tab).
+ </para>
+
+ <para>
+ In a future version, "bounce range" will replace the range with a new
+ region based on the bounced audio file which will include track FX,
+ etc. Currently, no dialog box is offered to allow the user to name the
+ bounced file or choose its location on disk. The bounced audio is just
+ placed in the sounds directory of the project directory. There is
+ currently no visual feedback that the bounce has been accomplished.
+ </para>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xml/working_with_regions.xml b/manual/xml/working_with_regions.xml
new file mode 100644
index 0000000000..1c8cea8209
--- /dev/null
+++ b/manual/xml/working_with_regions.xml
@@ -0,0 +1,645 @@
+<?xml version="1.0" standalone="no"?>
+
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+]>
+
+<section id="sn-working-with-regions">
+ <title>Working with Regions</title>
+ <para>
+ Regions are the basic elements of editing and composing in Ardour. Each
+ region represents a single, contiguous section of one or more audio
+ files. Regions are defined by a fixed set of attributes:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ the source audio file(s) they represent
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ a starting point in the audio file(s)
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ a length
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ When placed into a
+ <glossterm linkend="gt-playlist">playlist</glossterm>, they gain
+ additional attributes:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ a position along the timeline
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ a layer
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ There are <emphasis>other attributes</emphasis> as well, but they do not
+ define the region. Things you should know about regions:
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term>Regions are Cheap</term>
+ <listitem>
+ <para>
+ By themselves, regions do not consume hardly any of your
+ computer's resources. Each region requires a small amount of
+ memory, and represents a rather small amount of CPU work if placed
+ into an active track. So, don't worry about creating regions
+ whenever you need to.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Regions are not audio files</term>
+ <listitem>
+ <para>
+ Although a region can represent an entire audio file, they are
+ never equivalent to an audio file. Most regions represent just
+ parts of an audio file(s) on disk, and removing a region from a
+ track has nothing to do with removing the audio file(s) from the
+ disk ((the <emphasis>Destroy</emphasis> operation, one of Ardour's
+ few destructive operations, can affect this)). Changing the length
+ of a region has no effect on the audio file(s) on disk. Splitting
+ and copying regions does not alter the audio file in anyway, nor
+ does it create new audio files ((the <emphasis>Export</emphasis> ,
+ <emphasis>Bounce</emphasis> and <emphasis>Reverse</emphasis>
+ operations do create new audio files)).
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <section id="region-naming">
+ <title>Region Naming</title>
+ <para>
+ Regions are initially named using either:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ the name of the playlist for which they were recorded
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ the name of the embedded/imported audio file they represent
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section id="whole-file-region-names">
+ <title>Whole File Region Names</title>
+ <para>
+ These are not audio files, but regions that represent the full
+ extent of an audio file. Every time a new recording is done, or a
+ new file is embedded/imported, a new region is created that
+ represents the entire audio file(s) This region will have the name
+ of the playlist/original file, followed by a "-" and then a number.
+ </para>
+
+ <para>
+ For recorded regions, the number will increase each time a new
+ recording is made. So, for example, if there is a playlist called
+ "Didgeridoo", the first recorded whole file region for that playlist
+ will be called "Digderidoo-1". The next one will be "Digeridoo-2"
+ and so on.
+ </para>
+
+ <para>
+ For imported/embedded files, the region name will be based on the
+ file name, but with any final suffix (e.g. ".wav" or ".aiff")
+ removed.
+ </para>
+
+ <para>
+ Normally, whole file regions are not inserted into tracks/playlists,
+ but regions derived from them are. The whole-file versions live in
+ the editor region list where they act as an organizing mechanism for
+ regions that are derived from them.
+ </para>
+ </section>
+
+ <section id="normal-region-names">
+ <title>Normal Region Names</title>
+ <para>
+ When a region is inserted into a track/playlist, its initial name
+ will end in a version number, such as ".1" or ".103". For a recorded
+ region, if the whole file region was "Hang drum-1", then the region
+ in the track will appear with the name "Hang drum-1.1". For an
+ imported/embedded region, if the whole file region was
+ "Bach:Invention3", then the region in the track will appear with the
+ name "Bach:Invention3.1".
+ </para>
+ </section>
+
+ <section id="copied-region-names">
+ <title>Copied Region Names</title>
+ <para>
+ If the region is a copy of another region, it will begin life with
+ the same name as the original. When an operation is carried out that
+ modifies one of the copies, that particular copy will be renamed by
+ incrementing the version number.
+ </para>
+ </section>
+
+ <section id="renaming-regions">
+ <title>Renaming Regions</title>
+ <para>
+ You can rename a region at any time. Use the <emphasis>region
+ context menu</emphasis> to popup the rename dialog. The new name
+ does not need to have a version number in it (in fact, it probably
+ should not). The region will retain its name until it is modified
+ after being copied.
+ </para>
+ </section>
+ </section>
+
+ <section id="selecting-regions">
+ <title>Selecting Regions</title>
+ <para>
+ In general, operations on regions apply to whichever regions are
+ currently <emphasis>selected</emphasis> .
+ </para>
+
+ <para>
+ To select a single region, click on it using
+ <mousebutton>Button1</mousebutton>.
+ </para>
+
+ <para>
+ To add an unselected region to the currently selected regions, click
+ on it using
+ <keycombo><keycap>Shift</keycap><mousebutton>Button1</mousebutton></keycombo>.
+ </para>
+
+ <para>
+ To remove a selected region from the currently selected regions, click
+ on it using
+ <keycombo><keycap>Shift</keycap><mousebutton>Button1</mousebutton></keycombo>.
+ </para>
+ </section>
+
+ <section id="removing-regions">
+ <title>Removing Regions</title>
+ <para>
+ Select the region(s) to be removed. Then press the "Delete" key or use
+ the standard key binding for "Cut" (
+ <keycombo><keycap>Ctrl</keycap><keycap>X</keycap></keycombo> by
+ default).
+ </para>
+
+ <para>
+ Note that "removing" a region is a non-destructive operation. It has
+ no effect on the audio file(s) stored on disk. If you really want to
+ destructively remove the region, use the context menu for the region
+ which has a "Destroy" item. This is not guaranteed to remove the audio
+ file from your disk storage, but it generally will.
+ </para>
+ </section>
+
+ <section id="moving-regions">
+ <title>Moving Regions</title>
+ <para>
+ To move a region, make sure you are in <emphasis>object</emphasis>
+ mouse mode. Move the mouse pointer into the waveform display part of
+ the region, press <mousebutton>Button1</mousebutton> and drag. The
+ region will follow the mouse pointer as you move it around. By
+ default, the region can move freely along the timeline - see
+ <xref linkend="sn-snap-settings"/> for information on how to force the
+ region to align to certain kinds of points along the timeline.
+ </para>
+
+ <para>
+ To move a region from one track to another, simply start a move as
+ described above, but move the mouse pointer into the desired track.
+ The region will follow the mouse pointer. Note that if you have other
+ kinds of "tracks" visible, the region will remain where it is as the
+ mouse pointer moves across them, and will then jump to the new track.
+ This serves as a visual reminder that you cannot drag an audio region
+ into an automation track or a bus, for example.
+ </para>
+
+ <section id="moving-more-than-one-region">
+ <title>Moving more than one region</title>
+ <para>
+ To move multiple regions, select them before moving. Then click+drag
+ on one of the selected regions. All the regions will move, keeping
+ their positions relative to each other.
+ </para>
+ </section>
+
+ <section id="region-fixed-time-motion">
+ <title>Fixed-time motion</title>
+ <para>
+ Sometimes, you want to move a region to another track, but keeping
+ its position along the timeline exactly the same. To do this, use
+ <mousebutton>Button2</mousebutton> rather than
+ <mousebutton>Button1</mousebutton>.
+ </para>
+ </section>
+ </section>
+
+ <section id="copying-regions">
+ <title>Copying Regions</title>
+ <para>
+ To copy a region, make sure you are in <emphasis>object</emphasis>
+ mouse mode. Move the mouse pointer into the waveform press the
+ <keycap>Ctrl</keycap> key, keep it down while pressing
+ <mousebutton>Button1</mousebutton> and drag. A new region is created
+ and will follow the mouse pointer as it moves. See
+ <xref linkend="moving-regions"/> for more details on moving the copied
+ region around.
+ </para>
+
+ <section id="copying-more-than-one-region">
+ <title>Copying more than one region</title>
+ <para>
+ To copy multiple regions, select them before copying. Then
+ click+drag on one of the selected regions. All the regions will be
+ copied and as they move, the will keep their positions relative to
+ each other.
+ </para>
+ </section>
+
+ <section id="region-fixed-time-copying">
+ <title>Fixed-time copying</title>
+ <para>
+ If you want to copy region(s) to other track(s) but keep the copies
+ at the exact position on the timeline as the originals, simply use
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button2</mousebutton></keycombo>
+ instead of
+ <keycombo><keycap>Ctrl</keycap><mousebutton>Button1</mousebutton></keycombo>.
+ </para>
+ </section>
+ </section>
+
+ <section id="trimming-regions">
+ <title>Trimming Regions</title>
+ <para></para>
+ </section>
+
+ <section id="auditioning-regions">
+ <title>Auditioning Regions</title>
+ <para></para>
+ </section>
+
+ <section id="region-gain-envelopes">
+ <title>Region Gain Envelopes</title>
+ <para></para>
+ </section>
+
+ <section id="region-context-menu">
+<!-- needs work -->
+ <title>Region Context Menu</title>
+ <para>
+ If you context-click on a region, a popup menu will appear. At or near
+ the top of that menu is a list of all regions that exist in the
+ clicked-upon track under the mouse pointer. Each region entry (shown
+ by name) points to a submenu that contains region-specific operations:
+ </para>
+
+ <variablelist>
+ <title></title>
+ <varlistentry>
+ <term><guilabel>Popup region editor</guilabel></term>
+ <listitem>
+ <para>
+ creates and displays the editor for this region, allowing even
+ more specific control over the region than this menu
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Raise to top layer</guilabel></term>
+ <listitem>
+ <para>
+ moves the region to the top layer of this track (works only in
+ "Most recently added/moved/trimmed regions are higher"
+ <emphasis>layer mode</emphasis>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Lower to bottom layer</guilabel></term>
+ <listitem>
+ <para>
+ moves the region to the bottom layer of this track (works only
+ in "Most recently added/moved/trimmed regions are higher"
+ <emphasis>layer mode</emphasis>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Define sync point</guilabel></term>
+ <listitem>
+ <para>
+ if the edit cursor is within this region, defines the region
+ sync point at the edit cursor location.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Remove sync point</guilabel></term>
+ <listitem>
+ <para></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Audition</guilabel></term>
+ <listitem>
+ <para>
+ plays this region via the
+ <glossterm linkend="gt-auditioner">auditioner</glossterm>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Export</guilabel></term>
+ <listitem>
+ <para>
+ exports this region to a new audio file, via the export dialog
+ (thus allowing resampling, dithering, format specification etc.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Bounce</guilabel></term>
+ <listitem>
+ <para>
+ re-records this region (with any plugins/inserts applied) to a
+ new audio file, and replaces the region with one referring to
+ the new file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Lock</guilabel></term>
+ <listitem>
+ <para>
+ prevents the region from being moved, trimmed, or modified in
+ almost any way.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Unlock</guilabel></term>
+ <listitem>
+ <para>
+ removes the lock on region modification
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Mute</guilabel></term>
+ <listitem>
+ <para>
+ makes the region silent during playback
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Unmute</guilabel></term>
+ <listitem>
+ <para></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Toggle envelope visibility</guilabel></term>
+ <listitem>
+ <para>
+ shows/hides the region gain envelope
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Toggle envelope active</guilabel></term>
+ <listitem>
+ <para>
+ turns the region gain envelope on/off (the line is gray when the
+ envelope is off, green when it is on)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Original position</guilabel></term>
+ <listitem>
+ <para>
+ if the region was recorded (and Broadcast WAVE was the native
+ file format) moves the region to its original capture position
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Normalize</guilabel></term>
+ <listitem>
+ <para>
+ alters the gain processing of the region so that the loudest
+ sample is at 0dBFS
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>DeNormalize</guilabel></term>
+ <listitem>
+ <para>
+ undoes the effect of a normalize
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Reverse</guilabel></term>
+ <listitem>
+ <para>
+ writes the region to a new audio file with the contents
+ reversed, and replaces the region with one referring to the new
+ file
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Nudge</guilabel></term>
+ <listitem>
+ <para>
+ moves the region in various ways
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Nudge fwd</guilabel></term>
+ <listitem>
+ <para>
+ moves the region forward by the amount shown in the nudge clock
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Nudge bwd</guilabel></term>
+ <listitem>
+ <para>
+ moves the region backward by the amount shown in the nudge clock
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Nudge fwd by capture offset</guilabel></term>
+ <listitem>
+ <para>
+ moves the region forward by the same offset that it might have
+ been (incorrectly) adjusted by when captured
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Nudge bwd by capture offset</guilabel></term>
+ <listitem>
+ <para>
+ moves the region backwards by the same offset that it might have
+ been (incorrectly) adjusted by when captured
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Trim</guilabel></term>
+ <listitem>
+ <para></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Start to edit cursor</guilabel></term>
+ <listitem>
+ <para>
+ adjusts the start of the region to the current position of the
+ edit cursor (if possible)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Edit cursor to end</guilabel></term>
+ <listitem>
+ <para>
+ adjusts the end of the region to the current position of the
+ edit cursor (if possible)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Split</guilabel></term>
+ <listitem>
+ <para>
+ if the edit cursor is within the region, splits the region at
+ the editor cursor location
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Make mono regions</guilabel></term>
+ <listitem>
+ <para>
+ if the region is a multi-channel one, creates new regions
+ corresponding to each channel. The new regions are added to the
+ editor's region list, not the track.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Duplicate</guilabel></term>
+ <listitem>
+ <para>
+ pops up a dialog allowing the region to be copied 1 or more
+ times. Each copy is placed directly after the original or
+ previous copy.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Fill Track</guilabel></term>
+ <listitem>
+ <para>
+ copies the region as many times as necessary to fill the track
+ to the current session end mark. Each copy is placed directly
+ after the original or previous copy.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Remove</guilabel></term>
+ <listitem>
+ <para>
+ remove the region from the track (non-destructive)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><guilabel>Destroy</guilabel></term>
+ <listitem>
+ <para>
+ remove the region from the track and the editor region list, and
+ if no other regions are referencing it, remove the audio file
+ that the region is derived from. (
+ <emphasis>DESTRUCTIVE</emphasis> )
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </section>
+<!--
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="Some_Subsection.xml" />
+ -->
+</section>
diff --git a/manual/xmlformat/BUGS b/manual/xmlformat/BUGS
new file mode 100644
index 0000000000..d1e81954fa
--- /dev/null
+++ b/manual/xmlformat/BUGS
@@ -0,0 +1,55 @@
+xmlformat bugs
+
+Ruby version is slower than the Perl version, a difference that shows up
+particularly for larger documents. I haven't done any profiling to determine
+which parts of the program account for the differences.
+
+----------
+Within normalized elements, the line-wrapping algorithm preserves inline
+tags, but it doesn't take any internal line-breaks within those tags into
+account in its line-length calculations. Consider this element:
+
+<para>
+This is text with an inline <inline-element attr="This is
+an attribute
+value">element</inline-element> in the middle.
+</para>
+
+The opening <inline-element> tag is considered to have a length
+equal to its total number of characters. The line-wrapping algorithm
+could be made more complex to take the line-breaks into account.
+I haven't bothered, and may never bother. If such a change is made, no
+indenting should be applied that would change the attribute value.
+
+----------
+Line-wrapping length calculations don't take into account the possibility
+that text from a different element may occur on the same line if break
+values are set to zero. For example, with a wrap-length of 15, you could
+end up with output like this:
+
+<listitem><para>This is a line
+of text.</para></listitem><listitem><para>This is a line
+of text.</para></listitem>
+
+The middle line has more than 15 characters of text.
+
+This also shows that wrap-length doesn't take into account the length of
+tags of enclosing blocks on the same line, which can also be considered a
+bug.
+
+Fix: Set all your break values > 0.
+
+----------
+Normalization converts runs of spaces to single spaces. This means that
+if you write two spaces after periods in text, normalization will
+convert them to single spaces. Even if normalization didn't do that,
+the two spaces would be lost if line-wrapping is enabled and they occur
+at a line break.
+
+I don't know if this is really a bug, but it's something to be aware of.
+
+----------
+Doesn't recognize multi-byte files. In some cases, you can work around this.
+For example, an editor might save a file as Unicode even when the document
+contains only ASCII characters. Re-save the file as an ASCII file (or
+some single-byte encoding such as ISO-8859-1) and it should work.
diff --git a/manual/xmlformat/ChangeLog b/manual/xmlformat/ChangeLog
new file mode 100644
index 0000000000..0de7f5fb8e
--- /dev/null
+++ b/manual/xmlformat/ChangeLog
@@ -0,0 +1,28 @@
+Version 1.04 (released 2006-08-14)
+- Assign each token an input line number and display the line number in
+ error messages. This provides better information to the user about
+ the location of problems in input files.
+- Print the token stack when an error occurs. This provides some idea of
+ the context of the element that is malformed or has malformed content.
+
+Version 1.03 (released 2004-03-26)
+- In xmlformat.rb, made some changes needed for Ruby 1.8:
+ - Convert @@xml_spe parsing expression to Regexp with Regexp.new().
+ scan() method doesn't work with string argument now, apparently.
+ - In parsing patterns, change literal ] to \\] to suppress warnings
+- In xmlformat.pl:
+ - In parsing patterns, change literal ] to \\]. This isn't actually
+ necessary, but better preserves parallelism with Ruby version.
+
+Version 1.02 (released 2004-02-06)
+- Added --in-place/-i option for in-place reformatting. (Requires named
+ input file or files.)
+- Added --backup/-b option for making backup of each input file (used with
+ --in-place).
+- If multiple input files are named on the command line, they are processed
+ as separate documents, not as one combined input. (This was necessary
+ to make --in-place and --backup work correctly.)
+- Added a tutorial document.
+
+Version 1.01 (released 2004-01-18)
+- Initial public release.
diff --git a/manual/xmlformat/INSTALL b/manual/xmlformat/INSTALL
new file mode 100644
index 0000000000..59017c8abd
--- /dev/null
+++ b/manual/xmlformat/INSTALL
@@ -0,0 +1,29 @@
+There are two versions of xmlformat:
+
+- xmlformat.rb, written in Ruby
+- xmlformat.pl, written in Perl
+
+Both should produce identical results.
+
+To install xmlformat, copy the version you want to use to some public
+directory that is listed in your PATH variable. You may wish to rename
+the script to xmlformat so that you don't have to type the .rb or .pl
+extension each time you invoke it.
+
+Example:
+
+ cp xmlformat.rb /usr/local/bin/xmlformat
+(or)
+ cp xmlformat.pl /usr/local/bin/xmlformat
+
+If you want to install both versions, do not rename them:
+
+ cp xmlformat.rb /usr/local/bin/xmlformat.rb
+ cp xmlformat.pl /usr/local/bin/xmlformat.pl
+
+In this case you will need to specify the extension when invoking the program
+to indicate which version you want.
+
+If your Ruby or Perl programs are not at the location listed in the
+first line of the installed script, you'll need to edit that line
+to have the correct location.
diff --git a/manual/xmlformat/LICENSE b/manual/xmlformat/LICENSE
new file mode 100644
index 0000000000..14bd362640
--- /dev/null
+++ b/manual/xmlformat/LICENSE
@@ -0,0 +1,93 @@
+xmlformat is distributed under a BSD-style license. This license
+applies to the entire xmlformat distribution, with the exception of
+the REX parser (described below).
+
+Copyright (c) 2004, 2005, Kitebird, LLC. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+3. Neither the name of Kitebird nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+The REX parser
+
+xmlformat contains code based on the REX parser, which is Copyright (c) 1998,
+Robert D. Cameron. REX is described in this document:
+
+ http://www.cs.sfu.ca/~cameron/REX.html
+
+The document contains a Perl implementation of REX:
+
+--- begin REX code ---
+# REX/Perl 1.0
+# Robert D. Cameron "REX: XML Shallow Parsing with Regular Expressions",
+# Technical Report TR 1998-17, School of Computing Science, Simon Fraser
+# University, November, 1998.
+# Copyright (c) 1998, Robert D. Cameron.
+# The following code may be freely used and distributed provided that
+# this copyright and citation notice remains intact and that modifications
+# or additions are clearly identified.
+
+$TextSE = "[^<]+";
+$UntilHyphen = "[^-]*-";
+$Until2Hyphens = "$UntilHyphen(?:[^-]$UntilHyphen)*-";
+$CommentCE = "$Until2Hyphens>?";
+$UntilRSBs = "[^\\]]*](?:[^\\]]+])*]+";
+$CDATA_CE = "$UntilRSBs(?:[^\\]>]$UntilRSBs)*>";
+$S = "[ \\n\\t\\r]+";
+$NameStrt = "[A-Za-z_:]|[^\\x00-\\x7F]";
+$NameChar = "[A-Za-z0-9_:.-]|[^\\x00-\\x7F]";
+$Name = "(?:$NameStrt)(?:$NameChar)*";
+$QuoteSE = "\"[^\"]*\"|'[^']*'";
+$DT_IdentSE = "$S$Name(?:$S(?:$Name|$QuoteSE))*";
+$MarkupDeclCE = "(?:[^\\]\"'><]+|$QuoteSE)*>";
+$S1 = "[\\n\\r\\t ]";
+$UntilQMs = "[^?]*\\?+";
+$PI_Tail = "\\?>|$S1$UntilQMs(?:[^>?]$UntilQMs)*>";
+$DT_ItemSE =
+"<(?:!(?:--$Until2Hyphens>|[^-]$MarkupDeclCE)|\\?$Name(?:$PI_Tail))|%$Name;|$S";
+$DocTypeCE = "$DT_IdentSE(?:$S)?(?:\\[(?:$DT_ItemSE)*](?:$S)?)?>?";
+$DeclCE =
+"--(?:$CommentCE)?|\\[CDATA\\[(?:$CDATA_CE)?|DOCTYPE(?:$DocTypeCE)?";
+$PI_CE = "$Name(?:$PI_Tail)?";
+$EndTagCE = "$Name(?:$S)?>?";
+$AttValSE = "\"[^<\"]*\"|'[^<']*'";
+$ElemTagCE = "$Name(?:$S$Name(?:$S)?=(?:$S)?(?:$AttValSE))*(?:$S)?/?>?";
+$MarkupSPE =
+"<(?:!(?:$DeclCE)?|\\?(?:$PI_CE)?|/(?:$EndTagCE)?|(?:$ElemTagCE)?)";
+$XML_SPE = "$TextSE|$MarkupSPE";
+
+
+sub ShallowParse {
+ my($XML_document) = @_;
+ return $XML_document =~ /$XML_SPE/g;
+}
+--- end REX code ---
+
+The Perl and Ruby implementations of xmlformat contain parsers that
+are based on the preceding code and are essentially the same, with the
+exception of changes to variable and function names.
+
diff --git a/manual/xmlformat/README b/manual/xmlformat/README
new file mode 100644
index 0000000000..53c4ff6c53
--- /dev/null
+++ b/manual/xmlformat/README
@@ -0,0 +1,35 @@
+xmlformat - an XML document formatter
+
+Paul DuBois
+paul@kitebird.com
+
+This is the distribution for xmlformat 1.04.
+If you find bugs, please let me know.
+
+The current version of xmlformat is always available at:
+ http://www.kitebird.com/software/
+
+xmlformat is free software, distributed under a BSD-style license.
+For specific licensing information, see the LICENSE file.
+
+For installation instructions, see the INSTALL file. xmlformat has two
+implementations, one in Ruby and one in Perl. They should produce
+identical output in all cases.
+
+Documentation is in the docs subdirectory.
+
+Tests are in the tests directory, though you run them in the main
+xmlformat directory:
+- To run all tests:
+ make test
+- To run all tests for the Ruby version:
+ ./runtest all
+- To run all tests for the Perl version:
+ ./runtest -p all
+- To run an individual test for the Ruby version:
+ ./runtest testname
+- To run an individual test for the Perl version:
+ ./runtest -p testname
+
+A test name is the name of its .xml file, minus the .xml suffix.
+For more information, see tests/Notes.
diff --git a/manual/xmlformat/xmlformat-ardour.conf b/manual/xmlformat/xmlformat-ardour.conf
new file mode 100644
index 0000000000..552dc17778
--- /dev/null
+++ b/manual/xmlformat/xmlformat-ardour.conf
@@ -0,0 +1,137 @@
+# Comments are treated as CDATA and not touched. It's best to set
+# them out from other text if possible. A doublespace is nice but
+# code is still code, so it's not really that important. (Down, inner
+# stickler...)
+#
+
+*DEFAULT
+ format = block
+ entry-break = 1
+ element-break = 1
+ exit-break = 1
+ subindent = 2
+ normalize = no
+ wrap-length = 76
+
+*DOCUMENT
+ format = block
+ wrap-length = 256
+ element-break = 2
+
+article book
+ element-break = 2
+
+articleinfo bookinfo
+ normalize = yes
+
+year holder
+ entry-break = 0
+ exit-break = 0
+ normalize = yes
+
+firstname surname othername
+ entry-break = 0
+ exit-break = 0
+ normalize = yes
+
+revnumber date authorinitials
+ entry-break = 0
+ exit-break = 0
+ normalize = yes
+
+revremark
+ normalize = yes
+
+row listitem
+ entry-break = 1
+ exit-break = 1
+ normalize = yes
+
+tbody
+ element-break = 2
+section chapter glossary
+ entry-break = 1
+ exit-break = 1
+ normalize = yes
+
+# "Normalize" means make smart whitespace decisions
+para simpara example important note warning caution itemizedlist variablelist varlistentry entry quote figure glossdiv glossentry
+ entry-break = 1
+ exit-break = 1
+ normalize = yes
+
+title titleabbrev
+ format = inline
+ normalize = yes
+
+table
+ entry-break = 1
+ exit-break = 1
+ normalize = yes
+
+emphasis literal abbrev
+ format = inline
+
+trademark
+ format = inline
+
+# Do not fubar <screen> or <programlisting>
+screen programlisting
+ format = verbatim
+
+# <entry> is special because a linebreak has meaning, best leave the
+# decisions up to the experts
+#entry
+# format = verbatim
+
+command application filename option userinput computeroutput replaceable glossterm
+ format = inline
+
+# The <primary> and <secondary> subelements of <indexterm> are still block
+firstterm
+ format = inline
+ normalize = yes
+
+indexterm
+ format = block
+ normalize = no
+
+primary secondary
+# format = inline
+ entry-break = 0
+ exit-break = 0
+ normalize = yes
+
+varlistentry
+ element-break = 1
+
+term
+ entry-break = 0
+ exit-break = 0
+
+menuchoice guilabel guimenu guisubmenu guimenuitem guibutton keycap keycombo mousebutton
+ format = inline
+
+wordasword systemitem citetitle footnote email
+ format = inline
+
+acronym
+ format = inline
+
+# Make <ulink> and <xref> less goofy in their use of whitespace
+ulink xref link
+ format = inline
+
+# Cover OMF files
+creator description format identifier language maintainer omf relation subject type
+ format = block
+ normalize = yes
+ entry-break = 1
+ exit-break = 1
+
+# Cover rpm-info files
+details rights version
+ format = block
+ entry-break = 0
+ exit-break = 0
+ normalize = yes
diff --git a/manual/xmlformat/xmlformat.pl b/manual/xmlformat/xmlformat.pl
new file mode 100755
index 0000000000..877f5f110f
--- /dev/null
+++ b/manual/xmlformat/xmlformat.pl
@@ -0,0 +1,1745 @@
+#! /usr/bin/perl -w
+# vim:set ts=2 sw=2 expandtab:
+
+# xmlformat - configurable XML file formatter/pretty-printer
+
+# Copyright (c) 2004, 2005 Kitebird, LLC. All rights reserved.
+# Some portions are based on the REX shallow XML parser, which
+# is Copyright (c) 1998, Robert D. Cameron. These include the
+# regular expression parsing variables and the shallow_parse()
+# method.
+# This software is licensed as described in the file LICENSE,
+# which you should have received as part of this distribution.
+
+# Syntax: xmlformat [config-file] xml-file
+
+# Default config file is $ENV{XMLFORMAT_CONF} or ./xmlformat.conf, in that
+# order.
+
+# Paul DuBois
+# paul@kitebird.com
+# 2003-12-14
+
+# The input document first is parsed into a list of strings. Each string
+# represents one of the following:
+# - text node
+# - processing instruction (the XML declaration is treated as a PI)
+# - comment
+# - CDATA section
+# - DOCTYPE declaration
+# - element tag (either <abc>, </abc>, or <abc/>), *including attributes*
+
+# Entities are left untouched. They appear in their original form as part
+# of the text node in which they occur.
+
+# The list of strings then is converted to a hierarchical structure.
+# The document top level is represented by a reference to a list.
+# Each list element is a reference to a node -- a hash that has "type"
+# and "content" key/value pairs. The "type" key indicates the node
+# type and has one of the following values:
+
+# "text" - text node
+# "pi" - processing instruction node
+# "comment" - comment node
+# "CDATA" - CDATA section node
+# "DOCTYPE" - DOCTYPE node
+# "elt" - element node
+
+# (For purposes of this program, it's really only necessary to have "text",
+# "elt", and "other". The types other than "text" and "elt" currently are
+# all treated the same way.)
+
+# For all but element nodes, the "content" value is the text of the node.
+
+# For element nodes, the "content" hash is a reference to a list of
+# nodes for the element's children. In addition, an element node has
+# three additional key/value pairs:
+# - The "name" value is the tag name within the opening tag, minus angle
+# brackets or attributes.
+# - The "open_tag" value is the full opening tag, which may also be the
+# closing tag.
+# - The "close_tag" value depends on the opening tag. If the open tag is
+# "<abc>", the close tag is "</abc>". If the open tag is "<abc/>", the
+# close tag is the empty string.
+
+# If the tree structure is converted back into a string with
+# tree_stringify(), the result can be compared to the input file
+# as a regression test. The string should be identical to the original
+# input document.
+
+use strict;
+
+use Getopt::Long;
+$Getopt::Long::ignorecase = 0; # options are case sensitive
+$Getopt::Long::bundling = 1; # allow short options to be bundled
+
+my $PROG_NAME = "xmlformat";
+my $PROG_VERSION = "1.04";
+my $PROG_LANG = "Perl";
+
+# ----------------------------------------------------------------------
+
+package XMLFormat;
+
+use strict;
+
+# ----------------------------------------------------------------------
+
+# Regular expressions for parsing document components. Based on REX.
+
+# SPE = shallow parsing expression
+# SE = scanning expression
+# CE = completion expression
+# RSB = right square brackets
+# QM = question mark
+
+my $TextSE = "[^<]+";
+my $UntilHyphen = "[^-]*-";
+my $Until2Hyphens = "$UntilHyphen(?:[^-]$UntilHyphen)*-";
+my $CommentCE = "$Until2Hyphens>?";
+my $UntilRSBs = "[^\\]]*\\](?:[^\\]]+\\])*\\]+";
+my $CDATA_CE = "$UntilRSBs(?:[^\\]>]$UntilRSBs)*>";
+my $S = "[ \\n\\t\\r]+";
+my $NameStrt = "[A-Za-z_:]|[^\\x00-\\x7F]";
+my $NameChar = "[A-Za-z0-9_:.-]|[^\\x00-\\x7F]";
+my $Name = "(?:$NameStrt)(?:$NameChar)*";
+my $QuoteSE = "\"[^\"]*\"|'[^']*'";
+my $DT_IdentSE = "$S$Name(?:$S(?:$Name|$QuoteSE))*";
+my $MarkupDeclCE = "(?:[^\\]\"'><]+|$QuoteSE)*>";
+my $S1 = "[\\n\\r\\t ]";
+my $UntilQMs = "[^?]*\\?+";
+my $PI_Tail = "\\?>|$S1$UntilQMs(?:[^>?]$UntilQMs)*>";
+my $DT_ItemSE =
+"<(?:!(?:--$Until2Hyphens>|[^-]$MarkupDeclCE)|\\?$Name(?:$PI_Tail))|%$Name;|$S";
+my $DocTypeCE = "$DT_IdentSE(?:$S)?(?:\\[(?:$DT_ItemSE)*\\](?:$S)?)?>?";
+my $DeclCE =
+"--(?:$CommentCE)?|\\[CDATA\\[(?:$CDATA_CE)?|DOCTYPE(?:$DocTypeCE)?";
+my $PI_CE = "$Name(?:$PI_Tail)?";
+my $EndTagCE = "$Name(?:$S)?>?";
+my $AttValSE = "\"[^<\"]*\"|'[^<']*'";
+my $ElemTagCE = "$Name(?:$S$Name(?:$S)?=(?:$S)?(?:$AttValSE))*(?:$S)?/?>?";
+my $MarkupSPE =
+"<(?:!(?:$DeclCE)?|\\?(?:$PI_CE)?|/(?:$EndTagCE)?|(?:$ElemTagCE)?)";
+my $XML_SPE = "$TextSE|$MarkupSPE";
+
+# ----------------------------------------------------------------------
+
+# Allowable options and their possible values:
+# - The keys of this hash are the allowable option names
+# - The value for each key is list of allowable option values
+# - If the value is undef, the option value must be numeric
+# If any new formatting option is added to this program, it
+# must be specified here, *and* a default value for it should
+# be listed in the *DOCUMENT and *DEFAULT pseudo-element
+# option hashes.
+
+my %opt_list = (
+ "format" => [ "block", "inline", "verbatim" ],
+ "normalize" => [ "yes", "no" ],
+ "subindent" => undef,
+ "wrap-length" => undef,
+ "entry-break" => undef,
+ "exit-break" => undef,
+ "element-break" => undef
+);
+
+# Object creation: set up the default formatting configuration
+# and variables for maintaining input and output document.
+
+sub new
+{
+my $type = shift;
+
+ my $self = {};
+
+ # Formatting options for each element.
+
+ $self->{elt_opts} = { };
+
+ # The formatting options for the *DOCUMENT and *DEFAULT pseudo-elements can
+ # be overridden in the configuration file, but the options must also be
+ # built in to make sure they exist if not specified in the configuration
+ # file. Each of the structures must have a value for every option.
+
+ # Options for top-level document children.
+ # - Do not change entry-break: 0 ensures no extra newlines before
+ # first element of output.
+ # - Do not change exit-break: 1 ensures a newline after final element
+ # of output document.
+ # - It's probably best not to change any of the others, except perhaps
+ # if you want to increase the element-break.
+
+ $self->{elt_opts}->{"*DOCUMENT"} = {
+ "format" => "block",
+ "normalize" => "no",
+ "subindent" => 0,
+ "wrap-length" => 0,
+ "entry-break" => 0, # do not change
+ "exit-break" => 1, # do not change
+ "element-break" => 1
+ };
+
+ # Default options. These are used for any elements in the document
+ # that are not specified explicitly in the configuration file.
+
+ $self->{elt_opts}->{"*DEFAULT"} = {
+ "format" => "block",
+ "normalize" => "no",
+ "subindent" => 1,
+ "wrap-length" => 0,
+ "entry-break" => 1,
+ "exit-break" => 1,
+ "element-break" => 1
+ };
+
+ # Run the *DOCUMENT and *DEFAULT options through the option-checker
+ # to verify that the built-in values are legal.
+
+ my $err_count = 0;
+
+ foreach my $elt_name (keys (%{$self->{elt_opts}})) # ... for each element
+ {
+ # Check each option for element
+ while (my ($opt_name, $opt_val) = each (%{$self->{elt_opts}->{$elt_name}}))
+ {
+ my $err_msg;
+
+ ($opt_val, $err_msg) = check_option ($opt_name, $opt_val);
+ if (!defined ($err_msg))
+ {
+ $self->{elt_opts}->{$elt_name}->{$opt_name} = $opt_val;
+ }
+ else
+ {
+ warn "LOGIC ERROR: $elt_name default option is invalid\n";
+ warn "$err_msg\n";
+ ++$err_count;
+ }
+ }
+ }
+
+ # Make sure that the every option is represented in the
+ # *DOCUMENT and *DEFAULT structures.
+
+ foreach my $opt_name (keys (%opt_list))
+ {
+ foreach my $elt_name (keys (%{$self->{elt_opts}}))
+ {
+ if (!exists ($self->{elt_opts}->{$elt_name}->{$opt_name}))
+ {
+ warn "LOGIC ERROR: $elt_name has no default '$opt_name' option\n";
+ ++$err_count;
+ }
+ }
+ }
+
+ die "Cannot continue; internal default formatting options must be fixed\n"
+ if $err_count > 0;
+
+ bless $self, $type; # bless object and return it
+}
+
+# Initialize the variables that are used per-document
+
+sub init_doc_vars
+{
+my $self = shift;
+
+ # Elements that are used in the document but not named explicitly
+ # in the configuration file.
+
+ $self->{unconf_elts} = { };
+
+ # List of tokens for current document.
+
+ $self->{tokens} = [ ];
+
+ # List of line numbers for each token
+
+ $self->{line_num} = [ ];
+
+ # Document node tree (constructed from the token list).
+
+ $self->{tree} = [ ];
+
+ # Variables for formatting operations:
+ # out_doc = resulting output document (constructed from document tree)
+ # pending = array of pending tokens being held until flushed
+
+ $self->{out_doc} = "";
+ $self->{pending} = [ ];
+
+ # Inline elements within block elements are processed using the
+ # text normalization (and possible line-wrapping) values of their
+ # enclosing block. Blocks and inlines may be nested, so we maintain
+ # a stack that allows the normalize/wrap-length values of the current
+ # block to be determined.
+
+ $self->{block_name_stack} = [ ]; # for debugging
+ $self->{block_opts_stack} = [ ];
+
+ # A similar stack for maintaining each block's current break type.
+
+ $self->{block_break_type_stack} = [ ];
+}
+
+# Accessors for token list and resulting output document
+
+sub tokens
+{
+my $self = shift;
+
+ return $self->{tokens};
+}
+
+sub out_doc
+{
+my $self = shift;
+
+ return $self->{out_doc};
+}
+
+
+# Methods for adding strings to output document or
+# to the pending output array
+
+sub add_to_doc
+{
+my ($self, $str) = @_;
+
+ $self->{out_doc} .= $str;
+}
+
+sub add_to_pending
+{
+my ($self, $str) = @_;
+
+ push (@{$self->{pending}}, $str);
+}
+
+
+# Block stack mainenance methods
+
+# Push options onto or pop options off from the stack. When doing
+# this, also push or pop an element onto the break-level stack.
+
+sub begin_block
+{
+my ($self, $name, $opts) = @_;
+
+ push (@{$self->{block_name_stack}}, $name);
+ push (@{$self->{block_opts_stack}}, $opts);
+ push (@{$self->{block_break_type_stack}}, "entry-break");
+}
+
+sub end_block
+{
+my $self = shift;
+
+ pop (@{$self->{block_name_stack}});
+ pop (@{$self->{block_opts_stack}});
+ pop (@{$self->{block_break_type_stack}});
+}
+
+# Return the current block's normalization status or wrap length
+
+sub block_normalize
+{
+my $self = shift;
+
+ my $size = @{$self->{block_opts_stack}};
+ my $opts = $self->{block_opts_stack}->[$size-1];
+ return $opts->{normalize} eq "yes";
+}
+
+sub block_wrap_length
+{
+my $self = shift;
+
+ my $size = @{$self->{block_opts_stack}};
+ my $opts = $self->{block_opts_stack}->[$size-1];
+ return $opts->{"wrap-length"};
+}
+
+# Set the current block's break type, or return the number of newlines
+# for the block's break type
+
+sub set_block_break_type
+{
+my ($self, $type) = @_;
+
+ my $size = @{$self->{block_break_type_stack}};
+ $self->{block_break_type_stack}->[$size-1] = $type;
+}
+
+sub block_break_value
+{
+my $self = shift;
+
+ my $size = @{$self->{block_opts_stack}};
+ my $opts = $self->{block_opts_stack}->[$size-1];
+ $size = @{$self->{block_break_type_stack}};
+ my $type = $self->{block_break_type_stack}->[$size-1];
+ return $opts->{$type};
+}
+
+
+# ----------------------------------------------------------------------
+
+# Read configuration information. For each element, construct a hash
+# containing a hash key and value for each option name and value.
+# After reading the file, fill in missing option values for
+# incomplete option structures using the *DEFAULT options.
+
+sub read_config
+{
+my $self = shift;
+my $conf_file = shift;
+my @elt_names = ();
+my $err_msg;
+my $in_continuation = 0;
+my $saved_line = "";
+
+ open (FH, $conf_file) or die "Cannot read config file $conf_file: $!\n";
+ while (<FH>)
+ {
+ chomp;
+
+ next if /^\s*($|#)/; # skip blank lines, comments
+ if ($in_continuation)
+ {
+ $_ = $saved_line . " " . $_;
+ $saved_line = "";
+ $in_continuation = 0;
+ }
+ if (!/^\s/)
+ {
+ # Line doesn't begin with whitespace, so it lists element names.
+ # Names are separated by whitespace or commas, possibly followed
+ # by a continuation character or a comment.
+ if (/\\$/)
+ {
+ s/\\$//; # remove continuation character
+ $saved_line = $_;
+ $in_continuation = 1;
+ next;
+ }
+ s/\s*#.*$//; # remove any trailing comment
+ @elt_names = split (/[\s,]+/, $_);
+ # make sure each name has an entry in the elt_opts structure
+ foreach my $elt_name (@elt_names)
+ {
+ $self->{elt_opts}->{$elt_name} = { }
+ unless exists ($self->{elt_opts}->{$elt_name});
+ }
+ }
+ else
+ {
+ # Line begins with whitespace, so it contains an option
+ # to apply to the current element list, possibly followed by
+ # a comment. First check that there is a current list.
+ # Then parse the option name/value.
+
+ die "$conf_file:$.: Option setting found before any "
+ . "elements were named.\n"
+ if !@elt_names;
+ s/\s*#.*$//;
+ my ($opt_name, $opt_val) = /^\s+(\S+)(?:\s+|\s*=\s*)(\S+)$/;
+ die "$conf_file:$.: Malformed line: $_\n" unless defined ($opt_val);
+
+ # Check option. If illegal, die with message. Otherwise,
+ # add option to each element in current element list
+
+ ($opt_val, $err_msg) = check_option ($opt_name, $opt_val);
+ die "$conf_file:$.: $err_msg\n" if defined ($err_msg);
+ foreach my $elt_name (@elt_names)
+ {
+ $self->{elt_opts}->{$elt_name}->{$opt_name} = $opt_val;
+ }
+ }
+ }
+ close (FH);
+
+ # For any element that has missing option values, fill in the values
+ # using the options for the *DEFAULT pseudo-element. This speeds up
+ # element option lookups later. It also makes it unnecessary to test
+ # each option to see if it's defined: All element option structures
+ # will have every option defined.
+
+ my $def_opts = $self->{elt_opts}->{"*DEFAULT"};
+
+ foreach my $elt_name (keys (%{$self->{elt_opts}}))
+ {
+ next if $elt_name eq "*DEFAULT";
+ foreach my $opt_name (keys (%{$def_opts}))
+ {
+ next if exists ($self->{elt_opts}->{$elt_name}->{$opt_name}); # already set
+ $self->{elt_opts}->{$elt_name}->{$opt_name} = $def_opts->{$opt_name};
+ }
+ }
+}
+
+
+# Check option name to make sure it's legal. Check the value to make sure
+# that it's legal for the name. Return a two-element array:
+# (value, undef) if the option name and value are legal.
+# (undef, message) if an error was found; message contains error message.
+# For legal values, the returned value should be assigned to the option,
+# because it may get type-converted here.
+
+sub check_option
+{
+my ($opt_name, $opt_val) = @_;
+
+ # - Check option name to make sure it's a legal option
+ # - Then check the value. If there is a list of values
+ # the value must be one of them. Otherwise, the value
+ # must be an integer.
+
+ return (undef, "Unknown option name: $opt_name")
+ unless exists ($opt_list{$opt_name});
+ my $allowable_val = $opt_list{$opt_name};
+ if (defined ($allowable_val))
+ {
+ return (undef, "Unknown '$opt_name' value: $opt_val")
+ unless grep (/^$opt_val$/, @{$allowable_val});
+ }
+ else # other options should be numeric
+ {
+ # "$opt_val" converts $opt_val to string for pattern match
+ return (undef, "'$opt_name' value ($opt_val) should be an integer")
+ unless "$opt_val" =~ /^\d+$/;
+ }
+ return ($opt_val, undef);
+}
+
+
+# Return hash of option values for a given element. If no options are found:
+# - Add the element name to the list of unconfigured options.
+# - Assign the default options to the element. (This way the test for the
+# option fails only once.)
+
+sub get_opts
+{
+my $self = shift;
+my $elt_name = shift;
+
+ my $opts = $self->{elt_opts}->{$elt_name};
+ if (!defined ($opts))
+ {
+ $self->{unconf_elts}->{$elt_name} = 1;
+ $opts = $self->{elt_opts}->{$elt_name} = $self->{elt_opts}->{"*DEFAULT"};
+ }
+ return $opts;
+}
+
+
+# Display contents of configuration options to be used to process document.
+# For each element named in the elt_opts structure, display its format
+# type, and those options that apply to the type.
+
+sub display_config
+{
+my $self = shift;
+# Format types and the additional options that apply to each type
+my $format_opts = {
+ "block" => [
+ "entry-break",
+ "element-break",
+ "exit-break",
+ "subindent",
+ "normalize",
+ "wrap-length"
+ ],
+ "inline" => [ ],
+ "verbatim" => [ ]
+};
+
+ foreach my $elt_name (sort (keys (%{$self->{elt_opts}})))
+ {
+ print "$elt_name\n";
+ my %opts = %{$self->{elt_opts}->{$elt_name}};
+ my $format = $opts{format};
+ # Write out format type, then options that apply to the format type
+ print " format = $format\n";
+ foreach my $opt_name (@{$format_opts->{$format}})
+ {
+ print " $opt_name = $opts{$opt_name}\n";
+ }
+ print "\n";
+ }
+}
+
+
+# Display the list of elements that are used in the document but not
+# configured in the configuration file.
+
+# Then re-unconfigure the elements so that they won't be considered
+# as configured for the next document, if there is one.
+
+sub display_unconfigured_elements
+{
+my $self = shift;
+
+ my @elts = keys (%{$self->{unconf_elts}});
+ if (@elts == 0)
+ {
+ print "The document contains no unconfigured elements.\n";
+ }
+ else
+ {
+ print "The following document elements were assigned no formatting options:\n";
+ foreach my $line ($self->line_wrap ([ join (" ", sort (@elts)) ], 0, 0, 65))
+ {
+ print "$line\n";
+ }
+ }
+
+ foreach my $elt_name (@elts)
+ {
+ delete ($self->{elt_opts}->{$elt_name});
+ }
+}
+
+# ----------------------------------------------------------------------
+
+# Main document processing routine.
+# - Argument is a string representing an input document
+# - Return value is the reformatted document, or undef. An undef return
+# signifies either that an error occurred, or that some option was
+# given that suppresses document output. In either case, don't write
+# any output for the document. Any error messages will already have
+# been printed when this returns.
+
+sub process_doc
+{
+my $self = shift;
+my ($doc, $verbose, $check_parser, $canonize_only, $show_unconf_elts) = @_;
+my $str;
+
+ $self->init_doc_vars ();
+
+ # Perform lexical parse to split document into list of tokens
+ warn "Parsing document...\n" if $verbose;
+ $self->shallow_parse ($doc);
+
+ if ($check_parser)
+ {
+ warn "Checking parser...\n" if $verbose;
+ # concatentation of tokens should be identical to original document
+ if ($doc eq join ("", @{$self->tokens ()}))
+ {
+ print "Parser is okay\n";
+ }
+ else
+ {
+ print "PARSER ERROR: document token concatenation differs from document\n";
+ }
+ return undef;
+ }
+
+ # Assign input line number to each token
+ $self->assign_line_numbers ();
+
+ # Look for and report any error tokens returned by parser
+ warn "Checking document for errors...\n" if $verbose;
+ if ($self->report_errors () > 0)
+ {
+ warn "Cannot continue processing document.\n";
+ return undef;
+ }
+
+ # Convert the token list to a tree structure
+ warn "Converting document tokens to tree...\n" if $verbose;
+ if ($self->tokens_to_tree () > 0)
+ {
+ warn "Cannot continue processing document.\n";
+ return undef;
+ }
+
+ # Check: Stringify the tree to convert it back to a single string,
+ # then compare to original document string (should be identical)
+ # (This is an integrity check on the validity of the to-tree and stringify
+ # operations; if one or both do not work properly, a mismatch should occur.)
+ #$str = $self->tree_stringify ();
+ #print $str;
+ #warn "ERROR: mismatch between document and resulting string\n" if $doc ne $str;
+
+ # Canonize tree to remove extraneous whitespace
+ warn "Canonizing document tree...\n" if $verbose;
+ $self->tree_canonize ();
+
+ if ($canonize_only)
+ {
+ print $self->tree_stringify () . "\n";
+ return undef;
+ }
+
+ # One side-effect of canonizing the tree is that the formatting
+ # options are looked up for each element in the document. That
+ # causes the list of elements that have no explicit configuration
+ # to be built. Display the list and return if user requested it.
+
+ if ($show_unconf_elts)
+ {
+ $self->display_unconfigured_elements ();
+ return undef;
+ }
+
+ # Format the tree to produce formatted XML as a single string
+ warn "Formatting document tree...\n" if $verbose;
+ $self->tree_format ();
+
+ # If the document is not empty, add a newline and emit a warning if
+ # reformatting failed to add a trailing newline. This shouldn't
+ # happen if the *DOCUMENT options are set up with exit-break = 1,
+ # which is the reason for the warning rather than just silently
+ # adding the newline.
+
+ $str = $self->out_doc ();
+ if ($str ne "" && $str !~ /\n$/)
+ {
+ warn "LOGIC ERROR: trailing newline had to be added\n";
+ $str .= "\n";
+ }
+
+ return $str;
+}
+
+# ----------------------------------------------------------------------
+
+# Parse XML document into array of tokens and store array
+
+sub shallow_parse
+{
+my ($self, $xml_document) = @_;
+
+ $self->{tokens} = [ $xml_document =~ /$XML_SPE/g ];
+}
+
+# ----------------------------------------------------------------------
+
+# Extract a tag name from a tag and return it.
+
+# Dies if the tag cannot be found, because this is supposed to be
+# called only with a legal tag.
+
+sub extract_tag_name
+{
+my $tag = shift;
+
+ die "Cannot find tag name in tag: $tag\n" unless $tag =~ /^<\/?($Name)/;
+ return $1;
+}
+
+# ----------------------------------------------------------------------
+
+# Assign an input line number to each token. The number indicates
+# the line number on which the token begins.
+
+sub assign_line_numbers
+{
+my $self = shift;
+my $line_num = 1;
+
+ $self->{line_num} = [ ];
+ for (my $i = 0; $i < @{$self->{tokens}}; $i++)
+ {
+ my $token = $self->{tokens}->[$i];
+ push (@{$self->{line_num}}, $line_num);
+ # count newlines and increment line counter (tr returns no. of matches)
+ $line_num += ($token =~ tr/\n/\n/);
+ }
+}
+
+# ----------------------------------------------------------------------
+
+# Check token list for errors and report any that are found. Error
+# tokens are those that begin with "<" but do not end with ">".
+
+# Returns the error count.
+
+# Does not modify the original token list.
+
+sub report_errors
+{
+my $self = shift;
+my $err_count = 0;
+
+ for (my $i = 0; $i < @{$self->{tokens}}; $i++)
+ {
+ my $token = $self->{tokens}->[$i];
+ if ($token =~ /^</ && $token !~ />$/)
+ {
+ my $line_num = $self->{line_num}->[$i];
+ warn "Malformed token at line $line_num, token " . ($i+1) . ": $token\n";
+ ++$err_count;
+ }
+ }
+ warn "Number of errors found: $err_count\n" if $err_count > 0;
+ return $err_count;
+}
+
+# ----------------------------------------------------------------------
+
+# Helper routine to print tag stack for tokens_to_tree
+
+sub print_tag_stack
+{
+my ($label, @stack) = @_;
+ if (@stack < 1)
+ {
+ warn " $label: none\n";
+ }
+ else
+ {
+ warn " $label:\n";
+ for (my $i = 0; $i < @stack; $i++)
+ {
+ warn " ", ($i+1), ": ", $stack[$i], "\n";
+ }
+ }
+}
+
+# Convert the list of XML document tokens to a tree representation.
+# The implementation uses a loop and a stack rather than recursion.
+
+# Does not modify the original token list.
+
+# Returns an error count.
+
+sub tokens_to_tree
+{
+my $self = shift;
+
+ my @tag_stack = (); # stack for element tags
+ my @children_stack = (); # stack for lists of children
+ my $children = [ ]; # current list of children
+ my $err_count = 0;
+
+ for (my $i = 0; $i < @{$self->{tokens}}; $i++)
+ {
+ my $token = $self->{tokens}->[$i];
+ my $line_num = $self->{line_num}->[$i];
+ my $tok_err = "Error near line $line_num, token " . ($i+1) . " ($token)";
+ if ($token !~ /^</) # text
+ {
+ push (@{$children}, text_node ($token));
+ }
+ elsif ($token =~ /^<!--/) # comment
+ {
+ push (@{$children}, comment_node ($token));
+ }
+ elsif ($token =~ /^<\?/) # processing instruction
+ {
+ push (@{$children}, pi_node ($token));
+ }
+ elsif ($token =~ /^<!DOCTYPE/) # DOCTYPE
+ {
+ push (@{$children}, doctype_node ($token));
+ }
+ elsif ($token =~ /^<!\[/) # CDATA
+ {
+ push (@{$children}, cdata_node ($token));
+ }
+ elsif ($token =~ /^<\//) # element close tag
+ {
+ if (!@tag_stack)
+ {
+ warn "$tok_err: Close tag w/o preceding open tag; malformed document?\n";
+ ++$err_count;
+ next;
+ }
+ if (!@children_stack)
+ {
+ warn "$tok_err: Empty children stack; malformed document?\n";
+ ++$err_count;
+ next;
+ }
+ my $tag = pop (@tag_stack);
+ my $open_tag_name = extract_tag_name ($tag);
+ my $close_tag_name = extract_tag_name ($token);
+ if ($open_tag_name ne $close_tag_name)
+ {
+ warn "$tok_err: Tag mismatch; malformed document?\n";
+ warn " open tag: $tag\n";
+ warn " close tag: $token\n";
+ print_tag_stack ("enclosing tags", @tag_stack);
+ ++$err_count;
+ next;
+ }
+ my $elt = element_node ($tag, $token, $children);
+ $children = pop (@children_stack);
+ push (@{$children}, $elt);
+ }
+ else # element open tag
+ {
+ # If we reach here, we're seeing the open tag for an element:
+ # - If the tag is also the close tag (e.g., <abc/>), close the
+ # element immediately, giving it an empty child list.
+ # - Otherwise, push tag and child list on stacks, begin new child
+ # list for element body.
+ if ($token =~ /\/>$/) # tag is of form <abc/>
+ {
+ push (@{$children}, element_node ($token, "", [ ]));
+ }
+ else # tag is of form <abc>
+ {
+ push (@tag_stack, $token);
+ push (@children_stack, $children);
+ $children = [ ];
+ }
+ }
+ }
+
+ # At this point, the stacks should be empty if the document is
+ # well-formed.
+
+ if (@tag_stack)
+ {
+ warn "Error at EOF: Unclosed tags; malformed document?\n";
+ print_tag_stack ("unclosed tags", @tag_stack);
+ ++$err_count;
+ }
+ if (@children_stack)
+ {
+ warn "Error at EOF: Unprocessed child elements; malformed document?\n";
+# TODO: print out info about them
+ ++$err_count;
+ }
+
+ $self->{tree} = $children;
+ return $err_count;
+}
+
+
+# Node-generating helper methods for tokens_to_tree
+
+# Generic node generator
+
+sub node { return { "type" => $_[0], "content" => $_[1] }; }
+
+# Generators for specific non-element nodes
+
+sub text_node { return node ("text", $_[0]); }
+sub comment_node { return node ("comment", $_[0]); }
+sub pi_node { return node ("pi", $_[0]); }
+sub doctype_node { return node ("DOCTYPE", $_[0]); }
+sub cdata_node { return node ("CDATA", $_[0]); }
+
+# For an element node, create a standard node with the type and content
+# key/value pairs. Then add pairs for the "name", "open_tag", and
+# "close_tag" hash keys.
+
+sub element_node
+{
+my ($open_tag, $close_tag, $children) = @_;
+
+ my $elt = node ("elt", $children);
+ # name is the open tag with angle brackets and attibutes stripped
+ $elt->{name} = extract_tag_name ($open_tag);
+ $elt->{open_tag} = $open_tag;
+ $elt->{close_tag} = $close_tag;
+ return $elt;
+}
+
+# ----------------------------------------------------------------------
+
+# Convert the given XML document tree (or subtree) to string form by
+# concatentating all of its components. Argument is a reference
+# to a list of nodes at a given level of the tree.
+
+# Does not modify the node list.
+
+sub tree_stringify
+{
+my $self = shift;
+my $children = shift || $self->{tree}; # use entire tree if no arg;
+my $str = "";
+
+ for (my $i = 0; $i < @{$children}; $i++)
+ {
+ my $child = $children->[$i];
+
+ # - Elements have list of child nodes as content (process recursively)
+ # - All other node types have text content
+
+ if ($child->{type} eq "elt")
+ {
+ $str .= $child->{open_tag}
+ . $self->tree_stringify ($child->{content})
+ . $child->{close_tag};
+ }
+ else
+ {
+ $str .= $child->{content};
+ }
+ }
+ return $str;
+}
+
+# ----------------------------------------------------------------------
+
+
+# Put tree in "canonical" form by eliminating extraneous whitespace
+# from element text content.
+
+# $children is a list of child nodes
+
+# This function modifies the node list.
+
+# Canonizing occurs as follows:
+# - Comment, PI, DOCTYPE, and CDATA nodes remain untouched
+# - Verbatim elements and their descendants remain untouched
+# - Within non-normalized block elements:
+# - Delete all-whitespace text node children
+# - Leave other text node children untouched
+# - Within normalized block elements:
+# - Convert runs of whitespace (including line-endings) to single spaces
+# - Trim leading whitespace of first text node
+# - Trim trailing whitespace of last text node
+# - Trim whitespace that is adjacent to a verbatim or non-normalized
+# sub-element. (For example, if a <programlisting> is followed by
+# more text, delete any whitespace at beginning of that text.)
+# - Within inline elements:
+# - Normalize the same way as the enclosing block element, with the
+# exception that a space at the beginning or end is not removed.
+# (Otherwise, <para>three<literal> blind </literal>mice</para>
+# would become <para>three<literal>blind</literal>mice</para>.)
+
+sub tree_canonize
+{
+my $self = shift;
+
+ $self->{tree} = $self->tree_canonize2 ($self->{tree}, "*DOCUMENT");
+}
+
+
+sub tree_canonize2
+{
+my $self = shift;
+my $children = shift;
+my $par_name = shift;
+
+ # Formatting options for parent
+ my $par_opts = $self->get_opts ($par_name);
+
+ # If parent is a block element, remember its formatting options on
+ # the block stack so they can be used to control canonization of
+ # inline child elements.
+
+ $self->begin_block ($par_name, $par_opts) if $par_opts->{format} eq "block";
+
+ # Iterate through list of child nodes to preserve, modify, or
+ # discard whitespace. Return resulting list of children.
+
+ # Canonize element and text nodes. Leave everything else (comments,
+ # processing instructions, etc.) untouched.
+
+ my @new_children = ();
+
+ while (@{$children})
+ {
+ my $child = shift (@{$children});
+
+ if ($child->{type} eq "elt")
+ {
+ # Leave verbatim elements untouched. For other element nodes,
+ # canonize child list using options appropriate to element.
+
+ if ($self->get_opts ($child->{name})->{format} ne "verbatim")
+ {
+ $child->{content} = $self->tree_canonize2 ($child->{content},
+ $child->{name});
+ }
+ }
+ elsif ($child->{type} eq "text")
+ {
+ # Delete all-whitespace node or strip whitespace as appropriate.
+
+ # Paranoia check: We should never get here for verbatim elements,
+ # because normalization is irrelevant for them.
+
+ die "LOGIC ERROR: trying to canonize verbatim element $par_name!\n"
+ if $par_opts->{format} eq "verbatim";
+
+ if (!$self->block_normalize ())
+ {
+ # Enclosing block is not normalized:
+ # - Delete child all-whitespace text nodes.
+ # - Leave other text nodes untouched.
+
+ next if $child->{content} =~ /^\s*$/;
+ }
+ else
+ {
+ # Enclosing block is normalized, so normalize this text node:
+ # - Convert runs of whitespace characters (including
+ # line-endings characters) to single spaces.
+ # - Trim leading whitespace if this node is the first child
+ # of a block element or it follows a non-normalized node.
+ # - Trim leading whitespace if this node is the last child
+ # of a block element or it precedes a non-normalized node.
+
+ # These are nil if there is no prev or next child
+ my $prev_child = $new_children[$#new_children];
+ my $next_child = $children->[0];
+
+ $child->{content} =~ s/\s+/ /g;
+ $child->{content} =~ s/^ //
+ if (!defined ($prev_child) && $par_opts->{format} eq "block")
+ || $self->non_normalized_node ($prev_child);
+ $child->{content} =~ s/ $//
+ if (!defined ($next_child) && $par_opts->{format} eq "block")
+ || $self->non_normalized_node ($next_child);
+
+ # If resulting text is empty, discard the node.
+ next if $child->{content} =~ /^$/;
+ }
+ }
+ push (@new_children, $child);
+ }
+
+ # Pop block stack if parent was a block element
+ $self->end_block () if $par_opts->{format} eq "block";
+
+ return \@new_children;
+}
+
+
+# Helper function for tree_canonize().
+
+# Determine whether a node is normalized. This is used to check
+# the node that is adjacent to a given text node (either previous
+# or following).
+# - No is node is nil
+# - No if the node is a verbatim element
+# - If the node is a block element, yes or no according to its
+# normalize option
+# - No if the node is an inline element. Inlines are normalized
+# if the parent block is normalized, but this method is not called
+# except while examinine normalized blocks. So its inline children
+# are also normalized.
+# - No if node is a comment, PI, DOCTYPE, or CDATA section. These are
+# treated like verbatim elements.
+
+sub non_normalized_node
+{
+my $self = shift;
+my $node = shift;
+
+ return 0 if !$node;
+ my $type = $node->{type};
+ if ($type eq "elt")
+ {
+ my $node_opts = $self->get_opts ($node->{name});
+ if ($node_opts->{format} eq "verbatim")
+ {
+ return 1;
+ }
+ if ($node_opts->{format} eq "block")
+ {
+ return $node_opts->{normalize} eq "no";
+ }
+ if ($node_opts->{format} eq "inline")
+ {
+ return 0;
+ }
+ die "LOGIC ERROR: non_normalized_node: unhandled node format.\n";
+ }
+ if ($type eq "comment" || $type eq "pi" || $type eq "DOCTYPE"
+ || $type eq "CDATA")
+ {
+ return 1;
+ }
+ if ($type eq "text")
+ {
+ die "LOGIC ERROR: non_normalized_node: got called for text node.\n";
+ }
+ die "LOGIC ERROR: non_normalized_node: unhandled node type.\n";
+}
+
+# ----------------------------------------------------------------------
+
+# Format (pretty-print) the document tree
+
+# Does not modify the node list.
+
+# The class maintains two variables for storing output:
+# - out_doc stores content that has been seen and "flushed".
+# - pending stores an array of strings (content of text nodes and inline
+# element tags). These are held until they need to be flushed, at
+# which point they are concatenated and possibly wrapped/indented.
+# Flushing occurs when a break needs to be written, which happens
+# when something other than a text node or inline element is seen.
+
+# If parent name and children are not given, format the entire document.
+# Assume prevailing indent = 0 if not given.
+
+sub tree_format
+{
+my $self = shift;
+my $par_name = shift || "*DOCUMENT"; # format entire document if no arg
+my $children = shift || $self->{tree}; # use entire tree if no arg
+my $indent = shift || 0;
+
+ # Formatting options for parent element
+ my $par_opts = $self->get_opts ($par_name);
+
+ # If parent is a block element:
+ # - Remember its formatting options on the block stack so they can
+ # be used to control formatting of inline child elements.
+ # - Set initial break type to entry-break.
+ # - Shift prevailing indent right before generating child content.
+
+ if ($par_opts->{format} eq "block")
+ {
+ $self->begin_block ($par_name, $par_opts);
+ $self->set_block_break_type ("entry-break");
+ $indent += $par_opts->{"subindent"};
+ }
+
+ # Variables for keeping track of whether the previous child
+ # was a text node. Used for controlling break behavior in
+ # non-normalized block elements: No line breaks are added around
+ # text in such elements, nor is indenting added.
+
+ my $prev_child_is_text = 0;
+ my $cur_child_is_text = 0;
+
+ foreach my $child (@{$children})
+ {
+ $prev_child_is_text = $cur_child_is_text;
+
+ # Text nodes: just add text to pending output
+
+ if ($child->{type} eq "text")
+ {
+ $cur_child_is_text = 1;
+ $self->add_to_pending ($child->{content});
+ next;
+ }
+
+ $cur_child_is_text = 0;
+
+ # Element nodes: handle depending on format type
+
+ if ($child->{type} eq "elt")
+ {
+ my $child_opts = $self->get_opts ($child->{name});
+
+ # Verbatim elements:
+ # - Print literally without change (use _stringify).
+ # - Do not line-wrap or add any indent.
+
+ if ($child_opts->{format} eq "verbatim")
+ {
+ $self->flush_pending ($indent);
+ $self->emit_break (0)
+ unless $prev_child_is_text && !$self->block_normalize ();
+ $self->set_block_break_type ("element-break");
+ $self->add_to_doc ($child->{open_tag}
+ . $self->tree_stringify ($child->{content})
+ . $child->{close_tag});
+ next;
+ }
+
+ # Inline elements:
+ # - Do not break or indent.
+ # - Do not line-wrap content; just add content to pending output
+ # and let it be wrapped as part of parent's content.
+
+ if ($child_opts->{format} eq "inline")
+ {
+ $self->add_to_pending ($child->{open_tag});
+ $self->tree_format ($child->{name}, $child->{content}, $indent);
+ $self->add_to_pending ($child->{close_tag});
+ next;
+ }
+
+ # If we get here, node is a block element.
+
+ # - Break and flush any pending output
+ # - Break and indent (no indent if break count is zero)
+ # - Process element itself:
+ # - Put out opening tag
+ # - Put out element content
+ # - Put out any indent needed before closing tag. None needed if:
+ # - Element's exit-break is 0 (closing tag is not on new line,
+ # so don't indent it)
+ # - There is no separate closing tag (it was in <abc/> format)
+ # - Element has no children (tags will be written as
+ # <abc></abc>, so don't indent closing tag)
+ # - Element has children, but the block is not normalized and
+ # the last child is a text node
+ # - Put out closing tag
+
+ $self->flush_pending ($indent);
+ $self->emit_break ($indent)
+ unless $prev_child_is_text && !$self->block_normalize ();
+ $self->set_block_break_type ("element-break");
+ $self->add_to_doc ($child->{open_tag});
+ $self->tree_format ($child->{name}, $child->{content}, $indent);
+ $self->add_to_doc (" " x $indent)
+ unless $child_opts->{"exit-break"} <= 0
+ || $child->{close_tag} eq ""
+ || !@{$child->{content}}
+ || (@{$child->{content}}
+ && $child->{content}->[$#{$child->{content}}]->{type} eq "text"
+ && $child_opts->{normalize} eq "no");
+ $self->add_to_doc ($child->{close_tag});
+ next;
+ }
+
+ # Comments, PIs, etc. (everything other than text and elements),
+ # treat similarly to verbatim block:
+ # - Flush any pending output
+ # - Put out a break
+ # - Add node content to collected output
+
+ $self->flush_pending ($indent);
+ $self->emit_break (0)
+ unless $prev_child_is_text && !$self->block_normalize ();
+ $self->set_block_break_type ("element-break");
+ $self->add_to_doc ($child->{content});
+ }
+
+ $prev_child_is_text = $cur_child_is_text;
+
+ # Done processing current element's children now.
+
+ # If current element is a block element:
+ # - If there were any children, flush any pending output and put
+ # out the exit break.
+ # - Pop the block stack
+
+ if ($par_opts->{format} eq "block")
+ {
+ if (@{$children})
+ {
+ $self->flush_pending ($indent);
+ $self->set_block_break_type ("exit-break");
+ $self->emit_break (0)
+ unless $prev_child_is_text && !$self->block_normalize ();
+ }
+ $self->end_block ();
+ }
+}
+
+
+# Emit a break - the appropriate number of newlines according to the
+# enclosing block's current break type.
+
+# In addition, emit the number of spaces indicated by indent. (indent
+# > 0 when breaking just before emitting an element tag that should
+# be indented within its parent element.)
+
+# Exception: Emit no indent if break count is zero. That indicates
+# any following output will be written on the same output line, not
+# indented on a new line.
+
+# Initially, when processing a node's child list, the break type is
+# set to entry-break. Each subsequent break is an element-break.
+# (After child list has been processed, an exit-break is produced as well.)
+
+sub emit_break
+{
+my ($self, $indent) = @_;
+
+ # number of newlines to emit
+ my $break_value = $self->block_break_value ();
+
+ $self->add_to_doc ("\n" x $break_value);
+ # add indent if there *was* a break
+ $self->add_to_doc (" " x $indent) if $indent > 0 && $break_value > 0;
+}
+
+
+# Flush pending output to output document collected thus far:
+# - Wrap pending contents as necessary, with indent before *each* line.
+# - Add pending text to output document (thus "flushing" it)
+# - Clear pending array.
+
+sub flush_pending
+{
+my ($self, $indent) = @_;
+
+ # Do nothing if nothing to flush
+ return if !@{$self->{pending}};
+
+ # If current block is not normalized:
+ # - Text nodes cannot be modified (no wrapping or indent). Flush
+ # text as is without adding a break or indent.
+ # If current block is normalized:
+ # - Add a break.
+ # - If line wrap is disabled:
+ # - Add indent if there is a break. (If there isn't a break, text
+ # should immediately follow preceding tag, so don't add indent.)
+ # - Add text without wrapping
+ # - If line wrap is enabled:
+ # - First line indent is 0 if there is no break. (Text immediately
+ # follows preceding tag.) Otherwise first line indent is same as
+ # prevailing indent.
+ # - Any subsequent lines get the prevailing indent.
+
+ # After flushing text, advance break type to element-break.
+
+ my $s = "";
+
+ if (!$self->block_normalize ())
+ {
+ $s .= join ("", @{$self->{pending}});
+ }
+ else
+ {
+ $self->emit_break (0);
+ my $wrap_len = $self->block_wrap_length ();
+ my $break_value = $self->block_break_value ();
+ if ($wrap_len <= 0)
+ {
+ $s .= " " x $indent if $break_value > 0;
+ $s .= join ("", @{$self->{pending}});
+ }
+ else
+ {
+ my $first_indent = ($break_value > 0 ? $indent : 0);
+ # Wrap lines, then join by newlines (don't add one at end)
+ my @lines = $self->line_wrap ($self->{pending},
+ $first_indent,
+ $indent,
+ $wrap_len);
+ $s .= join ("\n", @lines);
+ }
+ }
+
+ $self->add_to_doc ($s);
+ $self->{pending} = [ ];
+ $self->set_block_break_type ("element-break");
+}
+
+
+# Perform line-wrapping of string array to lines no longer than given
+# length (including indent).
+# Any word longer than line length appears by itself on line.
+# Return array of lines (not newline-terminated).
+
+# $strs - reference to array of text items to be joined and line-wrapped.
+# Each item may be:
+# - A tag (such as <emphasis role="bold">). This should be treated as
+# an atomic unit, which is important for preserving inline tags intact.
+# - A possibly multi-word string (such as "This is a string"). In this
+# latter case, line-wrapping preserves internal whitespace in the
+# string, with the exception that if whitespace would be placed at
+# the end of a line, it is discarded.
+
+# $first_indent - indent for first line
+# $rest_indent - indent for any remaining lines
+# $max_len - maximum length of output lines (including indent)
+
+sub line_wrap
+{
+my ($self, $strs, $first_indent, $rest_indent, $max_len) = @_;
+
+ # First, tokenize the strings
+
+ my @words = ();
+ foreach my $str (@{$strs})
+ {
+ if ($str =~ /^</)
+ {
+ # String is a tag; treat as atomic unit and don't split
+ push (@words, $str);
+ }
+ else
+ {
+ # String of white and non-white tokens.
+ # Tokenize into white and non-white tokens.
+ push (@words, ($str =~ /\S+|\s+/g));
+ }
+ }
+
+ # Now merge tokens that are not separated by whitespace tokens. For
+ # example, "<i>", "word", "</i>" gets merged to "<i>word</i>". But
+ # "<i>", " ", "word", " ", "</i>" gets left as separate tokens.
+
+ my @words2 = ();
+ foreach my $word (@words)
+ {
+ # If there is a previous word that does not end with whitespace,
+ # and the currrent word does not begin with whitespace, concatenate
+ # current word to previous word. Otherwise append current word to
+ # end of list of words.
+ if (@words2 && $words2[$#words2] !~ /\s$/ && $word !~ /^\s/)
+ {
+ $words2[$#words2] .= $word;
+ }
+ else
+ {
+ push (@words2, $word);
+ }
+ }
+
+ my @lines = ();
+ my $line = "";
+ my $llen = 0;
+ # set the indent for the first line
+ my $indent = $first_indent;
+ # saved-up whitespace to put before next non-white word
+ my $white = "";
+
+ foreach my $word (@words2) # ... while words remain to wrap
+ {
+ # If word is whitespace, save it. It gets added before next
+ # word if no line-break occurs.
+ if ($word =~ /^\s/)
+ {
+ $white .= $word;
+ next;
+ }
+ my $wlen = length ($word);
+ if ($llen == 0)
+ {
+ # New output line; it gets at least one word (discard any
+ # saved whitespace)
+ $line = " " x $indent . $word;
+ $llen = $indent + $wlen;
+ $indent = $rest_indent;
+ $white = "";
+ next;
+ }
+ if ($llen + length ($white) + $wlen > $max_len)
+ {
+ # Word (plus saved whitespace) won't fit on current line.
+ # Begin new line (discard any saved whitespace).
+ push (@lines, $line);
+ $line = " " x $indent . $word;
+ $llen = $indent + $wlen;
+ $indent = $rest_indent;
+ $white = "";
+ next;
+ }
+ # add word to current line with saved whitespace between
+ $line .= $white . $word;
+ $llen += length ($white) + $wlen;
+ $white = "";
+ }
+
+ # push remaining line, if any
+ push (@lines, $line) if $line ne "";
+
+ return @lines;
+}
+
+1;
+
+# ----------------------------------------------------------------------
+
+# Begin main program
+
+package main;
+
+
+my $usage = <<EOF;
+Usage: $PROG_NAME [options] xml-file
+
+Options:
+--help, -h
+ Print this message and exit.
+--backup suffix -b suffix
+ Back up the input document, adding suffix to the input
+ filename to create the backup filename.
+--canonized-output
+ Proceed only as far as the document canonization stage,
+ printing the result.
+--check-parser
+ Parse the document into tokens and verify that their
+ concatenation is identical to the original input document.
+ This option suppresses further document processing.
+--config-file file_name, -f file_name
+ Specify the configuration filename. If no file is named,
+ xmlformat uses the file named by the environment variable
+ XMLFORMAT_CONF, if it exists, or ./xmlformat.conf, if it
+ exists. Otherwise, xmlformat uses built-in formatting
+ options.
+--in-place, -i
+ Format the document in place, replacing the contents of
+ the input file with the reformatted document. (It's a
+ good idea to use --backup along with this option.)
+--show-config
+ Show configuration options after reading configuration
+ file. This option suppresses document processing.
+--show-unconfigured-elements
+ Show elements that are used in the document but for
+ which no options were specified in the configuration
+ file. This option suppresses document output.
+--verbose, -v
+ Be verbose about processing stages.
+--version, -V
+ Show version information and exit.
+EOF
+
+# Variables for command line options; most are undefined initially.
+my $help;
+my $backup_suffix;
+my $conf_file;
+my $canonize_only;
+my $check_parser;
+my $in_place;
+my $show_conf;
+my $show_unconf_elts;
+my $show_version;
+my $verbose;
+
+GetOptions (
+ # =i means an integer argument is required after the option
+ # =s means a string argument is required after the option
+ # :s means a string argument is optional after the option
+ "help|h" => \$help, # print help message
+ "backup|b=s" => \$backup_suffix, # make backup using suffix
+ "canonized-output" => \$canonize_only, # print canonized document
+ "check-parser" => \$check_parser, # verify parser integrity
+ "config-file|f=s" => \$conf_file, # config file
+ "in-place|i" => \$in_place, # format in place
+ "show-config" => \$show_conf, # show configuration file
+ # need better name
+ "show-unconfigured-elements" => \$show_unconf_elts, # show unconfigured elements
+ "verbose|v" => \$verbose, # be verbose
+ "version|V" => \$show_version, # show version info
+) or do { print "$usage\n"; exit (1); };
+
+if (defined ($help))
+{
+ print "$usage\n";
+ exit (0);
+}
+
+if (defined ($show_version))
+{
+ print "$PROG_NAME $PROG_VERSION ($PROG_LANG version)\n";
+ exit (0);
+}
+
+# --in-place option requires a named file
+
+warn "WARNING: --in-place/-i option ignored (requires named input files)\n"
+ if defined ($in_place) && @ARGV == 0;
+
+# --backup/-b is meaningless without --in-place
+
+if (defined ($backup_suffix))
+{
+ if (!defined ($in_place))
+ {
+ die "--backup/-b option meaningless without --in-place/-i option\n";
+ }
+}
+
+# Save input filenames
+my @in_file = @ARGV;
+
+my $xf = XMLFormat->new ();
+
+# If a configuration file was named explicitly, use it. An error occurs
+# if the file does not exist.
+
+# If no configuration file was named, fall back to:
+# - The file named by the environment variable XMLFORMAT_CONF, if it exists
+# - ./xmlformat.conf, if it exists
+
+# If no configuration file can be found at all, the built-in default options
+# are used. (These are set up in new().)
+
+my $env_conf_file = $ENV{XMLFORMAT_CONF};
+my $def_conf_file = "./xmlformat.conf";
+
+# If no config file was named, but XMLFORMAT_CONF is set, use its value
+# as the config file name.
+if (!defined ($conf_file))
+{
+ $conf_file = $env_conf_file if defined ($env_conf_file);
+}
+# If config file still isn't defined, use the default file if it exists.
+if (!defined ($conf_file))
+{
+ if (-r $def_conf_file && ! -d $def_conf_file)
+ {
+ $conf_file = $def_conf_file;
+ }
+}
+if (defined ($conf_file))
+{
+ warn "Reading configuration file...\n" if $verbose;
+ die "Configuration file '$conf_file' is not readable.\n" if ! -r $conf_file;
+ die "Configuration file '$conf_file' is a directory.\n" if -d $conf_file;
+ $xf->read_config ($conf_file)
+}
+
+if ($show_conf) # show configuration and exit
+{
+ $xf->display_config ();
+ exit(0);
+}
+
+my ($in_doc, $out_doc);
+
+# Process arguments.
+# - If no files named, read string, write to stdout.
+# - If files named, read and process each one. Write output to stdout
+# unless --in-place option was given. Make backup of original file
+# if --backup option was given.
+
+if (@ARGV == 0)
+{
+ warn "Reading document...\n" if $verbose;
+ {
+ local $/ = undef;
+ $in_doc = <>; # slurp input document as single string
+ }
+
+ $out_doc = $xf->process_doc ($in_doc,
+ $verbose, $check_parser, $canonize_only, $show_unconf_elts);
+ if (defined ($out_doc))
+ {
+ warn "Writing output document...\n" if $verbose;
+ print $out_doc;
+ }
+}
+else
+{
+ foreach my $file (@ARGV)
+ {
+ warn "Reading document $file...\n" if $verbose;
+ open (IN, $file)
+ or die "Cannot read $file: $!\n";
+ {
+ local $/ = undef;
+ $in_doc = <IN>; # slurp input document as single string
+ }
+ close (IN);
+ $out_doc = $xf->process_doc ($in_doc,
+ $verbose, $check_parser, $canonize_only, $show_unconf_elts);
+ next unless defined ($out_doc);
+ if (defined ($in_place))
+ {
+ if (defined ($backup_suffix))
+ {
+ warn "Making backup of $file to $file$backup_suffix...\n" if $verbose;
+ rename ($file, $file . $backup_suffix)
+ or die "Could not rename $file to $file$backup_suffix: $!\n";
+ }
+ warn "Writing output document to $file...\n" if $verbose;
+ open (OUT, ">$file") or die "Cannot write to $file: $!\n";
+ print OUT $out_doc;
+ close (OUT);
+ }
+ else
+ {
+ warn "Writing output document...\n" if $verbose;
+ print $out_doc;
+ }
+ }
+}
+
+warn "Done!\n" if $verbose;
+
+exit (0);
diff --git a/manual/xsl/html.xsl b/manual/xsl/html.xsl
new file mode 100644
index 0000000000..f8ddf14e34
--- /dev/null
+++ b/manual/xsl/html.xsl
@@ -0,0 +1,158 @@
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:exsl="http://exslt.org/common"
+ version="1.0"
+ exclude-result-prefixes="exsl">
+
+<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets/xhtml/docbook.xsl"/>
+<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets/xhtml/chunk-common.xsl"/>
+<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets/xhtml/chunk-code.xsl"/>
+<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets/xhtml/manifest.xsl"/>
+
+<xsl:param name="html.stylesheet" select="'ardour_manual.css'"/>
+<xsl:param name="html.stylesheet.type" select="'text/css'"/>
+<xsl:param name="html.cleanup" select="1"/>
+<xsl:param name="html.ext" select="'.html'"/>
+<xsl:output method="html" indent="yes"/>
+
+<!-- Admonition Graphics -->
+<xsl:param name="admon.graphics" select="1"/>
+<xsl:param name="admon.graphics.path">./images/tango-icons/</xsl:param>
+<xsl:param name="callout.graphics.path">./images/tango-icons/</xsl:param>
+
+<!-- Remove table and inline style from admonitions -->
+
+<xsl:template name="graphical.admonition">
+ <xsl:variable name="admon.type">
+ <xsl:choose>
+ <xsl:when test="local-name(.)='note'">Note</xsl:when>
+ <xsl:when test="local-name(.)='warning'">Warning</xsl:when>
+ <xsl:when test="local-name(.)='caution'">Caution</xsl:when>
+ <xsl:when test="local-name(.)='tip'">Tip</xsl:when>
+ <xsl:when test="local-name(.)='important'">Important</xsl:when>
+ <xsl:otherwise>Note</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <div xmlns="http://www.w3.org/1999/xhtml" class="{name(.)}">
+ <xsl:call-template name="anchor"/>
+ <xsl:if test="$admon.textlabel != 0 or title">
+ <h2 class="title">
+ <xsl:apply-templates select="." mode="object.title.markup"/>
+ </h2>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </div>
+</xsl:template>
+
+<!--
+ I'm not using draft mode because with at least the version
+ of the stylesheets I have it inserts inline css. I'm not aware
+ of a non-hacky way around that so until I find a better
+ solution I'm using custom status fields:
+
+ ardour-draft
+
+ ardour-beta?
+ ardour-rc (release candidate)?
+
+-->
+
+<!-- Add css class for status -->
+<xsl:template name="body.attributes">
+ <xsl:if test="(ancestor-or-self::*[@status][1]/@status != '')">
+ <xsl:attribute name="class">
+ <xsl:value-of select="ancestor-or-self::*[@status][1]/@status"/>
+ </xsl:attribute>
+ </xsl:if>
+</xsl:template>
+
+<!-- titles after all elements -->
+<xsl:param name="formal.title.placement">
+figure after
+example after
+equation after
+table after
+procedure before
+</xsl:param>
+
+<!-- This sets the filename based on the ID. -->
+<xsl:param name="use.id.as.filename" select="'1'"/>
+
+<xsl:template match="command">
+ <xsl:call-template name="inline.monoseq"/>
+</xsl:template>
+
+<xsl:template match="application">
+ <xsl:call-template name="inline.boldseq"/>
+</xsl:template>
+
+<xsl:template match="guibutton">
+ <xsl:call-template name="inline.boldseq"/>
+</xsl:template>
+
+<xsl:template match="guiicon">
+ <xsl:call-template name="inline.boldseq"/>
+</xsl:template>
+
+<xsl:template match="guilabel">
+ <xsl:call-template name="inline.boldseq"/>
+</xsl:template>
+
+<xsl:template match="guimenu">
+ <xsl:call-template name="inline.boldseq"/>
+</xsl:template>
+
+<xsl:template match="guimenuitem">
+ <xsl:call-template name="inline.boldseq"/>
+</xsl:template>
+
+<xsl:template match="guisubmenu">
+ <xsl:call-template name="inline.boldseq"/>
+</xsl:template>
+
+<xsl:template match="mousebutton">
+ <xsl:call-template name="inline.boldseq"/>
+</xsl:template>
+
+<xsl:template match="filename">
+ <xsl:call-template name="inline.monoseq"/>
+</xsl:template>
+
+<!-- TOC -->
+<xsl:param name="section.autolabel" select="1"/>
+<xsl:param name="section.label.includes.component.label" select="1"/>
+<xsl:param name="generate.legalnotice.link" select="1"/>
+<xsl:param name="generate.revhistory.link" select="1"/>
+<xsl:param name="generate.toc">
+set toc
+book toc
+article toc
+chapter toc
+qandadiv toc
+qandaset toc
+sect1 nop
+sect2 nop
+sect3 nop
+sect4 nop
+sect5 nop
+section toc
+part toc
+</xsl:param>
+
+<!-- Limit TOC depth to 1 level -->
+<xsl:param name="toc.section.depth">1</xsl:param>
+
+<!--
+<xsl:template name="nongraphical.admonition">
+ <div class="{name(.)}">
+ <h2 class="title">
+ <xsl:call-template name="anchor"/>
+ <xsl:if test="$admon.textlabel != 0 or title">
+ <xsl:apply-templates select="." mode="object.title.markup"/>
+ </xsl:if>
+ </h2>
+ <xsl:apply-templates/>
+ </div>
+</xsl:template>
+-->
+</xsl:stylesheet>
diff --git a/svn_revision.h b/svn_revision.h
index abd97e0565..069c1be36a 100644
--- a/svn_revision.h
+++ b/svn_revision.h
@@ -1,4 +1,4 @@
#ifndef __ardour_svn_revision_h__
#define __ardour_svn_revision_h__
-static const char* ardour_svn_revision = "1345";
+static const char* ardour_svn_revision = "1607";
#endif
diff --git a/templates/2 Track.template.in b/templates/2 Track.template.in
index ffe37e9c83..3d798d77b4 100644
--- a/templates/2 Track.template.in
+++ b/templates/2 Track.template.in
@@ -66,7 +66,7 @@
</extra>
</Route>
<Route muted="no" soloed="no" phase-invert="no" mute-affects-pre-fader="yes" mute-affects-post-fader="yes" mute-affects-control-outs="yes" mute-affects-main-outs="yes" order-keys="editor=2:signal=2" diskstream-id="1088698381722129">
- <IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%2}{%JACK_OUTPUT%1}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1">
+ <IO name="Audio 2" id="1088698381722065" inputs="{%JACK_OUTPUT%1}{%JACK_OUTPUT%2}" outputs="{ardour:master/in 1}{ardour:master/in 2}" gain="1" iolimits="1,-1,-1,-1" automation-state="0x0" automation-style="0x1">
<Panner linked="no" link_direction="0">
<StreamPanner x="0.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/>
<StreamPanner x="1.000000" type="Equal Power Stereo" automation-state="0x0" automation-style="0x1" bypassed="no" muted="no"/>
diff --git a/tools/Spotlight Importer/GetMetadataForFile.c b/tools/Spotlight Importer/GetMetadataForFile.c
index 6b12614172..522b00cb0f 100644
--- a/tools/Spotlight Importer/GetMetadataForFile.c
+++ b/tools/Spotlight Importer/GetMetadataForFile.c
@@ -9,6 +9,7 @@
an array of Uniform Type Identifiers (UTI) for the LSItemContentTypes
that your importer can handle
+ (DONE)
----------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
diff --git a/tools/Spotlight Importer/Info.plist b/tools/Spotlight Importer/Info.plist
index da11c8db5b..13097298e9 100644
--- a/tools/Spotlight Importer/Info.plist
+++ b/tools/Spotlight Importer/Info.plist
@@ -11,13 +11,12 @@
To export this declaration, fill in the fields with your application's
information, and uncomment the block of XML.
-->
-
- <!--
+
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeIdentifier</key>
- <string>org.ardour.yourUTI</string>
+ <string>org.ardour.Ardour.session</string>
<key>UTTypeReferenceURL</key>
<string>http://www.ardour.org</string>
<key>UTTypeDescription</key>
@@ -30,15 +29,14 @@
<key>UTTypeTagSpecification</key>
<dict>
<key>com.apple.ostype</key>
- <string>XXXX</string>
+ <string>ArAs</string>
<key>public.filename-extension</key>
<array>
- <string>xxxx</string>
+ <string>ardour</string>
</array>
</dict>
</dict>
</array>
- -->
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
diff --git a/tools/Spotlight Importer/Spotlight Importer.xcodeproj/project.pbxproj b/tools/Spotlight Importer/Spotlight Importer.xcodeproj/project.pbxproj
index 39ee943965..c2729ee532 100644
--- a/tools/Spotlight Importer/Spotlight Importer.xcodeproj/project.pbxproj
+++ b/tools/Spotlight Importer/Spotlight Importer.xcodeproj/project.pbxproj
@@ -203,6 +203,11 @@
GCC_PRECOMPILE_PREFIX_HEADER = NO;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = /Library/Spotlight;
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.4u.sdk/usr/lib\"";
LIBRARY_STYLE = Bundle;
PRODUCT_NAME = "Spotlight Importer";
WRAPPER_EXTENSION = mdimporter;
@@ -222,6 +227,11 @@
GCC_PRECOMPILE_PREFIX_HEADER = NO;
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = /Library/Spotlight;
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(LIBRARY_SEARCH_PATHS_QUOTED_1)",
+ );
+ LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.4u.sdk/usr/lib\"";
LIBRARY_STYLE = Bundle;
PRODUCT_NAME = "Spotlight Importer";
WRAPPER_EXTENSION = mdimporter;
diff --git a/vst/ardevst b/vst/ardevst
index 093c4b72da..ee27cb3f32 100755
--- a/vst/ardevst
+++ b/vst/ardevst
@@ -1,5 +1,5 @@
#!/bin/sh
export ARDOUR_PATH=../gtk2_ardour/icons:../gtk2_ardour/pixmaps:../gtk2_ardour
-export LD_LIBRARY_PATH=../gtk2_ardour:../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libsndfile:../libs/appleutility:$$LD_LIBRARY_PATH
+export LD_LIBRARY_PATH=../gtk2_ardour:../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libsndfile:../libs/appleutility:$LD_LIBRARY_PATH
export GTK_PATH=$PWD/../libs/clearlooks:~/.ardour2
exec wine ./ardour_vst.exe.so "$@"