Merged with trunk R1612.
authorDavid Robillard <d@drobilla.net>
Sun, 18 Mar 2007 06:07:08 +0000 (06:07 +0000)
committerDavid Robillard <d@drobilla.net>
Sun, 18 Mar 2007 06:07:08 +0000 (06:07 +0000)
git-svn-id: svn://localhost/ardour2/branches/midi@1614 d708f5d6-7413-0410-9779-e7cbd77b26cf

710 files changed:
Makefile
SConstruct
ardour.dox
gtk2_ardour/SConscript
gtk2_ardour/about.cc
gtk2_ardour/about.h
gtk2_ardour/actions.cc
gtk2_ardour/add_route_dialog.cc
gtk2_ardour/analysis_window.cc
gtk2_ardour/ardbg
gtk2_ardour/ardev
gtk2_ardour/ardour.bindings [deleted file]
gtk2_ardour/ardour.bindings.in [new file with mode: 0644]
gtk2_ardour/ardour.colors
gtk2_ardour/ardour.menus
gtk2_ardour/ardour2_ui.rc
gtk2_ardour/ardour_image_compositor_socket.h
gtk2_ardour/ardour_message.cc [deleted file]
gtk2_ardour/ardour_message.h [deleted file]
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui2.cc
gtk2_ardour/ardour_ui_dependents.cc
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/ardour_ui_mixer.cc
gtk2_ardour/ardour_ui_options.cc
gtk2_ardour/audio_clock.cc
gtk2_ardour/audio_clock.h
gtk2_ardour/audio_region_editor.cc
gtk2_ardour/audio_region_editor.h
gtk2_ardour/audio_region_view.cc
gtk2_ardour/audio_region_view.h
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/audio_time_axis.h
gtk2_ardour/automation_gain_line.cc
gtk2_ardour/automation_line.cc
gtk2_ardour/automation_line.h
gtk2_ardour/automation_pan_line.cc
gtk2_ardour/axis_view.cc
gtk2_ardour/axis_view.h
gtk2_ardour/canvas-imageframe.h
gtk2_ardour/canvas-simplerect.c
gtk2_ardour/canvas-waveview.c
gtk2_ardour/colors.h
gtk2_ardour/connection_editor.cc
gtk2_ardour/connection_editor.h
gtk2_ardour/crossfade_edit.cc
gtk2_ardour/crossfade_edit.h
gtk2_ardour/crossfade_view.cc
gtk2_ardour/crossfade_view.h
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_audiotrack.cc
gtk2_ardour/editor_canvas.cc
gtk2_ardour/editor_canvas_events.cc
gtk2_ardour/editor_cursors.cc
gtk2_ardour/editor_edit_groups.cc
gtk2_ardour/editor_export_audio.cc
gtk2_ardour/editor_hscroller.cc
gtk2_ardour/editor_imageframe.cc
gtk2_ardour/editor_keyboard.cc
gtk2_ardour/editor_keys.cc
gtk2_ardour/editor_markers.cc
gtk2_ardour/editor_mixer.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_nudge.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_region_list.cc
gtk2_ardour/editor_route_list.cc
gtk2_ardour/editor_rulers.cc
gtk2_ardour/editor_selection.cc
gtk2_ardour/editor_selection_list.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/export_dialog.cc
gtk2_ardour/export_dialog.h
gtk2_ardour/export_range_markers_dialog.cc
gtk2_ardour/export_range_markers_dialog.h
gtk2_ardour/export_region_dialog.cc
gtk2_ardour/export_session_dialog.cc
gtk2_ardour/gain_automation_time_axis.cc
gtk2_ardour/gain_meter.cc
gtk2_ardour/gain_meter.h
gtk2_ardour/ghostregion.h
gtk2_ardour/grouped_buttons.cc [deleted file]
gtk2_ardour/grouped_buttons.h [deleted file]
gtk2_ardour/icons/crossfade_in_constant.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_in_dipped.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_in_fast-cut.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_in_slow-cut.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_in_slow-fade.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_in_transition.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_out_constant.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_out_dipped.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_out_fast-cut.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_out_slow-cut.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_out_slow-fade.png [new file with mode: 0644]
gtk2_ardour/icons/crossfade_out_transition.png [new file with mode: 0644]
gtk2_ardour/imageframe.cc
gtk2_ardour/imageframe.h
gtk2_ardour/imageframe_socket_handler.cc
gtk2_ardour/imageframe_socket_handler.h
gtk2_ardour/imageframe_time_axis.cc
gtk2_ardour/imageframe_time_axis.h
gtk2_ardour/imageframe_time_axis_group.cc
gtk2_ardour/imageframe_time_axis_group.h
gtk2_ardour/imageframe_time_axis_view.cc
gtk2_ardour/imageframe_time_axis_view.h
gtk2_ardour/imageframe_view.cc
gtk2_ardour/imageframe_view.h
gtk2_ardour/io_selector.cc
gtk2_ardour/io_selector.h
gtk2_ardour/keyboard.cc
gtk2_ardour/keyboard.h
gtk2_ardour/keyboard_target.cc [deleted file]
gtk2_ardour/keyboard_target.h [deleted file]
gtk2_ardour/ladspa_pluginui.cc
gtk2_ardour/location_ui.cc
gtk2_ardour/location_ui.h
gtk2_ardour/main.cc
gtk2_ardour/marker.cc
gtk2_ardour/marker.h
gtk2_ardour/marker_time_axis.cc
gtk2_ardour/marker_time_axis.h
gtk2_ardour/marker_time_axis_view.cc
gtk2_ardour/marker_time_axis_view.h
gtk2_ardour/marker_view.cc
gtk2_ardour/marker_view.h
gtk2_ardour/meter_bridge.cc [deleted file]
gtk2_ardour/meter_bridge.h [deleted file]
gtk2_ardour/meter_bridge_strip.cc [deleted file]
gtk2_ardour/meter_bridge_strip.h [deleted file]
gtk2_ardour/mixer_strip.cc
gtk2_ardour/mixer_strip.h
gtk2_ardour/mixer_ui.cc
gtk2_ardour/mixer_ui.h
gtk2_ardour/new_session_dialog.cc
gtk2_ardour/new_session_dialog.h
gtk2_ardour/option_editor.cc
gtk2_ardour/option_editor.h
gtk2_ardour/opts.cc
gtk2_ardour/opts.h
gtk2_ardour/pan_automation_time_axis.cc
gtk2_ardour/panner.cc
gtk2_ardour/panner2d.cc
gtk2_ardour/panner2d.h
gtk2_ardour/panner_ui.cc
gtk2_ardour/panner_ui.h
gtk2_ardour/playlist_selector.cc
gtk2_ardour/plugin_selector.cc
gtk2_ardour/plugin_ui.cc
gtk2_ardour/plugin_ui.h
gtk2_ardour/po/ru_RU.po
gtk2_ardour/prompter.cc
gtk2_ardour/prompter.h
gtk2_ardour/public_editor.h
gtk2_ardour/redirect_automation_line.cc
gtk2_ardour/redirect_automation_line.h
gtk2_ardour/redirect_automation_time_axis.cc
gtk2_ardour/redirect_box.cc
gtk2_ardour/redirect_box.h
gtk2_ardour/region_editor.h
gtk2_ardour/region_view.cc
gtk2_ardour/region_view.h
gtk2_ardour/rgb_macros.h
gtk2_ardour/route_params_ui.cc
gtk2_ardour/route_params_ui.h
gtk2_ardour/route_redirect_selection.cc
gtk2_ardour/route_redirect_selection.h
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_time_axis.h
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
gtk2_ardour/selectable.h
gtk2_ardour/selection.cc
gtk2_ardour/selection.h
gtk2_ardour/selection_templates.h
gtk2_ardour/send_ui.cc
gtk2_ardour/send_ui.h
gtk2_ardour/sfdb_ui.cc
gtk2_ardour/sfdb_ui.h
gtk2_ardour/simpleline.cc
gtk2_ardour/simpleline.h
gtk2_ardour/simplerect.cc
gtk2_ardour/simplerect.h
gtk2_ardour/tape_region_view.cc
gtk2_ardour/tape_region_view.h
gtk2_ardour/tempo_dialog.cc
gtk2_ardour/tempo_dialog.h
gtk2_ardour/time_axis_view.cc
gtk2_ardour/time_axis_view.h
gtk2_ardour/time_axis_view_item.cc
gtk2_ardour/time_axis_view_item.h
gtk2_ardour/time_selection.cc
gtk2_ardour/utils.cc
gtk2_ardour/utils.h
gtk2_ardour/visual_time_axis.cc
gtk2_ardour/visual_time_axis.h
gtk2_ardour/vst_pluginui.cc
gtk2_ardour/waveview.cc
gtk2_ardour/waveview.h
libs/ardour/SConscript
libs/ardour/ardour/ardour.h
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/audio_track.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/audiofilesource.h
libs/ardour/ardour/audiofilter.h
libs/ardour/ardour/audioplaylist.h
libs/ardour/ardour/audioregion.h
libs/ardour/ardour/audiosource.h
libs/ardour/ardour/auditioner.h
libs/ardour/ardour/automation_event.h
libs/ardour/ardour/click.h
libs/ardour/ardour/configuration.h
libs/ardour/ardour/configuration_variable.h
libs/ardour/ardour/configuration_vars.h
libs/ardour/ardour/connection.h
libs/ardour/ardour/crossfade.h
libs/ardour/ardour/crossfade_compare.h
libs/ardour/ardour/curve.h
libs/ardour/ardour/cycle_timer.h
libs/ardour/ardour/cycles.h
libs/ardour/ardour/dB.h
libs/ardour/ardour/destructive_filesource.h [deleted file]
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/export.h
libs/ardour/ardour/gain.h
libs/ardour/ardour/gdither.h
libs/ardour/ardour/gdither_types.h
libs/ardour/ardour/gdither_types_internal.h
libs/ardour/ardour/insert.h
libs/ardour/ardour/io.h
libs/ardour/ardour/ladspa_plugin.h
libs/ardour/ardour/location.h
libs/ardour/ardour/logcurve.h
libs/ardour/ardour/mix.h
libs/ardour/ardour/named_selection.h
libs/ardour/ardour/osc.h
libs/ardour/ardour/panner.h
libs/ardour/ardour/pcm_utils.h
libs/ardour/ardour/playlist.h
libs/ardour/ardour/playlist_templates.h
libs/ardour/ardour/plugin.h
libs/ardour/ardour/plugin_manager.h
libs/ardour/ardour/port.h
libs/ardour/ardour/redirect.h
libs/ardour/ardour/region.h
libs/ardour/ardour/reverse.h
libs/ardour/ardour/route.h
libs/ardour/ardour/route_group.h
libs/ardour/ardour/send.h
libs/ardour/ardour/session.h
libs/ardour/ardour/session_connection.h
libs/ardour/ardour/session_playlist.h
libs/ardour/ardour/session_route.h
libs/ardour/ardour/session_selection.h
libs/ardour/ardour/silentfilesource.h [new file with mode: 0644]
libs/ardour/ardour/slave.h
libs/ardour/ardour/sndfilesource.h
libs/ardour/ardour/soundseq.h
libs/ardour/ardour/source.h
libs/ardour/ardour/source_factory.h
libs/ardour/ardour/tempo.h
libs/ardour/ardour/types.h
libs/ardour/ardour/utils.h
libs/ardour/ardour/vst_plugin.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_playlist.cc
libs/ardour/audio_track.cc
libs/ardour/audioengine.cc
libs/ardour/audiofilesource.cc
libs/ardour/audiofilter.cc
libs/ardour/audioregion.cc
libs/ardour/audiosource.cc
libs/ardour/auditioner.cc
libs/ardour/automation_event.cc
libs/ardour/buffer.cc
libs/ardour/configuration.cc
libs/ardour/connection.cc
libs/ardour/control_protocol_manager.cc
libs/ardour/crossfade.cc
libs/ardour/curve.cc
libs/ardour/cycle_timer.cc
libs/ardour/default_click.cc
libs/ardour/destructive_filesource.cc [deleted file]
libs/ardour/diskstream.cc
libs/ardour/enums.cc
libs/ardour/gain.cc
libs/ardour/gdither.cc
libs/ardour/globals.cc
libs/ardour/import.cc
libs/ardour/insert.cc
libs/ardour/io.cc
libs/ardour/jack_slave.cc
libs/ardour/ladspa_plugin.cc
libs/ardour/location.cc
libs/ardour/macosx/English.lproj/InfoPlist.strings [new file with mode: 0644]
libs/ardour/macosx/Info.plist [new file with mode: 0644]
libs/ardour/macosx/ardour.xcodeproj/project.pbxproj [new file with mode: 0644]
libs/ardour/macosx/ardour_Prefix.pch [new file with mode: 0644]
libs/ardour/macosx/version.cc [new file with mode: 0644]
libs/ardour/macosx/version.h [new file with mode: 0644]
libs/ardour/midi_diskstream.cc
libs/ardour/mix.cc
libs/ardour/mtc_slave.cc
libs/ardour/named_selection.cc
libs/ardour/osc.cc
libs/ardour/panner.cc
libs/ardour/pcm_utils.cc
libs/ardour/playlist.cc
libs/ardour/playlist_factory.cc
libs/ardour/plugin.cc
libs/ardour/plugin_manager.cc
libs/ardour/port.cc
libs/ardour/redirect.cc
libs/ardour/region.cc
libs/ardour/region_factory.cc
libs/ardour/reverse.cc
libs/ardour/route.cc
libs/ardour/route_group.cc
libs/ardour/send.cc
libs/ardour/session.cc
libs/ardour/session_butler.cc
libs/ardour/session_click.cc
libs/ardour/session_command.cc
libs/ardour/session_control.cc [deleted file]
libs/ardour/session_events.cc
libs/ardour/session_export.cc
libs/ardour/session_feedback.cc
libs/ardour/session_midi.cc
libs/ardour/session_process.cc
libs/ardour/session_state.cc
libs/ardour/session_time.cc
libs/ardour/session_timefx.cc
libs/ardour/session_transport.cc
libs/ardour/session_vst.cc
libs/ardour/silentfilesource.cc [new file with mode: 0644]
libs/ardour/sndfilesource.cc
libs/ardour/source.cc
libs/ardour/source_factory.cc
libs/ardour/sse_functions_xmm.cc [new file with mode: 0644]
libs/ardour/tempo.cc
libs/ardour/utils.cc
libs/ardour/vst_plugin.cc
libs/clearlooks/clearlooks_theme_main.c
libs/fst/fst.h
libs/fst/vstwin.c
libs/glibmm2/autogen.sh
libs/gtkmm2ext/SConscript
libs/gtkmm2ext/barcontroller.cc
libs/gtkmm2ext/bindable_button.cc
libs/gtkmm2ext/fastmeter.cc
libs/gtkmm2ext/grouped_buttons.cc [new file with mode: 0644]
libs/gtkmm2ext/gtkmm2ext/auto_spin.h
libs/gtkmm2ext/gtkmm2ext/barcontroller.h
libs/gtkmm2ext/gtkmm2ext/bindable_button.h
libs/gtkmm2ext/gtkmm2ext/click_box.h
libs/gtkmm2ext/gtkmm2ext/doi.h
libs/gtkmm2ext/gtkmm2ext/fastmeter.h
libs/gtkmm2ext/gtkmm2ext/grouped_buttons.h [new file with mode: 0644]
libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
libs/gtkmm2ext/gtkmm2ext/gtkutils.h
libs/gtkmm2ext/gtkmm2ext/hexentry.h
libs/gtkmm2ext/gtkmm2ext/pixfader.h
libs/gtkmm2ext/gtkmm2ext/popup.h
libs/gtkmm2ext/gtkmm2ext/prompter.h
libs/gtkmm2ext/gtkmm2ext/selector.h
libs/gtkmm2ext/gtkmm2ext/slider_controller.h
libs/gtkmm2ext/gtkmm2ext/stateful_button.h
libs/gtkmm2ext/gtkmm2ext/tearoff.h
libs/gtkmm2ext/gtkmm2ext/textviewer.h
libs/gtkmm2ext/gtkmm2ext/utils.h
libs/gtkmm2ext/stateful_button.cc
libs/midi++2/macosx/English.lproj/InfoPlist.strings [new file with mode: 0644]
libs/midi++2/macosx/Info.plist [new file with mode: 0644]
libs/midi++2/macosx/midi++.xcodeproj/project.pbxproj [new file with mode: 0644]
libs/midi++2/macosx/midi++_Prefix.pch [new file with mode: 0644]
libs/midi++2/macosx/version.cc [new file with mode: 0644]
libs/midi++2/macosx/version.h [new file with mode: 0644]
libs/midi++2/midi++/alsa_rawmidi.h
libs/midi++2/midi++/alsa_sequencer.h
libs/midi++2/midi++/channel.h
libs/midi++2/midi++/factory.h
libs/midi++2/midi++/fd_midiport.h
libs/midi++2/midi++/fifomidi.h
libs/midi++2/midi++/manager.h
libs/midi++2/midi++/mmc.h
libs/midi++2/midi++/nullmidi.h
libs/midi++2/midi++/parser.h
libs/midi++2/midi++/port.h
libs/midi++2/midi++/port_request.h
libs/midi++2/midiparser.cc
libs/midi++2/mmc.cc
libs/midi++2/mtc.cc
libs/pbd/SConscript
libs/pbd/controllable.cc
libs/pbd/macosx/English.lproj/InfoPlist.strings [new file with mode: 0644]
libs/pbd/macosx/Info.plist [new file with mode: 0644]
libs/pbd/macosx/pbd.xcodeproj/project.pbxproj [new file with mode: 0644]
libs/pbd/macosx/pbd_Prefix.pch [new file with mode: 0644]
libs/pbd/macosx/version.cc [new file with mode: 0644]
libs/pbd/macosx/version.h [new file with mode: 0644]
libs/pbd/pbd/abstract_ui.cc
libs/pbd/pbd/abstract_ui.h
libs/pbd/pbd/command.h
libs/pbd/pbd/controllable.h
libs/pbd/pbd/error.h
libs/pbd/pbd/mathfix.h
libs/pbd/pbd/memento_command.h
libs/pbd/pbd/mountpoint.h
libs/pbd/pbd/pool.h
libs/pbd/pbd/rcu.h
libs/pbd/pbd/receiver.h
libs/pbd/pbd/replace_all.h [new file with mode: 0644]
libs/pbd/pbd/ringbuffer.h
libs/pbd/pbd/ringbufferNPT.h
libs/pbd/pbd/selectable.h
libs/pbd/pbd/stateful.h
libs/pbd/pbd/stl_delete.h
libs/pbd/pbd/stl_functors.h
libs/pbd/pbd/strsplit.h
libs/pbd/pbd/textreceiver.h
libs/pbd/pbd/thrown_error.h
libs/pbd/pbd/touchable.h
libs/pbd/pbd/transmitter.h
libs/pbd/pbd/undo.h
libs/pbd/stacktrace.cc
libs/pbd/strreplace.cc [new file with mode: 0644]
libs/pbd/strsplit.cc
libs/sigc++2/autogen.sh
libs/soundtouch/RateTransposer.cpp
libs/soundtouch/RateTransposer.h
libs/soundtouch/TDStretch.cpp
libs/soundtouch/cpu_detect_x86_gcc.cpp
libs/surfaces/control_protocol/basic_ui.cc
libs/surfaces/control_protocol/control_protocol.cc
libs/surfaces/control_protocol/control_protocol/basic_ui.h
libs/surfaces/control_protocol/control_protocol/control_protocol.h
libs/surfaces/frontier/kernel_drivers/BUILD [new file with mode: 0644]
libs/surfaces/frontier/kernel_drivers/Makefile [new file with mode: 0644]
libs/surfaces/frontier/kernel_drivers/README [new file with mode: 0644]
libs/surfaces/frontier/kernel_drivers/doc/keycodes.html [new file with mode: 0644]
libs/surfaces/frontier/kernel_drivers/tests/Makefile [new file with mode: 0644]
libs/surfaces/frontier/kernel_drivers/tests/README [new file with mode: 0644]
libs/surfaces/frontier/kernel_drivers/tests/tranzport.c [new file with mode: 0644]
libs/surfaces/frontier/kernel_drivers/tests/tranzport_lights.c [new file with mode: 0644]
libs/surfaces/frontier/kernel_drivers/tests/tranzport_tests.sh [new file with mode: 0755]
libs/surfaces/frontier/kernel_drivers/tranzport.c [new file with mode: 0644]
libs/surfaces/frontier/tests/Makefile [new file with mode: 0644]
libs/surfaces/frontier/tests/README [new file with mode: 0644]
libs/surfaces/frontier/tests/tranzport.c [new file with mode: 0644]
libs/surfaces/frontier/tests/tranzport_lights.c [new file with mode: 0644]
libs/surfaces/frontier/tranzport/SConscript [new file with mode: 0644]
libs/surfaces/frontier/tranzport/interface.cc [new file with mode: 0644]
libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc [new file with mode: 0644]
libs/surfaces/frontier/tranzport/tranzport_control_protocol.h [new file with mode: 0644]
libs/surfaces/generic_midi/SConscript
libs/surfaces/generic_midi/generic_midi_control_protocol.cc
libs/surfaces/generic_midi/midicontrollable.cc
libs/surfaces/generic_midi/midicontrollable.h
libs/surfaces/mackie/SConscript [new file with mode: 0644]
libs/surfaces/mackie/TODO [new file with mode: 0644]
libs/surfaces/mackie/bcf_surface.cc [new file with mode: 0644]
libs/surfaces/mackie/bcf_surface.h [new file with mode: 0644]
libs/surfaces/mackie/controls.cc [new file with mode: 0644]
libs/surfaces/mackie/controls.h [new file with mode: 0644]
libs/surfaces/mackie/interface.cc [new file with mode: 0644]
libs/surfaces/mackie/mackie_button_handler.cc [new file with mode: 0644]
libs/surfaces/mackie/mackie_button_handler.h [new file with mode: 0644]
libs/surfaces/mackie/mackie_control_exception.h [new file with mode: 0644]
libs/surfaces/mackie/mackie_control_protocol.cc [new file with mode: 0644]
libs/surfaces/mackie/mackie_control_protocol.h [new file with mode: 0644]
libs/surfaces/mackie/mackie_control_protocol_poll.cc [new file with mode: 0644]
libs/surfaces/mackie/mackie_midi_builder.cc [new file with mode: 0644]
libs/surfaces/mackie/mackie_midi_builder.h [new file with mode: 0644]
libs/surfaces/mackie/mackie_port.cc [new file with mode: 0644]
libs/surfaces/mackie/mackie_port.h [new file with mode: 0644]
libs/surfaces/mackie/mackie_surface.cc [new file with mode: 0644]
libs/surfaces/mackie/mackie_surface.h [new file with mode: 0644]
libs/surfaces/mackie/midi_byte_array.cc [new file with mode: 0644]
libs/surfaces/mackie/midi_byte_array.h [new file with mode: 0644]
libs/surfaces/mackie/route_signal.cc [new file with mode: 0644]
libs/surfaces/mackie/route_signal.h [new file with mode: 0644]
libs/surfaces/mackie/scripts/bank.rb [new file with mode: 0644]
libs/surfaces/mackie/scripts/bcf-controls.csv [new file with mode: 0644]
libs/surfaces/mackie/scripts/controls.rb [new file with mode: 0644]
libs/surfaces/mackie/scripts/dump.rb [new file with mode: 0755]
libs/surfaces/mackie/scripts/generate-button-handlers-cc.erb [new file with mode: 0644]
libs/surfaces/mackie/scripts/generate-button-handlers-h.erb [new file with mode: 0644]
libs/surfaces/mackie/scripts/generate-surface.rb [new file with mode: 0755]
libs/surfaces/mackie/scripts/host.rb [new file with mode: 0755]
libs/surfaces/mackie/scripts/mackie-controls.csv [new file with mode: 0644]
libs/surfaces/mackie/scripts/mackie.rb [new file with mode: 0644]
libs/surfaces/mackie/scripts/parse.rb [new file with mode: 0644]
libs/surfaces/mackie/scripts/signals.rb [new file with mode: 0644]
libs/surfaces/mackie/scripts/simple_host.rb [new file with mode: 0644]
libs/surfaces/mackie/scripts/surface-cc-template.erb [new file with mode: 0644]
libs/surfaces/mackie/scripts/surface-h-template.erb [new file with mode: 0644]
libs/surfaces/mackie/scripts/test_controls.rb [new file with mode: 0755]
libs/surfaces/mackie/scripts/transform.rb [new file with mode: 0644]
libs/surfaces/mackie/scripts/write.rb [new file with mode: 0644]
libs/surfaces/mackie/surface.cc [new file with mode: 0644]
libs/surfaces/mackie/surface.h [new file with mode: 0644]
libs/surfaces/mackie/surface_port.cc [new file with mode: 0644]
libs/surfaces/mackie/surface_port.h [new file with mode: 0644]
libs/surfaces/mackie/test.cc [new file with mode: 0644]
libs/surfaces/mackie/types.cc [new file with mode: 0644]
libs/surfaces/mackie/types.h [new file with mode: 0644]
libs/surfaces/tranzport/README [new file with mode: 0644]
libs/surfaces/tranzport/SConscript
libs/surfaces/tranzport/TODO [new file with mode: 0644]
libs/surfaces/tranzport/bling.cc [new file with mode: 0644]
libs/surfaces/tranzport/button_events.cc [new file with mode: 0644]
libs/surfaces/tranzport/button_yn.cc [new file with mode: 0644]
libs/surfaces/tranzport/buttons.cc [new file with mode: 0644]
libs/surfaces/tranzport/general.cc [new file with mode: 0644]
libs/surfaces/tranzport/init.cc [new file with mode: 0644]
libs/surfaces/tranzport/interface.cc
libs/surfaces/tranzport/io.cc [new file with mode: 0644]
libs/surfaces/tranzport/io_kernel.cc [new file with mode: 0644]
libs/surfaces/tranzport/io_midi.cc [new file with mode: 0644]
libs/surfaces/tranzport/io_usb.cc [new file with mode: 0644]
libs/surfaces/tranzport/lcd.cc [new file with mode: 0644]
libs/surfaces/tranzport/lights.cc [new file with mode: 0644]
libs/surfaces/tranzport/meter.cc [new file with mode: 0644]
libs/surfaces/tranzport/mode.cc [new file with mode: 0644]
libs/surfaces/tranzport/mode_loop.cc [new file with mode: 0644]
libs/surfaces/tranzport/mode_tuner.cc [new file with mode: 0644]
libs/surfaces/tranzport/panner.cc [new file with mode: 0644]
libs/surfaces/tranzport/screen.cc [new file with mode: 0644]
libs/surfaces/tranzport/show.cc [new file with mode: 0644]
libs/surfaces/tranzport/slider_gain.h [new file with mode: 0644]
libs/surfaces/tranzport/state.cc [new file with mode: 0644]
libs/surfaces/tranzport/tranzport_base.h [new file with mode: 0644]
libs/surfaces/tranzport/tranzport_common.h [new file with mode: 0644]
libs/surfaces/tranzport/tranzport_control_protocol.cc [deleted file]
libs/surfaces/tranzport/tranzport_control_protocol.h
libs/surfaces/tranzport/view_automation.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_bigmeter.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_bling.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_bus.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_config.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_layer.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_loop.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_manymeter.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_marker.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_master.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_plugins.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_std.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_tempo.cc [new file with mode: 0644]
libs/surfaces/tranzport/view_tuner.cc [new file with mode: 0644]
libs/surfaces/tranzport/wheel.cc [new file with mode: 0644]
libs/surfaces/tranzport/wheel_modes.cc [new file with mode: 0644]
manual/Makefile [new file with mode: 0644]
manual/catalog.xml [new file with mode: 0644]
manual/config/dbhelper.vim [new file with mode: 0644]
manual/css/ardour_manual.css [new file with mode: 0644]
manual/images/add_track_bus.png [new file with mode: 0644]
manual/images/admon-bg.png [new file with mode: 0644]
manual/images/con1.jpg [new file with mode: 0644]
manual/images/con2.jpg [new file with mode: 0644]
manual/images/internalhigheroverlap.png [new file with mode: 0644]
manual/images/internalloweroverlap.png [new file with mode: 0644]
manual/images/ladspa.jpg [new file with mode: 0644]
manual/images/manual_style.svg [new file with mode: 0644]
manual/images/matrixmixer.png [new file with mode: 0644]
manual/images/midiopts.jpg [new file with mode: 0644]
manual/images/mixer.png [new file with mode: 0644]
manual/images/mixer_strip_name_button_popup.png [new file with mode: 0644]
manual/images/mixerstrip.png [new file with mode: 0644]
manual/images/new_session_advanced_tab.png [new file with mode: 0644]
manual/images/new_session_select_directory.png [new file with mode: 0644]
manual/images/overlapearlyhigher.png [new file with mode: 0644]
manual/images/overlaplaterhigher.png [new file with mode: 0644]
manual/images/pluginmenu.jpg [new file with mode: 0644]
manual/images/plugins.jpg [new file with mode: 0644]
manual/images/qjackctl.png [new file with mode: 0644]
manual/images/qjopt.jpg [new file with mode: 0644]
manual/images/qjopts.jpg [new file with mode: 0644]
manual/images/qjpatch.jpg [new file with mode: 0644]
manual/images/save_session_dialog.png [new file with mode: 0644]
manual/images/save_template_dialog.png [new file with mode: 0644]
manual/images/session_control.png [new file with mode: 0644]
manual/images/signal_flow.png [new file with mode: 0644]
manual/images/tango-icons/COPYING [new file with mode: 0644]
manual/images/tango-icons/accessories-text-editor.svg [new file with mode: 0644]
manual/images/tango-icons/dialog-information.svg [new file with mode: 0644]
manual/images/tango-icons/dialog-warning.svg [new file with mode: 0644]
manual/images/tango-icons/emblem-important.svg [new file with mode: 0644]
manual/images/tango-icons/important.png [new file with mode: 0644]
manual/images/tango-icons/note.png [new file with mode: 0644]
manual/images/tango-icons/tip.png [new file with mode: 0644]
manual/images/tango-icons/warning.png [new file with mode: 0644]
manual/images/title-bg.png [new file with mode: 0644]
manual/images/track_name_field.png [new file with mode: 0644]
manual/images/transctls.jpg [new file with mode: 0644]
manual/images/watermark-draft.png [new file with mode: 0644]
manual/templates/chapter_template.xml [new file with mode: 0644]
manual/templates/section_template.xml [new file with mode: 0644]
manual/xml/adding_tracks.xml [new file with mode: 0644]
manual/xml/advanced_editing.xml [new file with mode: 0644]
manual/xml/ardour_basics.xml [new file with mode: 0644]
manual/xml/ardour_manual.xml [new file with mode: 0644]
manual/xml/automation.xml [new file with mode: 0644]
manual/xml/basic_editing.xml [new file with mode: 0644]
manual/xml/basic_recording.xml [new file with mode: 0644]
manual/xml/bcf2000.xml [new file with mode: 0644]
manual/xml/behringer_ddx3216.xml [new file with mode: 0644]
manual/xml/book_info.xml [new file with mode: 0644]
manual/xml/cleaning_up_a_session.xml [new file with mode: 0644]
manual/xml/clocks.xml [new file with mode: 0644]
manual/xml/closing_a_session.xml [new file with mode: 0644]
manual/xml/configuring_usb_device_access.xml [new file with mode: 0644]
manual/xml/contributing_to_the_manual.xml [new file with mode: 0644]
manual/xml/control_surfaces.xml [new file with mode: 0644]
manual/xml/creating_a_new_session.xml [new file with mode: 0644]
manual/xml/default_track_names.xml [new file with mode: 0644]
manual/xml/editing_concepts.xml [new file with mode: 0644]
manual/xml/editor_aligning_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_canvas_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_edit_cursor_position_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_locations_marks_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_miscellaneous_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_nudging_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_play_position_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_range_operations_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_region_operations_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_standard_editing_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_window.xml [new file with mode: 0644]
manual/xml/editor_window_controls.xml [new file with mode: 0644]
manual/xml/editor_window_group_list.xml [new file with mode: 0644]
manual/xml/editor_window_key_bindings.xml [new file with mode: 0644]
manual/xml/editor_window_region_list.xml [new file with mode: 0644]
manual/xml/editor_window_timeline.xml [new file with mode: 0644]
manual/xml/editor_window_track_list.xml [new file with mode: 0644]
manual/xml/editor_zoom_key_bindings.xml [new file with mode: 0644]
manual/xml/entities.ent [new file with mode: 0644]
manual/xml/exporting.xml [new file with mode: 0644]
manual/xml/exporting_to_cd.xml [new file with mode: 0644]
manual/xml/formatting_conventions.xml [new file with mode: 0644]
manual/xml/frontier_design_tranzport.xml [new file with mode: 0644]
manual/xml/general_key_bindings.xml [new file with mode: 0644]
manual/xml/generic_midi_control_surface.xml [new file with mode: 0644]
manual/xml/generic_mouse_actions.xml [new file with mode: 0644]
manual/xml/glossary.xml [new file with mode: 0644]
manual/xml/introduction.xml [new file with mode: 0644]
manual/xml/jack.xml [new file with mode: 0644]
manual/xml/key_bindings.xml [new file with mode: 0644]
manual/xml/known_issues.xml [new file with mode: 0644]
manual/xml/main_windows.xml [new file with mode: 0644]
manual/xml/midi_configuration.xml [new file with mode: 0644]
manual/xml/mixer_strip_list.xml [new file with mode: 0644]
manual/xml/mixer_strips.xml [new file with mode: 0644]
manual/xml/mixer_window.xml [new file with mode: 0644]
manual/xml/mixer_window_key_bindings.xml [new file with mode: 0644]
manual/xml/mixing.xml [new file with mode: 0644]
manual/xml/monitoring.xml [new file with mode: 0644]
manual/xml/mouse_operations.xml [new file with mode: 0644]
manual/xml/mouse_operations_mixer_controls.xml [new file with mode: 0644]
manual/xml/mouse_operations_object_mode.xml [new file with mode: 0644]
manual/xml/mouse_operations_range_mode.xml [new file with mode: 0644]
manual/xml/mouse_operations_region_gain_mode.xml [new file with mode: 0644]
manual/xml/mouse_operations_ruler.xml [new file with mode: 0644]
manual/xml/mouse_operations_zoom_mode.xml [new file with mode: 0644]
manual/xml/mouse_wheel_actions.xml [new file with mode: 0644]
manual/xml/opening_a_session.xml [new file with mode: 0644]
manual/xml/other_windows.xml [new file with mode: 0644]
manual/xml/plugins.xml [new file with mode: 0644]
manual/xml/preface.xml [new file with mode: 0644]
manual/xml/recording.xml [new file with mode: 0644]
manual/xml/renaming_tracks.xml [new file with mode: 0644]
manual/xml/saving_a_session.xml [new file with mode: 0644]
manual/xml/sessions.xml [new file with mode: 0644]
manual/xml/setting_up_to_record.xml [new file with mode: 0644]
manual/xml/snapshots.xml [new file with mode: 0644]
manual/xml/starting_up_your_system.xml [new file with mode: 0644]
manual/xml/synchronization.xml [new file with mode: 0644]
manual/xml/synchronization_concepts.xml [new file with mode: 0644]
manual/xml/templates.xml [new file with mode: 0644]
manual/xml/tracks_and_busses.xml [new file with mode: 0644]
manual/xml/transport_key_bindings.xml [new file with mode: 0644]
manual/xml/user_interface_conventions.xml [new file with mode: 0644]
manual/xml/using_existing_audio.xml [new file with mode: 0644]
manual/xml/video_synchronization_via_mtc.xml [new file with mode: 0644]
manual/xml/vst_plugins.xml [new file with mode: 0644]
manual/xml/what_is_different_about_ardour.xml [new file with mode: 0644]
manual/xml/why_is_it_called_ardour.xml [new file with mode: 0644]
manual/xml/working_with_crossfades.xml [new file with mode: 0644]
manual/xml/working_with_layers.xml [new file with mode: 0644]
manual/xml/working_with_playlists.xml [new file with mode: 0644]
manual/xml/working_with_ranges.xml [new file with mode: 0644]
manual/xml/working_with_regions.xml [new file with mode: 0644]
manual/xmlformat/BUGS [new file with mode: 0644]
manual/xmlformat/ChangeLog [new file with mode: 0644]
manual/xmlformat/INSTALL [new file with mode: 0644]
manual/xmlformat/LICENSE [new file with mode: 0644]
manual/xmlformat/README [new file with mode: 0644]
manual/xmlformat/xmlformat-ardour.conf [new file with mode: 0644]
manual/xmlformat/xmlformat.pl [new file with mode: 0755]
manual/xsl/html.xsl [new file with mode: 0644]
svn_revision.h
templates/2 Track.template.in
tools/Spotlight Importer/GetMetadataForFile.c
tools/Spotlight Importer/Info.plist
tools/Spotlight Importer/Spotlight Importer.xcodeproj/project.pbxproj
vst/ardevst

index 1a39c6d1797148bd0da67fd28b97c427b18c2aea..becce0e48c936a871bebc3e3fc045f48d9db8a23 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-all: scons cscope
+all: scons
 
 scons:
        scons
index 0a58a465967651089469ba427f7d97963a783fa7..906b04949e248023d682349d2b8f97100b5069bd 100644 (file)
@@ -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)
 
index 0ff7c85a414307dc4d1961e3931020c803c772b7..6b4f419a9e1f1288c2851769adafe95f50d2697f 100644 (file)
@@ -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. 
index 4dfe0b732293f142cf11882ec37954d10d91fc08..60e7bca331cc9808b171f5be687a4d975fe4e763 100644 (file)
@@ -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 +
index 34bb98199c33561fbd6dd8a321de8fe120e678f3..b0ec4f1436e549cc5712d21fa254a94eb8bb5760 100644 (file)
@@ -15,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
 };
 
index 3468a31a19e79ab27136504492116db44fe39e4d..2eb02dd223b4c5fe8b0cd100352e15752c32a98a 100644 (file)
@@ -15,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__
index d38287858248d8c707c1626bce5f082cbad9d063..6e4a525ba7a3f425e6d885f8c326d7af3825abbe 100644 (file)
@@ -15,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>
index 591fe642441b3b7bf74274c57c1159c9f9ce12e5..ea8233ff5216a85d4d6497b6e9752b3af46e6322 100644 (file)
@@ -15,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);
        }
 }
 
index dd749d2bb112a06a9f01f515528b81b8fecd1100..957dde3d1fcbcd60daf2ef9e9b519c942632bd96 100644 (file)
@@ -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>
index 95466a42b8b314ec5cf32ed45ebeec922aecaeac..ab99296f450df07b6ac4559aee8cff20654e72e9 100755 (executable)
@@ -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 $*
index ff68e11fbe1713f42e710163e2f644018b3857ca..5dd8fc9d1390a2c5ae826387973fb321bb35d093 100755 (executable)
@@ -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
deleted file mode 100644 (file)
index 3c7afcd..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-; ardour-2.0beta11.1 GtkAccelMap rc-file         -*- scheme -*-
-; this file is an automated accelerator map dump
-;
-; (gtk_accel_path "<Actions>/RegionList/RegionListSort" "")
-(gtk_accel_path "<Actions>/Common/Quit" "<Control>q")
-(gtk_accel_path "<Actions>/Common/Save" "<Control>s")
-; (gtk_accel_path "<Actions>/Editor/Pullup" "")
-; (gtk_accel_path "<Actions>/Editor/zoom-to-session" "")
-; (gtk_accel_path "<Actions>/JACK/JACKReconnect" "")
-; (gtk_accel_path "<Actions>/Editor/Autoconnect" "")
-; (gtk_accel_path "<Actions>/Editor/Edit" "")
-(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-end" "<Control>grave")
-; (gtk_accel_path "<Actions>/redirectmenu/copy" "")
-; (gtk_accel_path "<Actions>/options/MeterFalloffFaster" "")
-(gtk_accel_path "<Actions>/Transport/ToggleRollForgetCapture" "<Control>space")
-(gtk_accel_path "<Actions>/Transport/Record" "<Shift>r")
-; (gtk_accel_path "<Actions>/RegionList/SortByRegionLength" "")
-; (gtk_accel_path "<Actions>/options/MeterFalloffSlowest" "")
-; (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-sync" "")
-; (gtk_accel_path "<Actions>/redirectmenu/deactivate_all" "")
-; (gtk_accel_path "<Actions>/RegionList/SortByRegionPosition" "")
-; (gtk_accel_path "<Actions>/Editor/ZoomFocus" "")
-; (gtk_accel_path "<Actions>/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>/Zoom/zoom-focus-playhead" "")
-; (gtk_accel_path "<Actions>/Editor/center-edit-cursor" "")
-; (gtk_accel_path "<Actions>/Editor/Monitoring" "")
-; (gtk_accel_path "<Actions>/redirectmenu/deactivate" "")
-; (gtk_accel_path "<Actions>/options/LatchedRecordEnable" "")
-; (gtk_accel_path "<Actions>/Transport/TogglePunchIn" "")
-; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsPercentage" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-start" "bracketleft")
-; (gtk_accel_path "<Actions>/Main/Close" "")
-; (gtk_accel_path "<Actions>/Main/New" "")
-(gtk_accel_path "<Actions>/Editor/nudge-next-backward" "<Control>KP_Subtract")
-; (gtk_accel_path "<Actions>/Editor/EditSelectRangeOptions" "")
-; (gtk_accel_path "<Actions>/Transport/ToggleTimeMaster" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-thirds" "")
-(gtk_accel_path "<Actions>/Editor/align-regions-start-relative" "<Shift>a")
-; (gtk_accel_path "<Actions>/Main/Export" "")
-(gtk_accel_path "<Actions>/Editor/jump-forward-to-mark" "<Control>KP_Right")
-; (gtk_accel_path "<Actions>/Editor/Smpte30" "")
-; (gtk_accel_path "<Actions>/Editor/playhead-to-range-start" "")
-; (gtk_accel_path "<Actions>/Editor/Subframes" "")
-; (gtk_accel_path "<Actions>/Editor/Smpte2997drop" "")
-; (gtk_accel_path "<Actions>/Main/AddTrackBus" "")
-(gtk_accel_path "<Actions>/Editor/align-regions-end" "<Control><Mod2>a")
-; (gtk_accel_path "<Actions>/JACK/JACKDisconnect" "")
-; (gtk_accel_path "<Actions>/options/MeterFalloffFast" "")
-; (gtk_accel_path "<Actions>/options/FileDataFormatFloat" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-region-end" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-sync" "semicolon")
-; (gtk_accel_path "<Actions>/options/StopRecordingOnXrun" "")
-; (gtk_accel_path "<Actions>/Editor/addExternalAudioToRegionList" "")
-; (gtk_accel_path "<Actions>/RegionList/SortDescending" "")
-; (gtk_accel_path "<Actions>/options/DoNotRunPluginsWhileRecording" "")
-; (gtk_accel_path "<Actions>/Editor/PullupNone" "")
-(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-range" "r")
-(gtk_accel_path "<Actions>/Editor/jump-backward-to-mark" "<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>/Transport/Forward" "<Control>rightarrow")
-; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-seconds" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-frame" "")
-; (gtk_accel_path "<Actions>/Main/ExportSelection" "")
-; (gtk_accel_path "<Actions>/options/StopPluginsWithTransport" "")
-(gtk_accel_path "<Actions>/Editor/editor-paste" "<Control>v")
-(gtk_accel_path "<Actions>/Editor/scroll-tracks-down" "Page_Down")
-; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-minutes" "")
-; (gtk_accel_path "<Actions>/Main/FlushWastebasket" "")
-(gtk_accel_path "<Actions>/Editor/normalize-region" "n")
-(gtk_accel_path "<Actions>/Editor/nudge-forward" "KP_Add")
-; (gtk_accel_path "<Actions>/RegionList/SortByRegionEndinFile" "")
-; (gtk_accel_path "<Actions>/Editor/ToggleMeasureVisibility" "")
-; (gtk_accel_path "<Actions>/Zoom/zoom-focus-center" "")
-(gtk_accel_path "<Actions>/Editor/nudge-backward" "KP_Subtract")
-; (gtk_accel_path "<Actions>/options/LatchedSolo" "")
-; (gtk_accel_path "<Actions>/options/MeterHoldOff" "")
-; (gtk_accel_path "<Actions>/options/OutputAutoConnectMaster" "")
-; (gtk_accel_path "<Actions>/JACK/JACKLatency64" "")
-(gtk_accel_path "<Actions>/Editor/undo" "<Control>z")
-(gtk_accel_path "<Actions>/Editor/insert-region" "i")
-; (gtk_accel_path "<Actions>/Editor/center-playhead" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-start" "bracketright")
-; (gtk_accel_path "<Actions>/Snap/snap-to-region-start" "")
-; (gtk_accel_path "<Actions>/Editor/View" "")
-; (gtk_accel_path "<Actions>/Editor/Layering" "")
-; (gtk_accel_path "<Actions>/JACK/JACKLatency4096" "")
-(gtk_accel_path "<Actions>/Editor/scroll-tracks-up" "Page_Up")
-(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/EditCursorMovementOptions" "")
-; (gtk_accel_path "<Actions>/redirectmenu/activate_all" "")
-; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTapeTrack" "")
-; (gtk_accel_path "<Actions>/redirectmenu/paste" "")
-; (gtk_accel_path "<Actions>/Editor/Smpte25" "")
-; (gtk_accel_path "<Actions>/options/RegionEquivalentsOverlap" "")
-; (gtk_accel_path "<Actions>/Main/MeteringFallOffRate" "")
-; (gtk_accel_path "<Actions>/options/UseHardwareMonitoring" "")
-; (gtk_accel_path "<Actions>/Editor/Smpte24" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-mark" "")
-; (gtk_accel_path "<Actions>/Editor/CrossfadesShort" "")
-; (gtk_accel_path "<Actions>/Editor/Smpte5994" "")
-; (gtk_accel_path "<Actions>/JACK/JACKLatency8192" "")
-(gtk_accel_path "<Actions>/Editor/step-tracks-down" "downarrow")
-; (gtk_accel_path "<Actions>/Editor/toggle-xfades-visible" "")
-(gtk_accel_path "<Actions>/Editor/extend-range-to-end-of-region" "rightanglebracket")
-(gtk_accel_path "<Actions>/Editor/scroll-backward" "leftarrow")
-(gtk_accel_path "<Actions>/Editor/start-range" "<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" "")
-; (gtk_accel_path "<Actions>/Editor/RegionEditOps" "")
-; (gtk_accel_path "<Actions>/Editor/snap-magnetic" "")
-; (gtk_accel_path "<Actions>/Editor/playhead-to-range-end" "")
-(gtk_accel_path "<Actions>/Editor/scroll-playhead-forward" "<Shift>rightarrow")
-(gtk_accel_path "<Actions>/Editor/align-regions-sync-relative" "a")
-; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
-(gtk_accel_path "<Actions>/Editor/crop" "c")
-; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
-; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
-; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
-(gtk_accel_path "<Actions>/Transport/GotoStart" "Home")
-(gtk_accel_path "<Actions>/Editor/scroll-playhead-backward" "<Shift>leftarrow")
-(gtk_accel_path "<Actions>/Editor/split-region" "s")
-; (gtk_accel_path "<Actions>/Transport/ToggleAutoInput" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-thirtyseconds" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-minutes" "")
-(gtk_accel_path "<Actions>/Editor/align-regions-sync" "<Mod2>a")
-; (gtk_accel_path "<Actions>/Main/Windows" "")
-; (gtk_accel_path "<Actions>/Main/CleanupUnused" "")
-; (gtk_accel_path "<Actions>/redirectmenu/deselectall" "")
-; (gtk_accel_path "<Actions>/options/SoloViaBus" "")
-(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-zoom" "z")
-; (gtk_accel_path "<Actions>/RegionList/rlAudition" "")
-(gtk_accel_path "<Actions>/Editor/set-region-sync-position" "v")
-; (gtk_accel_path "<Actions>/Editor/PullupPlus4Plus1" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-region-boundary" "")
-; (gtk_accel_path "<Actions>/JACK/JACK" "")
-(gtk_accel_path "<Actions>/Editor/editor-cut" "<Control>x")
-; (gtk_accel_path "<Actions>/RegionList/SortAscending" "")
-; (gtk_accel_path "<Actions>/Main/Help" "")
-; (gtk_accel_path "<Actions>/options/UseExternalMonitoring" "")
-; (gtk_accel_path "<Actions>/Editor/Smpte23976" "")
-(gtk_accel_path "<Actions>/Common/goto-editor" "<Alt>e")
-(gtk_accel_path "<Actions>/Editor/select-all" "<Control>a")
-(gtk_accel_path "<Actions>/Editor/nudge-next-forward" "<Control>KP_Add")
-; (gtk_accel_path "<Actions>/Snap/snap-to-eighths" "")
-(gtk_accel_path "<Actions>/Editor/select-all-after-playhead" "<Shift><Control>p")
-(gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11")
-; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileLength" "")
-; (gtk_accel_path "<Actions>/Editor/Timecode" "")
-; (gtk_accel_path "<Actions>/Transport/PlaySelection" "")
-; (gtk_accel_path "<Actions>/Editor/PullupMinus4Minus1" "")
-(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<Shift><Control>e")
-; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileName" "")
-(gtk_accel_path "<Actions>/Editor/finish-range" "<Control>KP_Up")
-(gtk_accel_path "<Actions>/Transport/Loop" "l")
-; (gtk_accel_path "<Actions>/Editor/CrossfadesFull" "")
-(gtk_accel_path "<Actions>/Editor/finish-add-range" "<Shift><Control>KP_Up")
-; (gtk_accel_path "<Actions>/Transport/ToggleClick" "")
-; (gtk_accel_path "<Actions>/options/SendMTC" "")
-; (gtk_accel_path "<Actions>/Transport/TogglePunchOut" "")
-(gtk_accel_path "<Actions>/Editor/select-all-in-loop-range" "<Control>l")
-(gtk_accel_path "<Actions>/Editor/show-editor-mixer" "<Shift>e")
-; (gtk_accel_path "<Actions>/options/SoloInPlace" "")
-; (gtk_accel_path "<Actions>/Main/Options" "")
-; (gtk_accel_path "<Actions>/options/MeterFalloffMedium" "")
-(gtk_accel_path "<Actions>/Editor/toggle-follow-playhead" "f")
-; (gtk_accel_path "<Actions>/Main/SaveTemplate" "")
-(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<Control>uparrow")
-; (gtk_accel_path "<Actions>/RegionList/SortByRegionStartinFile" "")
-; (gtk_accel_path "<Actions>/options/GainReduceFastTransport" "")
-; (gtk_accel_path "<Actions>/Common/ToggleInspector" "")
-; (gtk_accel_path "<Actions>/Transport/ToggleAutoPlay" "")
-; (gtk_accel_path "<Actions>/Editor/playhead-to-next-region-sync" "")
-(gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<Alt>Return")
-; (gtk_accel_path "<Actions>/Editor/LayerMoveAddHigher" "")
-; (gtk_accel_path "<Actions>/Editor/Smpte60" "")
-; (gtk_accel_path "<Actions>/Main/Open" "")
-(gtk_accel_path "<Actions>/Editor/scroll-forward" "rightarrow")
-; (gtk_accel_path "<Actions>/Zoom/zoom-focus-left" "")
-; (gtk_accel_path "<Actions>/Main/TransportOptions" "")
-; (gtk_accel_path "<Actions>/Main/ControlSurfaces" "")
-; (gtk_accel_path "<Actions>/options/FileHeaderFormatBWF" "")
-; (gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "")
-; (gtk_accel_path "<Actions>/Editor/Smpte2997" "")
-; (gtk_accel_path "<Actions>/Editor/ToggleWaveformVisibility" "")
-(gtk_accel_path "<Actions>/Editor/redo" "<Control>r")
-; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsRegion" "")
-; (gtk_accel_path "<Actions>/Main/ExportSession" "")
-; (gtk_accel_path "<Actions>/options/InputAutoConnectPhysical" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-edit-cursor" "")
-(gtk_accel_path "<Actions>/Editor/temporal-zoom-in" "minus")
-; (gtk_accel_path "<Actions>/JACK/Latency" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-end" "F2")
-; (gtk_accel_path "<Actions>/redirectmenu/rename" "")
-; (gtk_accel_path "<Actions>/RegionList/rlShowAuto" "")
-(gtk_accel_path "<Actions>/Editor/select-all-before-playhead" "<Control>p")
-; (gtk_accel_path "<Actions>/Editor/addExistingAudioFiles" "")
-; (gtk_accel_path "<Actions>/Main/Session" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-start" "F1")
-; (gtk_accel_path "<Actions>/Main/AudioFileFormat" "")
-; (gtk_accel_path "<Actions>/Transport/Transport" "")
-(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-timefx" "t")
-; (gtk_accel_path "<Actions>/RegionList/SortByRegionName" "")
-; (gtk_accel_path "<Actions>/Main/KeyMouse Actions" "")
-(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-gain" "g")
-; (gtk_accel_path "<Actions>/Snap/snap-to-frame" "")
-; (gtk_accel_path "<Actions>/Editor/SnapTo" "")
-(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<Control>downarrow")
-; (gtk_accel_path "<Actions>/Editor/Crossfades" "")
-; (gtk_accel_path "<Actions>/Editor/PullupPlus4" "")
-(gtk_accel_path "<Actions>/Editor/add-location-from-playhead" "KP_Enter")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-end" "<Control>bracketleft")
-; (gtk_accel_path "<Actions>/Main/MeteringHoldTime" "")
-; (gtk_accel_path "<Actions>/Editor/PullupPlus1" "")
-; (gtk_accel_path "<Actions>/Editor/Smpte24976" "")
-; (gtk_accel_path "<Actions>/options/FileDataFormat24bit" "")
-; (gtk_accel_path "<Actions>/Editor/SnapMode" "")
-(gtk_accel_path "<Actions>/Common/ToggleOptionsEditor" "<Control>o")
-; (gtk_accel_path "<Actions>/Editor/PullupMinus4" "")
-(gtk_accel_path "<Actions>/Common/goto-mixer" "<Alt>m")
-; (gtk_accel_path "<Actions>/Editor/addExternalAudioToTrack" "")
-; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileCreationDate" "")
-; (gtk_accel_path "<Actions>/redirectmenu/activate" "")
-(gtk_accel_path "<Actions>/Editor/extend-range-to-start-of-region" "leftanglebracket")
-; (gtk_accel_path "<Actions>/Editor/PullupMinus1" "")
-; (gtk_accel_path "<Actions>/Editor/snap-normal" "")
-; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTrack" "")
-(gtk_accel_path "<Actions>/Common/ToggleBigClock" "<Alt>b")
-; (gtk_accel_path "<Actions>/Snap/snap-to-asixteenthbeat" "")
-(gtk_accel_path "<Actions>/Editor/select-all-in-punch-range" "<Control>d")
-; (gtk_accel_path "<Actions>/redirectmenu/edit" "")
-(gtk_accel_path "<Actions>/Editor/duplicate-region" "d")
-; (gtk_accel_path "<Actions>/JACK/JACKLatency2048" "")
-; (gtk_accel_path "<Actions>/Editor/ToggleWaveformsWhileRecording" "")
-; (gtk_accel_path "<Actions>/Zoom/zoom-focus-right" "")
-(gtk_accel_path "<Actions>/Editor/remove-last-capture" "<Control>Delete")
-; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE" "")
-(gtk_accel_path "<Actions>/Transport/GotoZero" "KP_Insert")
-(gtk_accel_path "<Actions>/Transport/GotoEnd" "End")
-; (gtk_accel_path "<Actions>/redirectmenu/cut" "")
-; (gtk_accel_path "<Actions>/redirectmenu/newinsert" "")
-; (gtk_accel_path "<Actions>/options/UseMMC" "")
-; (gtk_accel_path "<Actions>/options/MeterFalloffOff" "")
-(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-object" "o")
-; (gtk_accel_path "<Actions>/Editor/PullupMinus4Plus1" "")
-; (gtk_accel_path "<Actions>/Editor/MeterHold" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-cd-frame" "")
-; (gtk_accel_path "<Actions>/options/StopTransportAtEndOfSession" "")
-; (gtk_accel_path "<Actions>/Main/Cleanup" "")
-; (gtk_accel_path "<Actions>/Main/Snapshot" "")
-; (gtk_accel_path "<Actions>/Transport/ToggleVideoSync" "")
-(gtk_accel_path "<Actions>/Transport/ToggleRoll" "space")
-; (gtk_accel_path "<Actions>/RegionList/SortBySourceFilesystem" "")
-(gtk_accel_path "<Actions>/Common/ToggleColorManager" "<Alt>c")
-; (gtk_accel_path "<Actions>/Common/About" "")
-; (gtk_accel_path "<Actions>/JACK/JACKLatency32" "")
-(gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
-; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE64" "")
-(gtk_accel_path "<Actions>/Editor/brush-at-mouse" "<Control>b")
-; (gtk_accel_path "<Actions>/RegionList/rlShowAll" "")
-(gtk_accel_path "<Actions>/Transport/Rewind" "<Control>leftarrow")
-; (gtk_accel_path "<Actions>/RegionList/SortByRegionTimestamp" "")
-; (gtk_accel_path "<Actions>/options/VerifyRemoveLastCapture" "")
-; (gtk_accel_path "<Actions>/options/OutputAutoConnectPhysical" "")
-(gtk_accel_path "<Actions>/Editor/step-tracks-up" "uparrow")
-(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-start" "Tab")
-; (gtk_accel_path "<Actions>/options/SendMMC" "")
-; (gtk_accel_path "<Actions>/Editor/toggle-auto-xfades" "")
-; (gtk_accel_path "<Actions>/Main/AudioFileFormatHeader" "")
-; (gtk_accel_path "<Actions>/options/MeterHoldShort" "")
-; (gtk_accel_path "<Actions>/options/MeterHoldMedium" "")
-(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<Control>e")
-; (gtk_accel_path "<Actions>/Editor/Subframes80" "")
-; (gtk_accel_path "<Actions>/options/FileHeaderFormatCAF" "")
-(gtk_accel_path "<Actions>/Common/ToggleLocations" "<Alt>l")
-; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurface" "")
-(gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
-; (gtk_accel_path "<Actions>/JACK/JACKLatency256" "")
-(gtk_accel_path "<Actions>/Editor/select-all-between-cursors" "u")
-; (gtk_accel_path "<Actions>/Editor/LayerAddHigher" "")
-; (gtk_accel_path "<Actions>/Editor/Solo" "")
-; (gtk_accel_path "<Actions>/JACK/JACKLatency1024" "")
-; (gtk_accel_path "<Actions>/Main/ExportRangeMarkers" "")
-(gtk_accel_path "<Actions>/Editor/set-playhead" "p")
-; (gtk_accel_path "<Actions>/Editor/toggle-xfades-active" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-bar" "")
-; (gtk_accel_path "<Actions>/Editor/LayerLaterHigher" "")
-; (gtk_accel_path "<Actions>/redirectmenu/selectall" "")
-(gtk_accel_path "<Actions>/Editor/editor-copy" "<Control>c")
-; (gtk_accel_path "<Actions>/Snap/snap-to-quarters" "")
-(gtk_accel_path "<Actions>/Editor/temporal-zoom-out" "equal")
-; (gtk_accel_path "<Actions>/options/UseSoftwareMonitoring" "")
-; (gtk_accel_path "<Actions>/Editor/Subframes100" "")
-(gtk_accel_path "<Actions>/Editor/mute-unmute-region" "m")
-; (gtk_accel_path "<Actions>/options/OutputAutoConnectManual" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-region-sync" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-sync" "apostrophe")
-; (gtk_accel_path "<Actions>/redirectmenu/clear" "")
-; (gtk_accel_path "<Actions>/Editor/PullupPlus4Minus1" "")
-; (gtk_accel_path "<Actions>/JACK/JACKLatency512" "")
-(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-end" "<Control>bracketright")
-; (gtk_accel_path "<Actions>/Main/Recent" "")
-; (gtk_accel_path "<Actions>/redirectmenu/newplugin" "")
-; (gtk_accel_path "<Actions>/options/InputAutoConnectManual" "")
-; (gtk_accel_path "<Actions>/options/MeterHoldLong" "")
-; (gtk_accel_path "<Actions>/Snap/snap-to-seconds" "")
diff --git a/gtk2_ardour/ardour.bindings.in b/gtk2_ardour/ardour.bindings.in
new file mode 100644 (file)
index 0000000..d8316a0
--- /dev/null
@@ -0,0 +1,317 @@
+; ardour-2.0beta11.1 GtkAccelMap rc-file         -*- scheme -*-
+; this file is an automated accelerator map dump
+;
+; (gtk_accel_path "<Actions>/RegionList/RegionListSort" "")
+(gtk_accel_path "<Actions>/Common/Quit" "<Control>q")
+(gtk_accel_path "<Actions>/Common/Save" "<Control>s")
+; (gtk_accel_path "<Actions>/Editor/Pullup" "")
+; (gtk_accel_path "<Actions>/Editor/zoom-to-session" "")
+; (gtk_accel_path "<Actions>/JACK/JACKReconnect" "")
+; (gtk_accel_path "<Actions>/Editor/Autoconnect" "")
+; (gtk_accel_path "<Actions>/Editor/Edit" "")
+(gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-end" "<Control>comma")
+; (gtk_accel_path "<Actions>/redirectmenu/copy" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFaster" "")
+(gtk_accel_path "<Actions>/Transport/ToggleRollForgetCapture" "<Control>space")
+(gtk_accel_path "<Actions>/Transport/Record" "<Shift>r")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionLength" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffSlowest" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-sync" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deactivate_all" "")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionPosition" "")
+; (gtk_accel_path "<Actions>/Editor/ZoomFocus" "")
+; (gtk_accel_path "<Actions>/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>period")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-playhead" "")
+; (gtk_accel_path "<Actions>/Editor/center-edit-cursor" "")
+; (gtk_accel_path "<Actions>/Editor/Monitoring" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deactivate" "")
+; (gtk_accel_path "<Actions>/options/LatchedRecordEnable" "")
+; (gtk_accel_path "<Actions>/Transport/TogglePunchIn" "")
+; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsPercentage" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-start" "bracketleft")
+; (gtk_accel_path "<Actions>/Main/Close" "")
+; (gtk_accel_path "<Actions>/Main/New" "")
+(gtk_accel_path "<Actions>/Editor/nudge-next-backward" "<Control>KP_Subtract")
+; (gtk_accel_path "<Actions>/Editor/EditSelectRangeOptions" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleTimeMaster" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-thirds" "")
+(gtk_accel_path "<Actions>/Editor/align-regions-start-relative" "<Shift>a")
+; (gtk_accel_path "<Actions>/Main/Export" "")
+(gtk_accel_path "<Actions>/Editor/jump-forward-to-mark" "<Control>KP_Right")
+; (gtk_accel_path "<Actions>/Editor/Smpte30" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-range-start" "")
+; (gtk_accel_path "<Actions>/Editor/Subframes" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte2997drop" "")
+; (gtk_accel_path "<Actions>/Main/AddTrackBus" "")
+(gtk_accel_path "<Actions>/Editor/align-regions-end" "<Control><Mod2>a")
+; (gtk_accel_path "<Actions>/JACK/JACKDisconnect" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFast" "")
+; (gtk_accel_path "<Actions>/options/FileDataFormatFloat" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-end" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-sync" "semicolon")
+; (gtk_accel_path "<Actions>/options/StopRecordingOnXrun" "")
+; (gtk_accel_path "<Actions>/Editor/addExternalAudioToRegionList" "")
+; (gtk_accel_path "<Actions>/RegionList/SortDescending" "")
+; (gtk_accel_path "<Actions>/options/DoNotRunPluginsWhileRecording" "")
+; (gtk_accel_path "<Actions>/Editor/PullupNone" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-range" "r")
+(gtk_accel_path "<Actions>/Editor/jump-backward-to-mark" "<Control>KP_Left")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormatData" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffFastest" "")
+; (gtk_accel_path "<Actions>/Editor/audition-at-mouse" "")
+(gtk_accel_path "<Actions>/Transport/Forward" "<Control>rightarrow")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-seconds" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-frame" "")
+; (gtk_accel_path "<Actions>/Main/ExportSelection" "")
+; (gtk_accel_path "<Actions>/options/StopPluginsWithTransport" "")
+(gtk_accel_path "<Actions>/Editor/editor-paste" "<Control>v")
+(gtk_accel_path "<Actions>/Editor/scroll-tracks-down" "Page_Down")
+; (gtk_accel_path "<Actions>/Snap/snap-to-smpte-minutes" "")
+; (gtk_accel_path "<Actions>/Main/FlushWastebasket" "")
+(gtk_accel_path "<Actions>/Editor/normalize-region" "n")
+(gtk_accel_path "<Actions>/Editor/nudge-forward" "KP_Add")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionEndinFile" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleMeasureVisibility" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-center" "")
+(gtk_accel_path "<Actions>/Editor/nudge-backward" "KP_Subtract")
+; (gtk_accel_path "<Actions>/options/LatchedSolo" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldOff" "")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectMaster" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency64" "")
+(gtk_accel_path "<Actions>/Editor/undo" "<Control>z")
+(gtk_accel_path "<Actions>/Editor/insert-region" "i")
+; (gtk_accel_path "<Actions>/Editor/center-playhead" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-start" "bracketright")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-start" "")
+; (gtk_accel_path "<Actions>/Editor/View" "")
+; (gtk_accel_path "<Actions>/Editor/Layering" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency4096" "")
+(gtk_accel_path "<Actions>/Editor/scroll-tracks-up" "Page_Up")
+(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" "comma")
+; (gtk_accel_path "<Actions>/Editor/EditCursorMovementOptions" "")
+; (gtk_accel_path "<Actions>/redirectmenu/activate_all" "")
+; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTapeTrack" "")
+; (gtk_accel_path "<Actions>/redirectmenu/paste" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte25" "")
+; (gtk_accel_path "<Actions>/options/RegionEquivalentsOverlap" "")
+; (gtk_accel_path "<Actions>/Main/MeteringFallOffRate" "")
+; (gtk_accel_path "<Actions>/options/UseHardwareMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte24" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-mark" "")
+; (gtk_accel_path "<Actions>/Editor/CrossfadesShort" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte5994" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency8192" "")
+(gtk_accel_path "<Actions>/Editor/step-tracks-down" "downarrow")
+; (gtk_accel_path "<Actions>/Editor/toggle-xfades-visible" "")
+(gtk_accel_path "<Actions>/Editor/extend-range-to-end-of-region" "rightanglebracket")
+(gtk_accel_path "<Actions>/Editor/scroll-backward" "leftarrow")
+(gtk_accel_path "<Actions>/Editor/start-range" "<Control>KP_Down")
+; (gtk_accel_path "<Actions>/ShuttleActions/SetShuttleUnitsSemitones" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency128" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-beat" "")
+; (gtk_accel_path "<Actions>/Editor/RegionEditOps" "")
+; (gtk_accel_path "<Actions>/Editor/snap-magnetic" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-range-end" "")
+(gtk_accel_path "<Actions>/Editor/scroll-playhead-forward" "<Shift>rightarrow")
+(gtk_accel_path "<Actions>/Editor/align-regions-sync-relative" "a")
+; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
+(gtk_accel_path "<Actions>/Editor/crop" "c")
+; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "")
+; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
+; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
+(gtk_accel_path "<Actions>/Transport/GotoStart" "Home")
+(gtk_accel_path "<Actions>/Editor/scroll-playhead-backward" "<Shift>leftarrow")
+(gtk_accel_path "<Actions>/Editor/split-region" "s")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoInput" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-thirtyseconds" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-minutes" "")
+(gtk_accel_path "<Actions>/Editor/align-regions-sync" "<Mod2>a")
+; (gtk_accel_path "<Actions>/Main/Windows" "")
+; (gtk_accel_path "<Actions>/Main/CleanupUnused" "")
+; (gtk_accel_path "<Actions>/redirectmenu/deselectall" "")
+; (gtk_accel_path "<Actions>/options/SoloViaBus" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-zoom" "z")
+; (gtk_accel_path "<Actions>/RegionList/rlAudition" "")
+(gtk_accel_path "<Actions>/Editor/set-region-sync-position" "v")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4Plus1" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-boundary" "")
+; (gtk_accel_path "<Actions>/JACK/JACK" "")
+(gtk_accel_path "<Actions>/Editor/editor-cut" "<Control>x")
+; (gtk_accel_path "<Actions>/RegionList/SortAscending" "")
+; (gtk_accel_path "<Actions>/Main/Help" "")
+; (gtk_accel_path "<Actions>/options/UseExternalMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte23976" "")
+(gtk_accel_path "<Actions>/Common/goto-editor" "<Alt>e")
+(gtk_accel_path "<Actions>/Editor/select-all" "<Control>a")
+(gtk_accel_path "<Actions>/Editor/nudge-next-forward" "<Control>KP_Add")
+; (gtk_accel_path "<Actions>/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")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileLength" "")
+; (gtk_accel_path "<Actions>/Editor/Timecode" "")
+; (gtk_accel_path "<Actions>/Transport/PlaySelection" "")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4Minus1" "")
+(gtk_accel_path "<Actions>/Editor/select-all-after-edit-cursor" "<Shift><Control>e")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileName" "")
+(gtk_accel_path "<Actions>/Editor/finish-range" "<Control>KP_Up")
+(gtk_accel_path "<Actions>/Transport/Loop" "l")
+; (gtk_accel_path "<Actions>/Editor/CrossfadesFull" "")
+(gtk_accel_path "<Actions>/Editor/finish-add-range" "<Shift><Control>KP_Up")
+; (gtk_accel_path "<Actions>/Transport/ToggleClick" "")
+; (gtk_accel_path "<Actions>/options/SendMTC" "")
+; (gtk_accel_path "<Actions>/Transport/TogglePunchOut" "")
+(gtk_accel_path "<Actions>/Editor/select-all-in-loop-range" "<Control>l")
+(gtk_accel_path "<Actions>/Editor/show-editor-mixer" "<Shift>e")
+; (gtk_accel_path "<Actions>/options/SoloInPlace" "")
+; (gtk_accel_path "<Actions>/Main/Options" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffMedium" "")
+(gtk_accel_path "<Actions>/Editor/toggle-follow-playhead" "f")
+; (gtk_accel_path "<Actions>/Main/SaveTemplate" "")
+(gtk_accel_path "<Actions>/Transport/TransitionToRoll" "<Control>uparrow")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionStartinFile" "")
+; (gtk_accel_path "<Actions>/options/GainReduceFastTransport" "")
+; (gtk_accel_path "<Actions>/Common/ToggleInspector" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoPlay" "")
+; (gtk_accel_path "<Actions>/Editor/playhead-to-next-region-sync" "")
+(gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<Alt>Return")
+; (gtk_accel_path "<Actions>/Editor/LayerMoveAddHigher" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte60" "")
+; (gtk_accel_path "<Actions>/Main/Open" "")
+(gtk_accel_path "<Actions>/Editor/scroll-forward" "rightarrow")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-left" "")
+; (gtk_accel_path "<Actions>/Main/TransportOptions" "")
+; (gtk_accel_path "<Actions>/Main/ControlSurfaces" "")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatBWF" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleAutoReturn" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte2997" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleWaveformVisibility" "")
+(gtk_accel_path "<Actions>/Editor/redo" "<Control>r")
+; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsRegion" "")
+; (gtk_accel_path "<Actions>/Main/ExportSession" "")
+; (gtk_accel_path "<Actions>/options/InputAutoConnectPhysical" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-edit-cursor" "")
+(gtk_accel_path "<Actions>/Editor/temporal-zoom-in" "minus")
+; (gtk_accel_path "<Actions>/JACK/Latency" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-end" "F2")
+; (gtk_accel_path "<Actions>/redirectmenu/rename" "")
+; (gtk_accel_path "<Actions>/RegionList/rlShowAuto" "")
+(gtk_accel_path "<Actions>/Editor/select-all-before-playhead" "<Control>p")
+; (gtk_accel_path "<Actions>/Editor/addExistingAudioFiles" "")
+; (gtk_accel_path "<Actions>/Main/Session" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-start" "F1")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormat" "")
+; (gtk_accel_path "<Actions>/Transport/Transport" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-timefx" "t")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionName" "")
+; (gtk_accel_path "<Actions>/Main/KeyMouse Actions" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-gain" "g")
+; (gtk_accel_path "<Actions>/Snap/snap-to-frame" "")
+; (gtk_accel_path "<Actions>/Editor/SnapTo" "")
+(gtk_accel_path "<Actions>/Transport/TransitionToReverse" "<Control>downarrow")
+; (gtk_accel_path "<Actions>/Editor/Crossfades" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4" "")
+(gtk_accel_path "<Actions>/Editor/add-location-from-playhead" "KP_Enter")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-end" "<Control>bracketleft")
+; (gtk_accel_path "<Actions>/Main/MeteringHoldTime" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus1" "")
+; (gtk_accel_path "<Actions>/Editor/Smpte24976" "")
+; (gtk_accel_path "<Actions>/options/FileDataFormat24bit" "")
+; (gtk_accel_path "<Actions>/Editor/SnapMode" "")
+(gtk_accel_path "<Actions>/Common/ToggleOptionsEditor" "<Control>o")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4" "")
+(gtk_accel_path "<Actions>/Common/goto-mixer" "<Alt>m")
+; (gtk_accel_path "<Actions>/Editor/addExternalAudioToTrack" "")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFileCreationDate" "")
+; (gtk_accel_path "<Actions>/redirectmenu/activate" "")
+(gtk_accel_path "<Actions>/Editor/extend-range-to-start-of-region" "leftanglebracket")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus1" "")
+; (gtk_accel_path "<Actions>/Editor/snap-normal" "")
+; (gtk_accel_path "<Actions>/Editor/addExternalAudioAsTrack" "")
+(gtk_accel_path "<Actions>/Common/ToggleBigClock" "<Alt>b")
+; (gtk_accel_path "<Actions>/Snap/snap-to-asixteenthbeat" "")
+(gtk_accel_path "<Actions>/Editor/select-all-in-punch-range" "<Control>d")
+; (gtk_accel_path "<Actions>/redirectmenu/edit" "")
+(gtk_accel_path "<Actions>/Editor/duplicate-region" "d")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency2048" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleWaveformsWhileRecording" "")
+; (gtk_accel_path "<Actions>/Zoom/zoom-focus-right" "")
+(gtk_accel_path "<Actions>/Editor/remove-last-capture" "<Control>Delete")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE" "")
+(gtk_accel_path "<Actions>/Transport/GotoZero" "KP_Insert")
+(gtk_accel_path "<Actions>/Transport/GotoEnd" "End")
+; (gtk_accel_path "<Actions>/redirectmenu/cut" "")
+; (gtk_accel_path "<Actions>/redirectmenu/newinsert" "")
+; (gtk_accel_path "<Actions>/options/UseMMC" "")
+; (gtk_accel_path "<Actions>/options/MeterFalloffOff" "")
+(gtk_accel_path "<Actions>/MouseMode/set-mouse-mode-object" "o")
+; (gtk_accel_path "<Actions>/Editor/PullupMinus4Plus1" "")
+; (gtk_accel_path "<Actions>/Editor/MeterHold" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-cd-frame" "")
+; (gtk_accel_path "<Actions>/options/StopTransportAtEndOfSession" "")
+; (gtk_accel_path "<Actions>/Main/Cleanup" "")
+; (gtk_accel_path "<Actions>/Main/Snapshot" "")
+; (gtk_accel_path "<Actions>/Transport/ToggleVideoSync" "")
+(gtk_accel_path "<Actions>/Transport/ToggleRoll" "space")
+; (gtk_accel_path "<Actions>/RegionList/SortBySourceFilesystem" "")
+(gtk_accel_path "<Actions>/Common/ToggleColorManager" "<Alt>c")
+; (gtk_accel_path "<Actions>/Common/About" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency32" "")
+(gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatWAVE64" "")
+(gtk_accel_path "<Actions>/Editor/brush-at-mouse" "<Control>b")
+; (gtk_accel_path "<Actions>/RegionList/rlShowAll" "")
+(gtk_accel_path "<Actions>/Transport/Rewind" "<Control>leftarrow")
+; (gtk_accel_path "<Actions>/RegionList/SortByRegionTimestamp" "")
+; (gtk_accel_path "<Actions>/options/VerifyRemoveLastCapture" "")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectPhysical" "")
+(gtk_accel_path "<Actions>/Editor/step-tracks-up" "uparrow")
+(gtk_accel_path "<Actions>/Editor/playhead-to-next-region-start" "period")
+; (gtk_accel_path "<Actions>/options/SendMMC" "")
+; (gtk_accel_path "<Actions>/Editor/toggle-auto-xfades" "")
+; (gtk_accel_path "<Actions>/Main/AudioFileFormatHeader" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldShort" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldMedium" "")
+(gtk_accel_path "<Actions>/Editor/select-all-before-edit-cursor" "<Control>e")
+; (gtk_accel_path "<Actions>/Editor/Subframes80" "")
+; (gtk_accel_path "<Actions>/options/FileHeaderFormatCAF" "")
+(gtk_accel_path "<Actions>/Common/ToggleLocations" "<Alt>l")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurface" "")
+(gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency256" "")
+(gtk_accel_path "<Actions>/Editor/select-all-between-cursors" "u")
+; (gtk_accel_path "<Actions>/Editor/LayerAddHigher" "")
+; (gtk_accel_path "<Actions>/Editor/Solo" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency1024" "")
+; (gtk_accel_path "<Actions>/Main/ExportRangeMarkers" "")
+(gtk_accel_path "<Actions>/Editor/set-playhead" "p")
+; (gtk_accel_path "<Actions>/Editor/toggle-xfades-active" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-bar" "")
+; (gtk_accel_path "<Actions>/Editor/LayerLaterHigher" "")
+; (gtk_accel_path "<Actions>/redirectmenu/selectall" "")
+(gtk_accel_path "<Actions>/Editor/editor-copy" "<Control>c")
+; (gtk_accel_path "<Actions>/Snap/snap-to-quarters" "")
+(gtk_accel_path "<Actions>/Editor/temporal-zoom-out" "equal")
+; (gtk_accel_path "<Actions>/options/UseSoftwareMonitoring" "")
+; (gtk_accel_path "<Actions>/Editor/Subframes100" "")
+(gtk_accel_path "<Actions>/Editor/mute-unmute-region" "m")
+; (gtk_accel_path "<Actions>/options/OutputAutoConnectManual" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-region-sync" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-previous-region-sync" "apostrophe")
+; (gtk_accel_path "<Actions>/redirectmenu/clear" "")
+; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceFeedback" "")
+; (gtk_accel_path "<Actions>/Editor/PullupPlus4Minus1" "")
+; (gtk_accel_path "<Actions>/JACK/JACKLatency512" "")
+(gtk_accel_path "<Actions>/Editor/edit-cursor-to-next-region-end" "<Control>bracketright")
+; (gtk_accel_path "<Actions>/Main/Recent" "")
+; (gtk_accel_path "<Actions>/redirectmenu/newplugin" "")
+; (gtk_accel_path "<Actions>/options/InputAutoConnectManual" "")
+; (gtk_accel_path "<Actions>/options/MeterHoldLong" "")
+; (gtk_accel_path "<Actions>/Snap/snap-to-seconds" "")
index 456859162f0876d8cc299ce0e240c699b4cdab51..9cf1ad359f62812d0b7c09f53d0484f25631a7be 100644 (file)
@@ -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
+
index 040c6464c1ba5c16fe18c1a8554e92779a503d34..f24d5280eaa324780cfbc10bd215008d1edf24cb 100644 (file)
                    <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'/>
                    <menuitem action='LatchedSolo'/>
                    <menuitem action='SoloInPlace'/>
                    <menuitem action='SoloViaBus'/>
+                   <menuitem action='ShowSoloMutes'/>
                </menu>
               <menu action='Crossfades'>
                   <menuitem action='toggle-xfades-active'/>
                <menuitem action='SendMMC'/>
                <menuitem action='UseMMC'/>
                <separator/>
+               <menuitem action='UseOSC'/>
                <menuitem action='StopPluginsWithTransport'/>
                <menuitem action='DoNotRunPluginsWhileRecording'/>
                <menuitem action='LatchedRecordEnable'/>
index 7d033680761a6a5f55ea017415d523dd1489bd5e..b008a4cd17177a34d1ec9b07caaf9f6081bf0aa1 100644 (file)
@@ -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"
 
index ad0a7b79c63c74d8c5d6504889bba132b0101ac0..6ed92ef8ac8c66e5d05c3622c179fd050d4be0ff 100644 (file)
@@ -15,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 (file)
index 2948559..0000000
+++ /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_message.h b/gtk2_ardour/ardour_message.h
deleted file mode 100644 (file)
index a9ac02a..0000000
+++ /dev/null
@@ -1,47 +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$
-
-*/
-
-#ifndef __ardour_message_h__
-#define __ardour_message_h__
-
-#include <string>
-
-#include <gtkmm/box.h>
-#include <gtkmm/button.h>
-#include <gtkmm/label.h>
-
-#include "ardour_dialog.h"
-
-class ArdourMessage : public ArdourDialog
-{
-  public:
-       ArdourMessage (Gtk::Window* parent, 
-                      std::string name, std::string msg, 
-                      bool grabfocus = true, 
-                      bool autorun = true);
-       ~ArdourMessage();
-
-  private:
-       Gtk::Label  label;
-       
-};
-
-#endif // __ardour_message_h__
index 3ecc618eba0b4d325ed082c70a4dfa7c5bc0042c..275c7d7cdcbb22191819a008d794d77e08109b5d 100644 (file)
@@ -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
@@ -333,6 +345,63 @@ ARDOUR_UI::configure_handler (GdkEventConfigure* conf)
        return FALSE;
 }
 
+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 ()
 {
@@ -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()
 {
@@ -490,6 +623,13 @@ ARDOUR_UI::every_point_one_seconds ()
        return TRUE;
 }
 
+gint
+ARDOUR_UI::every_point_oh_five_seconds ()
+{
+       MidRapidScreenUpdate(); /* EMIT_SIGNAL */
+       return true;
+}
+
 gint
 ARDOUR_UI::every_point_zero_one_seconds ()
 {
@@ -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);
        }
@@ -1243,24 +1351,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)
 {
@@ -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;
        }
 }
@@ -1595,12 +1729,6 @@ ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window)
        return TRUE;
 }
 
-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;
+}
index 45a795dec38320ebd6fd2a5363a7c88f5d360bd5..171974deaa6bd8a5948531e206f2a5cb7c4dea77 100644 (file)
@@ -15,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__ */
index a39bcb124d4ddbd8b60aa261b9c3e30b3386bc7b..eec94b525f4dd7e82d02be1262848b165048d99e 100644 (file)
@@ -15,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>
 #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);
 
@@ -83,46 +85,14 @@ ARDOUR_UI::setup_windows ()
        return 0;
 }
 
-void
-ARDOUR_UI::setup_adjustables ()
-{
-       adjuster_table.set_homogeneous (true);
-
-       online_control_strings.push_back (_("MMC + Local"));
-       online_control_strings.push_back (_("MMC"));
-       online_control_strings.push_back (_("Local"));
-
-       online_control_button = new GlobalClickBox ("CONTROL",
-                                                   online_control_strings);
-
-       online_control_button->adjustment.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;
                }
@@ -749,6 +696,13 @@ ARDOUR_UI::mouse_shuttle (double x, bool force)
        return true;
 }
 
+void
+ARDOUR_UI::set_shuttle_fract (double f)
+{
+       shuttle_fract = f;
+       use_shuttle_fract (false);
+}
+
 void
 ARDOUR_UI::use_shuttle_fract (bool force)
 {
index 9c6daa8952f724a439cfcbdb0894432cb0b94956..5617cdbc4f3c87015ebf04cc625ec1b71a9d3bd4 100644 (file)
@@ -15,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
index 140ee649ea59f07b678609672b01e9e67b13858a..765eb53282eac390ca10c588522a5469c456af48 100644 (file)
@@ -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")));
        }
index b6e31d12d821ac098114e0566270ef6b391ffd66..7f0ddeef78f04ea00686229f4b4e714f1c9b3d7f 100644 (file)
@@ -15,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);
@@ -526,6 +542,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 ()
 {
index 991f37c3a7a2cb4669bf1ec842049f638d824a78..dfc5d644b0765fb924f846eb59d7ffc2d5d35d7c 100644 (file)
@@ -15,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;
 }
+
index 5674d6dee1099e8da27b024ca721544341b9ee06..c7db8f4ec60c1927b87712b570ab846b4366258d 100644 (file)
@@ -15,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"
@@ -63,6 +63,12 @@ ARDOUR_UI::toggle_use_mmc ()
        ActionManager::toggle_config_state ("options", "UseMMC", &Configuration::set_mmc_control, &Configuration::get_mmc_control);
 }
 
+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 ()
 {
@@ -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:
@@ -225,6 +231,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)
 {
@@ -389,6 +428,12 @@ ARDOUR_UI::toggle_LatchedSolo()
        ActionManager::toggle_config_state ("options", "LatchedSolo", &Configuration::set_solo_latched, &Configuration::get_solo_latched);
 }
 
+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 ()
 {
@@ -471,6 +516,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 ()
 {
@@ -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")) {
index 481e91b09a052779c4c77c45edbf84e2ce872fe1..1334bfdc4b498d449ccad14f6587d8ea5785bff3 100644 (file)
@@ -15,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
index 662cb949e64deeb5880176ee32fcc147c8e01b93..f0790dcbc8748e92e7c4ded609b729ba457c3c0f 100644 (file)
@@ -15,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__
index b7106a079660ec16bd3eeafdd68a9b48317e2f7b..4f1d0852bdeec14e746966a3e8b6f49eba0d88aa 100644 (file)
@@ -15,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>
index a84aec27c0f8136a87a9a764a9e0852fe86e34ad..024f390d409f3702d60030ddb5b9101dea11e833 100644 (file)
@@ -15,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__
index 4bded299b443408c1a6310fddcdca26156b59915..ee2dd63b6cb39eca1a3fd3fb9fd90368836e176c 100644 (file)
@@ -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;
index a59972b807c90e903735a4ff9f700d7f6aa69ad0..233e1a7c9b050d3c2ca41d6ac1b6d42fe92e8398 100644 (file)
@@ -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__ */
index 11d151fb914a49c5843d7260b48af558c7e5ab71..5e0728b05ab4855a65b393f1cdac19cd9bc693bb 100644 (file)
@@ -15,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");
index 95bd8c0955f86d268060d3545b6f7c2f0b1e21a7..d8c3f07cc1837dedab895b0b86e5557dae897418 100644 (file)
@@ -15,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;
index 74e4f64e3c81ce00d8f378fe41a04af7bee4377d..006543df18ac15f51aa9d82bfef1b69a0e64ab7f 100644 (file)
@@ -15,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>
index 55986898555fdf5c3f19e48e3a42518a0343cd2d..4978a1ef68e14cde3752b87268450eb98c7cbad3 100644 (file)
@@ -15,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>
index 1349efac4bd4ff8f9faf5ecb934b4bfefd3b058f..4942643b65d8bf2461572965ea4aacdec80a17ec 100644 (file)
@@ -15,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__
index aacfbdde75972ac92cc8bf338bae87538019c900..04cfb0a31109bde247112be15b79cd8d400ae515 100644 (file)
@@ -15,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>
index e69fdf0540fe48611585b3b6e661e2ff8797b1db..0c57eebfca5da2d1fbea5cb5e05238004ff4ac56 100644 (file)
@@ -15,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>
index 4ae8f8d46e597ce0e15818c0d615f96e06336834..51f744c4e550e7cbd38fadb5a70d6ca7fb1f89d0 100644 (file)
@@ -15,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__
index 6c2e5ab8b6fe0400b6157f89626a3de7b8f0b49c..7c66c5e1dba27d78d1a274b5125cf35e6b1addf0 100644 (file)
 
 #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>
 
 
index d59096e68b40279d28139eedd078b2399077f69b..54339b9e3a999e390613bd00f1942d1fd8973244 100644 (file)
@@ -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
index 747761ea9ae887e6fb1dfb5425580f5aa535ce3d..c8e9f613327aa0edea45d315b815f4d4ec9846f1 100644 (file)
@@ -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
index e6bdf1de4dbf25954434997f215b333315bf20f5..6997a61c70d9554641b7f9f1f283cbd21eada6d5 100644 (file)
@@ -104,3 +104,6 @@ COLORID(cTrimHandleLockedStart)
 COLORID(cTrimHandleLockedEnd)
 COLORID(cTrimHandleStart)
 COLORID(cTrimHandleEnd)
+COLORID(cEditCursor)
+COLORID(cPlayHead)
+
index a7c6e265ed5adb6aa14c4bcba5c85eda031d35e9..79d7605497c4ce849cdd51c83f2fc108d6819cb2 100644 (file)
@@ -15,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>
index 71d201cd8df2a3bfe2022ae5bccff71e40feb841..aca85c7a83482d32e048832a553a67752cec6821 100644 (file)
@@ -15,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__
index 208ef13aab7f5f4a5cb01cc78f63bb6eeb5f5a65..26d61035ba566447abfd8a0e3ba5589c8d1970d6 100644 (file)
@@ -15,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);
index 3c9a6a13c10a9f3248cc22c72dded9fd17222bf9..4f2a617d9205bbabd8308a04dbe5267889733f7c 100644 (file)
@@ -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;
index 281a3251bcb508be105f7cd587477f6d02e2b8e0..ef43ee987346bbf4b174641bd6a370f041d8a775 100644 (file)
@@ -15,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>
index 730813f78cfb099633ecf1378eca463a30132afb..556d8c80c59ac7b793391fc824d69e8cb638a95a 100644 (file)
@@ -15,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__
index 0f77f157f63f78cc228697ac2b68515c4d737f10..4df3b4ea11a33ec50945fd540bd3a5c79561a3c4 100644 (file)
@@ -15,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;
+}
index b0eaa83fd9004246fc4a173c0a4bdbd2fbcb5d0d..2e4b81208b695cc6ed8b1f3f21ff53c6843a1334 100644 (file)
@@ -15,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);
index 138fa8510e8cda7e48783c0e98e59f3762e22d62..e04941b32b4d6894e7f0895bf26f6065217ad05c 100644 (file)
@@ -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());
index a7d7d0de967ff7e11fe4d78cef0dc38545a4f386..2d7a7e2435239910d062213ea1b2fcb88241cc0e 100644 (file)
@@ -15,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);
                        } 
index f524dcdd40d1ce4167ddcb4db4f9a60a4f4cac2c..31f382dbffdef20a10941af0f1038f657f78be47 100644 (file)
@@ -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);
        }
 }
index 417d4ab0c4cbdfc5d3facf0ff54f973ce4a46bc5..617e3f4c8ead03a047fc0f6f15fb001b632e7f11 100644 (file)
@@ -15,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);
+}
+
index 4e0d6d5fe3ecde3f6f9a0ac3599e6503c4c8a38c..4a23e8b31608fd11ffededc23270b1a3ebac181e 100644 (file)
@@ -15,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) {
index 7cd13cf686fe636416d03bf1b0446d8000ab46c3..239d27d4f98dd413358e755f9100cc016c083117 100644 (file)
@@ -15,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;
index 2ee1773646b78327812f95a0f0c4c900fa6a57a9..20179f84c65b923fb0294d4555b5a90286c5b864 100644 (file)
@@ -15,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>
index ce7de29aa1aa28e7d7f69977104ba198e2fc541c..10438bfb023085c20b192f45577906db3e79b120 100644 (file)
@@ -15,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>
index c95d9230928381b64790030af129e0df7e788761..f5f94c416372ada64ea1ef53a5a4f932b964dc08 100644 (file)
@@ -15,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
index 84419dbe7ffc615fa380a647548788deef340d35..eb78fb5c7f7ba9b25943be5a26d49b4b27517120 100644 (file)
@@ -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"
index bfe61eae5cc165577bee12fd3d585297b57c61e0..e9082445c441b40e1bf69d4d2da2ba82b4cb0635 100644 (file)
@@ -15,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>
index 1bcaafd27957f1a045f801b012698b9498592630..b3081e8c8add34b17ca5d1720c45965c1db540b0 100644 (file)
@@ -15,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;
 }
 
index 238a45c4d13b05d253e37c04186d11f2ccd82090..06e99d0fbbe334721ee1accd61f6a7bd11e94c1d 100644 (file)
@@ -15,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)));
 
 }
 
@@ -560,6 +560,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 ()
 {
index 0e8901b88175e8c4c307e3ba87dd191a8107ce0c..cf0f831fa893462f903f876bfc872a915f416158 100644 (file)
@@ -15,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 ();
                }
-
+               
        }
 }
 
index a7095d9e090f70a7aad0def54fd01d2f22601640..e007a225d8448ef0e6f58e5ef48a847b2e818e45 100644 (file)
@@ -15,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));
index c6f5eeeb4819150def674e88a44e8d500b9ffb7f..1420fd6fc233cc163e8d062452b07f0de0552578 100644 (file)
@@ -15,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>
index 3a2658c204edff514a6927e4fa46bba7013372d0..fbf384ace95dc20a64a8d58241a0647f4897306a 100644 (file)
@@ -15,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
index 5bf704f649851d70c0d9382984eec669387c0aaa..5b1b9c63deb855b86963a5307cf733157857a8b8 100644 (file)
@@ -15,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>
 
 #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;
 
index 216e3a8e1be3c01c13b554d602e31f59fc8c9340..5c97685ee8b1fc989f8adbe35cd8093ccee1c9a8 100644 (file)
@@ -15,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>
 #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 ();
 }
index bc2328b52411039270093a045c5065c40336bf0a..9cf09d0acec10db2a2de5c8bd596b2bb82bcb704 100644 (file)
@@ -15,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();
index c1f563658b571aa7a8131bbea6559531b27ab224..3052fb72fa6428adc58c26ea5aae4df390e9ad71 100644 (file)
@@ -15,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)
index 864e527b595d408fe6a25028b390b43caf4948c5..1d75bf5d13e53248dbfad3aaf192a8493e5ee91b 100644 (file)
@@ -15,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"
index 8aa978a79c65f83a7ef135b6689981573d587570..ae2bda903e8f38342077c0d39927f65e1ccb1a56 100644 (file)
@@ -15,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
index bfc5ee85cdd1479cfe763236f23b17b51254e6ef..45cc42b11c54c0866c097b466990d87dc020ea81 100644 (file)
@@ -15,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>
index 921e6776aacbc6f981b36fc8b3e54f0edb63b208..bd5292032b109f6e9cc242592666156a85631340 100644 (file)
@@ -15,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());
 
index 13b327fe50d2b051f2d71d96687f32ad6751d681..2831384cd3680fd05de3bc179dcc3f2f75a9796d 100644 (file)
@@ -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;
index c91e1c101a25514e0fe6f3156942ed27904eea95..1184294a6712e6f5fd6314f80ade182486650ba9 100644 (file)
@@ -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;
        }
        
index 7aae9640bf3dba29742f5bb80f98c2f4657f3049..7d231c62d5f84bd39d749e057404541f5f2e3f98 100644 (file)
@@ -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
index 30ff05dc5ccfc0897e4fd3364009aa6c2432e0b5..cb3804c11b224f3694c4d6264cd3a22f3ada6b11 100644 (file)
@@ -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);
 
index 7cd7fdc06f64bdca7e72215130c3efdf87110413..006f9675b3c8640787873920cda5fd32d0fce555 100644 (file)
 #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 ()
 {
index c1261fdf236c44c6722b3898841f297445cf6f90..9890854d4b91e2ec7e42ffd0b4c1e495955285f5 100644 (file)
@@ -15,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>
index 2d7cd5883ef92ecd5e3981ce895285bf824453df..fa719bcca230a9c39b018b2a09bca52e2e50eb3f 100644 (file)
@@ -15,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"));
index 88105ce846afdd99ede76101053e4523c93d52b3..a24b93c034a21631df2c315236b60f8c3f9e033c 100644 (file)
@@ -15,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;
index 0255035ea1504f65e290f6c3720f3842d46ee402..77b22f942c6d3cdd7382a9a87868f2cb131df13c 100644 (file)
@@ -15,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/grouped_buttons.cc b/gtk2_ardour/grouped_buttons.cc
deleted file mode 100644 (file)
index 64c58d8..0000000
+++ /dev/null
@@ -1,96 +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$
-*/
-
-#include <gtkmm.h>
-
-#include "grouped_buttons.h"
-
-using namespace std;
-
-GroupedButtons::GroupedButtons (vector<Gtk::ToggleButton *>& buttonset)
-{
-       uint32_t n = 0;
-
-       buttons = buttonset;
-
-       for (vector<Gtk::ToggleButton *>::iterator i = buttons.begin(); i != buttons.end(); ++i, ++n) {
-               if ((*i)->get_active()) {
-                       current_active = n;
-               }
-               (*i)->signal_clicked().connect (sigc::bind (mem_fun (*this, &GroupedButtons::one_clicked), n));
-       }
-}
-
-GroupedButtons::GroupedButtons (uint32_t nbuttons, uint32_t first_active)
-{
-       buttons.reserve (nbuttons);
-       current_active = first_active;
-
-       for (uint32_t n = 0; n < nbuttons; ++n) {
-
-               Gtk::ToggleButton *button;
-               
-               button = manage (new (Gtk::ToggleButton));
-               
-               if (n == current_active) {
-                       button->set_active (true);
-               } 
-
-               button->signal_clicked().connect (sigc::bind (mem_fun (*this, &GroupedButtons::one_clicked), n));
-               buttons.push_back (button);
-       }
-}
-
-static gint
-reactivate_button (void *arg)
-{
-       Gtk::ToggleButton *b = (Gtk::ToggleButton *) arg;
-       b->set_active (true);
-       return FALSE;
-}
-
-void
-GroupedButtons::one_clicked (uint32_t which)
-{
-       if (buttons[which]->get_active()) {
-
-               if (which != current_active) {
-                       uint32_t old = current_active;
-                       current_active = which;
-                       buttons[old]->set_active (false);
-               }
-
-       } else if (which == current_active) {
-
-               /* Someobody tried to unset the current active
-                  button by clicking on it. This caused
-                  set_active (false) to be called. We don't
-                  allow that, so just reactivate it.
-
-                  Don't try this right here, because of some
-                  design glitches with GTK+ toggle buttons.
-                  Setting the button back to active from
-                  within the signal emission that marked
-                  it as inactive causes a segfault ...
-               */
-
-               gtk_idle_add (reactivate_button, buttons[which]);
-       }
-}
diff --git a/gtk2_ardour/grouped_buttons.h b/gtk2_ardour/grouped_buttons.h
deleted file mode 100644 (file)
index 2bb067f..0000000
+++ /dev/null
@@ -1,49 +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 __gtkmm2ext_grouped_buttons_h__
-#define __gtkmm2ext_grouped_buttons_h__
-
-#include <stdint.h>
-
-#include <vector>
-#include <sigc++/signal.h>
-
-namespace Gtk {
-       class ToggleButton;
-};
-
-class GroupedButtons : public sigc::trackable
-{
-  public:
-       GroupedButtons (uint32_t nbuttons, uint32_t first_active);
-       GroupedButtons (std::vector<Gtk::ToggleButton *>&);
-       
-       Gtk::ToggleButton& button (uint32_t which) {
-               return *buttons[which];
-       }
-
-  private:
-       std::vector<Gtk::ToggleButton *> buttons;
-       uint32_t current_active;
-       void one_clicked (uint32_t which);
-};
-
-#endif /* __gtkmm2ext_grouped_buttons_h__ */
diff --git a/gtk2_ardour/icons/crossfade_in_constant.png b/gtk2_ardour/icons/crossfade_in_constant.png
new file mode 100644 (file)
index 0000000..ce7d480
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_in_constant.png differ
diff --git a/gtk2_ardour/icons/crossfade_in_dipped.png b/gtk2_ardour/icons/crossfade_in_dipped.png
new file mode 100644 (file)
index 0000000..667e9d9
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_in_dipped.png 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 (file)
index 0000000..a55dab5
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_in_fast-cut.png 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 (file)
index 0000000..fe76c3b
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_in_slow-cut.png 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 (file)
index 0000000..a105967
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_in_slow-fade.png differ
diff --git a/gtk2_ardour/icons/crossfade_in_transition.png b/gtk2_ardour/icons/crossfade_in_transition.png
new file mode 100644 (file)
index 0000000..482e8a6
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_in_transition.png differ
diff --git a/gtk2_ardour/icons/crossfade_out_constant.png b/gtk2_ardour/icons/crossfade_out_constant.png
new file mode 100644 (file)
index 0000000..602ba80
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_out_constant.png differ
diff --git a/gtk2_ardour/icons/crossfade_out_dipped.png b/gtk2_ardour/icons/crossfade_out_dipped.png
new file mode 100644 (file)
index 0000000..3f1e84c
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_out_dipped.png 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 (file)
index 0000000..33eaafe
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_out_fast-cut.png 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 (file)
index 0000000..fd62602
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_out_slow-cut.png 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 (file)
index 0000000..d752879
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_out_slow-fade.png differ
diff --git a/gtk2_ardour/icons/crossfade_out_transition.png b/gtk2_ardour/icons/crossfade_out_transition.png
new file mode 100644 (file)
index 0000000..a48e645
Binary files /dev/null and b/gtk2_ardour/icons/crossfade_out_transition.png differ
index bc59fec2c0cb2ce4c4e4aca948001f16c955ffb8..7ff05ee9e94b693986d7f991d728a309ac0d333b 100644 (file)
@@ -4,7 +4,6 @@
 #include "imageframe_p.h"
 #include <libgnomecanvasmm/private/shape_p.h>
 
-/* $Id$ */
 
 /* rect.c
  *
index b2ff25b408d5026b6a2a4f7f26820fbf47fa331a..76787f8b88669ba6ba876022b806828a5f740f00 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <glibmm.h>
 
-/* $Id$ */
 
 /* rect.h
  * 
index a7f4d603a730f48a7ef25ac184846e8ec0f37298..96b61cafdd301bedc783b692fa32013c31680e6e 100644 (file)
@@ -15,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>
index 4dd8d696504e16fc213f725d40363a0636153eed..3a87f5bf718e446a2267e37fa9bbe0acc4e97c55 100644 (file)
@@ -15,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__
index ae288ec9ab28738828a9ebd4f61a0b0a8eef3fba..018fae68959e169c849bd65171cd050d64cfaa09 100644 (file)
@@ -15,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>
index cefd0c5d097f44333d42c716e4958e1b5a8a852d..4b3bf0c857faaff59dd80cf61a77907601bdecec 100644 (file)
@@ -15,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__
index 647d45b96327f0175fbe0969f2dddd3f5ff6cb7c..5dc76978b06dec938f1be6232f0e3ce6f2d10f9d 100644 (file)
@@ -15,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>
index 4619ae448a4da54016e40f636c46d2e336dc6085..ba7790c04aa0bb831c8dc0b7082aff26ca8d4afb 100644 (file)
@@ -15,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__
index 6e896ea5ecb93a789abe123a2619e979dd521f0b..91575f3cc54522f21881c35c995ba7e9a259ba04 100644 (file)
@@ -15,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>
index d51901d4e08ee4358702f4daa0ea7eb5b3e40e30..45725038d1f81ff339c14ec8b9eef664287d39b4 100644 (file)
@@ -15,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__
index 2c943dcae474181cc25209fa0c071d6a7ea8ac11..f8bba3aa842cc576d9b68be327cde5400878e165 100644 (file)
@@ -15,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>
index 71d9268fef358508bef3e69cc530d57df9c48993..db83264e46764061a3efbc383f3da05cb2780713 100644 (file)
@@ -15,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__
index 00d24287ed193b0846963d37cf4266123f56bd9c..5ad04b929d013ee19666df149868ffc698e8f75f 100644 (file)
@@ -15,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>
index 288edd0be552f0d9d5f1aacff5202ebd8d32ab0f..430926f76110583c6b50d645ef316dc46b3bc84b 100644 (file)
@@ -15,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__
index a6a14ad55b23c80494781eacbfea6841333ee275..83918da91836da6173ec10cc520856651a749968 100644 (file)
@@ -15,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());
index c13b06afe50f6dad2ff204fda0926303b713e297..ec55dc54db7e4ddd111fb3a983c7d1fc031211be 100644 (file)
@@ -15,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 (file)
index 71e4e96..0000000
+++ /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 (file)
index f542261..0000000
+++ /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__ */
-
index 6aaea06a7ea0aaeacb3b73c139b325c4ae00b3a7..1f7ba8d4c082c225c0af691eed9706c7bb02016d 100644 (file)
@@ -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)));
index b77c3a55615447bc0aa30807b86fe906620c7d36..e13366fd12d6a66b0a57944736a121451f94c640 100644 (file)
@@ -15,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>
index 580d47ff5d0eed5d4f7c265ac1b7136bcc7c1895..51daa6814da418332b646992ee017e24b16a769a 100644 (file)
@@ -15,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;
index e7ede36b39ee9f558fde5d05e1aa6199cddc2776..41a279f604983dca909ed36e60b37d509f9107f7 100644 (file)
@@ -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
     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;
 }
index d5517b4bcedeed72ae4c536a8bda071f1921771a..918a2786c9fffafd3c30f1f81eae6b12f9df2e0b 100644 (file)
@@ -15,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>
index e2e430778290d2e38ab8be3fcb3b9826239272f3..7865004d54e15de0a509f1fad2b397014e07ee8f 100644 (file)
@@ -15,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__
index 1c6e7af2c79e81817734e0324f770d582553c383..e10967d01a61778ed58f64695061afddc87ddaca 100644 (file)
@@ -15,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>
index e321fe40031b51c5085758261568ae189307ac6a..13288ce66f661f64d41591ea88f2f93a2782c9b1 100644 (file)
@@ -15,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__
index b6e87f871564a3cf8c0288b33ecc40e56e2a7fbf..f33e0bbefc202d4ba3c67a473b65a8682d2ff3af 100644 (file)
@@ -15,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>
index 4853f298552cdb998eb7eeacb2fa2f2a113067ce..fd23c1de878e1ed689ba4ab349cca91a07796a60 100644 (file)
@@ -15,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__
index f45a3ce9710432e7de3d6ee876a969db98a77dad..d82554f891e919322276f87acf66715161977348 100644 (file)
@@ -15,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>
index 04b85876495316e79cb30542c4a12c7e3c2f63e5..6c49a4dc0f606734340a89194bcaeedf0c17c0f2 100644 (file)
@@ -15,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 (file)
index 0e88eff..0000000
+++ /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 (file)
index 6ceb740..0000000
+++ /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 (file)
index 8a91603..0000000
+++ /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 (file)
index bdce16f..0000000
+++ /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__ */
-
-
index edc66c92bbf677e5299ea21bd5c8be53e5732884..bef8ee787f1272cd7d4808ab326b19acfcb0cf15 100644 (file)
@@ -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;
                }
index 430f774eb6f68abe1845c53dd98748e3abd18ef1..ea2569b644c5dc554a8cb41cf971ba2f01b03e8f 100644 (file)
@@ -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();
 
index f20171f9fba1553a55712dab0f841ad65dd464e5..d1089e48e6ab2e2c700da392d92bf02f082bd4d7 100644 (file)
@@ -15,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>
 #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;
        }
 
index 2a5b416ae0b995e8428cd72b5f60d117c31e2f19..bf9c9cbd18c6b63bedaa42776ea6d05ef4030503 100644 (file)
@@ -15,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;
index 9e094c9ad041d08019a511cd80d4ad07412539ef..4875ff835a2aa1a3763b6a487a49166bc1e2dfbd 100644 (file)
@@ -15,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"
index e0f488dc801a4705241063723f8f96c276163c21..0d4124f8cc9f1eac93bb940d3f7f526aa91d1bee 100644 (file)
@@ -15,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++ -*-
index 1c76f8079b5193496b15b751374c7a05191acea2..5dd972719337f5ba25b1708b61de00c811046c1b 100644 (file)
@@ -15,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>
 #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());
@@ -555,13 +560,23 @@ 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: "));
        }
 }
 
index cc28a74e603620e5e0b292b2e91338ab8a8726f7..7754b0555dc747b9e25dc23f616c84199800a424 100644 (file)
@@ -15,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();
index 792fde3a10a6df60edddc3ae21d7783f88c09042..608f684fc9f41ef587cfa42862b17c57b65afab7 100644 (file)
@@ -15,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;
index 710621ac6526d4888ac5b5eb4a064a43fc097fc8..fb780fc8aa3457db18aa2f0ceae6c4724682653f 100644 (file)
@@ -15,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__
index c484673c996136957f03a88fc35c0d9a3bf288a6..c008a10ff08903c554615f8a20e3a1cc02834e5b 100644 (file)
@@ -15,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>
index bb9b43218426bfe33219f85527cb98bc6cac99ca..d54d6b89ac9bc540c068127fade1d7d25f8210fe 100644 (file)
@@ -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);
index 1e6e4c16c943497925d5c2a9b047a6b745c25b99..34f367b25b1ba978f8c8c996142bcc8b66eb7ffe 100644 (file)
@@ -15,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;
index 1bf8879ba5d40e71d23c183db7a468689483875e..fb4929ad2d30685602fa6e694132b485632d5001 100644 (file)
@@ -15,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);
index af5379b40f9cf35f0498e3c8e0ec8dfd6b66118c..8f9a1b13949da012a907c991db646c15a0b6affb 100644 (file)
@@ -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"));
index 79a8085488da10231c0a0322073588ca4e3da1fa..d587359ecdf62ba74e80d70df88ed217290c9472 100644 (file)
@@ -15,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__
index ddb771bb1841b5a75238bb6ad07a1b0b13f7bf73..0ee99d141368cdc7906db1e81e09c2261ce8d907 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 
 */
 
index 8a52e8587f673e738bbb0b358ac5f846459e00fe..1283837e0cc75d0cc1f3ca53ff72fdad25e1a094 100644 (file)
@@ -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
index 26f38250a530a70cf64ee8b72e2441508e9d20e1..90d19d81b6aec6a3c97aedb7ecfd461bc13fb96b 100644 (file)
@@ -15,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)));
index c1d538b3d13e56ae9a4f6cd8015f4103a0a33589..2f15356c615c6f30e727c454a0a19a3bc8d27d5d 100644 (file)
@@ -15,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__
index 7a11f8bb1df9c6968d516c0fba12ec40c5193272..e5db030c2d544a864451de09781073603200694c 100644 (file)
 # 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
-#, fuzzy
-msgid "Solo in-place"
-msgstr "Соло"
-
-#: gtk2_ardour/ardour_ui_ed.cc:426
-msgid "Solo via bus"
-msgstr ""
+#: 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:429
-#, fuzzy
-msgid "Automatically create crossfades"
-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:431
-msgid "Unmute new full crossfades"
-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_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_ed.cc:401 gtk2_ardour/ardour_ui_ed.cc:408
+msgid "Medium"
+msgstr "Средне"
 
-#: gtk2_ardour/ardour_ui_options.cc:424 gtk2_ardour/ardour_ui_options.cc:504
-#, fuzzy
-msgid "MTC"
-msgstr "MMC"
+#: gtk2_ardour/ardour_ui_ed.cc:402 gtk2_ardour/editor.cc:1359
+#: gtk2_ardour/editor.cc:1376
+msgid "Fast"
+msgstr "Быстро"
 
-#: gtk2_ardour/audio_clock.cc:1742 gtk2_ardour/editor.cc:189
-msgid "SMPTE"
-msgstr "SMPTE"
+#: gtk2_ardour/ardour_ui_ed.cc:403
+msgid "Faster"
+msgstr "Быстрее"
 
-#: gtk2_ardour/audio_clock.cc:1743 gtk2_ardour/editor.cc:188
-#: gtk2_ardour/editor_rulers.cc:359
-msgid "Bars:Beats"
-msgstr "��акт:Доля"
+#: gtk2_ardour/ardour_ui_ed.cc:404 gtk2_ardour/editor.cc:1360
+#: gtk2_ardour/editor.cc:1377
+msgid "Fastest"
+msgstr "��ыстрее всего"
 
-#: gtk2_ardour/audio_clock.cc:1744
+#: 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:435
+msgid "Solo via bus"
+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: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: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:824
+#, fuzzy
+msgid "ST"
+msgstr "УСТАНОВИТЬ"
+
+#: gtk2_ardour/audio_clock.cc:1801 gtk2_ardour/editor.cc:180
+msgid "Timecode"
+msgstr "Тайм-код"
+
+#: 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: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:127 gtk2_ardour/editor.cc:3618
+#: gtk2_ardour/editor_actions.cc:287
+msgid "Magnetic"
+msgstr "��агнитное"
 
-#: gtk2_ardour/editor.cc:136 gtk2_ardour/editor.cc:3595
-#, fuzzy
-msgid "Magnetic Snap"
-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:1782
+msgid "Envelope Active"
+msgstr "Огибающая активна"
 
-#: gtk2_ardour/editor.cc:1824
+#: 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:288
+#: gtk2_ardour/editor_actions.cc:283
+msgid "Snap Mode"
+msgstr "Режим привязки"
+
+#: 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: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:145
-#, fuzzy
+#: 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 ""
-
-#: gtk2_ardour/io_selector.cc:651 gtk2_ardour/io_selector.cc:678
-#: gtk2_ardour/io_selector.cc:731
-msgid "port"
-msgstr "порт"
+msgstr "Доступных портов JACK не осталось."
 
-#: 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:66
+msgid "<b>Busses</b>"
+msgstr "<b>Шины</b>"
 
-#: gtk2_ardour/new_session_dialog.cc:45
-msgid "Create Session Directory In :"
-msgstr "Создать каталог сессии в:"
+#: gtk2_ardour/new_session_dialog.cc:67
+msgid "<b>Inputs</b>"
+msgstr "<b>Входы</b>"
 
-#: gtk2_ardour/new_session_dialog.cc:47
-msgid "Use Session Template :"
-msgstr "Использовать шаблон:"
+#: gtk2_ardour/new_session_dialog.cc:68
+msgid "<b>Outputs</b>"
+msgstr "<b>Выходы</b>"
+
+#: 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: соединения"
index a10bd92f72a4c1ae9ba9fcfbc2e3d5b18e8f7f0d..0e1732b2371157c2eb3357cb03c6bf5f3a11534e 100644 (file)
@@ -15,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"
index 5e8e71f3c55334486a754aef2a1e440d49f77490..4e97e64e6ff32ce199a18a7976d74c1274a0dbf0 100644 (file)
@@ -15,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__
index 5821110b6cd202e53dc2914cf0a8234ad2c7946a..0baecd43d9a115650b406fab50a526762797ebe7 100644 (file)
@@ -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;
index 1ea5013295ef79d445483a5d0ba9be616d05a65f..b1b19d530f296592e3788267ed1e27107083dcb5 100644 (file)
@@ -15,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"
index ad39f6625cae4fd977aafa3c4cde12f9cf3dce18..71e4d23e6415aa721bfcc88fa553e35b9e7fd123 100644 (file)
@@ -15,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__
index 529c0b565da3e1e22d815ff37f81703e6feb7dc8..acffda4ff19034aaadc520d777943de22d75dde2 100644 (file)
@@ -15,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>
index fac6ede6f3a6a66252d9fb8b638cd1ac6e9d6ff7..63d3ec9d8ee47438f22e3193fdb1c18774952190 100644 (file)
@@ -15,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 (_("\
index 7ab7d03cac115cebc977d32676f8b008b0a61027..7e93efee1bcfc0f361c82e828f7430f64716f4f0 100644 (file)
@@ -15,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*);
index 70590b0db5886e155507c0e17e7e09da343e1d2c..394ad6bcfb4e780f9444bfd90e50cc4ae76c4d31 100644 (file)
@@ -15,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__
index aff5866c8d445fe3cffec35ac59ad3f5a9bd3680..f11ec2a307668d952ef3b6d8d5dd0c674a37e972 100644 (file)
@@ -15,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;
@@ -375,6 +384,18 @@ RegionView::set_frame_color ()
        TimeAxisViewItem::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()
 {
index 435e878bc8c5ec85cae7a3610f796b65f4bc5d93..74073b404e7ad9029e1f10b58141ccff0c2b5df3 100644 (file)
@@ -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;
 
index 310e0a224d47250ce14eae7fadbb3c39e7deb3a0..5660e90ee6f11d527320ed0e9bb0dfea36f4b781 100644 (file)
@@ -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__
index 14d9fa02cbc8b90d095da9397de252aa5c0c9eff..386815ea27e69320c39aef328a8195f8998c1c7b 100644 (file)
@@ -15,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());
 }
index 394383de6bbdf92cc12be23963f7c67244bdea11..c0b70cbdb1669c25a5c74b86cd47e9810be009c3 100644 (file)
@@ -15,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;
index 76f202dd92c8ba4da9cdc12aead47b5e6b41df83..5ad795c6f5e3b781538c2493c33d6f149b8ae6ce 100644 (file)
@@ -15,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>
index 60d301e762e500ba3640e1252fdf79979da5aad6..8f0cfaf5436fb0f4a900a671705a84d8207113cc 100644 (file)
@@ -15,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__
index 9684f74024b083469db5bfe8cfcdcc3dc1423874..b2f9ebf13f1798188f242831c23479189523f359 100644 (file)
@@ -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)) {
index c597f2893ca3a0fa774c3c87db666d398394bd4d..a72bc5a2cf6866b91b0a15e84d14f83432785a28 100644 (file)
@@ -15,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__
index e7fa77f4dab3682cbbd1b7a5f54c52f6115bb68b..303d05dc8625dd9cd5fc6903c7c13d10f11bbee8 100644 (file)
@@ -15,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,22 +355,30 @@ 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)
 {
@@ -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;
index bad47ac274393a0691ccf36a1ba94575e59b73ae..f7749b0b4b29cd06c6ce2341107e5259bc7d7a9a 100644 (file)
@@ -15,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);
index b52214c9c9610e14e5f4257f5ccd2bf2e09dc1db..51fc5da027bafb62d5013dc336d0215e22b5558b 100644 (file)
@@ -15,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__
index 8a34752cddde583560a30a10567b4fdc69647df8..8a9d27a4ed2c30762f62ad07e3017dcd8e4d5051 100644 (file)
@@ -15,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>
index 5422888536fdb0efe1ee92ea9f9bebed57339851..00bc6eeaaaed697fb89aef3d5e68fd70582d1266 100644 (file)
@@ -15,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__
index 5440112ad6cb5ad2c4ef322ca1b062641ac104cb..4e02ab9061d0e18cdc95b9b98aeaa2890be220a6 100644 (file)
@@ -15,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__
index c4656834a66919f2c67bf2e7cc7afa86e53d79e1..8faa3158481c1bd6b9921d272a320689392d6ad5 100644 (file)
@@ -15,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>
index b64e3c8e58328904be79a0ae468a44da8983a8f5..2d041bb4fe82a2184d28c97e9f81339dcf4ab0df 100644 (file)
@@ -15,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__
index f18b543e0ca424dd694b8bf49d21eba1a0cf733e..19e265b79e87dbd2eb5db84ef9b0689054a4f024 100644 (file)
@@ -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;
        }
 }
+
index fb0b7da60022e96456fa6d341800b9939d84e31e..bbc6e2edd49154ad1520c006e283c3c82dd2fc48 100644 (file)
@@ -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 ();
index 4a50ccb4aafae2a66f65c3128985ec98fc84f90d..b1fecba840a82595b28e3f18446ec9fec74dc753 100644 (file)
@@ -3,7 +3,6 @@
 #include "simpleline.h"
 #include "simpleline_p.h"
 
-/* $Id$ */
 
 /* line.ccg
  *
index 92afa4997512cc95d966f9402e524c1566b3d86a..3e23ace83b9bb12fda8082ba1bbdb5b2e4912ebb 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <glibmm.h>
 
-/* $Id$ */
 
 /* line.h
  * 
index b9bedbefd9c5560a3922db2469cdad0f1b00cd1f..bb69fc34ca72932efb8e534556d50e5dfd216053 100644 (file)
@@ -4,7 +4,6 @@
 #include "simplerect_p.h"
 #include <libgnomecanvasmm/private/shape_p.h>
 
-/* $Id$ */
 
 /* rect.c
  *
index 329823ab2fc9a5c3dafdb0a50d8327c82aa3a5ec..299b27a8682f28e4f937d0d749266344275a1413 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <glibmm.h>
 
-/* $Id$ */
 
 /* rect.h
  * 
index e697afddb9be121fadf029f6a5402800e3557758..f46d1c05dc9e8e6ac9c09c4d9692519a2eba5fd9 100644 (file)
@@ -15,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>
index fbedf19ebc3171188045370cd2a4627671694470..048c9bcc5bbc59fd7b54fce08c697bedf9d51e27 100644 (file)
@@ -15,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__
index c5816e36d15c1c832da595cbe63f23207d67aef7..4dae10814979c4d820cdc0fdfb2246938168a11b 100644 (file)
@@ -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
index 720a87c4ba6fd4f11b1ec6fd9cc2d224468e4c47..09a91dd3e301e3bb29c5a8229cee07e5f5897912 100644 (file)
@@ -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 
index 53a0ee45531bf137942f15fbecb9d4746faa3f2d..a0267d7e862aca50fbbc52e45fd82f326feeb3c5 100644 (file)
@@ -15,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 
 
index 96437a9991b55a211ac48f96f60ca46d670939ae..1f401967eb917adeafcc8a4004b2f4205c9562cc 100644 (file)
@@ -15,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__
index a008e2af1a97bf54ef254a1f8eff2eaaf7a23c0c..87eac74ccfeb2a30ace0219e225bfa0e1a27f516 100644 (file)
@@ -15,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
  */
index 80d917704187a75cdc7ba9ad2d670d712c36d6d9..d41ad5a327894c187367bd4890f219d5a0cb0a60 100644 (file)
@@ -15,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
index c0a05abc458ff13fa2edb0fad6425f5b8f0cfb86..eac7bd70f54ebf0dbf4f6caf01462ba40729581d 100644 (file)
@@ -15,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>
index 887494829eab97dbc8c4fd3102cd1bc029e6233d..fbebf0d51afc0a1a888a192ca4292bf8dbb811dc 100644 (file)
@@ -15,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;
+               
+       }
+}
+
index 6d5ff0702d8b7443577a6cb30ac58ea6db0894a1..2d2f879073f7badaeeeb2410c956536ade341093 100644 (file)
@@ -15,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__ */
index 20fe13603e742a8bb188edd6f0a057d7a2f9f045..b68597114488e8e95a2992d22476b0f15186e1a6 100644 (file)
@@ -15,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>
index d569ca37332ef5ac984790a39c72db08ec296caf..6d1396bc54a2e1b6c70fa398ca554c726e412ee5 100644 (file)
@@ -15,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__
index 5e65475c46acbcb155a89bffa22363eb05f39481..1320ccdc7a03ff3642f1565ef5bc875ed6794944 100644 (file)
@@ -15,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>
index 92e4fdd24a4bb6192952c162850ba747c3993308..d9316c110ea229496cd89582c85dfec9f6ab484e 100644 (file)
@@ -1,7 +1,6 @@
 #include "waveview.h"
 #include "waveview_p.h"
 
-/* $Id$ */
 
 /* waveview.cc
  *
index 56d0ed76753b9c178184c4b1984307584fc69222..cfa7fd416db4c5a7a3b7b0ab0fcba95daa65f287 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <glibmm.h>
 
-/* $Id$ */
 
 /* waveview.h
  * 
index 878b41e82af04094599c27f0d6081b13bc992099..772f8474005e8ac3e69f4fd0bbcbfd71dad6b248 100644 (file)
@@ -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')))
index 5cc2359632d36f60604c45c16fc1a70ee4b3f83f..332b9af7330044dddd9dff13f5dd249b401e2825 100644 (file)
@@ -15,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__
index 1da8903a41b1c61d62b86db8fcf91932a80bfba6..4846a20cbdc8463dcba98b971deb8eaffafb2132 100644 (file)
@@ -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
index e87434b0fbd5f14d4a5dc919323227415b23495a..3546545329e5f8f683f31109b529a69993fcf975 100644 (file)
@@ -15,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__
index 3dbd30f84156d190dbf6232f376c18009823747b..48a3426d53d9858ab0d03a7ec5f292c9ac8cfd53 100644 (file)
@@ -15,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 ();
index 0e1caf5245a9b42a832087e66fd06f42d36407d6..913cd7d5ed8d4593586892a469dd863702b15013 100644 (file)
 #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; }
 };
index c8762dbf694d66c6bd3233dfd80c0485178b6230..6b60544942891f40d46ab4f693efe8a6c3db4edc 100644 (file)
@@ -15,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__
index 36fe027a6fda44e74a219aad48a5d19c688b111d..39f41d5d1cf1fd4dea52e8fbf2b7b5bd2d1fb4c3 100644 (file)
@@ -15,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__
index e3c5db561dd7e936106e9e58a525a8396a9d2bbc..3b592a54ee3874f210a62a24216de13c2d0d815f 100644 (file)
@@ -15,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__
index 0734a66319b66183a7cbe6ab6470ed12e0b9728c..812c30e8c297ebfc18f2520316d8cba5fe03e82d 100644 (file)
@@ -15,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);
 };
 
 }
index e6091cfba0dd7852c11b93a59c1a40a84c287ee4..06d521ea219ba03a57f5ea0d5898db7617c000ef 100644 (file)
@@ -15,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__
index a2cfb23e61161fa179ddc0df7d344f4a0daffceb..007bad7259052240f5d8019962c5de64859bd776 100644 (file)
@@ -15,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__
index 71214978a56a7779ccaeb18d5a39b1eb547457ed..60499b98dac73606d3d4f8bab5056eb93126cbba 100644 (file)
@@ -15,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__
index bb49b2dce4703a308411f59ff675b291deb1424f..31cb74ab3343294f2e4fb41581ccd68aa7a6c4a1 100644 (file)
@@ -15,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__
index 8710369a6431b4af4fd78de3970fda9ead1d3585..81e282ff64fcc1a6527a330fa54c468cf17c8a4c 100644 (file)
@@ -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());
index 703352b3050f6841460911303a5bcb55f422b6f7..674a9232b5971203940a29ceffe01aa39bb3bfb4 100644 (file)
@@ -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 */
 
index da4d4e26840524c8988a8c9afd7a47bf42058cc1..d2f1cb4294e701f5b88961c9f3b5ba3005bf3b8c 100644 (file)
@@ -15,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__
index 3eafed818cf60dc03edcdbeac6d6bf9101c55c96..7346e645fb136e8fbf795258ab2ec597eebe6ff3 100644 (file)
@@ -15,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__
index 2ecf79c04ccd6aa7361a5dabbb59cb57f5b0ab40..b92806a6bb52dfdd2be61bfbbc8938dd44d460b9 100644 (file)
@@ -15,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__
index df984b74e0a4bf598d540d67e1908fc0dc6d165c..dd63439f08500db8dde2521f6df6fc3e48442984 100644 (file)
@@ -15,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__
index b9cbbbf0a8ded5550947f0a33c45228309cf6b0a..4e1a50e6026b09217fa0e86d9b32f5e888e80b90 100644 (file)
@@ -15,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__
index a6f34d59be5d16a77a72f09ccac99d4908de648a..f1422880b86cc974c6c75bb8e328302389db56b1 100644 (file)
@@ -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__
index 703de6fb1a1eff7aaff0d0684f1d51395ee1d550..b67e58106714a54a00581eec1ad0322299d948a6 100644 (file)
@@ -15,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 (file)
index 2e6f5d0..0000000
+++ /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__ */
index a81921b9f173973aa1663acd80c256b6240b0877..10b3bbfe920671729fc6f5999cfc085f0f089f95 100644 (file)
@@ -15,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;
index f66acec893ac9b3f0d264de05599f615b04a05dc..66e5b1b7d55ac216a24355f817198b4125039372 100644 (file)
@@ -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;
 
index 3613ea1a5a77dd1ca80438d7d7426f1f279b0422..5832f7110104e1595d9eeef4398487f615960574 100644 (file)
@@ -15,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__
index 51343b13c4d9df38584092c29391ac5f2ebcec8a..67efcc3583f334613944ad12219592f70c97a52c 100644 (file)
@@ -15,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
index 46feb55fbcf3348284a5d934fdc828d21dc88f87..bcc0097d7fcd1ddab556cde3bc5ac2db0bf5ecbc 100644 (file)
@@ -15,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
index 55d5792833768d3ce9bbe46d3cd049a4f5388634..e73a256310b48cd1ad8caa647ff90f65e33cb55e 100644 (file)
@@ -15,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
index 31e59e670488a0e7f401da267d13439e556282ab..e58cb717540d2c9d6a5e34a079395326056fa80d 100644 (file)
@@ -15,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__
index c4df46415b859b838ddd673002f5ae6592a81192..51423e9ab256424f11b3558a6ab88165e7aefc02 100644 (file)
@@ -15,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);
index 27e8bc5e842a7352b6ea17d57d296a741aaaa0f3..f1f1bb8811fe2df08daaaf5130774fd705185d37 100644 (file)
@@ -15,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__
index 57e13de5af3542ba1f9d3d5e338206ceb84f53e6..6625b7dbf5b384307a5954952a86814aa4f1fbc6 100644 (file)
@@ -15,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;
index ac60a10fd79e27a3b48c712f58a3f0e55fa83d14..dd58263313322a1d00f3225bf38120897bccf71a 100644 (file)
@@ -15,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__
index 653b61cb9517dc4b71c4c9273a916f6b761dadd8..5555f5437ec2fba1c8653356d782612b5a45aa34 100644 (file)
@@ -15,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__ */
index fd5777ccf640895202570aaa4865a3de7cc58bb3..7636099e1f62e5725bd9645c1daa3c1453502424 100644 (file)
@@ -15,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__
index 0a34f44a41bfa35a273b4a25c3031e694ce0a5a9..ca2f4488ddd077c84eb1acc5d6d70a0ef3efa486 100644 (file)
@@ -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
index 79bff7d2a5bd6bad667a6f660460133c11698349..9d6a7e7fb6e006794aa12b3b947ba2ee1841c3b6 100644 (file)
@@ -15,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__
index 6866e5325192e4cf189847171c12dc9d503e8671..5e6436cc94e66da64b0a51164e7b56b49f7b3375 100644 (file)
@@ -15,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__
index 9893f7391a69e20dda942844a8afb4564e10f64f..54863b6fb0878f97afc0c2dbc5308fec662646f6 100644 (file)
@@ -15,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__
index 603e0bef376c34006f0c3beb3ed9b337abbf982b..bf072a71c1a98f50b16b408a998f25bbdb94efce 100644 (file)
@@ -15,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__
index 431b55db8b81137c94cadfa5b0c2aa0c7c7d7780..feb86f1b7b2e4a2bf399d08ce234d7d6460c965a 100644 (file)
@@ -15,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__
index 8e6c0bd1c780ff3d4d1e5b8f822e2b580588d9ef..b4d2e5e99dcd86443a99c6491e37161be79cbd66 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <ardour/types.h>
 #include <ardour/plugin.h>
-#include <ardour/audio_unit.h>
 
 namespace ARDOUR {
 
index 4e4ad0fec6f51bde83ca17a2a256f9d98085ecf2..7891a0e6f20a7fdb725799e694aae232cb3bca50 100644 (file)
@@ -15,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__
index 8c3de09c105d4eb24f19e3bd3586ea6959646ab1..fac2241f143e6e2176730df235ad16f03176b11d 100644 (file)
@@ -15,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__
index 46865d8357b8b1568cc5e2fb3279a71eb2c32a54..716c7dec20cddfb7980b807e46d0766fea1037aa 100644 (file)
@@ -15,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__
index c60df990f2f4e9af5ee33cf62fe7054e5cd8cac1..3296c77c6219a3f62963171aeb0f0b575ca05a69 100644 (file)
@@ -15,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__
index 2f94e0c80a43548cfc72a366c09b0eeb036cc303..70091ef85d2caf0d93daa90cca11945931401df1 100644 (file)
@@ -15,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);
index d87d3fa3a487bbf18a839ce94bd1ac274423fc85..55448df45bc8f6c39ff8eaae10a9419c7045b8df 100644 (file)
@@ -15,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__
index eceb301bf87ab87b369e989823860bcfd6d33fd6..d4c0572811a072d0b56f639da174c170557257ad 100644 (file)
@@ -15,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__
index 63fa608499bb4d69960a6845f4021d1993513304..2022b21a05196309cb92919975218a1661c890cd 100644 (file)
@@ -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 ();
index addc896b0b2b987d4102d9e81cd817a8a1db3e8e..d5e32c7904c3f75d2fc15a819a107ac1de85348a 100644 (file)
@@ -15,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__
index 20cf4d8f2e7bd7f7a863df2c84d1bb8f78d6dd57..baeb74916d461351ef2afab02b5e1fab71ce10f5 100644 (file)
@@ -15,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__
index feacc14775a8cc76f80b6cf15b824e29bad412a1..0c70bf407d41be3c6f922a5fe7b5e46fb5e01515 100644 (file)
@@ -15,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__
index a110c2c3da986f2232bc018b5eb931171276cfd3..4169a3a51146df0d4b4d4af71480d0bde70abc50 100644 (file)
@@ -15,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 (file)
index 0000000..92ef076
--- /dev/null
@@ -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__ */
+
index d4a7e2f22a861a667fa1966b722351a2cf234ac4..170facb1debd76e97d29cb08518a6e2382f656a5 100644 (file)
@@ -15,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 {
 
index a5000a4b63dcf4adc15243527e59fe4d2ee7040b..2fc3872887644b3dfad3c7763f37af8bacdd4a8f 100644 (file)
@@ -15,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 ();
index 4a318e9750e71c610f449a2b83e334ae662f1394..c7157428ee4e3090b7c194a18e0869e9706a5845 100644 (file)
@@ -15,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__
index 8eaab14ec5ea9c7cec1eff4b8acc0c44b0e3fca4..45c91950fcb51375ca2f27a5f3a40151bec88c5f 100644 (file)
@@ -15,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__
index b69645b031e5b1795f45918506ef892ea209ee97..a8b0ae54a3fe41070ff609e80f6166b1d55cda69 100644 (file)
@@ -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);
 
index f8751b5d2bc8587a460179b0bf75cda1500ec16b..5e3e93e48b8595ac6f2be64b2435d16a9f59d343 100644 (file)
@@ -15,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__
index 30cdcd82328f02dc498937d4a364d688b8967748..b155965cabe09319a679892d2adf2fd133b01f62 100644 (file)
@@ -15,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);
index de97a5c1508618ba071fae15cc7c00fcdcaca19c..20badf5ea1c9248bb18ca12cb2fe32ef0ad54dc1 100644 (file)
@@ -15,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__
index 8034341bccbf6e3b95a0bc40cdafff813212a137..f7ec486d3652e09827c5531e9e8537e4e3b6bbe0 100644 (file)
@@ -15,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__
index 7165a58b27898657476028b35f2051cd1b11d4cd..eeaa095fbd63c35306450d35b7b82db64b682acd 100644 (file)
@@ -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];
@@ -2308,11 +2347,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 ();
index a6d73e8544cb7207383e98b2636aadde4b55783f..9dd7064f69d5a603c9da34eca33295f63930a86f 100644 (file)
@@ -15,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:
index b0ac7a4bd78dffaa234015b1f07f745b37156a4c..111bd9f4a9a7619dd324720451a3c7b568157a72 100644 (file)
@@ -15,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
index 816e3bbf0ceeb147441f15f410471527334194af..6fc97703d68afa5f6a92d1d97959274ea2f6cce4 100644 (file)
     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;
+       }
+}
index fa38cca0a0643bd0b1d579a20bd2838e4fe6b6a5..1d10109aa1d0f4d66d989989264ad497c0f9f47d 100644 (file)
 
 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));
+       }
 }
index 4c38ecec201e28893b2ebc4c18738625fe3d46db..d4d59d4a60a38de093a61e437e29b0af51d5e789 100644 (file)
@@ -15,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 ();
                }
        }
 
index 38f8ed3652dc966cd6137952a412054a58ddda09..8bb40e9bcb011e9cf7aa109bae7ccd8fa976b066 100644 (file)
@@ -15,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();
        }
 
index 203590a4e124dacfd5316e15599fb7d853838766..6fe2f67e052dc03374493c06bd0f3fdfa0f47240 100644 (file)
@@ -15,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;
index 7bbc4cd0ba3534a4022ba3b22f63e0b5dfb1d0c4..0ba30b2b8be5503878bdaa6e15356b23d20ee367 100644 (file)
@@ -15,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 */
index af6fffdeb95e026ba4d8c06af734bfbb58eab8e3..341fa82091902c0f4898320bf42d82cdeedf24b7 100644 (file)
@@ -15,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>
index d4a370685c1a536dd0ccab0e0c9ee59d941bf91c..f13aa82207617b51ca841a73f65594178fe5e592 100644 (file)
@@ -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);
index a0f2b5e036139ea7a1452c54d02b334e916b2768..c8d71c5155b2199ea8065cb109483ba69c63189d 100644 (file)
@@ -15,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
 }
+
index fbfd02d50904cf6b4775c814309babca8233553f..13b7dc4ddb1e9593e0bc385bfe12723719e066a1 100644 (file)
@@ -15,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>
index 72f56794d727bd17c0a2b44543456420953f9c75..899790dddc75f8156d0f908791b98ed66cafeadc 100644 (file)
@@ -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 {
index 66d1e099dadc408daf36c916112a08d04e0cd499..d75758dfb03e4d6c6eb58558aa112d1eee9634b3 100644 (file)
@@ -15,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>
index 8465094775b8f6cca356061fa6fbbfeb253467cd..5a1dc108f86062181c638dfc8dc80dcfa30c8d25 100644 (file)
@@ -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>
index 3031d5a7ec93c624a481a277496a927edb26c7eb..143cb841ecf8f2e8878132a312df3c5de7842811 100644 (file)
@@ -15,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>
index b4067a2051de31b9762ca0eb224d0d15187d062b..5bdbeb2ac5f5d4144d56a5b13082e007c58e4251 100644 (file)
@@ -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 (file)
index 5eada19..0000000
+++ /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);
-}
-       
index 09c5b75b86b1111532e0e06d245e43734996621f..c8fd2e48bf069f11aa7da7775ec554d509e391f7 100644 (file)
@@ -15,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 ();
 }
index 0460df43d88e0a482eb651a0bf9c8ef603a07cf1..4220adf7eb2242d9453e58cee85b82685adaa4ba 100644 (file)
@@ -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);
index 0b77bea279854b8310b2038e19bb9c1b8f25c9d3..369df7348c43aec94a2bdd5e58b3ec08c1f793dd 100644 (file)
@@ -15,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>
index ec6bfaa2ea3428784fb948fccf9d737568079ff5..7242f857c8f94f217ab73752a72213dece277514 100644 (file)
@@ -15,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>
index 549f4b7dbbc78d1aee5cb621d0a65049225d2d73..f5e841f00f11b421a2a9c0e2cdbdb6f5c0e5e671 100644 (file)
@@ -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); }
index 4466c40a321d9d74a75ee92466e6bc9f7d9669ec..7c0deccca1a750fe6ed507fcfda63a62dab00669 100644 (file)
@@ -15,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;
 }
+
index d109642fd4f7d0de30fe921091e0cf4a5537a6fc..e5d77c395199b0f70d2874bd73d7408698c149ec 100644 (file)
@@ -15,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>
index b7472781a80ae2c5fb7fa3ca51182f61bda89f32..a9284d779c6883173aab106566e21c0260e0b1d5 100644 (file)
@@ -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);
index 2e03b2f45df68fc78f752d1158a638a0c152f58b..a06e295a099f1a2ed734f6d28ebf1f956d1e36f8 100644 (file)
@@ -15,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>
index c21d09e01b1715dbeaffd6dfaed69d2b86238cb8..ba944f3c08f3192f9e1fb93feacc210dc1bfa28c 100644 (file)
@@ -15,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
index bec87e5dd6b6d41863304aa3e5e0183720bdde81..3d04c66824009351d9113624ffdbe65b5f56c1b6 100644 (file)
@@ -15,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 (file)
index 0000000..0c0caca
Binary files /dev/null and b/libs/ardour/macosx/English.lproj/InfoPlist.strings differ
diff --git a/libs/ardour/macosx/Info.plist b/libs/ardour/macosx/Info.plist
new file mode 100644 (file)
index 0000000..9314910
--- /dev/null
@@ -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 (file)
index 0000000..4026b65
--- /dev/null
@@ -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 (file)
index 0000000..b03e5d3
--- /dev/null
@@ -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 (file)
index 0000000..9da3d2c
--- /dev/null
@@ -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 (file)
index 0000000..9c575ee
--- /dev/null
@@ -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__ */
index b11e3f30625bf7f04ec2da5fa3c7b79217923e63..06b75211f79c3d058edc422643268a20ef2c57b6 100644 (file)
@@ -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>
index 6b7755e4989be051f6538978e123e1a6138cf875..2d31c8ccc89fa0b5ab433d384c05b792a2dc9f05 100644 (file)
@@ -15,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
@@ -91,6 +89,25 @@ compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current)
        return 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)
 {              
@@ -125,6 +142,13 @@ veclib_compute_peak (ARDOUR::Sample *buf, nframes_t nsamples, float current)
         return f_max(current, tmpmax);
 }
 
+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)
 {
index 2b4b2ae5bf718f08215908ff670e43394db4a81a..3447a92ce4bc9bcc53115cd381fadc2653fdafe3 100644 (file)
@@ -15,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) {
                
index b5a71f6403a3cc2453f279c828a9630d812d7155..fbb4b748df5176ed71e7d9c93d6c149e8ca5dcf2 100644 (file)
@@ -15,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>
index 933fba8740065ff9fe69bc2570ccc570dcf02205..d999386005300afc1c2e93c03b00deaf0a200221 100644 (file)
@@ -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;
 }
 
index 8ba662aaf454c99427f31333d9abe82a4627a2fc..8e41e706871dd1aba624e18a4b49e12a7859900c 100644 (file)
@@ -15,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
index dd18fe8690c059559f9da4093aae07dd5f957372..08d8a63d6e60471479865cc1ad76a1742dc684e6 100644 (file)
@@ -15,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>
index db84b015bbc999d0a44e4bf7a7f26e98bea0c0a1..325ef27a18ad27cb92b7675a90bd83b0438522d6 100644 (file)
@@ -15,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;
index 862f85a402f87236dc47b2f49f5d10f0d8d701cc..a801bae76c76d58a1e5e31961b7a8990c66d4579 100644 (file)
@@ -15,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>
index 3b471014eb503199216d69200fb4f7d405c224c7..b1fb43fc8f3e33b2e093435c951705fda45bb251 100644 (file)
@@ -15,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>
index 09da4c9ca7a2d9eda23f8d770ebe4527f53f927c..9af7ad0451de02ba5a248e6d44599e0f4ec0addc 100644 (file)
@@ -15,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
index 9e77128e4ca8f57aecb0c22ba854b897c79a78a3..d9c93c250b64a8cdee8b9d311bb83dfe933c58d6 100644 (file)
@@ -15,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>
index dbdd3d1dddf12fb574d5b5fae958ad44929609a5..ba895f6447f0b9b12a0fb5a418a6c845f837982e 100644 (file)
@@ -15,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>
index 973e14fd313a25b9a2dc53516fcc594a6bbb2949..15609706b253a62ccfbbaa0d72b35aeeedecb9ac 100644 (file)
@@ -15,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);
index 4041852f4e3d458f13f96f1310a987db85e93d11..a0aa3be75994da26d4f5d79b2591e1d1364b6ad1 100644 (file)
@@ -15,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>
index 2279331701be94f2f145c2bdb642d25b271023d8..c7ebecea317029172a8d927a7cb005421861b3ab 100644 (file)
@@ -15,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));
index d41574183124ddf5318667a66991b911e1595549..43c233e4d7efb706c3e29d0ed3782896fffbf7ea 100644 (file)
@@ -15,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) {
index c2aa59ed8b6db32ea73af708d4e280a1eb5c4ef1..13b90474ccbc3d230f564e37eb9383951c12f1dc 100644 (file)
@@ -15,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
index 0141007803bcdf8766e309145dfc6f3a582ab2ae..39c917571ad019d47c0fd5a3f421c824642e348b 100644 (file)
@@ -15,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>
index 764b25dc9ba9003e381060d54bc96e068f8bba03..9d0b13fccde137346e24d88909009bede12b2f50 100644 (file)
@@ -15,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);
index bb02eede91cb7677917feea4e919f19e95fe1774..16c8d9cffa7b361bd19ec1cea2dfad789238765e 100644 (file)
@@ -15,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
index f09c7232d74110c2de5816b91563d5d0761fd73b..9dccce04f28905deac516378706339db38edf84b 100644 (file)
@@ -15,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>
index 7cf52b741ff4835022d77d298aa85bc053ca4a8c..62067bfb461f935d99df66e5ea82f762609e4b8a 100644 (file)
@@ -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 (file)
index afecc14..0000000
+++ /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);
-               }
-       }
-}
-
index 981f9505d9bf92fa40dd6d77c73c4bdcd1a8d722..35c1019c0e43cb11ce6906b8be920a34b2e2216f 100644 (file)
@@ -15,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>
index 6902a426c3c0fb98e1ba757ff5e0a05c912caee3..e2d79b86d3079d9502a772044ebdc5dbf1ee0881 100644 (file)
@@ -15,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);
+       }
+}
index 1fd8389e117a27c230c0393b4f6f56321068c5c6..2bb9886f50abad1991690568479a7c2f8f7caba7 100644 (file)
@@ -15,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>
index 18bf9b83e13f08c63669eb7efbfb279c3524c9da..2a078565b5e65bf938e0528b69c6aac270ab89bc 100644 (file)
@@ -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
index 2de3448cd16d32b9dc724ea71329d445604212f2..9b8b7f1d2462c22af797ae7cf1ea6888cc15d83a 100644 (file)
@@ -15,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);
                        
                }
 
index c8a81be4d48ffded9f3c5f01e028e041a55ffec1..aae5830b34da78225c025218ad872c89325e15b1 100644 (file)
@@ -15,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;
 }
 
@@ -1989,6 +2063,15 @@ Session::template_dir ()
        return path;
 }
 
+string
+Session::export_dir () const
+{
+       string res = _path;
+       res += export_dir_name;
+       res += '/';
+       return res;
+}
+
 string
 Session::suffixed_search_path (string suffix, bool data)
 {
@@ -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 ();
index 585dad6b1a4038fca0ca364ee0989ef8a3e1486e..836958f6675f8eb9dd448b64546bc4b60717727f 100644 (file)
@@ -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>
index 69a42ec8b89755f8aca857b3071986ed8c3c66d3..4061b2ccd0e93eeec3f5ed907dbae785e14846d9 100644 (file)
@@ -15,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))));
index ad3573a72e0bd8e61fd7b8775b204b54ed3ebae6..3ee74231e0885dfa9aaf54b0bd88db947192cc11 100644 (file)
@@ -15,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 {
index 70bf1a8042034043114565eda175d141c2f80377..16233feba23f3a528dc79caaaf09cc2112039b82 100644 (file)
@@ -15,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/libs/ardour/silentfilesource.cc b/libs/ardour/silentfilesource.cc
new file mode 100644 (file)
index 0000000..b34944e
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+    Copyright (C) 2007 Paul Davis 
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <ardour/silentfilesource.h>
+
+using namespace ARDOUR;
+
+SilentFileSource::SilentFileSource (Session& s, const XMLNode& node, nframes_t len, float sr)
+       : AudioFileSource (s, node, false)
+{
+       _length = len;
+       _sample_rate = sr;
+}
+
+SilentFileSource::~SilentFileSource ()
+{
+}
+
+void
+SilentFileSource::set_length (nframes_t len)
+{
+       _length = len;
+}
index 2885240a5193cee69a5c745ccc10d39ed9ff9322..d11afa736b6485989732f2a7179ec5cf3e3330c0 100644 (file)
@@ -15,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;
index db2147493aaf971e4ea353e8ed3fa4489a9b8568..c4cf1156cda303215b135c07933532e25bf85149 100644 (file)
@@ -15,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>
index 560bf03e7f5eb802063c1f3636300f2af88e3fe7..143d5648094752c788e23ec36b0f2bf3955875a0 100644 (file)
@@ -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 (file)
index 0000000..5554462
--- /dev/null
@@ -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);
+}
+
+
+
index e86c30dd4d90c7ac843dc0b0d62c4e8e3bcbcb05..cd59e93054145fb05160c52f1aad2fdecfd9ab46 100644 (file)
@@ -15,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>
index e0ef8fd0b339e411a36a31f9c9dd8421d7e1a58b..51a0414d0c9af6cc31b60dd561b88f33abc4e1a4 100644 (file)
@@ -15,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
index 5d7a303fc626ff78e6167c9e91d7be0ec65cb5c2..ed78b0942d005834d42ea52eff34bf5b7d9541c0 100644 (file)
@@ -15,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>
index d30d4dd0b78c5b387ceef652a453d2fd11ee954e..5356f915dd55d96c79acbe3481ae2d03de4ca4d2 100644 (file)
@@ -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
index 9055eac6206b4bdb5ee8800f871b44126d5c28c2..493cb2e5722e7424bfda435a023b991776efb219 100644 (file)
@@ -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*);
index 8911ff4a0117f45fabca0e6c900ec6318f4c4506..55061c2b72d93a186f3f1a601606b38c8fa93dae 100644 (file)
@@ -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;
        }
index c58ddd27a23e31d52be18f6e34538dcfaff7d2bb..f2f287d325f12511b4945c4ef73e90615353f1bc 100755 (executable)
@@ -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=.
 
index 9c7511c85dadcbaec7348a1cf7666f0bdf99c94b..579ba5dd8e964eb47b367ed1ff04b25977c93e8a 100644 (file)
@@ -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
index f59d192ff1402a78575d74a060f8a64128277699..c3c15b4281bf47ff229da0b90f3b6f3be3a054cb 100644 (file)
@@ -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;
index 76b89deb024125bbbc94c15dca32dd8f282490ad..3c3cad6e46ddd04def011484da23686568cfbe25 100644 (file)
@@ -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),
@@ -89,17 +89,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)
 {
index 3c489e08ffbcbb6f3500555b6103afbe4cc28d36..253dad80a24a6206695aa481e689f183d8b3b91c 100644 (file)
@@ -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/libs/gtkmm2ext/grouped_buttons.cc b/libs/gtkmm2ext/grouped_buttons.cc
new file mode 100644 (file)
index 0000000..b16b983
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+    Copyright (C) 2001 Paul Davis 
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    $Id$
+*/
+
+#include <gtkmm.h>
+
+#include <gtkmm2ext/grouped_buttons.h>
+
+using namespace std;
+
+GroupedButtons::GroupedButtons (vector<Gtk::ToggleButton *>& buttonset)
+{
+       uint32_t n = 0;
+
+       buttons = buttonset;
+
+       for (vector<Gtk::ToggleButton *>::iterator i = buttons.begin(); i != buttons.end(); ++i, ++n) {
+               if ((*i)->get_active()) {
+                       current_active = n;
+               }
+               (*i)->signal_clicked().connect (sigc::bind (mem_fun (*this, &GroupedButtons::one_clicked), n));
+       }
+}
+
+GroupedButtons::GroupedButtons (uint32_t nbuttons, uint32_t first_active)
+{
+       buttons.reserve (nbuttons);
+       current_active = first_active;
+
+       for (uint32_t n = 0; n < nbuttons; ++n) {
+
+               Gtk::ToggleButton *button;
+               
+               button = manage (new (Gtk::ToggleButton));
+               
+               if (n == current_active) {
+                       button->set_active (true);
+               } 
+
+               button->signal_clicked().connect (sigc::bind (mem_fun (*this, &GroupedButtons::one_clicked), n));
+               buttons.push_back (button);
+       }
+}
+
+static gint
+reactivate_button (void *arg)
+{
+       Gtk::ToggleButton *b = (Gtk::ToggleButton *) arg;
+       b->set_active (true);
+       return FALSE;
+}
+
+void
+GroupedButtons::one_clicked (uint32_t which)
+{
+       if (buttons[which]->get_active()) {
+
+               if (which != current_active) {
+                       uint32_t old = current_active;
+                       current_active = which;
+                       buttons[old]->set_active (false);
+               }
+
+       } else if (which == current_active) {
+
+               /* Someobody tried to unset the current active
+                  button by clicking on it. This caused
+                  set_active (false) to be called. We don't
+                  allow that, so just reactivate it.
+
+                  Don't try this right here, because of some
+                  design glitches with GTK+ toggle buttons.
+                  Setting the button back to active from
+                  within the signal emission that marked
+                  it as inactive causes a segfault ...
+               */
+
+               gtk_idle_add (reactivate_button, buttons[which]);
+       }
+}
index 68da2249a05ff4998cb2fce8307ca4364aabafef..b692a7ccdc2daa59b13d2d9bf5856a264a3ff8ea 100644 (file)
@@ -15,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__
index e5b8e31b58209912246f4ea098f11f545a1f82ac..c91f4c8a06a495973f499b33a760ac08f95a4a90 100644 (file)
@@ -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__
index 193612540551db5d4873cc4d4aa6b2a56df82f91..2ddd3628fc30177933920542af3e02d0b4a42642 100644 (file)
@@ -15,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:
index e4aee36ebebd36be65447e53f6ee92ea8b98a125..8f9fb55717fa5f04925407a847f6b87e25252241 100644 (file)
@@ -15,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__
index 16a9a6549c2c899babed42eb1cdf305b31b54691..6ad1f7dd949ca6dbf3f306c4427fad05dc93a4f0 100644 (file)
@@ -15,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__
index d624f29afb71f9a6ecef012918f87eac9f8af6c1..775cb201cd21a6957731b745638b6ce813fcf293 100644 (file)
@@ -15,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/libs/gtkmm2ext/gtkmm2ext/grouped_buttons.h b/libs/gtkmm2ext/gtkmm2ext/grouped_buttons.h
new file mode 100644 (file)
index 0000000..99d9f8f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+    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.
+
+*/
+
+#ifndef __gtkmm2ext_grouped_buttons_h__
+#define __gtkmm2ext_grouped_buttons_h__
+
+#include <stdint.h>
+
+#include <vector>
+#include <sigc++/signal.h>
+
+namespace Gtk {
+       class ToggleButton;
+};
+
+class GroupedButtons : public sigc::trackable
+{
+  public:
+       GroupedButtons (uint32_t nbuttons, uint32_t first_active);
+       GroupedButtons (std::vector<Gtk::ToggleButton *>&);
+       
+       Gtk::ToggleButton& button (uint32_t which) {
+               return *buttons[which];
+       }
+
+  private:
+       std::vector<Gtk::ToggleButton *> buttons;
+       uint32_t current_active;
+       void one_clicked (uint32_t which);
+};
+
+#endif /* __gtkmm2ext_grouped_buttons_h__ */
index a692e64c9c36df5e817b958d18c082fb8f0635e1..b6a52c6c0cb1db80c1faa714d525167e520be6be 100644 (file)
@@ -15,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__
index 18410405604fca8b3c0760ab8d5eacf941f27faa..832423f31d0c84cdf0850981af4fdfb0a2a7cc53 100644 (file)
@@ -15,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__
index 785d6eef36eda12a353872ed774b7a14ae651f14..410f54274ebaa9be6049df0e5f8bdb2c6cc57c2f 100644 (file)
@@ -15,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__
index bb4176240a678193acb8189df7aa6866ebb791d9..d974f5d5bc64b153d7028ca5d51596c9039d0c75 100644 (file)
@@ -15,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__
index 89f14b4c50e65504d503e20177df2f49edaf031b..1db357341dcb2f404d06693dc3fd47f33ded088f 100644 (file)
@@ -15,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__
index 9847e73661880b369aff8816d55ae327a388b869..10870ee7522909eb2e649a8b4bc4cf396927a378 100644 (file)
@@ -15,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__
index 9eb07cfbfec705c41382157df57dd5274ee3efea..841742db03230e6060d19bf6856da4da044dfba3 100644 (file)
@@ -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__
index c137dbabf5ecb3d755324a05e6d81c023602b171..74ff36816b5b6bf1ffacfbd4411ebff9dcb7264d 100644 (file)
@@ -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__
index f684903836783735da7f4664c22a5804cd500561..c86402e54e7b5841a488071da4c3fe8fe9683f05 100644 (file)
@@ -15,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__
 
 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(); }
 };
 
 };
index fd36cb641625b36649c73f1c42978e1fbd449d02..5e80892b98a7c3e0d083e434b9e612fd91d3f6f3 100644 (file)
@@ -15,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__
index 280eb4437d3a2c4b519f66feeeab323bebe4b8da..9cc639cd75e9e5799ec1d436af4035dd93a23a45 100644 (file)
@@ -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__
index 97dab523aab59d12481ba1cc0a18a801e3d66d21..ca1b88abba48cca8f9e2fc0c8ec4855b8a37ca8d 100644 (file)
@@ -15,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__
index 074d0866511bcd0326c42574fd6f3c2f8ae193d9..ffcafab123e74f37bdb3dbb7b786658fe16add83 100644 (file)
@@ -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 (file)
index 0000000..a7b6345
Binary files /dev/null and b/libs/midi++2/macosx/English.lproj/InfoPlist.strings differ
diff --git a/libs/midi++2/macosx/Info.plist b/libs/midi++2/macosx/Info.plist
new file mode 100644 (file)
index 0000000..8eebfc9
--- /dev/null
@@ -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 (file)
index 0000000..49896b1
--- /dev/null
@@ -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 (file)
index 0000000..8f1f982
--- /dev/null
@@ -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 (file)
index 0000000..72e767b
--- /dev/null
@@ -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 (file)
index 0000000..7ff7d8c
--- /dev/null
@@ -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__ */
index f6c17541c20edeb51655d6f2d44550fc22b78e44..8e50609fbe818bdc0ea8c04c37be6a63732c4e86 100644 (file)
@@ -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__
index a4b4ba856f161b37826d1999c9fa4e0a2e443e1f..7fe880fe636e025a76e6c83b143c5c7525725117 100644 (file)
@@ -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__
index e1ffb954a51b862b24121ebbe1fcae587ae56dec..5a4a397b9d0a4306ccafe3ca4267901750c3734e 100644 (file)
@@ -15,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__
index 1d5c7e0b30ca6a8916b6a40db1255256ff9a689b..df7f35e0738afbb08dd232911a7eaee72ae0b004 100644 (file)
@@ -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__
index 3ff05b21c84c7da272002e357dfd6bda0e324525..8a1af55967a82e44e7b052d95c25ad7b6d79fd3f 100644 (file)
@@ -15,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__
index 200d90eda8da21b59bc343366febb57c11e46217..57d1502c453d8804a59f414e98115c69f1f03ef5 100644 (file)
@@ -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__
index d5a49eb0a3b4c0cb6315beca68db945bf678cfe7..80de408ee1bb8331afe66ed1095eca70e972c397 100644 (file)
@@ -15,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__
index 2d569f122c1bc141b80ce96fb2d27c75d9f7de2e..bc23beb0a1e6cf6410cef662a6913aa4ca6ccc0d 100644 (file)
@@ -15,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"
index 75445facb7e204ac9800be7f6e0a2720e48927dd..1474da77edf57d871273eb3cc3638661dc69e393 100644 (file)
@@ -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__
index 36d19f3da90a566333d791e34685cc06c20ed2b4..73c7c75f614732dbce9ac36e9afb4939243d7aee 100644 (file)
@@ -15,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;
index a706127eff01e0ee4865283643abb8ea8196822b..e4338cf95226fceb940e398de10795f15c3394c4 100644 (file)
@@ -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__
index 86838dd04d2fb5fcb8a113f2ed204340641f5411..0cb4ffded662a8291935ea5a00a3d6d5960e52f8 100644 (file)
@@ -15,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__
index 7c294784131dd32d8b1f2deac3ba2ff4b7783c1e..a1f6ce39b43ad73c9033bf67683c3e8922120c9d 100644 (file)
@@ -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;
index 61c47e856f96d82edd7e21ab74b6d17ccc40c116..28d6393fb453c154c0bc5707a3a3a9af24c19479 100644 (file)
@@ -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 << ' ';
        }
index 19fdb1fabd510b82ff164b0936c43faf884619eb..7fd86eff354453e9822e716c84407efa5717535b 100644 (file)
@@ -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:
index afb24a43117920dd60202fc19af7df2227c9466b..12664a1fca2232a316ab67b1e6ab136db9f77b59 100644 (file)
@@ -36,6 +36,7 @@ pthread_utils.cc
 receiver.cc
 stacktrace.cc
 stateful.cc
+strreplace.cc
 strsplit.cc
 textreceiver.cc
 transmitter.cc
index 049ad0aa213543677b907de12146e34e8bd509c8..00638e6c06cc3312b159723913b3671523ef49aa 100644 (file)
@@ -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 (file)
index 0000000..d847901
Binary files /dev/null and b/libs/pbd/macosx/English.lproj/InfoPlist.strings differ
diff --git a/libs/pbd/macosx/Info.plist b/libs/pbd/macosx/Info.plist
new file mode 100644 (file)
index 0000000..0c31617
--- /dev/null
@@ -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 (file)
index 0000000..535d16b
--- /dev/null
@@ -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 (file)
index 0000000..a774fac
--- /dev/null
@@ -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 (file)
index 0000000..61a94f6
--- /dev/null
@@ -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 (file)
index 0000000..ec6c854
--- /dev/null
@@ -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__ */
index eca53916afc1462b2ba9ed6cc5d424b5f5994957..97f19e1fe5d66d2c317241aee17e4a6c88270022 100644 (file)
@@ -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);
                        } 
                }
        }
index f80db7bf1a155341c0209f486ef2f9fc7e2fe2d5..88c27aa0bce7c3787db8106bf2eee9a97d8983c6 100644 (file)
@@ -15,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__
index 8044b51a83cd7cd7f8e6f04275e0cce78c1b0737..23bcf85b91cee4c6e46acd481b5b7f2115afc817 100644 (file)
@@ -15,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__
index c88eb298bcca4193dc57a5408d3a35d3fc2dcd31..c152013c663f896c5d43b4ce6fbb4a23c5cd165d 100644 (file)
@@ -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;
 };
 
 }
index 4136f02ee225d1e02fc3adfb625a0f810576db5f..58842d68eb900da7622651c96090c4638296e2ab 100644 (file)
@@ -15,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__
index f0dc7e491e168c00c3d3acdabfa3511c247e6131..fd0468905f321f08613bdf66b5796ce78f52071b 100644 (file)
@@ -15,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__
index fe1aa8e7d049dd827fbdf4b784a980935bcc01b0..d913b2c0fe198eeeff73ca242daf4a627855f038 100644 (file)
@@ -15,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__
index 86ccc581901aa701bbed8b59585873084a5920cf..e0ec1be7f9f2c59c4f2569d6ce238aa74e46d973 100644 (file)
@@ -15,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__
index f8e19e72fb9281ec360026693062a330dd2a06cd..d604680ae26d7ce875b3e01fe9464fefa9c306d3 100644 (file)
@@ -15,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__
index a8f3cdd5bc72e5e5b23026ddcc7a6a9013b7736e..8b0b8b3548dca2784895f85e5f84923df1475e03 100644 (file)
@@ -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);
                
index 5ce238df636aebc243812a8fe095749e55af36cb..93192ce7873322da97d1be27047b8a594b31bce6 100644 (file)
@@ -15,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 (file)
index 0000000..4434637
--- /dev/null
@@ -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__
index 1d9c9b04e333990d2ba610e8cab6dcb170506d55..d98601461e684eea5e5bf2d478877e8cd33ee3c1 100644 (file)
     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;
index fee2efce3d8c78c4900eb09d0cb08580bf04c456..9db09098d6412a2fb91a0b724d116ebf44a5589a 100644 (file)
@@ -15,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
index 470bc3cfcc9c0f2fd6efdc456aa131b87b1f05ff..85f3e79ab004c06d0b76da6ea871fc101bafa796 100644 (file)
@@ -15,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__
index 5fbac11e5c7abcda4ec8ebfa9a721ae0cb68c7fa..550db5a24ea15c96dd8ecd95f7c31332348d7c1e 100644 (file)
@@ -15,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__
index 6e5bfa073424f2f5980c9c3be0b8a858a399eb94..66fb0273870fff7f449d7ed988f0585177acf8d3 100644 (file)
@@ -15,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__
index 4a96e91a28789f21556d269bd131cbb2a518f0a7..3c83a1ae2f243f276685d530031752d735007682 100644 (file)
@@ -15,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__
index e55ad1c825c6e2531fa9a8e72cb15895c92c472c..f36a3ae5f0f6535de58e8b4dbc295898a42a3fef 100644 (file)
@@ -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__
index b8bfe5bc7824b0c9e0362bbcf2162a536313c53c..e5900fc6528477e7b40b7b207db7cae537e01d88 100644 (file)
@@ -15,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__
index 83cf8acfac94e8d3686edbe70f4e6eb17c8d977f..0a63085f118623a08470708f97b78297e7e3cab4 100644 (file)
@@ -15,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__
index 0298574dfabdd5bd55d9a956b3036b969cf225f1..12f1c443fd4c5848e541011c474b3da8412173d8 100644 (file)
@@ -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__
index 357cb9965fcffc6be67d7ea5f3ef1977c12c17d5..61ac9bd8d84463452ab994d251f03022f24d557f 100644 (file)
@@ -15,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__
index 4dfab5178fcc893122c00de0e87f3b450941e81d..9539d8b41dc734fd8ac88bcc33c1186d177de734 100644 (file)
@@ -15,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__
index a653fe3033c487e1d5d49d87161dadceb9001d16..8a6eb606b219cbab981b3b85db2bdadec1ad581b 100644 (file)
@@ -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 (file)
index 0000000..dd90baf
--- /dev/null
@@ -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;
+}
+
index 7f29a778870ac8b4d9fa3b90e8cf643db5bbe205..1fb61121501d63419ae6f27f2db6162920727ab9 100644 (file)
@@ -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);
+       }
+}
index ebb519d373e559aff4b8d801fde4fcc9ab6bab45..09597765c67e1d927f299f5cd823e53f953d1311 100755 (executable)
@@ -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=.
 
index 740d099239d815dfa10c6ae681c4d88880702c1f..493d5326f20ab529364ce2538fcc08f178eff3d6 100644 (file)
@@ -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;
 
index f7c03f759e657ef740d2ae27a546c7b449b30295..5315d6fec3ca8a3269aad4a8dd3eb63cca95236d 100644 (file)
@@ -150,7 +150,7 @@ public:
     void clear();
 
     /// Returns nonzero if there aren't any samples available for outputting.
-    uint isEmpty();
+    int isEmpty() const;
 };
 
 }
index f1b85b5f177c78731f7879e397a2b1761023f132..c71c65967f8ae0673e8df3e61b4404709bd14d06 100644 (file)
@@ -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.
index b4ccdc2834521c7dd41d29e3a9afa62d9516ab80..b58b80fa06f0a6cadf890bd5190c9d4a2c6ef608 100644 (file)
@@ -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 */
index e6642d3394cdf6f30fd45bae00094856500aa978..44445192be017b44875c19a1ee29700001ce1b40 100644 (file)
@@ -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>
index d660c10800fd7836d78c39d189671973d86847d3..1ef7a2c1b492405e6f3ee15eca03f245336c5666 100644 (file)
@@ -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>
index 23b274ca01f56fbc4080e6b1cc538e7d28dd3a9b..7bc6b25c32508ce8f6943e794a58df6424974001 100644 (file)
@@ -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__
index a689d494314d97ae606bf50f113ac389d3e74413..c0961645ab4fdf42f2d3b2d6a958ab15155d5863 100644 (file)
@@ -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 (file)
index 0000000..dc612e2
--- /dev/null
@@ -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 (file)
index 0000000..223fcdb
--- /dev/null
@@ -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 (file)
index 0000000..51b4af0
--- /dev/null
@@ -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 (file)
index 0000000..651517a
--- /dev/null
@@ -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 (file)
index 0000000..534bc7d
--- /dev/null
@@ -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 (file)
index 0000000..f9efd18
--- /dev/null
@@ -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 (file)
index 0000000..2ef5b6c
--- /dev/null
@@ -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 (file)
index 0000000..4096ee6
--- /dev/null
@@ -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 (executable)
index 0000000..540c62f
--- /dev/null
@@ -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 (file)
index 0000000..6893f66
--- /dev/null
@@ -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 (file)
index 0000000..aafb9aa
--- /dev/null
@@ -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 (file)
index 0000000..f9efd18
--- /dev/null
@@ -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 (file)
index 0000000..1eeacd6
--- /dev/null
@@ -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 (file)
index 0000000..28a8462
--- /dev/null
@@ -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 (file)
index 0000000..5d390f3
--- /dev/null
@@ -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 (file)
index 0000000..f6d0dc8
--- /dev/null
@@ -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/frontier/tranzport/tranzport_control_protocol.cc b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
new file mode 100644 (file)
index 0000000..c874a05
--- /dev/null
@@ -0,0 +1,1949 @@
+/*
+    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.
+
+*/
+
+/* Design notes: The tranzport is a unique device, basically a 
+   20 lcd gui with 22 shift keys and 8 blinking lights. 
+
+   As such it has several unique constraints. 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.
+
+   It will be good one day, to break the gui, keyboard, and blinking light
+   components into separate parts, but for now, this remains monolithic.
+
+   A more complex surface might have hundreds of lights and several displays.
+
+   mike.taht@gmail.com
+ */
+
+#define DEFAULT_USB_TIMEOUT 10
+#define MAX_RETRY 1
+#define MAX_TRANZPORT_INFLIGHT 4
+#define DEBUG_TRANZPORT 0
+#define HAVE_TRANZPORT_KERNEL_DRIVER 0
+
+#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>
+
+BaseUI::RequestType LEDChange = BaseUI::new_request_type ();
+BaseUI::RequestType Print = BaseUI::new_request_type ();
+BaseUI::RequestType SetCurrentTrack = BaseUI::new_request_type ();
+
+/* Base Tranzport cmd strings */
+
+static const uint8_t cmd_light_on[] =  { 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00 };
+static const uint8_t cmd_light_off[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
+static const uint8_t cmd_write_screen[] =  { 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00 };
+
+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);
+}
+
+
+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 = BlingOff;
+       timerclear (&last_wheel_motion);
+       last_wheel_dir = 1;
+       last_track_gain = FLT_MAX;
+       display_mode = DisplayNormal;
+       gain_fraction = 0.0;
+       invalidate();
+       screen_init();
+       lights_init();
+       print(0,0,"!!Welcome to Ardour!!");
+       print(1,0,"!Peace through Music!");
+}
+
+void TranzportControlProtocol::light_validate (LightID light) 
+{
+       lights_invalid[light] = 0;
+}
+
+void TranzportControlProtocol::light_invalidate (LightID light) 
+{
+       lights_invalid[light] = 1;
+}
+
+void TranzportControlProtocol::lights_validate () 
+{
+       memset (lights_invalid, 0, sizeof (lights_invalid)); 
+}
+
+void TranzportControlProtocol::lights_invalidate () 
+{
+       memset (lights_invalid, 1, sizeof (lights_invalid)); 
+}
+
+void TranzportControlProtocol::lights_init()
+{
+       for (uint32_t i = 0; i < sizeof(lights_current)/sizeof(lights_current[0]); i++) {
+               lights_invalid[i] = lights_current[i] = 
+                       lights_pending[i] = lights_flash[i] = false;
+       }
+}
+
+
+
+int
+TranzportControlProtocol::lights_flush ()
+{
+       if ( _device_status == STATUS_OFFLINE) { return (0); }
+
+       //  Figure out iterators one day soon
+       //  for (LightID i = i.start(), i = i.end(); i++) {
+       //  if (lights_pending[i] != lights_current[i] || lights_invalid[i]) {
+       //    if (light_set(i, lights_pending[i])) { 
+       //       return i-1;
+       //    } 
+       //  }
+       //}
+       if ((lights_pending[LightRecord] != lights_current[LightRecord]) || lights_invalid[LightRecord]) {
+               if (light_set(LightRecord,lights_pending[LightRecord])) {
+                       return 1;
+               }
+       }
+       if ((lights_pending[LightTrackrec] != lights_current[LightTrackrec]) || lights_invalid[LightTrackrec]) {
+               if (light_set(LightTrackrec,lights_pending[LightTrackrec])) {
+                       return 1;
+               }
+       }
+
+       if ((lights_pending[LightTrackmute] != lights_current[LightTrackmute]) || lights_invalid[LightTrackmute]) {
+               if (light_set(LightTrackmute,lights_pending[LightTrackmute])) {
+                       return 1;
+               }
+       }
+
+       if ((lights_pending[LightTracksolo] != lights_current[LightTracksolo]) || lights_invalid[LightTracksolo]) {
+               if (light_set(LightTracksolo,lights_pending[LightTracksolo])) {
+                       return 1;
+               }
+       }
+       if ((lights_pending[LightAnysolo] != lights_current[LightAnysolo]) || lights_invalid[LightAnysolo]) {
+               if (light_set(LightAnysolo,lights_pending[LightAnysolo])) {
+                       return 1;
+               }
+       }
+       if ((lights_pending[LightLoop] != lights_current[LightLoop]) || lights_invalid[LightLoop]) {
+               if (light_set(LightLoop,lights_pending[LightLoop])) {
+                       return 1;
+               }
+       }
+       if ((lights_pending[LightPunch] != lights_current[LightPunch]) || lights_invalid[LightPunch]) {
+               if (light_set(LightPunch,lights_pending[LightPunch])) {
+                       return 1;
+               }
+       }
+
+       return 0;
+}
+
+// Screen specific commands
+
+void
+TranzportControlProtocol::screen_clear ()
+{
+       const char *blank = "                    ";
+       print(0,0,blank); 
+       print(1,0,blank);
+}
+
+void TranzportControlProtocol::screen_invalidate ()
+{
+       for(int row = 0; row < 2; row++) {
+               for(int col = 0; col < 20; col++) {
+                       screen_invalid[row][col] = true;
+                       screen_current[row][col] = 0x7f;
+                       screen_pending[row][col] = ' ';
+                       // screen_flash[row][col] = ' ';
+               }
+       }
+       // memset (&screen_invalid, 1, sizeof(screen_invalid));
+       // memset (&screen_current, 0x7F, sizeof (screen_current)); // fill cache with a character we otherwise never use
+}
+
+void TranzportControlProtocol::screen_validate ()
+{
+}
+
+void TranzportControlProtocol::screen_init ()
+{
+       screen_invalidate();
+}
+
+int
+TranzportControlProtocol::screen_flush ()
+{
+       int cell = 0, row, col_base, col, pending = 0;
+       if ( _device_status == STATUS_OFFLINE) { return (-1); }
+
+       for (row = 0; row < 2 && pending == 0; row++) {
+               for (col_base = 0, col = 0; col < 20 && pending == 0; ) {
+                       if ((screen_pending[row][col] != screen_current[row][col]) 
+                                       || screen_invalid[row][col]) {
+
+                               /* something in this cell is different, so dump the cell to the device. */
+
+                               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(write(cmd) != 0) {
+                                       /* try to update this cell on the next go-round */
+#if DEBUG_TRANZPORT > 4
+                                       printf("usb screen update failed for some reason... why? \ncmd and data were %02x %02x %02x %02x %02x %02x %02x %02x\n", 
+                                                       cmd[0],cmd[1],cmd[2], cmd[3], cmd[4], cmd[5],cmd[6],cmd[7]); 
+#endif
+                                       pending += 1;   
+                                       // Shouldn't need to do this
+                                       // screen_invalid[row][col_base] = screen_invalid[row][col_base+1] = 
+                                       // screen_invalid[row][col_base+2] = screen_invalid[row][col_base+3] = true;
+
+                               } else {
+                                       /* successful write: copy to current cached display */
+                                       screen_invalid[row][col_base] = screen_invalid[row][col_base+1] = 
+                                               screen_invalid[row][col_base+2] = screen_invalid[row][col_base+3] = false;
+                                       memcpy (&screen_current[row][col_base], &screen_pending[row][col_base], 4);
+                               }
+
+                               /* skip the rest of the 4 character cell since we wrote+copied it already */
+
+                               col_base += 4;
+                               col = col_base;
+                               cell++;
+
+                       } else {
+
+                               col++;
+
+                               if (col && col % 4 == 0) {
+                                       cell++;
+                                       col_base += 4;
+                               }
+                       }
+               }
+       }
+       return pending;
+}
+
+
+//  Tranzport specific
+
+void TranzportControlProtocol::invalidate() 
+{
+       lcd_damage(); lights_invalidate(); screen_invalidate(); // one of these days lcds can be fine but screens not
+}
+
+TranzportControlProtocol::~TranzportControlProtocol ()
+{
+       set_active (false);
+}
+
+
+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;
+                       } else {
+                               return -1;
+                       }
+
+               } else {
+                       cerr << "Begin tranzport shutdown\n";
+                       screen_clear ();
+                       lcd_damage();
+                       lights_off ();
+                       for(int x = 0; x < 10 && flush(); x++) { usleep(1000); }
+                       pthread_cancel_one (thread);
+                       cerr << "Tranzport Thread dead\n";
+                       close ();
+                       _active = false;
+                       cerr << "End tranzport shutdown\n";
+               } 
+       }
+
+       return 0;
+}
+
+void
+TranzportControlProtocol::show_track_gain ()
+{
+       if (route_table[0]) {
+               gain_t g = route_get_gain (0);
+               if ((g != last_track_gain) || lcd_isdamaged(0,9,8)) {
+                       char buf[16]; 
+                       snprintf (buf, sizeof (buf), "%6.1fdB", coefficient_to_dB (route_get_effective_gain (0)));
+                       print (0, 9, buf); 
+                       last_track_gain = g;
+               }
+       } else {
+               print (0, 9, "        "); 
+       }
+}
+
+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, these 3 aren't done yet
+
+void
+TranzportControlProtocol::enter_recording_mode ()
+{
+       lcd_damage(); // excessive
+       screen_clear ();
+       lights_off ();
+       display_mode = DisplayRecording;
+}
+
+void
+TranzportControlProtocol::enter_bling_mode ()
+{
+       lcd_damage();
+       screen_clear ();
+       lights_off ();
+       display_mode = DisplayBling;
+}
+
+void
+TranzportControlProtocol::enter_config_mode ()
+{
+       lcd_damage();
+       screen_clear ();
+       lights_off ();
+       display_mode = DisplayConfig;
+}
+
+
+void
+TranzportControlProtocol::enter_big_meter_mode ()
+{
+       screen_clear ();
+       lcd_damage();
+       lights_off ();
+       last_meter_fill = 0;
+       display_mode = DisplayBigMeter;
+}
+
+void
+TranzportControlProtocol::enter_normal_display_mode ()
+{
+       screen_clear ();
+       lcd_damage();
+       lights_off ();
+       display_mode = DisplayNormal;
+       //  normal_update();
+}
+
+
+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;
+}
+
+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.98) {
+               light_on (LightAnysolo);
+       }
+
+       /* 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) || lcd_isdamaged(1,9,8)) {
+               char buf[16];
+               BBT_Time bbt;
+               session->tempo_map().bbt_time (where, bbt);
+               sprintf (buf, "%03" PRIu32 "|%02" PRIu32 "|%04" PRIu32, bbt.bars,bbt.beats,bbt.ticks);
+               last_bars = bbt.bars;
+               last_beats = bbt.beats;
+               last_ticks = bbt.ticks;
+               last_where = where;
+
+               if(last_ticks < 1960) { print (1, 9, buf); } // save a write so we can do leds
+
+               // if displaymode is recordmode show beats but not yet
+               lights_pending[LightRecord] = false;
+               lights_pending[LightAnysolo] = false;
+               switch(last_beats) {
+                       case 1: if(last_ticks < 500 || last_ticks > 1960) lights_pending[LightRecord] = true; break;
+                       default: if(last_ticks < 250) lights_pending[LightAnysolo] = true;
+               }
+
+               // update lights for tempo one day
+               //        if (bbt_upper_info_label) {
+               //     TempoMap::Metric m (session->tempo_map().metric_at (when));
+               //     sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
+               //      bbt_lower_info_label->set_text (buf);
+               //      sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
+               //      bbt_upper_info_label->set_text (buf);
+       }
+       }
+
+
+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::_monitor_work (void* arg)
+{
+       return static_cast<TranzportControlProtocol*>(arg)->monitor_work ();
+}
+
+// I note that these usb specific open, close, probe, read routines are basically 
+// pure boilerplate and could easily be abstracted elsewhere
+
+#if !HAVE_TRANZPORT_KERNEL_DRIVER
+
+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);
+               }
+       }
+
+       error << _("Tranzport: no device detected") << endmsg;
+       return -1;
+}
+
+int
+TranzportControlProtocol::open_core (struct usb_device* dev)
+{
+       if (!(udev = usb_open (dev))) {
+               error << _("Tranzport: cannot open USB transport") << endmsg;
+               return -1;
+       }
+        
+       if (usb_claim_interface (udev, 0) < 0) {
+               error << _("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) {
+               error << _("Tranzport: cannot release interface") << endmsg;
+               ret = -1;
+       }
+
+       if (usb_close (udev)) {
+               error << _("Tranzport: cannot close device") << endmsg;
+               udev = 0;
+               ret = 0;
+       }
+
+       return ret;
+}
+
+int TranzportControlProtocol::read(uint8_t *buf, uint32_t timeout_override) 
+{
+       int val;
+       // Get smarter about handling usb errors soon. Like disconnect
+       //  pthread_testcancel();
+       val = usb_interrupt_read (udev, READ_ENDPOINT, (char *) buf, 8, 10);
+       //  pthread_testcancel();
+       return val;
+} 
+
+       
+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) {
+#if DEBUG_TRANZPORT
+               printf("usb_interrupt_write failed: %d\n", val);
+#endif
+               return val;
+               }
+
+       if (val != 8) {
+#if DEBUG_TRANZPORT
+               printf("usb_interrupt_write failed: %d\n", val);
+#endif
+               return -1;
+               }
+       ++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
+
+}      
+
+#else
+#error Kernel API not defined yet for Tranzport
+// Something like open(/dev/surface/tranzport/event) for reading and raw for writing)
+#endif
+
+// We have a state "Unknown" - STOP USING SPACES FOR IT - switching to arrow character
+// We have another state - no_retry. Misleading, as we still retry on the next pass
+// I think it's pointless to keep no_retry and instead we should throttle writes 
+// We have an "displayed" screen
+// We always draw into the pending screen, which could be any of several screens
+// We have an active screen
+// Print arg - we have 
+// setactive
+// so someday I think we need a screen object.
+
+/*
+screen_flash.clear();
+screen_flash.print(0,0,"Undone:"); // Someday pull the undo stack from somewhere
+screen_flash.print(1,0,"Nextup:"); 
+
+if(flash_messages && lcd.getactive() != screen_flash) lcd.setactive(screen_flash,2000);
+
+screen::setactive(screen_name,duration); // duration in ms
+screen::getactive();
+*/
+
+
+int
+TranzportControlProtocol::flush ()
+{
+       int pending = 0;
+       if(!(pending = lights_flush())) {
+               pending = screen_flush(); 
+       } 
+       return pending;
+}
+
+// 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)
+{
+       bool result = false;
+       int endcol = col+length-1;
+       if((endcol > 19)) { endcol = 19; } 
+       if((row >= 0 && row < 2) && (col >=0 && col < 20)) {
+               for(int c = col; c < endcol; c++) {
+                       screen_invalid[row][c] = true;
+               }
+               result = true;
+       }
+       return result;
+}
+
+// Gotta switch to bitfields, this is collossally dumb
+// Still working on the layering, arguably screen_invalid should be lcd_invalid
+
+bool TranzportControlProtocol::lcd_isdamaged () 
+{
+       for(int r = 0; r < 2; r++) {
+               for(int c = 0; c < 20; c++) {
+                       if(screen_invalid[r][c]) {
+#if DEBUG_TRANZPORT > 5        
+                               printf("row: %d,col: %d is damaged, should redraw it\n", r,c);
+#endif
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+bool TranzportControlProtocol::lcd_isdamaged (int row, int col, int length)
+{
+       bool result = 0;
+       int endcol = col+length;
+       if((endcol > 19)) { endcol = 19; } 
+       if((row >= 0 && row < 2) && (col >=0 && col < 20)) {
+               for(int c = col; c < endcol; c++) {
+                       if(screen_invalid[row][c]) {
+#if DEBUG_TRANZPORT > 5        
+                               printf("row: %d,col: %d is damaged, should redraw it\n", row,c);
+#endif
+                               return true;
+                       }
+               }
+       }
+       return result;
+}
+
+// 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)
+{
+       return write(cmd,timeout_override);
+}
+
+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);
+}
+
+// Lights are buffered
+
+void
+TranzportControlProtocol::lights_on ()
+{
+       lights_pending[LightRecord] = lights_pending[LightTrackrec] = 
+               lights_pending[LightTrackmute] =  lights_pending[LightTracksolo] = 
+               lights_pending[LightAnysolo] =   lights_pending[LightLoop] = 
+               lights_pending[LightPunch] = true;
+}
+
+void
+TranzportControlProtocol::lights_off ()
+{
+       lights_pending[LightRecord] = lights_pending[LightTrackrec] = 
+               lights_pending[LightTrackmute] =  lights_pending[LightTracksolo] = 
+               lights_pending[LightAnysolo] =   lights_pending[LightLoop] = 
+               lights_pending[LightPunch] = false;
+}
+
+int
+TranzportControlProtocol::light_on (LightID light)
+{
+       lights_pending[light] = true;
+       return 0;
+}
+
+int
+TranzportControlProtocol::light_off (LightID light)
+{
+       lights_pending[light] = false;
+       return 0;
+}
+
+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[light] = false;
+               return 0;
+       } else {
+               return -1;
+       }
+}
+
+int TranzportControlProtocol::rtpriority_set(int priority) 
+{
+       struct sched_param rtparam;
+       int err;
+       // preallocate and memlock some stack with memlock?
+       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;
+}
+
+// Slowly breaking this into where I can make usb processing it's own thread.
+
+void*
+TranzportControlProtocol::monitor_work ()
+{
+       uint8_t buf[8];
+       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);
+       next_track ();
+       rtpriority_set();
+       inflight=0;
+       flush();
+
+       while (true) {
+
+               /* bInterval for this beastie is 10ms */
+
+               if (_device_status == STATUS_OFFLINE) {
+                       first_time = true;
+                       if(offline++ == 1) { 
+                               cerr << "Transport has gone offline\n";
+                       }
+               } else { 
+                       offline = 0; // hate writing this
+               }
+
+               val = read(buf);
+
+               if (val == 8) {
+                       process (buf);
+               }
+
+#if DEBUG_TRANZPORT > 2
+               if(inflight > 1) printf("Inflight: %d\n", inflight);
+#endif
+
+
+               if (_device_status != STATUS_OFFLINE) {
+                       if (first_time) {
+                               invalidate();
+                               lcd_clear ();
+                               lights_off ();
+                               first_time = false;
+                               offline = 0;
+                               pending = 3; // Give some time for the device to recover
+                       }
+                       /* update whatever needs updating */
+                       update_state ();
+
+                       /* still struggling with a good means of exerting flow control */
+                       // 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;
+}
+
+int TranzportControlProtocol::lights_show_recording() 
+{
+       //   FIXME, flash recording light when recording and transport is moving
+       return     lights_show_normal();
+}
+
+// gotta do bling next!
+
+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
+       }
+       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 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:
+                       lights_show_bling();
+                       normal_update();
+                       break;
+
+               case DisplayBlingMeter:
+                       lights_show_bling();
+                       show_meter();
+                       break;
+       }
+       return 0;
+
+}
+
+#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)
+{
+       // 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]);
+
+       uint32_t this_button_mask;
+       uint32_t button_changes;
+
+       _device_status = buf[1];
+
+       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];
+
+       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);
+       return 0;
+}
+
+void
+TranzportControlProtocol::show_current_track ()
+{
+       char pad[11];
+       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, 10).c_str();
+               if((len = strlen(v)) > 0) {
+                       strncpy(pad,(char *)v,len);
+               }
+               print (0, 0, pad);
+       }
+}
+
+void
+TranzportControlProtocol::button_event_battery_press (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_battery_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_backlight_press (bool shifted)
+{
+#if DEBUG_TRANZPORT
+       printf("backlight pressed\n");
+#endif
+}
+
+void
+TranzportControlProtocol::button_event_backlight_release (bool shifted)
+{
+#if DEBUG_TRANZPORT
+       printf("backlight released\n\n");
+#endif
+       if (shifted) {
+               lcd_damage();
+               lcd_clear();
+               last_where += 1; /* force time redisplay */
+               last_track_gain = FLT_MAX;
+               normal_update(); //  redraw_screen();  
+       }
+}
+
+void
+TranzportControlProtocol::button_event_trackleft_press (bool shifted)
+{
+       prev_track ();
+}
+
+void
+TranzportControlProtocol::button_event_trackleft_release (bool shifted)
+{
+}
+
+void
+TranzportControlProtocol::button_event_trackright_press (bool shifted)
+{
+       next_track ();
+}
+
+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)
+{
+       if (shifted) {
+               redo (); // someday flash the screen with what was redone
+       } else {
+               undo (); // someday flash the screen with what was 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)
+{
+}
+
+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 button_event_mute (bool pressed, bool shifted)
+{
+       static int was_pressed = 0;
+       //  if(pressed) { }
+}
+
+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;
+               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::config ()
+{
+  // FIXME
+}
+
+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);
+               }
+       }
+}
+
+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::step_pan_right ()
+{
+}
+
+void
+TranzportControlProtocol::step_pan_left ()
+{
+}
+
+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::next_track ()
+{
+       ControlProtocol::next_track (current_track_id);
+       gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
+}
+
+void
+TranzportControlProtocol::prev_track ()
+{
+       ControlProtocol::prev_track (current_track_id);
+       gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
+}
+
+void
+TranzportControlProtocol::show_wheel_mode ()
+{
+       string text;
+
+       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());
+}
+
+// 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);
+}
+
+void
+TranzportControlProtocol::print_noretry (int row, int col, const char *text)
+{
+       int cell;
+       uint32_t left = strlen (text);
+       char tmp[5];
+       int base_col;
+       
+       if (row < 0 || row > 1) {
+               return;
+       }
+
+       if (col < 0 || col > 19) {
+               return;
+       }
+
+       while (left) {
+
+               if (col >= 0 && col < 4) {
+                       cell = 0;
+                       base_col = 0;
+               } else if (col >= 4 && col < 8) {
+                       cell = 1;
+                       base_col = 4;
+               } else if (col >= 8 && col < 12) {
+                       cell = 2;
+                       base_col = 8;
+               } else if (col >= 12 && col < 16) {
+                       cell = 3;
+                       base_col = 12;
+               } else if (col >= 16 && col < 20) {
+                       cell = 4;
+                       base_col = 16;
+               } else {
+                       return;
+               }
+
+               int offset = col % 4;
+
+               /* copy current cell contents into tmp */
+               
+               memcpy (tmp, &screen_pending[row][base_col], 4);
+               
+               /* overwrite with new text */
+               
+               uint32_t tocopy = min ((4U - offset), left);
+               
+               memcpy (tmp+offset, text, tocopy);
+               
+               /* copy it back to pending */
+               
+               memcpy (&screen_pending[row][base_col], tmp, 4);
+               
+               text += tocopy;
+               left -= tocopy;
+               col  += tocopy;
+       }
+}      
+
+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)
+{
+       return 0;
+}
+
+int
+TranzportControlProtocol::save (char *name) 
+{
+       // Presently unimplemented
+       return 0;
+}
+
+int
+TranzportControlProtocol::load (char *name) 
+{
+       // Presently unimplemented
+       return 0;
+}
diff --git a/libs/surfaces/frontier/tranzport/tranzport_control_protocol.h b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.h
new file mode 100644 (file)
index 0000000..f13e4a3
--- /dev/null
@@ -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
index 6c76e054649b8410ce3a2ac8ba6017968a9a491c..b0921888528961d54ff3545164184f339d8fff45 100644 (file)
@@ -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)
index 0256d5c3597aa15b074f43c392581509e3b34ceb..1a9570c6a27b0ab90b2bdb1e87c524d1ba370914 100644 (file)
@@ -15,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;
                        }
                }
index 75b5699f18bf7c3e460bce2ab5c810f338ba5c8e..7f6f889df5e568d83ac95b71b3ee2ac2c67b754a 100644 (file)
@@ -15,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
index 8b631729161bfdc0a03eb1689b885f556a3b8ca8..7e0243971c52a4e3c7fe03ab9ea972f798c31cc1 100644 (file)
@@ -15,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 (file)
index 0000000..7bd1357
--- /dev/null
@@ -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 (file)
index 0000000..a9cb1b9
--- /dev/null
@@ -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 (file)
index 0000000..2aaa70f
--- /dev/null
@@ -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 (file)
index 0000000..a5fd3bf
--- /dev/null
@@ -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 (file)
index 0000000..e980811
--- /dev/null
@@ -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 (file)
index 0000000..1092c40
--- /dev/null
@@ -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 (file)
index 0000000..eda485b
--- /dev/null
@@ -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 (file)
index 0000000..f7ac2ab
--- /dev/null
@@ -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 (file)
index 0000000..ee4187c
--- /dev/null
@@ -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 (file)
index 0000000..afe7016
--- /dev/null
@@ -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 (file)
index 0000000..81d2495
--- /dev/null
@@ -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 (file)
index 0000000..d71979b
--- /dev/null
@@ -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 (file)
index 0000000..05681c0
--- /dev/null
@@ -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 (file)
index 0000000..8ed98a5
--- /dev/null
@@ -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 (file)
index 0000000..f0c3d51
--- /dev/null
@@ -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 (file)
index 0000000..9bcee63
--- /dev/null
@@ -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 (file)
index 0000000..2ad5cf6
--- /dev/null
@@ -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 (file)
index 0000000..b527f71
--- /dev/null
@@ -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 (file)
index 0000000..735cbc5
--- /dev/null
@@ -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 (file)
index 0000000..192af6a
--- /dev/null
@@ -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 (file)
index 0000000..e77ece1
--- /dev/null
@@ -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 (file)
index 0000000..d77d052
--- /dev/null
@@ -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 (file)
index 0000000..0239980
--- /dev/null
@@ -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 (file)
index 0000000..e148254
--- /dev/null
@@ -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 (file)
index 0000000..6a6d66f
--- /dev/null
@@ -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 (file)
index 0000000..b56fd60
--- /dev/null
@@ -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 (executable)
index 0000000..f1e341f
--- /dev/null
@@ -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 (file)
index 0000000..62bc65d
--- /dev/null
@@ -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 (file)
index 0000000..605b6c2
--- /dev/null
@@ -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 (executable)
index 0000000..c6a0288
--- /dev/null
@@ -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 (executable)
index 0000000..8972cba
--- /dev/null
@@ -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 (file)
index 0000000..5dbb629
--- /dev/null
@@ -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 (file)
index 0000000..4c4080a
--- /dev/null
@@ -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 (file)
index 0000000..3a225a5
--- /dev/null
@@ -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 (file)
index 0000000..8182e56
--- /dev/null
@@ -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 (file)
index 0000000..a5c07f2
--- /dev/null
@@ -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 (file)
index 0000000..3b29be3
--- /dev/null
@@ -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 (file)
index 0000000..2f54f66
--- /dev/null
@@ -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 (executable)
index 0000000..782b0d4
--- /dev/null
@@ -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 (file)
index 0000000..e0221e1
--- /dev/null
@@ -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 (file)
index 0000000..20b7247
--- /dev/null
@@ -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 (file)
index 0000000..01be2c6
--- /dev/null
@@ -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 (file)
index 0000000..0ccde75
--- /dev/null
@@ -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 (file)
index 0000000..8aa1be7
--- /dev/null
@@ -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 (file)
index 0000000..87419f1
--- /dev/null
@@ -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 (file)
index 0000000..3510585
--- /dev/null
@@ -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 (file)
index 0000000..d2818d7
--- /dev/null
@@ -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 (file)
index 0000000..2b47e15
--- /dev/null
@@ -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 (file)
index 0000000..e2d37c8
--- /dev/null
@@ -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.
index 5d390f3e2ffe29b9986f3209f749de846d6029b4..a154685299477ef7cc93e24a23d71fcd6a59ec89 100644 (file)
@@ -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 (file)
index 0000000..216a5bc
--- /dev/null
@@ -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 (file)
index 0000000..c60b699
--- /dev/null
@@ -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 (file)
index 0000000..37c62a6
--- /dev/null
@@ -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 (file)
index 0000000..04b6ab5
--- /dev/null
@@ -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 (file)
index 0000000..df5a88e
--- /dev/null
@@ -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 (file)
index 0000000..103a3b7
--- /dev/null
@@ -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 (file)
index 0000000..94f85bd
--- /dev/null
@@ -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;
+}
+
index f6d0dc820665c0a2bcb462bef2df8917aa36965a..f9b82fa6515bdc7dd0a88f7b7b5c3774ea221864 100644 (file)
@@ -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 (file)
index 0000000..14242ea
--- /dev/null
@@ -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 (file)
index 0000000..5e29e9a
--- /dev/null
@@ -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 (file)
index 0000000..0fd10cf
--- /dev/null
@@ -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 (file)
index 0000000..c4a004a
--- /dev/null
@@ -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 (file)
index 0000000..88f9ea3
--- /dev/null
@@ -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 (file)
index 0000000..c0e8092
--- /dev/null
@@ -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 (file)
index 0000000..cc57846
--- /dev/null
@@ -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 (file)
index 0000000..03d715e
--- /dev/null
@@ -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 (file)
index 0000000..b9ea9f2
--- /dev/null
@@ -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 (file)
index 0000000..a686f81
--- /dev/null
@@ -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 (file)
index 0000000..4a177db
--- /dev/null
@@ -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 (file)
index 0000000..51062de
--- /dev/null
@@ -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 (file)
index 0000000..30c8fbf
--- /dev/null
@@ -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 (file)
index 0000000..1bb4971
--- /dev/null
@@ -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 (file)
index 0000000..1cb55b4
--- /dev/null
@@ -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 (file)
index 0000000..510f24f
--- /dev/null
@@ -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 (file)
index 0000000..06b07bd
--- /dev/null
@@ -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.cc b/libs/surfaces/tranzport/tranzport_control_protocol.cc
deleted file mode 100644 (file)
index bbb78d3..0000000
+++ /dev/null
@@ -1,1950 +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$
-*/
-
-/* Design notes: The tranzport is a unique device, basically a 
-   20 lcd gui with 22 shift keys and 8 blinking lights. 
-
-   As such it has several unique constraints. 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.
-
-   It will be good one day, to break the gui, keyboard, and blinking light
-   components into separate parts, but for now, this remains monolithic.
-
-   A more complex surface might have hundreds of lights and several displays.
-
-   mike.taht@gmail.com
- */
-
-#define DEFAULT_USB_TIMEOUT 10
-#define MAX_RETRY 1
-#define MAX_TRANZPORT_INFLIGHT 4
-#define DEBUG_TRANZPORT 0
-#define HAVE_TRANZPORT_KERNEL_DRIVER 0
-
-#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>
-
-BaseUI::RequestType LEDChange = BaseUI::new_request_type ();
-BaseUI::RequestType Print = BaseUI::new_request_type ();
-BaseUI::RequestType SetCurrentTrack = BaseUI::new_request_type ();
-
-/* Base Tranzport cmd strings */
-
-static const uint8_t cmd_light_on[] =  { 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00 };
-static const uint8_t cmd_light_off[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
-static const uint8_t cmd_write_screen[] =  { 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00 };
-
-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);
-}
-
-
-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 = BlingOff;
-       timerclear (&last_wheel_motion);
-       last_wheel_dir = 1;
-       last_track_gain = FLT_MAX;
-       display_mode = DisplayNormal;
-       gain_fraction = 0.0;
-       invalidate();
-       screen_init();
-       lights_init();
-       print(0,0,"!!Welcome to Ardour!!");
-       print(1,0,"!Peace through Music!");
-}
-
-void TranzportControlProtocol::light_validate (LightID light) 
-{
-       lights_invalid[light] = 0;
-}
-
-void TranzportControlProtocol::light_invalidate (LightID light) 
-{
-       lights_invalid[light] = 1;
-}
-
-void TranzportControlProtocol::lights_validate () 
-{
-       memset (lights_invalid, 0, sizeof (lights_invalid)); 
-}
-
-void TranzportControlProtocol::lights_invalidate () 
-{
-       memset (lights_invalid, 1, sizeof (lights_invalid)); 
-}
-
-void TranzportControlProtocol::lights_init()
-{
-       for (uint32_t i = 0; i < sizeof(lights_current)/sizeof(lights_current[0]); i++) {
-               lights_invalid[i] = lights_current[i] = 
-                       lights_pending[i] = lights_flash[i] = false;
-       }
-}
-
-
-
-int
-TranzportControlProtocol::lights_flush ()
-{
-       if ( _device_status == STATUS_OFFLINE) { return (0); }
-
-       //  Figure out iterators one day soon
-       //  for (LightID i = i.start(), i = i.end(); i++) {
-       //  if (lights_pending[i] != lights_current[i] || lights_invalid[i]) {
-       //    if (light_set(i, lights_pending[i])) { 
-       //       return i-1;
-       //    } 
-       //  }
-       //}
-       if ((lights_pending[LightRecord] != lights_current[LightRecord]) || lights_invalid[LightRecord]) {
-               if (light_set(LightRecord,lights_pending[LightRecord])) {
-                       return 1;
-               }
-       }
-       if ((lights_pending[LightTrackrec] != lights_current[LightTrackrec]) || lights_invalid[LightTrackrec]) {
-               if (light_set(LightTrackrec,lights_pending[LightTrackrec])) {
-                       return 1;
-               }
-       }
-
-       if ((lights_pending[LightTrackmute] != lights_current[LightTrackmute]) || lights_invalid[LightTrackmute]) {
-               if (light_set(LightTrackmute,lights_pending[LightTrackmute])) {
-                       return 1;
-               }
-       }
-
-       if ((lights_pending[LightTracksolo] != lights_current[LightTracksolo]) || lights_invalid[LightTracksolo]) {
-               if (light_set(LightTracksolo,lights_pending[LightTracksolo])) {
-                       return 1;
-               }
-       }
-       if ((lights_pending[LightAnysolo] != lights_current[LightAnysolo]) || lights_invalid[LightAnysolo]) {
-               if (light_set(LightAnysolo,lights_pending[LightAnysolo])) {
-                       return 1;
-               }
-       }
-       if ((lights_pending[LightLoop] != lights_current[LightLoop]) || lights_invalid[LightLoop]) {
-               if (light_set(LightLoop,lights_pending[LightLoop])) {
-                       return 1;
-               }
-       }
-       if ((lights_pending[LightPunch] != lights_current[LightPunch]) || lights_invalid[LightPunch]) {
-               if (light_set(LightPunch,lights_pending[LightPunch])) {
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
-// Screen specific commands
-
-void
-TranzportControlProtocol::screen_clear ()
-{
-       const char *blank = "                    ";
-       print(0,0,blank); 
-       print(1,0,blank);
-}
-
-void TranzportControlProtocol::screen_invalidate ()
-{
-       for(int row = 0; row < 2; row++) {
-               for(int col = 0; col < 20; col++) {
-                       screen_invalid[row][col] = true;
-                       screen_current[row][col] = 0x7f;
-                       screen_pending[row][col] = ' ';
-                       // screen_flash[row][col] = ' ';
-               }
-       }
-       // memset (&screen_invalid, 1, sizeof(screen_invalid));
-       // memset (&screen_current, 0x7F, sizeof (screen_current)); // fill cache with a character we otherwise never use
-}
-
-void TranzportControlProtocol::screen_validate ()
-{
-}
-
-void TranzportControlProtocol::screen_init ()
-{
-       screen_invalidate();
-}
-
-int
-TranzportControlProtocol::screen_flush ()
-{
-       int cell = 0, row, col_base, col, pending = 0;
-       if ( _device_status == STATUS_OFFLINE) { return (-1); }
-
-       for (row = 0; row < 2 && pending == 0; row++) {
-               for (col_base = 0, col = 0; col < 20 && pending == 0; ) {
-                       if ((screen_pending[row][col] != screen_current[row][col]) 
-                                       || screen_invalid[row][col]) {
-
-                               /* something in this cell is different, so dump the cell to the device. */
-
-                               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(write(cmd) != 0) {
-                                       /* try to update this cell on the next go-round */
-#if DEBUG_TRANZPORT > 4
-                                       printf("usb screen update failed for some reason... why? \ncmd and data were %02x %02x %02x %02x %02x %02x %02x %02x\n", 
-                                                       cmd[0],cmd[1],cmd[2], cmd[3], cmd[4], cmd[5],cmd[6],cmd[7]); 
-#endif
-                                       pending += 1;   
-                                       // Shouldn't need to do this
-                                       // screen_invalid[row][col_base] = screen_invalid[row][col_base+1] = 
-                                       // screen_invalid[row][col_base+2] = screen_invalid[row][col_base+3] = true;
-
-                               } else {
-                                       /* successful write: copy to current cached display */
-                                       screen_invalid[row][col_base] = screen_invalid[row][col_base+1] = 
-                                               screen_invalid[row][col_base+2] = screen_invalid[row][col_base+3] = false;
-                                       memcpy (&screen_current[row][col_base], &screen_pending[row][col_base], 4);
-                               }
-
-                               /* skip the rest of the 4 character cell since we wrote+copied it already */
-
-                               col_base += 4;
-                               col = col_base;
-                               cell++;
-
-                       } else {
-
-                               col++;
-
-                               if (col && col % 4 == 0) {
-                                       cell++;
-                                       col_base += 4;
-                               }
-                       }
-               }
-       }
-       return pending;
-}
-
-
-//  Tranzport specific
-
-void TranzportControlProtocol::invalidate() 
-{
-       lcd_damage(); lights_invalidate(); screen_invalidate(); // one of these days lcds can be fine but screens not
-}
-
-TranzportControlProtocol::~TranzportControlProtocol ()
-{
-       set_active (false);
-}
-
-
-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;
-                       } else {
-                               return -1;
-                       }
-
-               } else {
-                       cerr << "Begin tranzport shutdown\n";
-                       screen_clear ();
-                       lcd_damage();
-                       lights_off ();
-                       for(int x = 0; x < 10 && flush(); x++) { usleep(1000); }
-                       pthread_cancel_one (thread);
-                       cerr << "Tranzport Thread dead\n";
-                       close ();
-                       _active = false;
-                       cerr << "End tranzport shutdown\n";
-               } 
-       }
-
-       return 0;
-}
-
-void
-TranzportControlProtocol::show_track_gain ()
-{
-       if (route_table[0]) {
-               gain_t g = route_get_gain (0);
-               if ((g != last_track_gain) || lcd_isdamaged(0,9,8)) {
-                       char buf[16]; 
-                       snprintf (buf, sizeof (buf), "%6.1fdB", coefficient_to_dB (route_get_effective_gain (0)));
-                       print (0, 9, buf); 
-                       last_track_gain = g;
-               }
-       } else {
-               print (0, 9, "        "); 
-       }
-}
-
-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, these 3 aren't done yet
-
-void
-TranzportControlProtocol::enter_recording_mode ()
-{
-       lcd_damage(); // excessive
-       screen_clear ();
-       lights_off ();
-       display_mode = DisplayRecording;
-}
-
-void
-TranzportControlProtocol::enter_bling_mode ()
-{
-       lcd_damage();
-       screen_clear ();
-       lights_off ();
-       display_mode = DisplayBling;
-}
-
-void
-TranzportControlProtocol::enter_config_mode ()
-{
-       lcd_damage();
-       screen_clear ();
-       lights_off ();
-       display_mode = DisplayConfig;
-}
-
-
-void
-TranzportControlProtocol::enter_big_meter_mode ()
-{
-       screen_clear ();
-       lcd_damage();
-       lights_off ();
-       last_meter_fill = 0;
-       display_mode = DisplayBigMeter;
-}
-
-void
-TranzportControlProtocol::enter_normal_display_mode ()
-{
-       screen_clear ();
-       lcd_damage();
-       lights_off ();
-       display_mode = DisplayNormal;
-       //  normal_update();
-}
-
-
-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;
-}
-
-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.98) {
-               light_on (LightAnysolo);
-       }
-
-       /* 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) || lcd_isdamaged(1,9,8)) {
-               char buf[16];
-               BBT_Time bbt;
-               session->tempo_map().bbt_time (where, bbt);
-               sprintf (buf, "%03" PRIu32 "|%02" PRIu32 "|%04" PRIu32, bbt.bars,bbt.beats,bbt.ticks);
-               last_bars = bbt.bars;
-               last_beats = bbt.beats;
-               last_ticks = bbt.ticks;
-               last_where = where;
-
-               if(last_ticks < 1960) { print (1, 9, buf); } // save a write so we can do leds
-
-               // if displaymode is recordmode show beats but not yet
-               lights_pending[LightRecord] = false;
-               lights_pending[LightAnysolo] = false;
-               switch(last_beats) {
-                       case 1: if(last_ticks < 500 || last_ticks > 1960) lights_pending[LightRecord] = true; break;
-                       default: if(last_ticks < 250) lights_pending[LightAnysolo] = true;
-               }
-
-               // update lights for tempo one day
-               //        if (bbt_upper_info_label) {
-               //     TempoMap::Metric m (session->tempo_map().metric_at (when));
-               //     sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
-               //      bbt_lower_info_label->set_text (buf);
-               //      sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
-               //      bbt_upper_info_label->set_text (buf);
-       }
-       }
-
-
-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::_monitor_work (void* arg)
-{
-       return static_cast<TranzportControlProtocol*>(arg)->monitor_work ();
-}
-
-// I note that these usb specific open, close, probe, read routines are basically 
-// pure boilerplate and could easily be abstracted elsewhere
-
-#if !HAVE_TRANZPORT_KERNEL_DRIVER
-
-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);
-               }
-       }
-
-       error << _("Tranzport: no device detected") << endmsg;
-       return -1;
-}
-
-int
-TranzportControlProtocol::open_core (struct usb_device* dev)
-{
-       if (!(udev = usb_open (dev))) {
-               error << _("Tranzport: cannot open USB transport") << endmsg;
-               return -1;
-       }
-        
-       if (usb_claim_interface (udev, 0) < 0) {
-               error << _("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) {
-               error << _("Tranzport: cannot release interface") << endmsg;
-               ret = -1;
-       }
-
-       if (usb_close (udev)) {
-               error << _("Tranzport: cannot close device") << endmsg;
-               udev = 0;
-               ret = 0;
-       }
-
-       return ret;
-}
-
-int TranzportControlProtocol::read(uint8_t *buf, uint32_t timeout_override) 
-{
-       int val;
-       // Get smarter about handling usb errors soon. Like disconnect
-       //  pthread_testcancel();
-       val = usb_interrupt_read (udev, READ_ENDPOINT, (char *) buf, 8, 10);
-       //  pthread_testcancel();
-       return val;
-} 
-
-       
-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) {
-#if DEBUG_TRANZPORT
-               printf("usb_interrupt_write failed: %d\n", val);
-#endif
-               return val;
-               }
-
-       if (val != 8) {
-#if DEBUG_TRANZPORT
-               printf("usb_interrupt_write failed: %d\n", val);
-#endif
-               return -1;
-               }
-       ++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
-
-}      
-
-#else
-#error Kernel API not defined yet for Tranzport
-// Something like open(/dev/surface/tranzport/event) for reading and raw for writing)
-#endif
-
-// We have a state "Unknown" - STOP USING SPACES FOR IT - switching to arrow character
-// We have another state - no_retry. Misleading, as we still retry on the next pass
-// I think it's pointless to keep no_retry and instead we should throttle writes 
-// We have an "displayed" screen
-// We always draw into the pending screen, which could be any of several screens
-// We have an active screen
-// Print arg - we have 
-// setactive
-// so someday I think we need a screen object.
-
-/*
-screen_flash.clear();
-screen_flash.print(0,0,"Undone:"); // Someday pull the undo stack from somewhere
-screen_flash.print(1,0,"Nextup:"); 
-
-if(flash_messages && lcd.getactive() != screen_flash) lcd.setactive(screen_flash,2000);
-
-screen::setactive(screen_name,duration); // duration in ms
-screen::getactive();
-*/
-
-
-int
-TranzportControlProtocol::flush ()
-{
-       int pending = 0;
-       if(!(pending = lights_flush())) {
-               pending = screen_flush(); 
-       } 
-       return pending;
-}
-
-// 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)
-{
-       bool result = false;
-       int endcol = col+length-1;
-       if((endcol > 19)) { endcol = 19; } 
-       if((row >= 0 && row < 2) && (col >=0 && col < 20)) {
-               for(int c = col; c < endcol; c++) {
-                       screen_invalid[row][c] = true;
-               }
-               result = true;
-       }
-       return result;
-}
-
-// Gotta switch to bitfields, this is collossally dumb
-// Still working on the layering, arguably screen_invalid should be lcd_invalid
-
-bool TranzportControlProtocol::lcd_isdamaged () 
-{
-       for(int r = 0; r < 2; r++) {
-               for(int c = 0; c < 20; c++) {
-                       if(screen_invalid[r][c]) {
-#if DEBUG_TRANZPORT > 5        
-                               printf("row: %d,col: %d is damaged, should redraw it\n", r,c);
-#endif
-                               return true;
-                       }
-               }
-       }
-       return false;
-}
-
-bool TranzportControlProtocol::lcd_isdamaged (int row, int col, int length)
-{
-       bool result = 0;
-       int endcol = col+length;
-       if((endcol > 19)) { endcol = 19; } 
-       if((row >= 0 && row < 2) && (col >=0 && col < 20)) {
-               for(int c = col; c < endcol; c++) {
-                       if(screen_invalid[row][c]) {
-#if DEBUG_TRANZPORT > 5        
-                               printf("row: %d,col: %d is damaged, should redraw it\n", row,c);
-#endif
-                               return true;
-                       }
-               }
-       }
-       return result;
-}
-
-// 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)
-{
-       return write(cmd,timeout_override);
-}
-
-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);
-}
-
-// Lights are buffered
-
-void
-TranzportControlProtocol::lights_on ()
-{
-       lights_pending[LightRecord] = lights_pending[LightTrackrec] = 
-               lights_pending[LightTrackmute] =  lights_pending[LightTracksolo] = 
-               lights_pending[LightAnysolo] =   lights_pending[LightLoop] = 
-               lights_pending[LightPunch] = true;
-}
-
-void
-TranzportControlProtocol::lights_off ()
-{
-       lights_pending[LightRecord] = lights_pending[LightTrackrec] = 
-               lights_pending[LightTrackmute] =  lights_pending[LightTracksolo] = 
-               lights_pending[LightAnysolo] =   lights_pending[LightLoop] = 
-               lights_pending[LightPunch] = false;
-}
-
-int
-TranzportControlProtocol::light_on (LightID light)
-{
-       lights_pending[light] = true;
-       return 0;
-}
-
-int
-TranzportControlProtocol::light_off (LightID light)
-{
-       lights_pending[light] = false;
-       return 0;
-}
-
-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[light] = false;
-               return 0;
-       } else {
-               return -1;
-       }
-}
-
-int TranzportControlProtocol::rtpriority_set(int priority) 
-{
-       struct sched_param rtparam;
-       int err;
-       // preallocate and memlock some stack with memlock?
-       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;
-}
-
-// Slowly breaking this into where I can make usb processing it's own thread.
-
-void*
-TranzportControlProtocol::monitor_work ()
-{
-       uint8_t buf[8];
-       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);
-       next_track ();
-       rtpriority_set();
-       inflight=0;
-       flush();
-
-       while (true) {
-
-               /* bInterval for this beastie is 10ms */
-
-               if (_device_status == STATUS_OFFLINE) {
-                       first_time = true;
-                       if(offline++ == 1) { 
-                               cerr << "Transport has gone offline\n";
-                       }
-               } else { 
-                       offline = 0; // hate writing this
-               }
-
-               val = read(buf);
-
-               if (val == 8) {
-                       process (buf);
-               }
-
-#if DEBUG_TRANZPORT > 2
-               if(inflight > 1) printf("Inflight: %d\n", inflight);
-#endif
-
-
-               if (_device_status != STATUS_OFFLINE) {
-                       if (first_time) {
-                               invalidate();
-                               lcd_clear ();
-                               lights_off ();
-                               first_time = false;
-                               offline = 0;
-                               pending = 3; // Give some time for the device to recover
-                       }
-                       /* update whatever needs updating */
-                       update_state ();
-
-                       /* still struggling with a good means of exerting flow control */
-                       // 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;
-}
-
-int TranzportControlProtocol::lights_show_recording() 
-{
-       //   FIXME, flash recording light when recording and transport is moving
-       return     lights_show_normal();
-}
-
-// gotta do bling next!
-
-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
-       }
-       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 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:
-                       lights_show_bling();
-                       normal_update();
-                       break;
-
-               case DisplayBlingMeter:
-                       lights_show_bling();
-                       show_meter();
-                       break;
-       }
-       return 0;
-
-}
-
-#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)
-{
-       // 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]);
-
-       uint32_t this_button_mask;
-       uint32_t button_changes;
-
-       _device_status = buf[1];
-
-       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];
-
-       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);
-       return 0;
-}
-
-void
-TranzportControlProtocol::show_current_track ()
-{
-       char pad[11];
-       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, 10).c_str();
-               if((len = strlen(v)) > 0) {
-                       strncpy(pad,(char *)v,len);
-               }
-               print (0, 0, pad);
-       }
-}
-
-void
-TranzportControlProtocol::button_event_battery_press (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_battery_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_backlight_press (bool shifted)
-{
-#if DEBUG_TRANZPORT
-       printf("backlight pressed\n");
-#endif
-}
-
-void
-TranzportControlProtocol::button_event_backlight_release (bool shifted)
-{
-#if DEBUG_TRANZPORT
-       printf("backlight released\n\n");
-#endif
-       if (shifted) {
-               lcd_damage();
-               lcd_clear();
-               last_where += 1; /* force time redisplay */
-               last_track_gain = FLT_MAX;
-               normal_update(); //  redraw_screen();  
-       }
-}
-
-void
-TranzportControlProtocol::button_event_trackleft_press (bool shifted)
-{
-       prev_track ();
-}
-
-void
-TranzportControlProtocol::button_event_trackleft_release (bool shifted)
-{
-}
-
-void
-TranzportControlProtocol::button_event_trackright_press (bool shifted)
-{
-       next_track ();
-}
-
-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)
-{
-       if (shifted) {
-               redo (); // someday flash the screen with what was redone
-       } else {
-               undo (); // someday flash the screen with what was 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)
-{
-}
-
-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 button_event_mute (bool pressed, bool shifted)
-{
-       //static int was_pressed = 0;
-       //  if(pressed) { }
-}
-
-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;
-               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::config ()
-{
-  // FIXME
-}
-
-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);
-               }
-       }
-}
-
-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::step_pan_right ()
-{
-}
-
-void
-TranzportControlProtocol::step_pan_left ()
-{
-}
-
-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::next_track ()
-{
-       ControlProtocol::next_track (current_track_id);
-       gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
-}
-
-void
-TranzportControlProtocol::prev_track ()
-{
-       ControlProtocol::prev_track (current_track_id);
-       gain_fraction = gain_to_slider_position (route_get_effective_gain (0));
-}
-
-void
-TranzportControlProtocol::show_wheel_mode ()
-{
-       string text;
-
-       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());
-}
-
-// 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);
-}
-
-void
-TranzportControlProtocol::print_noretry (int row, int col, const char *text)
-{
-       int cell;
-       uint32_t left = strlen (text);
-       char tmp[5];
-       int base_col;
-       
-       if (row < 0 || row > 1) {
-               return;
-       }
-
-       if (col < 0 || col > 19) {
-               return;
-       }
-
-       while (left) {
-
-               if (col >= 0 && col < 4) {
-                       cell = 0;
-                       base_col = 0;
-               } else if (col >= 4 && col < 8) {
-                       cell = 1;
-                       base_col = 4;
-               } else if (col >= 8 && col < 12) {
-                       cell = 2;
-                       base_col = 8;
-               } else if (col >= 12 && col < 16) {
-                       cell = 3;
-                       base_col = 12;
-               } else if (col >= 16 && col < 20) {
-                       cell = 4;
-                       base_col = 16;
-               } else {
-                       return;
-               }
-
-               int offset = col % 4;
-
-               /* copy current cell contents into tmp */
-               
-               memcpy (tmp, &screen_pending[row][base_col], 4);
-               
-               /* overwrite with new text */
-               
-               uint32_t tocopy = min ((4U - offset), left);
-               
-               memcpy (tmp+offset, text, tocopy);
-               
-               /* copy it back to pending */
-               
-               memcpy (&screen_pending[row][base_col], tmp, 4);
-               
-               text += tocopy;
-               left -= tocopy;
-               col  += tocopy;
-       }
-}      
-
-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)
-{
-       return 0;
-}
-
-int
-TranzportControlProtocol::save (char *name) 
-{
-       // Presently unimplemented
-       return 0;
-}
-
-int
-TranzportControlProtocol::load (char *name) 
-{
-       // Presently unimplemented
-       return 0;
-}
index f13e4a3a44d57cc7300ddbb87b6c8e5c8ba846f3..929cca3e2b827c70d0607862837b73a6e5ecf6c9 100644 (file)
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..8de9e3a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..4c0b18a
--- /dev/null
@@ -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 (file)
index 0000000..bc9683e
--- /dev/null
@@ -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 (file)
index 0000000..06b3ae0
--- /dev/null
@@ -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 (file)
index 0000000..7696526
--- /dev/null
@@ -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 (file)
index 0000000..b605a10
--- /dev/null
@@ -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 (file)
index 0000000..08f3581
--- /dev/null
@@ -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 (file)
index 0000000..95da193
--- /dev/null
@@ -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 (file)
index 0000000..8dfab00
Binary files /dev/null and b/manual/images/add_track_bus.png differ
diff --git a/manual/images/admon-bg.png b/manual/images/admon-bg.png
new file mode 100644 (file)
index 0000000..37406fa
Binary files /dev/null and b/manual/images/admon-bg.png differ
diff --git a/manual/images/con1.jpg b/manual/images/con1.jpg
new file mode 100644 (file)
index 0000000..8b3d0a7
Binary files /dev/null and b/manual/images/con1.jpg differ
diff --git a/manual/images/con2.jpg b/manual/images/con2.jpg
new file mode 100644 (file)
index 0000000..03cd368
Binary files /dev/null and b/manual/images/con2.jpg differ
diff --git a/manual/images/internalhigheroverlap.png b/manual/images/internalhigheroverlap.png
new file mode 100644 (file)
index 0000000..50ad2b1
Binary files /dev/null and b/manual/images/internalhigheroverlap.png differ
diff --git a/manual/images/internalloweroverlap.png b/manual/images/internalloweroverlap.png
new file mode 100644 (file)
index 0000000..32c16b5
Binary files /dev/null and b/manual/images/internalloweroverlap.png differ
diff --git a/manual/images/ladspa.jpg b/manual/images/ladspa.jpg
new file mode 100644 (file)
index 0000000..680b18c
Binary files /dev/null and b/manual/images/ladspa.jpg differ
diff --git a/manual/images/manual_style.svg b/manual/images/manual_style.svg
new file mode 100644 (file)
index 0000000..86f03ad
--- /dev/null
@@ -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 (file)
index 0000000..2d63efe
Binary files /dev/null and b/manual/images/matrixmixer.png differ
diff --git a/manual/images/midiopts.jpg b/manual/images/midiopts.jpg
new file mode 100644 (file)
index 0000000..08e49c7
Binary files /dev/null and b/manual/images/midiopts.jpg differ
diff --git a/manual/images/mixer.png b/manual/images/mixer.png
new file mode 100644 (file)
index 0000000..ace8901
Binary files /dev/null and b/manual/images/mixer.png 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 (file)
index 0000000..6092cec
Binary files /dev/null and b/manual/images/mixer_strip_name_button_popup.png differ
diff --git a/manual/images/mixerstrip.png b/manual/images/mixerstrip.png
new file mode 100644 (file)
index 0000000..1121b2d
Binary files /dev/null and b/manual/images/mixerstrip.png differ
diff --git a/manual/images/new_session_advanced_tab.png b/manual/images/new_session_advanced_tab.png
new file mode 100644 (file)
index 0000000..6fa5c93
Binary files /dev/null and b/manual/images/new_session_advanced_tab.png differ
diff --git a/manual/images/new_session_select_directory.png b/manual/images/new_session_select_directory.png
new file mode 100644 (file)
index 0000000..d689748
Binary files /dev/null and b/manual/images/new_session_select_directory.png differ
diff --git a/manual/images/overlapearlyhigher.png b/manual/images/overlapearlyhigher.png
new file mode 100644 (file)
index 0000000..5223e09
Binary files /dev/null and b/manual/images/overlapearlyhigher.png differ
diff --git a/manual/images/overlaplaterhigher.png b/manual/images/overlaplaterhigher.png
new file mode 100644 (file)
index 0000000..5b7bd13
Binary files /dev/null and b/manual/images/overlaplaterhigher.png differ
diff --git a/manual/images/pluginmenu.jpg b/manual/images/pluginmenu.jpg
new file mode 100644 (file)
index 0000000..fd14de0
Binary files /dev/null and b/manual/images/pluginmenu.jpg differ
diff --git a/manual/images/plugins.jpg b/manual/images/plugins.jpg
new file mode 100644 (file)
index 0000000..4c19f7d
Binary files /dev/null and b/manual/images/plugins.jpg differ
diff --git a/manual/images/qjackctl.png b/manual/images/qjackctl.png
new file mode 100644 (file)
index 0000000..bcdef4b
Binary files /dev/null and b/manual/images/qjackctl.png differ
diff --git a/manual/images/qjopt.jpg b/manual/images/qjopt.jpg
new file mode 100644 (file)
index 0000000..1d68393
Binary files /dev/null and b/manual/images/qjopt.jpg differ
diff --git a/manual/images/qjopts.jpg b/manual/images/qjopts.jpg
new file mode 100644 (file)
index 0000000..efe8b9a
Binary files /dev/null and b/manual/images/qjopts.jpg differ
diff --git a/manual/images/qjpatch.jpg b/manual/images/qjpatch.jpg
new file mode 100644 (file)
index 0000000..a6a45ee
Binary files /dev/null and b/manual/images/qjpatch.jpg differ
diff --git a/manual/images/save_session_dialog.png b/manual/images/save_session_dialog.png
new file mode 100644 (file)
index 0000000..3af28d2
Binary files /dev/null and b/manual/images/save_session_dialog.png differ
diff --git a/manual/images/save_template_dialog.png b/manual/images/save_template_dialog.png
new file mode 100644 (file)
index 0000000..1266f8b
Binary files /dev/null and b/manual/images/save_template_dialog.png differ
diff --git a/manual/images/session_control.png b/manual/images/session_control.png
new file mode 100644 (file)
index 0000000..adba5f6
Binary files /dev/null and b/manual/images/session_control.png differ
diff --git a/manual/images/signal_flow.png b/manual/images/signal_flow.png
new file mode 100644 (file)
index 0000000..35fdcba
Binary files /dev/null and b/manual/images/signal_flow.png differ
diff --git a/manual/images/tango-icons/COPYING b/manual/images/tango-icons/COPYING
new file mode 100644 (file)
index 0000000..e709d0c
--- /dev/null
@@ -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 (file)
index 0000000..aa7188e
--- /dev/null
@@ -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 (file)
index 0000000..1e957cc
--- /dev/null
@@ -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 (file)
index 0000000..51f7ff3
--- /dev/null
@@ -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 (file)
index 0000000..835d6fc
--- /dev/null
@@ -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 (file)
index 0000000..6bdddcb
Binary files /dev/null and b/manual/images/tango-icons/important.png differ
diff --git a/manual/images/tango-icons/note.png b/manual/images/tango-icons/note.png
new file mode 100644 (file)
index 0000000..45c3643
Binary files /dev/null and b/manual/images/tango-icons/note.png differ
diff --git a/manual/images/tango-icons/tip.png b/manual/images/tango-icons/tip.png
new file mode 100644 (file)
index 0000000..98d249a
Binary files /dev/null and b/manual/images/tango-icons/tip.png differ
diff --git a/manual/images/tango-icons/warning.png b/manual/images/tango-icons/warning.png
new file mode 100644 (file)
index 0000000..cee66db
Binary files /dev/null and b/manual/images/tango-icons/warning.png differ
diff --git a/manual/images/title-bg.png b/manual/images/title-bg.png
new file mode 100644 (file)
index 0000000..00fc7ed
Binary files /dev/null and b/manual/images/title-bg.png differ
diff --git a/manual/images/track_name_field.png b/manual/images/track_name_field.png
new file mode 100644 (file)
index 0000000..8cf02b9
Binary files /dev/null and b/manual/images/track_name_field.png differ
diff --git a/manual/images/transctls.jpg b/manual/images/transctls.jpg
new file mode 100644 (file)
index 0000000..695c593
Binary files /dev/null and b/manual/images/transctls.jpg differ
diff --git a/manual/images/watermark-draft.png b/manual/images/watermark-draft.png
new file mode 100644 (file)
index 0000000..b4fffd2
Binary files /dev/null and b/manual/images/watermark-draft.png differ
diff --git a/manual/templates/chapter_template.xml b/manual/templates/chapter_template.xml
new file mode 100644 (file)
index 0000000..ea28654
--- /dev/null
@@ -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 (file)
index 0000000..e5cb7ae
--- /dev/null
@@ -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 (file)
index 0000000..999c659
--- /dev/null
@@ -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 (file)
index 0000000..980f333
--- /dev/null
@@ -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 (file)
index 0000000..d936f31
--- /dev/null
@@ -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 (file)
index 0000000..abbed68
--- /dev/null
@@ -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 (file)
index 0000000..0f19d07
--- /dev/null
@@ -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 (file)
index 0000000..4f19157
--- /dev/null
@@ -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 (file)
index 0000000..ba40c96
--- /dev/null
@@ -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 (file)
index 0000000..64c1b2f
--- /dev/null
@@ -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 (file)
index 0000000..697498f
--- /dev/null
@@ -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 (file)
index 0000000..06e4cbf
--- /dev/null
@@ -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 (file)
index 0000000..9a5e3d9
--- /dev/null
@@ -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 (file)
index 0000000..aa3ba8f
--- /dev/null
@@ -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 (file)
index 0000000..4a14497
--- /dev/null
@@ -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 (file)
index 0000000..88781b0
--- /dev/null
@@ -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 (file)
index 0000000..7a74f94
--- /dev/null
@@ -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 (file)
index 0000000..3d9bdd2
--- /dev/null
@@ -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 (file)
index 0000000..d969f04
--- /dev/null
@@ -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 (file)
index 0000000..e16d152
--- /dev/null
@@ -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 (file)
index 0000000..c73bb00
--- /dev/null
@@ -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 (file)
index 0000000..8a6c677
--- /dev/null
@@ -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 (file)
index 0000000..e9b3eb4
--- /dev/null
@@ -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 (file)
index 0000000..1190e3e
--- /dev/null
@@ -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 (file)
index 0000000..d83c446
--- /dev/null
@@ -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 (file)
index 0000000..1fd40d1
--- /dev/null
@@ -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 (file)
index 0000000..8c0560d
--- /dev/null
@@ -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 (file)
index 0000000..52024cb
--- /dev/null
@@ -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 (file)
index 0000000..111de88
--- /dev/null
@@ -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 (file)
index 0000000..e830c2c
--- /dev/null
@@ -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 (file)
index 0000000..d8f2389
--- /dev/null
@@ -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 (file)
index 0000000..8f56afa
--- /dev/null
@@ -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 (file)
index 0000000..092a4ce
--- /dev/null
@@ -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 (file)
index 0000000..42b645c
--- /dev/null
@@ -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 (file)
index 0000000..a96ed75
--- /dev/null
@@ -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 (file)
index 0000000..7c7990e
--- /dev/null
@@ -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 (file)
index 0000000..f9352aa
--- /dev/null
@@ -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 (file)
index 0000000..9ede6fa
--- /dev/null
@@ -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 (file)
index 0000000..b8afa14
--- /dev/null
@@ -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 (file)
index 0000000..f21530b
--- /dev/null
@@ -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 (file)
index 0000000..fb34fb3
--- /dev/null
@@ -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 (file)
index 0000000..2042e29
--- /dev/null
@@ -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 (file)
index 0000000..3908a53
--- /dev/null
@@ -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 (file)
index 0000000..675999f
--- /dev/null
@@ -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 (file)
index 0000000..edf77ad
--- /dev/null
@@ -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 (file)
index 0000000..675d894
--- /dev/null
@@ -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 (file)
index 0000000..fdc26d4
--- /dev/null
@@ -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 (file)
index 0000000..e07b2c4
--- /dev/null
@@ -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 (file)
index 0000000..27c1463
--- /dev/null
@@ -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 (file)
index 0000000..8798a45
--- /dev/null
@@ -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 (file)
index 0000000..f3b5081
--- /dev/null
@@ -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 (file)
index 0000000..0cdeedd
--- /dev/null
@@ -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 (file)
index 0000000..56d6a17
--- /dev/null
@@ -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 (file)
index 0000000..32eb2c7
--- /dev/null
@@ -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 (file)
index 0000000..ca72916
--- /dev/null
@@ -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 (file)
index 0000000..b381ced
--- /dev/null
@@ -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 (file)
index 0000000..8346773
--- /dev/null
@@ -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 (file)
index 0000000..b207203
--- /dev/null
@@ -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 (file)
index 0000000..6f181cb
--- /dev/null
@@ -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 (file)
index 0000000..8479e16
--- /dev/null
@@ -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 (file)
index 0000000..b1e06ea
--- /dev/null
@@ -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 (file)
index 0000000..d2e42c4
--- /dev/null
@@ -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 (file)
index 0000000..59b96f8
--- /dev/null
@@ -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 (file)
index 0000000..3ed66cb
--- /dev/null
@@ -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 (file)
index 0000000..7883bb4
--- /dev/null
@@ -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 (file)
index 0000000..09b0585
--- /dev/null
@@ -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 (file)
index 0000000..765c049
--- /dev/null
@@ -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 (file)
index 0000000..c750031
--- /dev/null
@@ -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 (file)
index 0000000..b717c31
--- /dev/null
@@ -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 (file)
index 0000000..d3c2069
--- /dev/null
@@ -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 (file)
index 0000000..033217e
--- /dev/null
@@ -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 (file)
index 0000000..ce364fa
--- /dev/null
@@ -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 (file)
index 0000000..6b3feb6
--- /dev/null
@@ -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 (file)
index 0000000..22aa34e
--- /dev/null
@@ -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 (file)
index 0000000..b430a90
--- /dev/null
@@ -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 (file)
index 0000000..a9e31f5
--- /dev/null
@@ -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 (file)
index 0000000..88b94bd
--- /dev/null
@@ -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 (file)
index 0000000..dcb3d38
--- /dev/null
@@ -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 (file)
index 0000000..684edb2
--- /dev/null
@@ -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 (file)
index 0000000..5c626fe
--- /dev/null
@@ -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 (file)
index 0000000..0947baf
--- /dev/null
@@ -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 (file)
index 0000000..0b39eb7
--- /dev/null
@@ -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 (file)
index 0000000..d008a64
--- /dev/null
@@ -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 (file)
index 0000000..c2a3954
--- /dev/null
@@ -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 (file)
index 0000000..61f80ad
--- /dev/null
@@ -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 (file)
index 0000000..1aba2db
--- /dev/null
@@ -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 (file)
index 0000000..3b5af01
--- /dev/null
@@ -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 (file)
index 0000000..476b5fb
--- /dev/null
@@ -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 (file)
index 0000000..ff41c30
--- /dev/null
@@ -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 (file)
index 0000000..55b6599
--- /dev/null
@@ -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 (file)
index 0000000..412da4b
--- /dev/null
@@ -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 (file)
index 0000000..bd843ca
--- /dev/null
@@ -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 (file)
index 0000000..ccf56cc
--- /dev/null
@@ -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 (file)
index 0000000..f21e0f9
--- /dev/null
@@ -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 (file)
index 0000000..1c8cea8
--- /dev/null
@@ -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 (file)
index 0000000..d1e8195
--- /dev/null
@@ -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 (file)
index 0000000..0de7f5f
--- /dev/null
@@ -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 (file)
index 0000000..59017c8
--- /dev/null
@@ -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 (file)
index 0000000..14bd362
--- /dev/null
@@ -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 (file)
index 0000000..53c4ff6
--- /dev/null
@@ -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 (file)
index 0000000..552dc17
--- /dev/null
@@ -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 (executable)
index 0000000..877f5f1
--- /dev/null
@@ -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 (file)
index 0000000..f8ddf14
--- /dev/null
@@ -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>
index abd97e056583743ddaf42c6badd9230c9ef6a630..069c1be36ab472e25e9adaa5bba53aa7a60d3517 100644 (file)
@@ -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
index ffe37e9c83155515b3056e7b3e7f2b122ace6326..3d798d77b4b8c61bda1c6a5c00c5741684ccbdf1 100644 (file)
@@ -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"/>
index 6b1261417224298aff9e4b7ba7d6a2a1e0d07d31..522b00cb0f1ebe8e2ec94d45f68a6aa20bfe2935 100644 (file)
@@ -9,6 +9,7 @@
    an array of Uniform Type Identifiers (UTI) for the LSItemContentTypes 
    that your importer can handle
   
+   (DONE)
    ----------------------------------------------------------------------------- */
 
 /* -----------------------------------------------------------------------------
index da11c8db5b06c25c45267a8d32f25b2ccf189da1..13097298e9453016eb662e2ead849a0fc36ccb28 100644 (file)
        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>
                        <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>
index 39ee9439652612188ed4c13b6de406b57fb4dbce..c2729ee5324d4b177ba462dda607072689d7f340 100644 (file)
                                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;
                                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;
index 093c4b72da3d048c089d9a631c094ff9a8f03eea..ee27cb3f321f100ff235507d766c5f1faee94f9f 100755 (executable)
@@ -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 "$@"