mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 07:14:56 +01:00
Merged with trunk R1393.
git-svn-id: svn://localhost/ardour2/branches/midi@1395 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
cd37c36326
commit
f9f5ec85fb
85 changed files with 5136 additions and 2848 deletions
|
|
@ -1,7 +0,0 @@
|
|||
.sconf_temp
|
||||
.sconsign.dblite
|
||||
ardour.rc
|
||||
config.log
|
||||
scache.conf
|
||||
.gdb_history
|
||||
docs/
|
||||
|
|
@ -16,7 +16,7 @@ import SCons.Node.FS
|
|||
SConsignFile()
|
||||
EnsureSConsVersion(0, 96)
|
||||
|
||||
ardour_version = '2.0beta10'
|
||||
ardour_version = '2.0beta11.1'
|
||||
|
||||
subst_dict = { }
|
||||
|
||||
|
|
@ -659,7 +659,8 @@ opt_flags[:0] = [
|
|||
"-O3",
|
||||
"-fomit-frame-pointer",
|
||||
"-ffast-math",
|
||||
"-fstrength-reduce"
|
||||
"-fstrength-reduce",
|
||||
"-fno-strict-aliasing"
|
||||
]
|
||||
|
||||
if env['DEBUG'] == 1:
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
<Option name="quieten-at-speed" value="1.000000"/>
|
||||
<Option name="use-vst" value="yes"/>
|
||||
<Option name="use-tranzport" value="yes"/>
|
||||
<Option name="destructive-xfade-msecs" value="500"/>
|
||||
<Option name="destructive-xfade-msecs" value="20"/>
|
||||
</Config>
|
||||
<extra>
|
||||
<Keyboard edit-button="3" edit-modifier="4" delete-button="3" delete-modifier="1" snap-modifier="32"/>
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ editor_region_list.cc
|
|||
editor_route_list.cc
|
||||
editor_rulers.cc
|
||||
editor_scrub.cc
|
||||
editor_selection.cc
|
||||
editor_selection_list.cc
|
||||
editor_tempodisplay.cc
|
||||
editor_timefx.cc
|
||||
|
|
@ -326,6 +327,7 @@ env.Alias ('tarball', env.Distribute (env['DISTTREE'],
|
|||
[ 'SConscript',
|
||||
'i18n.h', 'gettext.h',
|
||||
'ardour.sh.in',
|
||||
'ardev_common.sh.in',
|
||||
'ardour2_ui.rc', 'splash.png',
|
||||
'ardour.menus', 'ardour.bindings', 'ardour.colors',
|
||||
'editor_xpms'
|
||||
|
|
|
|||
|
|
@ -226,7 +226,6 @@ AnalysisWindow::analyze_data (Gtk::Button *button)
|
|||
TimeSelection ts = s.time;
|
||||
RegionSelection ars = s.regions;
|
||||
|
||||
|
||||
for (TrackSelection::iterator i = s.tracks.begin(); i != s.tracks.end(); ++i) {
|
||||
boost::shared_ptr<AudioPlaylist> pl
|
||||
= boost::dynamic_pointer_cast<AudioPlaylist>((*i)->playlist());
|
||||
|
|
@ -278,7 +277,7 @@ AnalysisWindow::analyze_data (Gtk::Button *button)
|
|||
|
||||
TimeAxisView *current_axis = (*i);
|
||||
|
||||
for (std::set<RegionView *>::iterator j = ars.begin(); j != ars.end(); ++j) {
|
||||
for (RegionSelection::iterator j = ars.begin(); j != ars.end(); ++j) {
|
||||
// Check that the region is actually audio (so we can analyze it)
|
||||
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*j);
|
||||
if (!arv)
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
cd `dirname "$0"`/..
|
||||
|
||||
#export G_DEBUG=fatal_criticals
|
||||
|
||||
export ARDOUR_PATH=gtk2_ardour/icons:gtk2_ardour/pixmaps:gtk2_ardour
|
||||
export GTK_PATH=libs/clearlooks
|
||||
|
||||
|
||||
export LD_LIBRARY_PATH=libs/surfaces/control_protocol:libs/ardour:libs/midi++2:libs/pbd:libs/soundtouch:libs/gtkmm2ext:libs/sigc++2:libs/glibmm2:libs/gtkmm2/atk:libs/gtkmm2/pango:libs/gtkmm2/gdk:libs/gtkmm2/gtk:libs/libgnomecanvasmm:libs/libsndfile:libs/appleutility:$LD_LIBRARY_PATH
|
||||
|
||||
# DYLD_LIBRARY_PATH is for darwin.
|
||||
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
||||
# For the internal clearlooks engine
|
||||
export GTK_PATH=$PWD/libs/clearlooks:~/.ardour2
|
||||
|
||||
EXECUTABLE=gtk2_ardour/ardour-2.0beta10
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
; ardour-2.0beta10 GtkAccelMap rc-file -*- scheme -*-
|
||||
; ardour-2.0beta11.1 GtkAccelMap rc-file -*- scheme -*-
|
||||
; this file is an automated accelerator map dump
|
||||
;
|
||||
; (gtk_accel_path "<Actions>/RegionList/RegionListSort" "")
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
; (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>Right")
|
||||
(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" "")
|
||||
|
|
@ -70,9 +70,9 @@
|
|||
(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>/Main/FlushWastebasket" "")
|
||||
; (gtk_accel_path "<Actions>/RegionList/SortByRegionEndinFile" "")
|
||||
; (gtk_accel_path "<Actions>/Editor/ToggleMeasureVisibility" "")
|
||||
; (gtk_accel_path "<Actions>/Zoom/zoom-focus-center" "")
|
||||
|
|
@ -99,6 +99,7 @@
|
|||
; (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" "")
|
||||
|
|
@ -111,12 +112,14 @@
|
|||
(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")
|
||||
|
|
@ -124,6 +127,7 @@
|
|||
; (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" "")
|
||||
|
|
@ -170,6 +174,7 @@
|
|||
; (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" "")
|
||||
|
|
@ -202,13 +207,14 @@
|
|||
; (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>/MouseMode/set-mouse-mode-timefx" "t")
|
||||
; (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")
|
||||
|
|
@ -261,7 +267,7 @@
|
|||
; (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>Left")
|
||||
(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" "")
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@
|
|||
<separator/>
|
||||
<menuitem action='Record'/>
|
||||
<separator/>
|
||||
<menuitem action='TransitionToRoll'/>
|
||||
<menuitem action='TransitionToReverse'/>
|
||||
<separator/>
|
||||
<menuitem action='jump-forward-to-mark'/>
|
||||
<menuitem action='jump-backward-to-mark'/>
|
||||
<menuitem action='add-location-from-playhead'/>
|
||||
|
|
@ -203,6 +206,9 @@
|
|||
<menuitem action='scroll-forward'/>
|
||||
<menuitem action='scroll-backward'/>
|
||||
<separator/>
|
||||
<menuitem action='scroll-playhead-forward'/>
|
||||
<menuitem action='scroll-playhead-backward'/>
|
||||
<separator/>
|
||||
<menuitem action='ToggleWaveformVisibility'/>
|
||||
<menuitem action='ToggleWaveformsWhileRecording'/>
|
||||
<menuitem action='ToggleMeasureVisibility'/>
|
||||
|
|
@ -334,6 +340,7 @@
|
|||
<menuitem action='StopPluginsWithTransport'/>
|
||||
<menuitem action='DoNotRunPluginsWhileRecording'/>
|
||||
<menuitem action='LatchedRecordEnable'/>
|
||||
<menuitem action='RegionEquivalentsOverlap'/>
|
||||
<separator/>
|
||||
<menuitem action='VerifyRemoveLastCapture'/>
|
||||
<menuitem action='StopRecordingOnXrun'/>
|
||||
|
|
|
|||
|
|
@ -323,6 +323,17 @@ style "ardour_adjusters" = "default_buttons_menus"
|
|||
bg[ACTIVE] = { 0.06, 0.06, 0.06 }
|
||||
}
|
||||
|
||||
style "editor_hscrollbar" = "ardour_adjusters"
|
||||
{
|
||||
#
|
||||
# special case: we want this scrollbar to be as tall as the
|
||||
# zoom focus selector combobox. scrollbars don't expand to
|
||||
# fill the space available to them, so we have to explicitly
|
||||
# make it bigger.
|
||||
#
|
||||
GtkRange::slider_width = 27
|
||||
}
|
||||
|
||||
style "ardour_progressbars" = "default_buttons_menus"
|
||||
{
|
||||
bg[NORMAL] = { 0, 0, 0 }
|
||||
|
|
@ -1372,6 +1383,7 @@ 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"
|
||||
|
|
|
|||
|
|
@ -659,6 +659,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
|
|||
void toggle_GainReduceFastTransport();
|
||||
void toggle_LatchedSolo();
|
||||
void toggle_LatchedRecordEnable ();
|
||||
void toggle_RegionEquivalentsOverlap ();
|
||||
|
||||
void mtc_port_changed ();
|
||||
void map_solo_model ();
|
||||
|
|
|
|||
|
|
@ -237,6 +237,22 @@ ARDOUR_UI::install_actions ()
|
|||
ActionManager::register_action (transport_actions, X_("ToggleRollForgetCapture"), _("Stop + Forget Capture"), bind (mem_fun(*editor, &PublicEditor::toggle_playback), true));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::transport_sensitive_actions.push_back (act);
|
||||
|
||||
/* these two behave as follows:
|
||||
|
||||
- if transport speed != 1.0 or != -1.0, change speed to 1.0 or -1.0 (respectively)
|
||||
- otherwise do nothing
|
||||
*/
|
||||
|
||||
ActionManager::register_action (transport_actions, X_("TransitionToRoll"), _("Transition To Roll"), bind (mem_fun (*editor, &PublicEditor::transition_to_rolling), true));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
ActionManager::register_action (transport_actions, X_("TransitionToReverse"), _("Transition To Reverse"), bind (mem_fun (*editor, &PublicEditor::transition_to_rolling), false));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
|
||||
act = ActionManager::register_action (transport_actions, X_("Loop"), _("Play Loop Range"), mem_fun(*this, &ARDOUR_UI::toggle_session_auto_loop));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
ActionManager::transport_sensitive_actions.push_back (act);
|
||||
|
|
@ -387,6 +403,7 @@ ARDOUR_UI::install_actions ()
|
|||
ActionManager::register_toggle_action (option_actions, X_("StopTransportAtEndOfSession"), _("Stop transport at session end"), mem_fun (*this, &ARDOUR_UI::toggle_StopTransportAtEndOfSession));
|
||||
ActionManager::register_toggle_action (option_actions, X_("GainReduceFastTransport"), _("-12dB gain reduce ffwd/rewind"), mem_fun (*this, &ARDOUR_UI::toggle_GainReduceFastTransport));
|
||||
ActionManager::register_toggle_action (option_actions, X_("LatchedRecordEnable"), _("Rec-enable stays engaged at stop"), mem_fun (*this, &ARDOUR_UI::toggle_LatchedRecordEnable));
|
||||
ActionManager::register_toggle_action (option_actions, X_("RegionEquivalentsOverlap"), _("Region equivalents overlap"), mem_fun (*this, &ARDOUR_UI::toggle_RegionEquivalentsOverlap));
|
||||
|
||||
act = ActionManager::register_toggle_action (option_actions, X_("DoNotRunPluginsWhileRecording"), _("Do not run plugins while recording"), mem_fun (*this, &ARDOUR_UI::toggle_DoNotRunPluginsWhileRecording));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <pbd/convert.h>
|
||||
#include <pbd/stacktrace.h>
|
||||
|
||||
#include <gtkmm2ext/utils.h>
|
||||
|
||||
|
|
@ -101,6 +102,9 @@ ARDOUR_UI::set_native_file_header_format (HeaderFormat hf)
|
|||
case AIFF:
|
||||
action = X_("FileHeaderFormatAIFF");
|
||||
break;
|
||||
default:
|
||||
fatal << string_compose (_("programming error: %1"), "illegal file header format in ::set_native_file_header_format") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
Glib::RefPtr<Action> act = ActionManager::get_action ("options", action);
|
||||
|
|
@ -125,6 +129,9 @@ ARDOUR_UI::set_native_file_data_format (SampleFormat sf)
|
|||
case FormatInt24:
|
||||
action = X_("FileDataFormat24bit");
|
||||
break;
|
||||
default:
|
||||
fatal << string_compose (_("programming error: %1"), "illegal file data format in ::set_native_file_data_format") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
Glib::RefPtr<Action> act = ActionManager::get_action ("options", action);
|
||||
|
|
@ -340,6 +347,12 @@ ARDOUR_UI::toggle_LatchedRecordEnable()
|
|||
ActionManager::toggle_config_state ("options", "LatchedRecordEnable", &Configuration::set_latched_record_enable, &Configuration::get_latched_record_enable);
|
||||
}
|
||||
|
||||
void
|
||||
ARDOUR_UI::toggle_RegionEquivalentsOverlap()
|
||||
{
|
||||
ActionManager::toggle_config_state ("options", "RegionEquivalentsOverlap", &Configuration::set_use_overlap_equivalency, &Configuration::get_use_overlap_equivalency);
|
||||
}
|
||||
|
||||
void
|
||||
ARDOUR_UI::toggle_DoNotRunPluginsWhileRecording()
|
||||
{
|
||||
|
|
@ -737,6 +750,8 @@ ARDOUR_UI::set_meter_falloff (MeterFalloff val)
|
|||
void
|
||||
ARDOUR_UI::parameter_changed (const char* parameter_name)
|
||||
{
|
||||
ENSURE_GUI_THREAD (bind (mem_fun (*this, &ARDOUR_UI::parameter_changed), parameter_name));
|
||||
|
||||
#define PARAM_IS(x) (!strcmp (parameter_name, (x)))
|
||||
|
||||
if (PARAM_IS ("slave-source")) {
|
||||
|
|
@ -846,7 +861,10 @@ ARDOUR_UI::parameter_changed (const char* parameter_name)
|
|||
primary_clock.set (0, true);
|
||||
secondary_clock.set (0, true);
|
||||
}
|
||||
} else if (PARAM_IS ("use-overlap-equivalency")) {
|
||||
ActionManager::map_some_state ("options", "RegionEquivalentsOverlap", &Configuration::get_use_overlap_equivalency);
|
||||
}
|
||||
|
||||
|
||||
#undef PARAM_IS
|
||||
}
|
||||
|
|
|
|||
|
|
@ -768,6 +768,17 @@ AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
|
|||
// Check SMPTE fields for sanity (may also adjust fields)
|
||||
smpte_sanitize_display();
|
||||
break;
|
||||
case Bars:
|
||||
case Beats:
|
||||
case Ticks:
|
||||
// Bars or beats should never be 0
|
||||
if (atoi(bars_label.get_text()) == 0) {
|
||||
bars_label.set_text("001");
|
||||
}
|
||||
if (atoi(beats_label.get_text()) == 0) {
|
||||
beats_label.set_text("01");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,55 +247,6 @@ AudioRegionView::fade_out_changed ()
|
|||
{
|
||||
reset_fade_out_shape ();
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegionView::set_fade_in_shape (AudioRegion::FadeShape shape)
|
||||
{
|
||||
AutomationList& alist = audio_region()->fade_in();
|
||||
XMLNode& before (alist.get_state());
|
||||
trackview.session().begin_reversible_command ("fade in shape");
|
||||
audio_region()->set_fade_in_shape (shape);
|
||||
XMLNode& after (alist.get_state());
|
||||
trackview.session().add_command (new MementoCommand<AutomationList>(alist, &before, &after));
|
||||
trackview.session().commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegionView::set_fade_out_shape (AudioRegion::FadeShape shape)
|
||||
{
|
||||
AutomationList& alist = audio_region()->fade_out();
|
||||
XMLNode& before (alist.get_state());
|
||||
trackview.session().begin_reversible_command ("fade out shape");
|
||||
audio_region()->set_fade_out_shape (shape);
|
||||
XMLNode& after (alist.get_state());
|
||||
trackview.session().add_command (new MementoCommand<AutomationList>(alist, &before, &after));
|
||||
trackview.session().commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegionView::set_fade_in_active (bool yn)
|
||||
{
|
||||
AutomationList& alist = audio_region()->fade_in();
|
||||
XMLNode& before (alist.get_state());
|
||||
trackview.session().begin_reversible_command ("fade in shape");
|
||||
audio_region()->set_fade_in_active (yn);
|
||||
XMLNode& after (alist.get_state());
|
||||
trackview.session().add_command (new MementoCommand<AutomationList>(alist, &before, &after));
|
||||
trackview.session().commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegionView::set_fade_out_active (bool yn)
|
||||
{
|
||||
AutomationList& alist = audio_region()->fade_out();
|
||||
XMLNode& before (alist.get_state());
|
||||
trackview.session().begin_reversible_command ("fade out shape");
|
||||
audio_region()->set_fade_out_active (yn);
|
||||
XMLNode& after (alist.get_state());
|
||||
trackview.session().add_command (new MementoCommand<AutomationList>(alist, &before, &after));
|
||||
trackview.session().commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
AudioRegionView::fade_in_active_changed ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -93,10 +93,6 @@ class AudioRegionView : public RegionView
|
|||
|
||||
void reset_fade_in_shape_width (nframes_t);
|
||||
void reset_fade_out_shape_width (nframes_t);
|
||||
void set_fade_in_active (bool);
|
||||
void set_fade_out_active (bool);
|
||||
void set_fade_in_shape (ARDOUR::AudioRegion::FadeShape);
|
||||
void set_fade_out_shape (ARDOUR::AudioRegion::FadeShape);
|
||||
|
||||
virtual void entered ();
|
||||
virtual void exited ();
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@
|
|||
#include "utils.h"
|
||||
#include "color.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
using namespace Editing;
|
||||
|
|
@ -129,7 +131,7 @@ AudioStreamView::set_amplitude_above_axis (gdouble app)
|
|||
void
|
||||
AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wait_for_waves)
|
||||
{
|
||||
AudioRegionView *region_view;
|
||||
AudioRegionView *region_view = 0;
|
||||
|
||||
ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r));
|
||||
|
||||
|
|
@ -166,6 +168,10 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wai
|
|||
region_view = new TapeAudioRegionView (canvas_group, _trackview, region,
|
||||
_samples_per_unit, region_color);
|
||||
break;
|
||||
default:
|
||||
fatal << string_compose (_("programming error: %1"), "illegal track mode in ::add_region_view_internal") << endmsg;
|
||||
/*NOTREACHED*/
|
||||
|
||||
}
|
||||
|
||||
region_view->init (region_color, wait_for_waves);
|
||||
|
|
|
|||
|
|
@ -642,9 +642,8 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
|
|||
|
||||
if (view_index && pi != npoints && /* not the first, not the last */
|
||||
(((this_rx == prev_rx) && (this_ry == prev_ry)) || /* same point */
|
||||
(this_rx == prev_rx) || /* identical x coordinate */
|
||||
(((this_rx - prev_rx) < (box_size + 2)) && /* not identical, but still too close horizontally */
|
||||
((abs ((int)(this_ry - prev_ry)) < (int) (box_size + 2)))))) { /* too close vertically */
|
||||
(abs ((int)(this_ry - prev_ry)) < (int) (box_size + 2))))) { /* too close vertically */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,14 @@ struct AutomationSelectable : public Selectable
|
|||
|
||||
AutomationSelectable (nframes_t s, nframes_t e, double l, double h, TimeAxisView& atv)
|
||||
: start (s), end (e), low_fract (l), high_fract (h), track (atv) {}
|
||||
|
||||
bool operator== (const AutomationSelectable& other) {
|
||||
return start == other.start &&
|
||||
end == other.end &&
|
||||
low_fract == other.low_fract &&
|
||||
high_fract == other.high_fract &&
|
||||
&track == &other.track;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __ardour_gtk_automation_selectable_h__ */
|
||||
|
|
|
|||
|
|
@ -573,7 +573,7 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
|
|||
case Cut:
|
||||
if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
|
||||
editor.get_cut_buffer().add (what_we_got);
|
||||
_session.add_command (new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
|
||||
_session.add_command (new MementoCommand<AutomationList>(alist, new XMLNode (before), &alist.get_state()));
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -585,7 +585,7 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
|
|||
|
||||
case Clear:
|
||||
if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
|
||||
_session.add_command (new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
|
||||
_session.add_command (new MementoCommand<AutomationList>(alist, new XMLNode (before), &alist.get_state()));
|
||||
delete what_we_got;
|
||||
what_we_got = 0;
|
||||
ret = true;
|
||||
|
|
@ -594,6 +594,8 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
|
|||
}
|
||||
}
|
||||
|
||||
delete &before;
|
||||
|
||||
if (what_we_got) {
|
||||
for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) {
|
||||
double foo = (*x)->value;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <pbd/convert.h>
|
||||
#include <pbd/error.h>
|
||||
#include <pbd/stacktrace.h>
|
||||
#include <pbd/memento_command.h>
|
||||
|
||||
#include <gtkmm/image.h>
|
||||
|
|
@ -359,6 +360,8 @@ Editor::Editor (AudioEngine& eng)
|
|||
edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscrollbar_button_release));
|
||||
edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscrollbar_allocate));
|
||||
|
||||
edit_hscrollbar.set_name ("EditorHScrollbar");
|
||||
|
||||
build_cursors ();
|
||||
setup_toolbar ();
|
||||
|
||||
|
|
@ -1230,35 +1233,35 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
|
|||
case FadeInItem:
|
||||
case FadeInHandleItem:
|
||||
if (arv->audio_region()->fade_in_active()) {
|
||||
items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
|
||||
items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*this, &Editor::set_fade_in_active), false)));
|
||||
} else {
|
||||
items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
|
||||
items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_in_active), true)));
|
||||
}
|
||||
|
||||
items.push_back (SeparatorElem());
|
||||
|
||||
items.push_back (MenuElem (_("Linear"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_shape), AudioRegion::Linear)));
|
||||
items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_shape), AudioRegion::LogB)));
|
||||
items.push_back (MenuElem (_("Slow"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_shape), AudioRegion::Fast)));
|
||||
items.push_back (MenuElem (_("Fast"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_shape), AudioRegion::LogA)));
|
||||
items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_shape), AudioRegion::Slow)));
|
||||
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 (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogA)));
|
||||
items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Slow)));
|
||||
break;
|
||||
|
||||
case FadeOutItem:
|
||||
case FadeOutHandleItem:
|
||||
if (arv->audio_region()->fade_out_active()) {
|
||||
items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
|
||||
items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*this, &Editor::set_fade_out_active), false)));
|
||||
} else {
|
||||
items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
|
||||
items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_out_active), true)));
|
||||
}
|
||||
|
||||
items.push_back (SeparatorElem());
|
||||
|
||||
items.push_back (MenuElem (_("Linear"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_shape), AudioRegion::Linear)));
|
||||
items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_shape), AudioRegion::Fast)));
|
||||
items.push_back (MenuElem (_("Slow"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_shape), AudioRegion::LogB)));
|
||||
items.push_back (MenuElem (_("Fast"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_shape), AudioRegion::LogA)));
|
||||
items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_shape), AudioRegion::Slow)));
|
||||
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)));
|
||||
|
||||
break;
|
||||
|
||||
|
|
@ -1606,7 +1609,7 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region>
|
|||
become selected.
|
||||
*/
|
||||
|
||||
// region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
|
||||
region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
|
||||
|
||||
items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
|
||||
items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
|
||||
|
|
@ -2777,543 +2780,6 @@ Editor::commit_reversible_command ()
|
|||
}
|
||||
}
|
||||
|
||||
struct TrackViewByPositionSorter
|
||||
{
|
||||
bool operator() (const TimeAxisView* a, const TimeAxisView *b) {
|
||||
return a->y_position < b->y_position;
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
Editor::extend_selection_to_track (TimeAxisView& view)
|
||||
{
|
||||
if (selection->selected (&view)) {
|
||||
/* already selected, do nothing */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selection->tracks.empty()) {
|
||||
|
||||
if (!selection->selected (&view)) {
|
||||
selection->set (&view);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* something is already selected, so figure out which range of things to add */
|
||||
|
||||
TrackViewList to_be_added;
|
||||
TrackViewList sorted = track_views;
|
||||
TrackViewByPositionSorter cmp;
|
||||
bool passed_clicked = false;
|
||||
bool forwards;
|
||||
|
||||
sorted.sort (cmp);
|
||||
|
||||
if (!selection->selected (&view)) {
|
||||
to_be_added.push_back (&view);
|
||||
}
|
||||
|
||||
/* figure out if we should go forward or backwards */
|
||||
|
||||
for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
|
||||
|
||||
if ((*i) == &view) {
|
||||
passed_clicked = true;
|
||||
}
|
||||
|
||||
if (selection->selected (*i)) {
|
||||
if (passed_clicked) {
|
||||
forwards = true;
|
||||
} else {
|
||||
forwards = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
passed_clicked = false;
|
||||
|
||||
if (forwards) {
|
||||
|
||||
for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
|
||||
|
||||
if ((*i) == &view) {
|
||||
passed_clicked = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (passed_clicked) {
|
||||
if ((*i)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
if (selection->selected (*i)) {
|
||||
break;
|
||||
} else if (!(*i)->hidden()) {
|
||||
to_be_added.push_back (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (TrackViewList::reverse_iterator r = sorted.rbegin(); r != sorted.rend(); ++r) {
|
||||
|
||||
if ((*r) == &view) {
|
||||
passed_clicked = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (passed_clicked) {
|
||||
|
||||
if ((*r)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (selection->selected (*r)) {
|
||||
break;
|
||||
} else if (!(*r)->hidden()) {
|
||||
to_be_added.push_back (*r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!to_be_added.empty()) {
|
||||
selection->add (to_be_added);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
|
||||
{
|
||||
bool commit = false;
|
||||
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
if (selection->selected (&view)) {
|
||||
if (!no_remove) {
|
||||
selection->remove (&view);
|
||||
commit = true;
|
||||
}
|
||||
} else {
|
||||
selection->add (&view);
|
||||
commit = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case Selection::Add:
|
||||
if (!selection->selected (&view)) {
|
||||
selection->add (&view);
|
||||
commit = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case Selection::Set:
|
||||
if (selection->selected (&view) && selection->tracks.size() == 1) {
|
||||
/* no commit necessary */
|
||||
} else {
|
||||
selection->set (&view);
|
||||
commit = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case Selection::Extend:
|
||||
commit = extend_selection_to_track (view);
|
||||
break;
|
||||
}
|
||||
|
||||
return commit;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::set_selected_track_from_click (Selection::Operation op, bool no_remove)
|
||||
{
|
||||
if (!clicked_routeview) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return set_selected_track (*clicked_routeview, op, no_remove);
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::set_selected_control_point_from_click (Selection::Operation op, bool no_remove)
|
||||
{
|
||||
if (!clicked_control_point) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* select this point and any others that it represents */
|
||||
|
||||
double y1, y2;
|
||||
nframes_t x1, x2;
|
||||
|
||||
x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
|
||||
x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
|
||||
y1 = clicked_control_point->get_x() - 10;
|
||||
y2 = clicked_control_point->get_y() + 10;
|
||||
|
||||
return select_all_within (x1, x2, y1, y2, op);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::get_relevant_tracks (set<RouteTimeAxisView*>& relevant_tracks)
|
||||
{
|
||||
/* step one: get all selected tracks and all tracks in the relevant edit groups */
|
||||
|
||||
for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
|
||||
|
||||
RouteTimeAxisView* atv = dynamic_cast<RouteTimeAxisView*>(*ti);
|
||||
|
||||
if (!atv) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RouteGroup* group = atv->route()->edit_group();
|
||||
|
||||
if (group && group->is_active()) {
|
||||
|
||||
/* active group for this track, loop over all tracks and get every member of the group */
|
||||
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
|
||||
RouteTimeAxisView* tatv;
|
||||
|
||||
if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
|
||||
|
||||
if (tatv->route()->edit_group() == group) {
|
||||
relevant_tracks.insert (tatv);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
relevant_tracks.insert (atv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::mapover_tracks (slot<void,RouteTimeAxisView&,uint32_t> sl)
|
||||
{
|
||||
set<RouteTimeAxisView*> relevant_tracks;
|
||||
|
||||
get_relevant_tracks (relevant_tracks);
|
||||
|
||||
uint32_t sz = relevant_tracks.size();
|
||||
|
||||
for (set<RouteTimeAxisView*>::iterator ati = relevant_tracks.begin(); ati != relevant_tracks.end(); ++ati) {
|
||||
sl (**ati, sz);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32_t ignored,
|
||||
RegionView* basis, vector<RegionView*>* all_equivs)
|
||||
{
|
||||
boost::shared_ptr<Playlist> pl;
|
||||
vector<boost::shared_ptr<Region> > results;
|
||||
RegionView* marv;
|
||||
boost::shared_ptr<Diskstream> ds;
|
||||
|
||||
if ((ds = tv.get_diskstream()) == 0) {
|
||||
/* bus */
|
||||
return;
|
||||
}
|
||||
|
||||
if (&tv == &basis->get_time_axis_view()) {
|
||||
/* looking in same track as the original */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ((pl = ds->playlist()) != 0) {
|
||||
pl->get_equivalent_regions (basis->region(), results);
|
||||
}
|
||||
|
||||
for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
|
||||
if ((marv = tv.view()->find_view (*ir)) != 0) {
|
||||
all_equivs->push_back (marv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove)
|
||||
{
|
||||
vector<RegionView*> all_equivalent_regions;
|
||||
bool commit = false;
|
||||
|
||||
if (!clicked_regionview || !clicked_routeview) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (op == Selection::Toggle || op == Selection::Set) {
|
||||
|
||||
mapover_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click),
|
||||
clicked_regionview, &all_equivalent_regions));
|
||||
|
||||
|
||||
/* add clicked regionview since we skipped all other regions in the same track as the one it was in */
|
||||
|
||||
all_equivalent_regions.push_back (clicked_regionview);
|
||||
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
|
||||
if (clicked_regionview->get_selected()) {
|
||||
if (press) {
|
||||
|
||||
/* whatever was clicked was selected already; do nothing here but allow
|
||||
the button release to deselect it
|
||||
*/
|
||||
|
||||
button_release_can_deselect = true;
|
||||
|
||||
} else {
|
||||
|
||||
if (button_release_can_deselect) {
|
||||
|
||||
/* just remove this one region, but only on a permitted button release */
|
||||
|
||||
selection->remove (clicked_regionview);
|
||||
commit = true;
|
||||
|
||||
/* no more deselect action on button release till a new press
|
||||
finds an already selected object.
|
||||
*/
|
||||
|
||||
button_release_can_deselect = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (press) {
|
||||
/* add all the equivalent regions, but only on button press */
|
||||
|
||||
if (!all_equivalent_regions.empty()) {
|
||||
commit = true;
|
||||
}
|
||||
|
||||
for (vector<RegionView*>::iterator i = all_equivalent_regions.begin(); i != all_equivalent_regions.end(); ++i) {
|
||||
selection->add (*i);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Selection::Set:
|
||||
if (!clicked_regionview->get_selected()) {
|
||||
selection->set (all_equivalent_regions);
|
||||
commit = true;
|
||||
} else {
|
||||
/* no commit necessary: clicked on an already selected region */
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* silly compiler */
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (op == Selection::Extend) {
|
||||
|
||||
list<Selectable*> results;
|
||||
nframes_t last_frame;
|
||||
nframes_t first_frame;
|
||||
|
||||
/* 1. find the last selected regionview in the track that was clicked in */
|
||||
|
||||
last_frame = 0;
|
||||
first_frame = max_frames;
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
|
||||
if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
|
||||
|
||||
if ((*x)->region()->last_frame() > last_frame) {
|
||||
last_frame = (*x)->region()->last_frame();
|
||||
}
|
||||
|
||||
if ((*x)->region()->first_frame() < first_frame) {
|
||||
first_frame = (*x)->region()->first_frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 2. figure out the boundaries for our search for new objects */
|
||||
|
||||
switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
|
||||
case OverlapNone:
|
||||
if (last_frame < clicked_regionview->region()->first_frame()) {
|
||||
first_frame = last_frame;
|
||||
last_frame = clicked_regionview->region()->last_frame();
|
||||
} else {
|
||||
last_frame = first_frame;
|
||||
first_frame = clicked_regionview->region()->first_frame();
|
||||
}
|
||||
break;
|
||||
|
||||
case OverlapExternal:
|
||||
if (last_frame < clicked_regionview->region()->first_frame()) {
|
||||
first_frame = last_frame;
|
||||
last_frame = clicked_regionview->region()->last_frame();
|
||||
} else {
|
||||
last_frame = first_frame;
|
||||
first_frame = clicked_regionview->region()->first_frame();
|
||||
}
|
||||
break;
|
||||
|
||||
case OverlapInternal:
|
||||
if (last_frame < clicked_regionview->region()->first_frame()) {
|
||||
first_frame = last_frame;
|
||||
last_frame = clicked_regionview->region()->last_frame();
|
||||
} else {
|
||||
last_frame = first_frame;
|
||||
first_frame = clicked_regionview->region()->first_frame();
|
||||
}
|
||||
break;
|
||||
|
||||
case OverlapStart:
|
||||
case OverlapEnd:
|
||||
/* nothing to do except add clicked region to selection, since it
|
||||
overlaps with the existing selection in this track.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
/* 2. find all selectable objects (regionviews in this case) between that one and the end of the
|
||||
one that was clicked.
|
||||
*/
|
||||
|
||||
set<RouteTimeAxisView*> relevant_tracks;
|
||||
|
||||
get_relevant_tracks (relevant_tracks);
|
||||
|
||||
for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
|
||||
(*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
|
||||
}
|
||||
|
||||
/* 3. convert to a vector of audio regions */
|
||||
|
||||
vector<RegionView*> regions;
|
||||
|
||||
for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
|
||||
RegionView* arv;
|
||||
|
||||
if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
|
||||
regions.push_back (arv);
|
||||
}
|
||||
}
|
||||
|
||||
if (!regions.empty()) {
|
||||
selection->add (regions);
|
||||
commit = true;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return commit;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
|
||||
{
|
||||
vector<RegionView*> all_equivalent_regions;
|
||||
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
|
||||
RouteTimeAxisView* tatv;
|
||||
|
||||
if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
|
||||
|
||||
boost::shared_ptr<Playlist> pl;
|
||||
vector<boost::shared_ptr<Region> > results;
|
||||
RegionView* marv;
|
||||
boost::shared_ptr<Diskstream> ds;
|
||||
|
||||
if ((ds = tatv->get_diskstream()) == 0) {
|
||||
/* bus */
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((pl = (ds->playlist())) != 0) {
|
||||
pl->get_region_list_equivalent_regions (region, results);
|
||||
}
|
||||
|
||||
for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
|
||||
if ((marv = tatv->view()->find_view (*ir)) != 0) {
|
||||
all_equivalent_regions.push_back (marv);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
begin_reversible_command (_("set selected regions"));
|
||||
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
/* XXX this is not correct */
|
||||
selection->toggle (all_equivalent_regions);
|
||||
break;
|
||||
case Selection::Set:
|
||||
selection->set (all_equivalent_regions);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
selection->add (all_equivalent_regions);
|
||||
break;
|
||||
case Selection::Add:
|
||||
selection->add (all_equivalent_regions);
|
||||
break;
|
||||
}
|
||||
|
||||
commit_reversible_command () ;
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, boost::weak_ptr<Region> weak_r)
|
||||
{
|
||||
RegionView* rv;
|
||||
boost::shared_ptr<Region> r (weak_r.lock());
|
||||
|
||||
if (!r) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioRegion> ar;
|
||||
|
||||
if ((ar = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((rv = sv->find_view (ar)) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* don't reset the selection if its something other than
|
||||
a single other region.
|
||||
*/
|
||||
|
||||
if (selection->regions.size() > 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
begin_reversible_command (_("set selected regions"));
|
||||
|
||||
selection->set (rv);
|
||||
|
||||
commit_reversible_command () ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_edit_group_solo (Route& route, bool yn)
|
||||
{
|
||||
|
|
@ -3571,82 +3037,16 @@ Editor::edit_controls_button_release (GdkEventButton* ev)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::track_selection_changed ()
|
||||
{
|
||||
switch (selection->tracks.size()){
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
set_selected_mixer_strip (*(selection->tracks.front()));
|
||||
break;
|
||||
}
|
||||
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
(*i)->set_selected (false);
|
||||
if (mouse_mode == MouseRange) {
|
||||
(*i)->hide_selection ();
|
||||
}
|
||||
}
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
(*i)->set_selected (true);
|
||||
if (mouse_mode == MouseRange) {
|
||||
(*i)->show_selection (selection->time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::time_selection_changed ()
|
||||
{
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
(*i)->hide_selection ();
|
||||
}
|
||||
|
||||
if (selection->tracks.empty()) {
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
(*i)->show_selection (selection->time);
|
||||
}
|
||||
} else {
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
(*i)->show_selection (selection->time);
|
||||
}
|
||||
}
|
||||
|
||||
if (selection->time.empty()) {
|
||||
ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
|
||||
} else {
|
||||
ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::region_selection_changed ()
|
||||
{
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
(*i)->set_selected_regionviews (selection->regions);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::point_selection_changed ()
|
||||
{
|
||||
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
|
||||
(*i)->set_selected_points (selection->points);
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
Editor::mouse_select_button_release (GdkEventButton* ev)
|
||||
{
|
||||
/* this handles just right-clicks */
|
||||
|
||||
if (ev->button != 3) {
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
Editor::TrackViewList *
|
||||
|
|
@ -4293,3 +3693,17 @@ Editor::idle_visual_changer ()
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct EditorOrderTimeAxisSorter {
|
||||
bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
|
||||
return a->order < b->order;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
Editor::sort_track_selection ()
|
||||
{
|
||||
EditorOrderTimeAxisSorter cmp;
|
||||
selection->tracks.sort (cmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
#include <ardour/session.h>
|
||||
#include <ardour/tempo.h>
|
||||
#include <ardour/location.h>
|
||||
#include <ardour/region.h>
|
||||
#include <ardour/audioregion.h>
|
||||
|
||||
#include "audio_clock.h"
|
||||
#include "gtk-custom-ruler.h"
|
||||
|
|
@ -171,6 +171,7 @@ class Editor : public PublicEditor
|
|||
void separate_region_from_selection ();
|
||||
void separate_regions_using_location (ARDOUR::Location&);
|
||||
void toggle_playback (bool with_abort);
|
||||
void transition_to_rolling (bool forward);
|
||||
|
||||
/* undo related */
|
||||
|
||||
|
|
@ -419,12 +420,15 @@ class Editor : public PublicEditor
|
|||
CrossfadeView* clicked_crossfadeview;
|
||||
ControlPoint* clicked_control_point;
|
||||
|
||||
void sort_track_selection ();
|
||||
|
||||
void get_relevant_tracks (std::set<RouteTimeAxisView*>& relevant_tracks);
|
||||
void get_equivalent_regions (RegionView* rv, std::vector<RegionView*>&);
|
||||
void mapover_tracks (sigc::slot<void,RouteTimeAxisView&,uint32_t> sl);
|
||||
|
||||
/* functions to be passed to mapover_tracks(), possibly with sigc::bind()-supplied arguments */
|
||||
|
||||
void mapped_set_selected_regionview_from_click (RouteTimeAxisView&, uint32_t, RegionView*, vector<RegionView*>*);
|
||||
void mapped_get_equivalent_regions (RouteTimeAxisView&, uint32_t, RegionView*, vector<RegionView*>*);
|
||||
void mapped_use_new_playlist (RouteTimeAxisView&, uint32_t);
|
||||
void mapped_use_copy_playlist (RouteTimeAxisView&, uint32_t);
|
||||
void mapped_clear_playlist (RouteTimeAxisView&, uint32_t);
|
||||
|
|
@ -439,7 +443,7 @@ class Editor : public PublicEditor
|
|||
bool set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove=false);
|
||||
|
||||
bool set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool no_remove=false);
|
||||
bool set_selected_track_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);
|
||||
bool set_selected_regionview_from_click (bool press, Selection::Operation op = Selection::Set, bool no_track_remove=false);
|
||||
|
||||
void set_selected_regionview_from_region_list (boost::shared_ptr<ARDOUR::Region> region, Selection::Operation op = Selection::Set);
|
||||
|
|
@ -904,6 +908,8 @@ class Editor : public PublicEditor
|
|||
void align_relative (ARDOUR::RegionPoint);
|
||||
void naturalize ();
|
||||
|
||||
void reset_focus ();
|
||||
|
||||
void cut ();
|
||||
void copy ();
|
||||
void paste (float times);
|
||||
|
|
@ -992,6 +998,7 @@ class Editor : public PublicEditor
|
|||
void edit_cursor_forward ();
|
||||
void playhead_backward ();
|
||||
void playhead_forward ();
|
||||
void scroll_playhead (bool forward);
|
||||
void scroll_backward (float pages=0.8f);
|
||||
void scroll_forward (float pages=0.8f);
|
||||
void scroll_tracks_down ();
|
||||
|
|
@ -1066,6 +1073,12 @@ class Editor : public PublicEditor
|
|||
void fade_in_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*);
|
||||
void fade_out_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*);
|
||||
|
||||
void set_fade_in_shape (ARDOUR::AudioRegion::FadeShape);
|
||||
void set_fade_out_shape (ARDOUR::AudioRegion::FadeShape);
|
||||
|
||||
void set_fade_in_active (bool);
|
||||
void set_fade_out_active (bool);
|
||||
|
||||
std::set<boost::shared_ptr<ARDOUR::Playlist> > motion_frozen_playlists;
|
||||
void region_drag_motion_callback (ArdourCanvas::Item*, GdkEvent*);
|
||||
void region_drag_finished_callback (ArdourCanvas::Item*, GdkEvent*);
|
||||
|
|
|
|||
|
|
@ -164,10 +164,12 @@ Editor::register_actions ()
|
|||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
act = ActionManager::register_action (editor_actions, "center-edit-cursor", _("Center Edit Cursor"), mem_fun(*this, &Editor::center_edit_cursor));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
act = ActionManager::register_action (editor_actions, "playhead-forward", _("Playhead Forward"), mem_fun(*this, &Editor::playhead_forward));
|
||||
|
||||
act = ActionManager::register_action (editor_actions, "scroll-playhead-forward", _("Playhead forward"), bind (mem_fun(*this, &Editor::scroll_playhead), true));;
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
act = ActionManager::register_action (editor_actions, "playhead-backward", _("Playhead Backward"), mem_fun(*this, &Editor::playhead_backward));
|
||||
act = ActionManager::register_action (editor_actions, "scroll-playhead-backward", _("Playhead Backward"), bind (mem_fun(*this, &Editor::scroll_playhead), false));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
|
||||
act = ActionManager::register_action (editor_actions, "playhead-to-edit", _("Playhead to Edit"), bind (mem_fun(*this, &Editor::cursor_align), true));
|
||||
ActionManager::session_sensitive_actions.push_back (act);
|
||||
act = ActionManager::register_action (editor_actions, "edit-to-playhead", _("Edit to Playhead"), bind (mem_fun(*this, &Editor::cursor_align), false));
|
||||
|
|
@ -1084,3 +1086,9 @@ Editor::parameter_changed (const char* parameter_name)
|
|||
|
||||
#undef PARAM_IS
|
||||
}
|
||||
|
||||
void
|
||||
Editor::reset_focus ()
|
||||
{
|
||||
track_canvas.grab_focus();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,6 +131,8 @@ Editor::do_embed (vector<ustring> paths, bool split, ImportMode mode, AudioTrack
|
|||
|
||||
for (a = paths.begin(); a != paths.end(); ) {
|
||||
|
||||
cerr << "Considering embed of " << (*a) << endl;
|
||||
|
||||
Glib::ustring path = *a;
|
||||
Glib::ustring pair_base;
|
||||
vector<ustring> to_embed;
|
||||
|
|
@ -264,12 +266,12 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
|
|||
boost::shared_ptr<AudioFileSource> source;
|
||||
SourceList sources;
|
||||
boost::shared_ptr<AudioRegion> region;
|
||||
string idspec;
|
||||
string linked_path;
|
||||
SoundFileInfo finfo;
|
||||
ustring region_name;
|
||||
uint32_t input_chan = 0;
|
||||
uint32_t output_chan = 0;
|
||||
int ret = 0;
|
||||
|
||||
track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
|
||||
ARDOUR_UI::instance()->flush_pending ();
|
||||
|
|
@ -301,7 +303,7 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
|
|||
|
||||
if (!AudioFileSource::get_soundfile_info (path, finfo, error_msg)) {
|
||||
error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), selection, error_msg ) << endmsg;
|
||||
return 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (check_sample_rate && (finfo.samplerate != (int) session->frame_rate())) {
|
||||
|
|
@ -311,27 +313,47 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
|
|||
choices.push_back (_("Cancel entire import"));
|
||||
choices.push_back (_("Don't embed it"));
|
||||
choices.push_back (_("Embed all without questions"));
|
||||
} else {
|
||||
choices.push_back (_("Cancel"));
|
||||
}
|
||||
|
||||
choices.push_back (_("Embed it anyway"));
|
||||
|
||||
Gtkmm2ext::Choice rate_choice (
|
||||
string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
|
||||
choices, false);
|
||||
|
||||
switch (rate_choice.run()) {
|
||||
int resx = rate_choice.run ();
|
||||
|
||||
switch (resx) {
|
||||
case 0: /* stop a multi-file import */
|
||||
case 1: /* don't import this one */
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto out;
|
||||
case 2: /* do it, and the rest without asking */
|
||||
check_sample_rate = false;
|
||||
break;
|
||||
case 3: /* do it */
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
ret = -2;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
choices.push_back (_("Cancel"));
|
||||
choices.push_back (_("Embed it anyway"));
|
||||
|
||||
Gtkmm2ext::Choice rate_choice (
|
||||
string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
|
||||
choices, false);
|
||||
|
||||
int resx = rate_choice.run ();
|
||||
|
||||
switch (resx) {
|
||||
case 0: /* don't import */
|
||||
ret = -1;
|
||||
goto out;
|
||||
case 1: /* do it */
|
||||
break;
|
||||
default:
|
||||
ret = -2;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -344,15 +366,13 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
|
|||
|
||||
for (int n = 0; n < finfo.channels; ++n)
|
||||
{
|
||||
idspec = path;
|
||||
idspec += string_compose(":%1", n);
|
||||
|
||||
try {
|
||||
source = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable
|
||||
(DataType::AUDIO, *session, idspec,
|
||||
(DataType::AUDIO, *session, path, n,
|
||||
(mode == ImportAsTapeTrack ?
|
||||
AudioFileSource::Destructive :
|
||||
AudioFileSource::Flag (0))));
|
||||
|
||||
sources.push_back(source);
|
||||
}
|
||||
|
||||
|
|
@ -388,7 +408,7 @@ Editor::embed_sndfile (vector<Glib::ustring> paths, bool split, bool multiple_fi
|
|||
|
||||
out:
|
||||
track_canvas.get_window()->set_cursor (*current_canvas_cursor);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
|
|||
|
||||
|
||||
try {
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *session, path, AudioFileSource::Flag (0)));
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, *session, path, false, session->frame_rate()));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
|
@ -258,6 +258,7 @@ Editor::write_region (string path, boost::shared_ptr<AudioRegion> region)
|
|||
|
||||
for (vector<boost::shared_ptr<AudioFileSource> >::iterator src = sources.begin(); src != sources.end(); ++src) {
|
||||
(*src)->update_header (0, *now, tnow);
|
||||
(*src)->mark_immutable ();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -343,7 +344,7 @@ Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list
|
|||
path = s;
|
||||
|
||||
try {
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *session, path, AudioFileSource::Flag (0)));
|
||||
fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (DataType::AUDIO, *session, path, false, session->frame_rate()));
|
||||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
|
|
@ -416,8 +417,9 @@ Editor::write_audio_range (AudioPlaylist& playlist, const ChanCount& count, list
|
|||
time (&tnow);
|
||||
now = localtime (&tnow);
|
||||
|
||||
for (uint32_t n=0; n < channels; ++n) {
|
||||
sources[n]->update_header (0, *now, tnow);
|
||||
for (vector<boost::shared_ptr<AudioFileSource> >::iterator s = sources.begin(); s != sources.end(); ++s) {
|
||||
(*s)->update_header (0, *now, tnow);
|
||||
(*s)->mark_immutable ();
|
||||
// do we need to ref it again?
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ Editor::kbd_do_split (GdkEvent* ev)
|
|||
nframes_t where = event_frame (ev);
|
||||
|
||||
if (entered_regionview) {
|
||||
if (selection->regions.find (entered_regionview) != selection->regions.end()) {
|
||||
if (selection->regions.contains (entered_regionview)) {
|
||||
split_regions_at (where, selection->regions);
|
||||
} else {
|
||||
RegionSelection s;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ Editor::show_editor_mixer (bool yn)
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
AudioTimeAxisView* atv;
|
||||
|
||||
|
|
|
|||
|
|
@ -291,8 +291,6 @@ void
|
|||
Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
|
||||
{
|
||||
bool commit = false;
|
||||
bool c1;
|
||||
bool c2;
|
||||
|
||||
/* in object/audition/timefx mode, any button press sets
|
||||
the selection if the object can be selected. this is a
|
||||
|
|
@ -310,6 +308,16 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
|
|||
return;
|
||||
}
|
||||
|
||||
if (event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) {
|
||||
|
||||
if ((event->button.state & Keyboard::RelevantModifierKeyMask) && event->button.button != 1) {
|
||||
|
||||
/* no selection action on modified button-2 or button-3 events */
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Selection::Operation op = Keyboard::selection_type (event->button.state);
|
||||
bool press = (event->type == GDK_BUTTON_PRESS);
|
||||
|
||||
|
|
@ -317,35 +325,33 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
|
|||
|
||||
switch (item_type) {
|
||||
case RegionItem:
|
||||
/* XXX make tying track/region selection optional */
|
||||
c1 = set_selected_track_from_click (op, true);
|
||||
c2 = set_selected_regionview_from_click (press, op, true);
|
||||
commit = (c1 || c2);
|
||||
commit = set_selected_regionview_from_click (press, op, true);
|
||||
break;
|
||||
|
||||
case RegionViewNameHighlight:
|
||||
case RegionViewName:
|
||||
/* XXX make tying track/region selection optional */
|
||||
c1 = set_selected_track_from_click (op, true);
|
||||
c2 = set_selected_regionview_from_click (press, op, true);
|
||||
commit = (c1 || c2);
|
||||
commit = set_selected_regionview_from_click (press, op, true);
|
||||
break;
|
||||
|
||||
case FadeInHandleItem:
|
||||
case FadeInItem:
|
||||
case FadeOutHandleItem:
|
||||
case FadeOutItem:
|
||||
commit = set_selected_regionview_from_click (press, op, true);
|
||||
break;
|
||||
|
||||
case GainAutomationControlPointItem:
|
||||
case PanAutomationControlPointItem:
|
||||
case RedirectAutomationControlPointItem:
|
||||
/* XXX make tying track/region selection optional */
|
||||
c1 = set_selected_track_from_click (op, true);
|
||||
c2 = set_selected_control_point_from_click (op, false);
|
||||
commit = (c1 || c2);
|
||||
commit = set_selected_control_point_from_click (op, false);
|
||||
break;
|
||||
|
||||
case StreamItem:
|
||||
commit = set_selected_track_from_click (op, true);
|
||||
// commit = set_selected_track_from_click (press, op, true);
|
||||
break;
|
||||
|
||||
case AutomationTrackItem:
|
||||
commit = set_selected_track_from_click (op, true);
|
||||
commit = set_selected_track_from_click (press, op, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -364,7 +370,7 @@ Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType it
|
|||
case StreamItem:
|
||||
case RegionItem:
|
||||
case AutomationTrackItem:
|
||||
commit = set_selected_track_from_click (op, true);
|
||||
commit = set_selected_track_from_click (true, op, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -500,9 +506,8 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
|
|||
break;
|
||||
|
||||
case MouseObject:
|
||||
if (Keyboard::modifier_state_contains (event->button.state,
|
||||
Keyboard::ModifierMask(Keyboard::Control|Keyboard::Alt))
|
||||
&& event->type == GDK_BUTTON_PRESS) {
|
||||
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Control|Keyboard::Alt)) &&
|
||||
event->type == GDK_BUTTON_PRESS) {
|
||||
|
||||
start_rubberband_select (item, event);
|
||||
|
||||
|
|
@ -1765,7 +1770,7 @@ Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
|||
nframes_t pos;
|
||||
nframes_t fade_length;
|
||||
|
||||
if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
||||
if ((int32_t)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
||||
pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
||||
}
|
||||
else {
|
||||
|
|
@ -1783,8 +1788,18 @@ Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
|||
} else {
|
||||
fade_length = pos - arv->region()->position();
|
||||
}
|
||||
/* mapover the region selection */
|
||||
|
||||
arv->reset_fade_in_shape_width (fade_length);
|
||||
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
||||
|
||||
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
|
||||
|
||||
if (!tmp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp->reset_fade_in_shape_width (fade_length);
|
||||
}
|
||||
|
||||
show_verbose_duration_cursor (arv->region()->position(), arv->region()->position() + fade_length, 10);
|
||||
|
||||
|
|
@ -1794,43 +1809,46 @@ Editor::fade_in_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
|||
void
|
||||
Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
{
|
||||
if (drag_info.first_move) return;
|
||||
|
||||
AudioRegionView* arv = static_cast<AudioRegionView*>(drag_info.data);
|
||||
nframes_t pos;
|
||||
nframes_t fade_length;
|
||||
|
||||
if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
||||
pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
||||
}
|
||||
else {
|
||||
pos = 0;
|
||||
}
|
||||
if (drag_info.first_move) return;
|
||||
|
||||
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
||||
snap_to (pos);
|
||||
if ((int32_t)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) {
|
||||
pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset;
|
||||
} else {
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
if (pos < (arv->region()->position() + 64)) {
|
||||
fade_length = 64; // this should be a minimum defined somewhere
|
||||
}
|
||||
else if (pos > arv->region()->last_frame()) {
|
||||
} else if (pos > arv->region()->last_frame()) {
|
||||
fade_length = arv->region()->length();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
fade_length = pos - arv->region()->position();
|
||||
}
|
||||
|
||||
begin_reversible_command (_("change fade in length"));
|
||||
AutomationList& alist = arv->audio_region()->fade_in();
|
||||
|
||||
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
||||
|
||||
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
|
||||
|
||||
if (!tmp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AutomationList& alist = tmp->audio_region()->fade_in();
|
||||
XMLNode &before = alist.get_state();
|
||||
|
||||
arv->audio_region()->set_fade_in_length (fade_length);
|
||||
tmp->audio_region()->set_fade_in_length (fade_length);
|
||||
|
||||
XMLNode &after = alist.get_state();
|
||||
session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
|
||||
}
|
||||
|
||||
commit_reversible_command ();
|
||||
fade_in_drag_motion_callback (item, event);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1880,7 +1898,18 @@ Editor::fade_out_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event
|
|||
fade_length = arv->region()->last_frame() - pos;
|
||||
}
|
||||
|
||||
arv->reset_fade_out_shape_width (fade_length);
|
||||
/* mapover the region selection */
|
||||
|
||||
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
||||
|
||||
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
|
||||
|
||||
if (!tmp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tmp->reset_fade_out_shape_width (fade_length);
|
||||
}
|
||||
|
||||
show_verbose_duration_cursor (arv->region()->last_frame() - fade_length, arv->region()->last_frame(), 10);
|
||||
|
||||
|
|
@ -1918,16 +1947,25 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve
|
|||
}
|
||||
|
||||
begin_reversible_command (_("change fade out length"));
|
||||
AutomationList& alist = arv->audio_region()->fade_out();
|
||||
|
||||
for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
|
||||
|
||||
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*i);
|
||||
|
||||
if (!tmp) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AutomationList& alist = tmp->audio_region()->fade_out();
|
||||
XMLNode &before = alist.get_state();
|
||||
|
||||
arv->audio_region()->set_fade_out_length (fade_length);
|
||||
tmp->audio_region()->set_fade_out_length (fade_length);
|
||||
|
||||
XMLNode &after = alist.get_state();
|
||||
session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
fade_out_drag_motion_callback (item, event);
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2709,8 +2747,6 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
|||
void
|
||||
Editor::start_region_copy_grab (ArdourCanvas::Item* item, GdkEvent* event)
|
||||
{
|
||||
cerr << "start region copy grab, selected regions = " << selection->regions.size() << endl;
|
||||
|
||||
if (selection->regions.empty() || clicked_regionview == 0) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -4651,16 +4687,15 @@ Editor::drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
|
|||
return;
|
||||
}
|
||||
|
||||
// if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
||||
// snap_to (drag_info.current_pointer_frame);
|
||||
|
||||
// if (drag_info.first_move) {
|
||||
// snap_to (drag_info.grab_frame);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
|
||||
if (drag_info.first_move) {
|
||||
snap_to (drag_info.grab_frame);
|
||||
}
|
||||
snap_to (drag_info.current_pointer_frame);
|
||||
}
|
||||
|
||||
/* base start and end on initial click position */
|
||||
|
||||
if (drag_info.current_pointer_frame < drag_info.grab_frame) {
|
||||
start = drag_info.current_pointer_frame;
|
||||
end = drag_info.grab_frame;
|
||||
|
|
@ -4672,8 +4707,7 @@ Editor::drag_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
|
|||
if (drag_info.current_pointer_y < drag_info.grab_y) {
|
||||
y1 = drag_info.current_pointer_y;
|
||||
y2 = drag_info.grab_y;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
y2 = drag_info.current_pointer_y;
|
||||
y1 = drag_info.grab_y;
|
||||
}
|
||||
|
|
@ -4720,7 +4754,7 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
|
|||
Selection::Operation op = Keyboard::selection_type (event->button.state);
|
||||
bool commit;
|
||||
|
||||
begin_reversible_command (_("select regions"));
|
||||
begin_reversible_command (_("rubberband selection"));
|
||||
|
||||
if (drag_info.grab_frame < drag_info.last_pointer_frame) {
|
||||
commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, op);
|
||||
|
|
@ -4733,6 +4767,7 @@ Editor::end_rubberband_select (ArdourCanvas::Item* item, GdkEvent* event)
|
|||
}
|
||||
|
||||
} else {
|
||||
selection->clear_tracks();
|
||||
selection->clear_regions();
|
||||
selection->clear_points ();
|
||||
selection->clear_lines ();
|
||||
|
|
|
|||
|
|
@ -756,6 +756,39 @@ Editor::cursor_to_selection_end (Cursor *cursor)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::scroll_playhead (bool forward)
|
||||
{
|
||||
nframes_t pos = playhead_cursor->current_frame;
|
||||
nframes_t delta = (nframes_t) floor (current_page_frames() / 0.8);
|
||||
|
||||
if (forward) {
|
||||
if (pos == max_frames) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos < max_frames - delta) {
|
||||
pos += delta ;
|
||||
} else {
|
||||
pos = max_frames;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (pos == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos > delta) {
|
||||
pos -= delta;
|
||||
} else {
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
session->request_locate (pos);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::playhead_backward ()
|
||||
{
|
||||
|
|
@ -1257,311 +1290,6 @@ Editor::add_location_from_audio_region ()
|
|||
session->commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::select_all_in_track (Selection::Operation op)
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
if (!clicked_axisview) {
|
||||
return;
|
||||
}
|
||||
|
||||
clicked_axisview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
|
||||
|
||||
switch (op) {
|
||||
case Selection::Toggle:
|
||||
selection->add (touched);
|
||||
break;
|
||||
case Selection::Set:
|
||||
selection->set (touched);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
case Selection::Add:
|
||||
selection->add (touched);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::select_all (Selection::Operation op)
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
|
||||
if ((*iter)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
(*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
|
||||
}
|
||||
begin_reversible_command (_("select all"));
|
||||
switch (op) {
|
||||
case Selection::Add:
|
||||
case Selection::Toggle:
|
||||
selection->add (touched);
|
||||
break;
|
||||
case Selection::Set:
|
||||
selection->set (touched);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::invert_selection_in_track ()
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
if (!clicked_axisview) {
|
||||
return;
|
||||
}
|
||||
|
||||
clicked_axisview->get_inverted_selectables (*selection, touched);
|
||||
selection->set (touched);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::invert_selection ()
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
|
||||
if ((*iter)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
(*iter)->get_inverted_selectables (*selection, touched);
|
||||
}
|
||||
|
||||
selection->set (touched);
|
||||
}
|
||||
|
||||
bool
|
||||
Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, Selection::Operation op)
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
|
||||
if ((*iter)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
(*iter)->get_selectables (start, end, top, bot, touched);
|
||||
}
|
||||
|
||||
cerr << "select all within found " << touched.size() << endl;
|
||||
|
||||
begin_reversible_command (_("select all within"));
|
||||
switch (op) {
|
||||
case Selection::Add:
|
||||
case Selection::Toggle:
|
||||
cerr << "toggle\n";
|
||||
selection->add (touched);
|
||||
break;
|
||||
case Selection::Set:
|
||||
cerr << "set\n";
|
||||
selection->set (touched);
|
||||
break;
|
||||
case Selection::Extend:
|
||||
cerr << "extend\n";
|
||||
/* not defined yet */
|
||||
break;
|
||||
}
|
||||
|
||||
cerr << "selection now has " << selection->points.size() << endl;
|
||||
|
||||
commit_reversible_command ();
|
||||
return !touched.empty();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selection_from_audio_region ()
|
||||
{
|
||||
if (selection->regions.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RegionView* rv = *(selection->regions.begin());
|
||||
boost::shared_ptr<Region> region = rv->region();
|
||||
|
||||
begin_reversible_command (_("set selection from region"));
|
||||
selection->set (0, region->position(), region->last_frame());
|
||||
commit_reversible_command ();
|
||||
|
||||
set_mouse_mode (Editing::MouseRange, false);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selection_from_punch()
|
||||
{
|
||||
Location* location;
|
||||
|
||||
if ((location = session->locations()->auto_punch_location()) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
set_selection_from_range (*location);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selection_from_loop()
|
||||
{
|
||||
Location* location;
|
||||
|
||||
if ((location = session->locations()->auto_loop_location()) == 0) {
|
||||
return;
|
||||
}
|
||||
set_selection_from_range (*location);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_selection_from_range (Location& loc)
|
||||
{
|
||||
begin_reversible_command (_("set selection from range"));
|
||||
selection->set (0, loc.start(), loc.end());
|
||||
commit_reversible_command ();
|
||||
|
||||
set_mouse_mode (Editing::MouseRange, false);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::select_all_selectables_using_time_selection ()
|
||||
{
|
||||
list<Selectable *> touched;
|
||||
|
||||
if (selection->time.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nframes_t start = selection->time[clicked_selection].start;
|
||||
nframes_t end = selection->time[clicked_selection].end;
|
||||
|
||||
if (end - start < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
|
||||
if ((*iter)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
(*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
|
||||
}
|
||||
|
||||
begin_reversible_command (_("select all from range"));
|
||||
selection->set (touched);
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Editor::select_all_selectables_using_punch()
|
||||
{
|
||||
Location* location = session->locations()->auto_punch_location();
|
||||
list<Selectable *> touched;
|
||||
|
||||
if (location == 0 || (location->end() - location->start() <= 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
|
||||
if ((*iter)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
(*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
|
||||
}
|
||||
begin_reversible_command (_("select all from punch"));
|
||||
selection->set (touched);
|
||||
commit_reversible_command ();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Editor::select_all_selectables_using_loop()
|
||||
{
|
||||
Location* location = session->locations()->auto_loop_location();
|
||||
list<Selectable *> touched;
|
||||
|
||||
if (location == 0 || (location->end() - location->start() <= 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
|
||||
if ((*iter)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
(*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
|
||||
}
|
||||
begin_reversible_command (_("select all from loop"));
|
||||
selection->set (touched);
|
||||
commit_reversible_command ();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
|
||||
{
|
||||
nframes_t start;
|
||||
nframes_t end;
|
||||
list<Selectable *> touched;
|
||||
|
||||
if (after) {
|
||||
begin_reversible_command (_("select all after cursor"));
|
||||
start = cursor->current_frame ;
|
||||
end = session->current_end_frame();
|
||||
} else {
|
||||
if (cursor->current_frame > 0) {
|
||||
begin_reversible_command (_("select all before cursor"));
|
||||
start = 0;
|
||||
end = cursor->current_frame - 1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
|
||||
if ((*iter)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
(*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
|
||||
}
|
||||
selection->set (touched);
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
|
||||
{
|
||||
nframes_t start;
|
||||
nframes_t end;
|
||||
list<Selectable *> touched;
|
||||
bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
|
||||
|
||||
if (cursor->current_frame == other_cursor->current_frame) {
|
||||
return;
|
||||
}
|
||||
|
||||
begin_reversible_command (_("select all between cursors"));
|
||||
if (other_cursor_is_first) {
|
||||
start = other_cursor->current_frame;
|
||||
end = cursor->current_frame - 1;
|
||||
|
||||
} else {
|
||||
start = cursor->current_frame;
|
||||
end = other_cursor->current_frame - 1;
|
||||
}
|
||||
|
||||
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
|
||||
if ((*iter)->hidden()) {
|
||||
continue;
|
||||
}
|
||||
(*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
|
||||
}
|
||||
selection->set (touched);
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::amplitude_zoom_step (bool in)
|
||||
{
|
||||
|
|
@ -1855,6 +1583,30 @@ Editor::edit_envelope ()
|
|||
|
||||
/* PLAYBACK */
|
||||
|
||||
void
|
||||
Editor::transition_to_rolling (bool fwd)
|
||||
{
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Config->get_slave_source()) {
|
||||
case None:
|
||||
case JACK:
|
||||
break;
|
||||
default:
|
||||
/* transport controlled by the master */
|
||||
return;
|
||||
}
|
||||
|
||||
if (session->is_auditioning()) {
|
||||
session->cancel_audition ();
|
||||
return;
|
||||
}
|
||||
|
||||
session->request_transport_speed (fwd ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
void
|
||||
Editor::toggle_playback (bool with_abort)
|
||||
{
|
||||
|
|
@ -2166,6 +1918,8 @@ Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& n
|
|||
nframes_t start = selection->time[clicked_selection].start;
|
||||
nframes_t end = selection->time[clicked_selection].end;
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
|
||||
boost::shared_ptr<AudioRegion> current;
|
||||
|
|
@ -2196,17 +1950,22 @@ Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& n
|
|||
void
|
||||
Editor::split_multichannel_region ()
|
||||
{
|
||||
vector<AudioRegion*> v;
|
||||
|
||||
AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview);
|
||||
|
||||
if (!clicked_arv || clicked_arv->audio_region()->n_channels() < 2) {
|
||||
if (selection->regions.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
clicked_arv->audio_region()->separate_by_channel (*session, v);
|
||||
vector<boost::shared_ptr<AudioRegion> > v;
|
||||
|
||||
/* nothing else to do, really */
|
||||
for (list<RegionView*>::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
|
||||
|
||||
AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*x);
|
||||
|
||||
if (!arv || arv->audio_region()->n_channels() < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(arv)->audio_region()->separate_by_channel (*session, v);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2229,6 +1988,8 @@ Editor::separate_region_from_selection ()
|
|||
|
||||
boost::shared_ptr<Playlist> playlist;
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
|
||||
AudioTimeAxisView* atv;
|
||||
|
|
@ -2337,6 +2098,8 @@ Editor::crop_region_to_selection ()
|
|||
|
||||
} else {
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
|
||||
|
||||
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*i);
|
||||
|
|
@ -2949,21 +2712,37 @@ struct lt_playlist {
|
|||
}
|
||||
};
|
||||
|
||||
struct PlaylistMapping {
|
||||
TimeAxisView* tv;
|
||||
boost::shared_ptr<Playlist> pl;
|
||||
|
||||
PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
|
||||
};
|
||||
|
||||
void
|
||||
Editor::cut_copy_regions (CutCopyOp op)
|
||||
{
|
||||
typedef std::map<boost::shared_ptr<AudioPlaylist>,boost::shared_ptr<AudioPlaylist> > PlaylistMapping;
|
||||
PlaylistMapping pmap;
|
||||
/* we can't use a std::map here because the ordering is important, and we can't trivially sort
|
||||
a map when we want ordered access to both elements. i think.
|
||||
*/
|
||||
|
||||
vector<PlaylistMapping> pmap;
|
||||
|
||||
nframes_t first_position = max_frames;
|
||||
|
||||
set<PlaylistState, lt_playlist> freezelist;
|
||||
pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
|
||||
|
||||
/* get ordering correct before we cut/copy */
|
||||
|
||||
selection->regions.sort_by_position_and_track ();
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
|
||||
|
||||
first_position = min ((*x)->region()->position(), first_position);
|
||||
|
||||
if (op == Cut || op == Clear) {
|
||||
boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
|
||||
boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
|
||||
|
||||
if (pl) {
|
||||
|
||||
|
|
@ -2978,59 +2757,86 @@ Editor::cut_copy_regions (CutCopyOp op)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimeAxisView* tv = &(*x)->get_trackview();
|
||||
vector<PlaylistMapping>::iterator z;
|
||||
|
||||
for (z = pmap.begin(); z != pmap.end(); ++z) {
|
||||
if ((*z).tv == tv) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (z == pmap.end()) {
|
||||
pmap.push_back (PlaylistMapping (tv));
|
||||
}
|
||||
}
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
|
||||
|
||||
boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
|
||||
boost::shared_ptr<AudioPlaylist> npl;
|
||||
boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
|
||||
|
||||
if (!pl) {
|
||||
/* impossible, but this handles it for the future */
|
||||
continue;
|
||||
}
|
||||
|
||||
TimeAxisView& tv = (*x)->get_trackview();
|
||||
boost::shared_ptr<Playlist> npl;
|
||||
RegionSelection::iterator tmp;
|
||||
|
||||
tmp = x;
|
||||
++tmp;
|
||||
|
||||
if (pl) {
|
||||
vector<PlaylistMapping>::iterator z;
|
||||
|
||||
PlaylistMapping::iterator pi = pmap.find (pl);
|
||||
|
||||
if (pi == pmap.end()) {
|
||||
// FIXME
|
||||
npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (DataType::AUDIO, *session, "cutlist", true));
|
||||
npl->freeze();
|
||||
pmap[pl] = npl;
|
||||
} else {
|
||||
npl = pi->second;
|
||||
for (z = pmap.begin(); z != pmap.end(); ++z) {
|
||||
if ((*z).tv == &tv) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME
|
||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
|
||||
assert (z != pmap.end());
|
||||
|
||||
if (!(*z).pl) {
|
||||
npl = PlaylistFactory::create (pl->data_type(), *session, "cutlist", true);
|
||||
npl->freeze();
|
||||
(*z).pl = npl;
|
||||
} else {
|
||||
npl = (*z).pl;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Region> r = (*x)->region();
|
||||
|
||||
switch (op) {
|
||||
case Cut:
|
||||
if (!ar) break;
|
||||
if (!r) break;
|
||||
|
||||
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
|
||||
pl->remove_region (((*x)->region()));
|
||||
npl->add_region (RegionFactory::create (r), r->position() - first_position);
|
||||
pl->remove_region (r);
|
||||
break;
|
||||
|
||||
case Copy:
|
||||
if (!ar) break;
|
||||
if (!r) break;
|
||||
|
||||
npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
|
||||
npl->add_region (RegionFactory::create (r), r->position() - first_position);
|
||||
break;
|
||||
|
||||
case Clear:
|
||||
pl->remove_region (((*x)->region()));
|
||||
pl->remove_region (r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
x = tmp;
|
||||
}
|
||||
|
||||
list<boost::shared_ptr<Playlist> > foo;
|
||||
|
||||
for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
|
||||
foo.push_back (i->second);
|
||||
/* the pmap is in the same order as the tracks in which selected regions occured */
|
||||
|
||||
for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
|
||||
(*i).pl->thaw();
|
||||
foo.push_back ((*i).pl);
|
||||
}
|
||||
|
||||
if (!foo.empty()) {
|
||||
|
|
@ -3096,6 +2902,10 @@ Editor::paste_internal (nframes_t position, float times)
|
|||
TrackSelection::iterator i;
|
||||
size_t nth;
|
||||
|
||||
/* get everything in the correct order */
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
|
||||
|
||||
/* undo/redo is handled by individual tracks */
|
||||
|
|
@ -3131,6 +2941,8 @@ Editor::paste_named_selection (float times)
|
|||
|
||||
begin_reversible_command (_("paste chunk"));
|
||||
|
||||
sort_track_selection ();
|
||||
|
||||
for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
|
||||
|
||||
AudioTimeAxisView* atv;
|
||||
|
|
@ -3242,8 +3054,6 @@ Editor::reset_point_selection ()
|
|||
{
|
||||
/* reset all selected points to the relevant default value */
|
||||
|
||||
cerr << "point selection has " << selection->points.size() << " entries\n";
|
||||
|
||||
for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
|
||||
|
||||
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
|
||||
|
|
@ -3610,3 +3420,99 @@ Editor::toggle_region_opaque ()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
|
||||
{
|
||||
begin_reversible_command (_("set fade in shape"));
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
|
||||
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
||||
|
||||
if (!tmp) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutomationList& alist = tmp->audio_region()->fade_in();
|
||||
XMLNode &before = alist.get_state();
|
||||
|
||||
tmp->audio_region()->set_fade_in_shape (shape);
|
||||
|
||||
XMLNode &after = alist.get_state();
|
||||
session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
|
||||
}
|
||||
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
|
||||
{
|
||||
begin_reversible_command (_("set fade out shape"));
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
|
||||
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
||||
|
||||
if (!tmp) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutomationList& alist = tmp->audio_region()->fade_out();
|
||||
XMLNode &before = alist.get_state();
|
||||
|
||||
tmp->audio_region()->set_fade_out_shape (shape);
|
||||
|
||||
XMLNode &after = alist.get_state();
|
||||
session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
|
||||
}
|
||||
|
||||
commit_reversible_command ();
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_fade_in_active (bool yn)
|
||||
{
|
||||
begin_reversible_command (_("set fade in active"));
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
|
||||
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
||||
|
||||
if (!tmp) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
|
||||
|
||||
XMLNode &before = ar->get_state();
|
||||
|
||||
ar->set_fade_in_active (yn);
|
||||
|
||||
XMLNode &after = ar->get_state();
|
||||
session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::set_fade_out_active (bool yn)
|
||||
{
|
||||
begin_reversible_command (_("set fade out active"));
|
||||
|
||||
for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
|
||||
AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
|
||||
|
||||
if (!tmp) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
|
||||
|
||||
XMLNode &before = ar->get_state();
|
||||
|
||||
ar->set_fade_out_active (yn);
|
||||
|
||||
XMLNode &after = ar->get_state();
|
||||
session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ using namespace Editing;
|
|||
void
|
||||
Editor::handle_region_removed (boost::weak_ptr<Region> wregion)
|
||||
{
|
||||
cerr << "removed region\n";
|
||||
ENSURE_GUI_THREAD (mem_fun (*this, &Editor::redisplay_regions));
|
||||
redisplay_regions ();
|
||||
}
|
||||
|
|
|
|||
1011
gtk2_ardour/editor_selection.cc
Normal file
1011
gtk2_ardour/editor_selection.cc
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -40,6 +40,7 @@
|
|||
#include "logmeter.h"
|
||||
#include "gui_thread.h"
|
||||
#include "keyboard.h"
|
||||
#include "public_editor.h"
|
||||
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/route.h>
|
||||
|
|
@ -567,7 +568,11 @@ GainMeter::gain_activated ()
|
|||
|
||||
f = min (f, 6.0f);
|
||||
|
||||
_io->set_gain (dB_to_coefficient (f), this);
|
||||
_io->set_gain (dB_to_coefficient(f), this);
|
||||
|
||||
if (gain_display.has_focus()) {
|
||||
PublicEditor::instance().reset_focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ LadspaPluginUI::build ()
|
|||
frame->add (*box);
|
||||
hpacker.pack_start(*frame,true,true);
|
||||
|
||||
x = 0;
|
||||
x = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -367,6 +367,11 @@ int main (int argc, char *argv[])
|
|||
gtk_set_locale ();
|
||||
|
||||
(void) bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
/* our i18n translations are all in UTF-8, so make sure
|
||||
that even if the user locale doesn't specify UTF-8,
|
||||
we use that when handling them.
|
||||
*/
|
||||
(void) bind_textdomain_codeset (PACKAGE,"UTF-8");
|
||||
(void) textdomain (PACKAGE);
|
||||
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -87,6 +87,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
|
|||
virtual void new_region_from_selection () = 0;
|
||||
virtual void separate_region_from_selection () = 0;
|
||||
virtual void toggle_playback (bool with_abort) = 0;
|
||||
virtual void transition_to_rolling (bool fwd) = 0;
|
||||
virtual nframes_t unit_to_frame (double unit) = 0;
|
||||
virtual double frame_to_unit (nframes_t frame) = 0;
|
||||
virtual double frame_to_unit (double frame) = 0;
|
||||
|
|
@ -144,6 +145,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
|
|||
|
||||
Glib::RefPtr<Gtk::ActionGroup> editor_actions;
|
||||
|
||||
virtual void reset_focus() = 0;
|
||||
|
||||
virtual bool canvas_control_point_event (GdkEvent* event,ArdourCanvas::Item*, ControlPoint*) = 0;
|
||||
virtual bool canvas_line_event (GdkEvent* event,ArdourCanvas::Item*, AutomationLine*) = 0;
|
||||
virtual bool canvas_selection_rect_event (GdkEvent* event,ArdourCanvas::Item*, SelectionRect*) = 0;
|
||||
|
|
|
|||
|
|
@ -22,22 +22,13 @@
|
|||
|
||||
#include "region_view.h"
|
||||
#include "region_selection.h"
|
||||
#include "time_axis_view.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
using namespace sigc;
|
||||
|
||||
|
||||
bool
|
||||
RegionComparator::operator() (const RegionView* a, const RegionView* b) const
|
||||
{
|
||||
if (a == b) {
|
||||
return false;
|
||||
} else {
|
||||
return a < b;
|
||||
}
|
||||
}
|
||||
|
||||
RegionSelection::RegionSelection ()
|
||||
{
|
||||
_current_start = 0;
|
||||
|
|
@ -46,9 +37,8 @@ RegionSelection::RegionSelection ()
|
|||
|
||||
RegionSelection::RegionSelection (const RegionSelection& other)
|
||||
{
|
||||
|
||||
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
|
||||
add (*i, false);
|
||||
add (*i);
|
||||
}
|
||||
_current_start = other._current_start;
|
||||
_current_end = other._current_end;
|
||||
|
|
@ -64,7 +54,7 @@ RegionSelection::operator= (const RegionSelection& other)
|
|||
clear_all();
|
||||
|
||||
for (RegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) {
|
||||
add (*i, false);
|
||||
add (*i);
|
||||
}
|
||||
|
||||
_current_start = other._current_start;
|
||||
|
|
@ -83,17 +73,17 @@ RegionSelection::clear_all()
|
|||
_current_end = 0;
|
||||
}
|
||||
|
||||
bool RegionSelection::contains (RegionView* rv)
|
||||
bool RegionSelection::contains (RegionView* rv) const
|
||||
{
|
||||
return this->find (rv) != end();
|
||||
return find (begin(), end(), rv) != end();
|
||||
}
|
||||
|
||||
void
|
||||
RegionSelection::add (RegionView* rv, bool dosort)
|
||||
bool
|
||||
RegionSelection::add (RegionView* rv)
|
||||
{
|
||||
if (contains (rv)) {
|
||||
/* we already have it */
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
rv->RegionViewGoingAway.connect (mem_fun(*this, &RegionSelection::remove_it));
|
||||
|
|
@ -106,11 +96,13 @@ RegionSelection::add (RegionView* rv, bool dosort)
|
|||
_current_end = rv->region()->last_frame();
|
||||
}
|
||||
|
||||
insert (rv);
|
||||
push_back (rv);
|
||||
|
||||
// add to layer sorted list
|
||||
|
||||
add_to_layer (rv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -124,7 +116,7 @@ RegionSelection::remove (RegionView* rv)
|
|||
{
|
||||
RegionSelection::iterator i;
|
||||
|
||||
if ((i = this->find (rv)) != end()) {
|
||||
if ((i = find (begin(), end(), rv)) != end()) {
|
||||
|
||||
erase (i);
|
||||
|
||||
|
|
@ -198,7 +190,7 @@ RegionSelection::add_to_layer (RegionView * rv)
|
|||
}
|
||||
|
||||
struct RegionSortByTime {
|
||||
bool operator() (const RegionView* a, const RegionView* b) {
|
||||
bool operator() (const RegionView* a, const RegionView* b) const {
|
||||
return a->region()->position() < b->region()->position();
|
||||
}
|
||||
};
|
||||
|
|
@ -217,3 +209,49 @@ RegionSelection::by_position (list<RegionView*>& foo) const
|
|||
foo.sort (sorter);
|
||||
return;
|
||||
}
|
||||
|
||||
struct RegionSortByTrack {
|
||||
bool operator() (const RegionView* a, const RegionView* b) const {
|
||||
|
||||
/* really, track and position */
|
||||
|
||||
if (a->get_trackview().order == b->get_trackview().order) {
|
||||
return a->region()->position() < b->region()->position();
|
||||
} else {
|
||||
return a->get_trackview().order < b->get_trackview().order;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
RegionSelection::by_track (list<RegionView*>& foo) const
|
||||
{
|
||||
list<RegionView*>::const_iterator i;
|
||||
RegionSortByTrack sorter;
|
||||
|
||||
for (i = _bylayer.begin(); i != _bylayer.end(); ++i) {
|
||||
foo.push_back (*i);
|
||||
}
|
||||
|
||||
foo.sort (sorter);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
RegionSelection::sort_by_position_and_track ()
|
||||
{
|
||||
RegionSortByTrack sorter;
|
||||
sort (sorter);
|
||||
}
|
||||
|
||||
bool
|
||||
RegionSelection::involves (const TimeAxisView& tv) const
|
||||
{
|
||||
for (RegionSelection::const_iterator i = begin(); i != end(); ++i) {
|
||||
if (&(*i)->get_trackview() == &tv) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,11 +29,7 @@ using std::set;
|
|||
|
||||
class RegionView;
|
||||
|
||||
struct RegionComparator {
|
||||
bool operator() (const RegionView* a, const RegionView* b) const;
|
||||
};
|
||||
|
||||
class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::trackable
|
||||
class RegionSelection : public std::list<RegionView*>, public sigc::trackable
|
||||
{
|
||||
public:
|
||||
RegionSelection();
|
||||
|
|
@ -41,9 +37,12 @@ class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::
|
|||
|
||||
RegionSelection& operator= (const RegionSelection&);
|
||||
|
||||
void add (RegionView*, bool dosort = true);
|
||||
bool add (RegionView*);
|
||||
bool remove (RegionView*);
|
||||
bool contains (RegionView*);
|
||||
void sort_by_position_and_track ();
|
||||
|
||||
bool contains (RegionView*) const;
|
||||
bool involves (const TimeAxisView&) const;
|
||||
|
||||
void clear_all();
|
||||
|
||||
|
|
@ -51,14 +50,15 @@ class RegionSelection : public set<RegionView*, RegionComparator>, public sigc::
|
|||
return _current_start;
|
||||
}
|
||||
|
||||
/* collides with list<>::end */
|
||||
/* "end" collides with list<>::end */
|
||||
|
||||
nframes_t end_frame () const {
|
||||
return _current_end;
|
||||
}
|
||||
|
||||
const list<RegionView *> & by_layer() const { return _bylayer; }
|
||||
void by_position (list<RegionView*>&) const;
|
||||
const std::list<RegionView *>& by_layer() const { return _bylayer; }
|
||||
void by_position (std::list<RegionView*>&) const;
|
||||
void by_track (std::list<RegionView*>&) const;
|
||||
|
||||
private:
|
||||
void remove_it (RegionView*);
|
||||
|
|
|
|||
|
|
@ -209,9 +209,9 @@ Selection::toggle (RegionView* r)
|
|||
RegionSelection::iterator i;
|
||||
|
||||
if ((i = find (regions.begin(), regions.end(), r)) == regions.end()) {
|
||||
regions.add (r);
|
||||
add (r);
|
||||
} else {
|
||||
regions.erase (i);
|
||||
remove (*i);
|
||||
}
|
||||
|
||||
RegionsChanged ();
|
||||
|
|
@ -224,9 +224,9 @@ Selection::toggle (vector<RegionView*>& r)
|
|||
|
||||
for (vector<RegionView*>::iterator x = r.begin(); x != r.end(); ++x) {
|
||||
if ((i = find (regions.begin(), regions.end(), (*x))) == regions.end()) {
|
||||
regions.add ((*x));
|
||||
add ((*x));
|
||||
} else {
|
||||
regions.erase (i);
|
||||
remove (*x);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -322,6 +322,7 @@ Selection::add (RegionView* r)
|
|||
{
|
||||
if (find (regions.begin(), regions.end(), r) == regions.end()) {
|
||||
regions.add (r);
|
||||
add (&r->get_trackview());
|
||||
RegionsChanged ();
|
||||
}
|
||||
}
|
||||
|
|
@ -333,8 +334,10 @@ Selection::add (vector<RegionView*>& v)
|
|||
|
||||
for (vector<RegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
|
||||
if (find (regions.begin(), regions.end(), (*i)) == regions.end()) {
|
||||
regions.add ((*i));
|
||||
changed = true;
|
||||
changed = regions.add ((*i));
|
||||
if (changed) {
|
||||
add (&(*i)->get_trackview());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -461,8 +464,13 @@ Selection::remove (const list<boost::shared_ptr<Playlist> >& pllist)
|
|||
void
|
||||
Selection::remove (RegionView* r)
|
||||
{
|
||||
regions.remove (r);
|
||||
if (regions.remove (r)) {
|
||||
RegionsChanged ();
|
||||
}
|
||||
|
||||
if (!regions.involves (r->get_trackview())) {
|
||||
remove (&r->get_trackview());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -537,12 +545,14 @@ void
|
|||
Selection::set (RegionView* r)
|
||||
{
|
||||
clear_regions ();
|
||||
clear_tracks ();
|
||||
add (r);
|
||||
}
|
||||
|
||||
void
|
||||
Selection::set (vector<RegionView*>& v)
|
||||
{
|
||||
clear_tracks ();
|
||||
clear_regions ();
|
||||
// make sure to deselect any automation selections
|
||||
clear_points();
|
||||
|
|
@ -616,6 +626,52 @@ Selection::empty ()
|
|||
;
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (const vector<AutomationSelectable*>& autos)
|
||||
{
|
||||
for (vector<AutomationSelectable*>::const_iterator x = autos.begin(); x != autos.end(); ++x) {
|
||||
if ((*x)->get_selected()) {
|
||||
points.remove (**x);
|
||||
} else {
|
||||
points.push_back (**x);
|
||||
}
|
||||
|
||||
delete *x;
|
||||
}
|
||||
|
||||
PointsChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
void
|
||||
Selection::toggle (list<Selectable*>& selectables)
|
||||
{
|
||||
RegionView* rv;
|
||||
AutomationSelectable* as;
|
||||
vector<RegionView*> rvs;
|
||||
vector<AutomationSelectable*> autos;
|
||||
|
||||
for (std::list<Selectable*>::iterator i = selectables.begin(); i != selectables.end(); ++i) {
|
||||
if ((rv = dynamic_cast<RegionView*> (*i)) != 0) {
|
||||
rvs.push_back (rv);
|
||||
} else if ((as = dynamic_cast<AutomationSelectable*> (*i)) != 0) {
|
||||
autos.push_back (as);
|
||||
} else {
|
||||
fatal << _("programming error: ")
|
||||
<< X_("unknown selectable type passed to Selection::toggle()")
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
}
|
||||
|
||||
if (!rvs.empty()) {
|
||||
toggle (rvs);
|
||||
}
|
||||
|
||||
if (!autos.empty()) {
|
||||
toggle (autos);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Selection::set (list<Selectable*>& selectables)
|
||||
{
|
||||
|
|
@ -640,7 +696,7 @@ Selection::add (list<Selectable*>& selectables)
|
|||
autos.push_back (as);
|
||||
} else {
|
||||
fatal << _("programming error: ")
|
||||
<< X_("unknown selectable type passed to Selection::set()")
|
||||
<< X_("unknown selectable type passed to Selection::add()")
|
||||
<< endmsg;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
|
@ -669,7 +725,6 @@ Selection::add (vector<AutomationSelectable*>& autos)
|
|||
{
|
||||
for (vector<AutomationSelectable*>::iterator i = autos.begin(); i != autos.end(); ++i) {
|
||||
points.push_back (**i);
|
||||
delete *i;
|
||||
}
|
||||
|
||||
PointsChanged ();
|
||||
|
|
|
|||
|
|
@ -92,49 +92,52 @@ class Selection : public sigc::trackable
|
|||
bool selected (TimeAxisView*);
|
||||
bool selected (RegionView*);
|
||||
|
||||
void set (list<Selectable*>&);
|
||||
void add (list<Selectable*>&);
|
||||
void set (std::list<Selectable*>&);
|
||||
void add (std::list<Selectable*>&);
|
||||
void toggle (std::list<Selectable*>&);
|
||||
|
||||
void set (TimeAxisView*);
|
||||
void set (const list<TimeAxisView*>&);
|
||||
void set (const std::list<TimeAxisView*>&);
|
||||
void set (RegionView*);
|
||||
void set (std::vector<RegionView*>&);
|
||||
long set (TimeAxisView*, nframes_t, nframes_t);
|
||||
void set (ARDOUR::AutomationList*);
|
||||
void set (boost::shared_ptr<ARDOUR::Playlist>);
|
||||
void set (const list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void set (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void set (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void set (AutomationSelectable*);
|
||||
|
||||
void toggle (TimeAxisView*);
|
||||
void toggle (const list<TimeAxisView*>&);
|
||||
void toggle (const std::list<TimeAxisView*>&);
|
||||
void toggle (RegionView*);
|
||||
void toggle (std::vector<RegionView*>&);
|
||||
long toggle (nframes_t, nframes_t);
|
||||
void toggle (ARDOUR::AutomationList*);
|
||||
void toggle (boost::shared_ptr<ARDOUR::Playlist>);
|
||||
void toggle (const list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void toggle (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void toggle (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void toggle (const std::vector<AutomationSelectable*>&);
|
||||
|
||||
void add (TimeAxisView*);
|
||||
void add (const list<TimeAxisView*>&);
|
||||
void add (const std::list<TimeAxisView*>&);
|
||||
void add (RegionView*);
|
||||
void add (std::vector<RegionView*>&);
|
||||
long add (nframes_t, nframes_t);
|
||||
void add (ARDOUR::AutomationList*);
|
||||
void add (boost::shared_ptr<ARDOUR::Playlist>);
|
||||
void add (const list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void add (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void add (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
|
||||
void remove (TimeAxisView*);
|
||||
void remove (const list<TimeAxisView*>&);
|
||||
void remove (const std::list<TimeAxisView*>&);
|
||||
void remove (RegionView*);
|
||||
void remove (uint32_t selection_id);
|
||||
void remove (nframes_t, nframes_t);
|
||||
void remove (ARDOUR::AutomationList*);
|
||||
void remove (boost::shared_ptr<ARDOUR::Playlist>);
|
||||
void remove (const list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void remove (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
|
||||
void remove (boost::shared_ptr<ARDOUR::Redirect>);
|
||||
void remove (const list<Selectable*>&);
|
||||
|
||||
void replace (uint32_t time_index, nframes_t start, nframes_t end);
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ SoundFileBox::play_btn_clicked ()
|
|||
|
||||
for (int n = 0; n < sf_info.channels; ++n) {
|
||||
try {
|
||||
afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path+":"+string_compose("%1", n), AudioFileSource::Flag (0)));
|
||||
afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, *_session, path, n, AudioFileSource::Flag (0)));
|
||||
srclist.push_back(afs);
|
||||
|
||||
} catch (failed_constructor& err) {
|
||||
|
|
|
|||
|
|
@ -232,6 +232,11 @@ class TimeAxisViewItem : public Selectable
|
|||
ArdourCanvas::Text* get_name_text();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the time axis that this item is upon
|
||||
*/
|
||||
TimeAxisView& get_trackview() const { return trackview; }
|
||||
|
||||
/**
|
||||
* Sets the samples per unit of this item.
|
||||
* this item is used to determine the relative visual size and position of this item
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ buffer_set.cc
|
|||
meter.cc
|
||||
amp.cc
|
||||
panner.cc
|
||||
destructive_filesource.cc
|
||||
audiofilesource.cc
|
||||
audiofilter.cc
|
||||
audioregion.cc
|
||||
|
|
|
|||
|
|
@ -101,6 +101,10 @@ class AudioFileSource : public AudioSource {
|
|||
bool destructive() const { return (_flags & Destructive); }
|
||||
virtual bool set_destructive (bool yn) { return false; }
|
||||
|
||||
Flag flags() const { return _flags; }
|
||||
|
||||
void mark_immutable ();
|
||||
|
||||
/* this should really be protected, but C++ is getting stricter
|
||||
and creating slots from protected member functions is starting
|
||||
to cause issues.
|
||||
|
|
@ -125,12 +129,12 @@ class AudioFileSource : public AudioSource {
|
|||
|
||||
int init (string idstr, bool must_exist);
|
||||
|
||||
uint16_t channel;
|
||||
string _path;
|
||||
Flag _flags;
|
||||
string _take_id;
|
||||
int64_t timeline_position;
|
||||
bool file_is_new;
|
||||
uint16_t channel;
|
||||
|
||||
bool _is_embedded;
|
||||
static bool determine_embeddedness(string path);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class AudioRegion : public Region
|
|||
void set_envelope_active (bool yn);
|
||||
void set_default_envelope ();
|
||||
|
||||
int separate_by_channel (ARDOUR::Session&, vector<AudioRegion*>&) const;
|
||||
int separate_by_channel (ARDOUR::Session&, vector<boost::shared_ptr<AudioRegion> >&) const;
|
||||
|
||||
/* filter */
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,13 @@ class ConfigVariableBase {
|
|||
virtual void add_to_node (XMLNode& node) = 0;
|
||||
virtual bool set_from_node (const XMLNode& node, Owner owner) = 0;
|
||||
|
||||
|
||||
protected:
|
||||
std::string _name;
|
||||
Owner _owner;
|
||||
|
||||
void notify ();
|
||||
void miss ();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
|
|
@ -41,10 +45,12 @@ class ConfigVariable : public ConfigVariableBase
|
|||
|
||||
virtual bool set (T val, Owner owner) {
|
||||
if (val == value) {
|
||||
miss ();
|
||||
return false;
|
||||
}
|
||||
value = val;
|
||||
_owner = (ConfigVariableBase::Owner)(_owner |owner);
|
||||
notify ();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +61,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;
|
||||
XMLNode* child = new XMLNode ("Option");
|
||||
child->add_property ("name", _name);
|
||||
child->add_property ("value", ss.str());
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ CONFIG_VARIABLE (HeaderFormat, native_file_header_format, "native-file-header-f
|
|||
|
||||
CONFIG_VARIABLE (uint32_t, osc_port, "osc-port", 3819)
|
||||
CONFIG_VARIABLE (bool, use_osc, "use-osc", true)
|
||||
CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", true)
|
||||
|
||||
/* crossfades */
|
||||
|
||||
|
|
@ -115,6 +114,7 @@ CONFIG_VARIABLE (bool, no_new_session_dialog, "no-new-session-dialog", false)
|
|||
CONFIG_VARIABLE (bool, use_vst, "use-vst", true)
|
||||
CONFIG_VARIABLE (uint32_t, subframes_per_frame, "subframes-per-frame", 100)
|
||||
CONFIG_VARIABLE (uint32_t, saved_history_depth, "save-history-depth", 100)
|
||||
CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", false)
|
||||
|
||||
/* BWAV */
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace ARDOUR {
|
|||
class CoreAudioSource : public AudioFileSource {
|
||||
public:
|
||||
CoreAudioSource (ARDOUR::Session&, const XMLNode&);
|
||||
CoreAudioSource (ARDOUR::Session&, const string& path_plus_channel, Flag);
|
||||
CoreAudioSource (ARDOUR::Session&, const string& path, int chn, Flag);
|
||||
~CoreAudioSource ();
|
||||
|
||||
float sample_rate() const;
|
||||
|
|
|
|||
|
|
@ -167,8 +167,6 @@ class Crossfade : public PBD::StatefulDestructible, public boost::enable_shared_
|
|||
void initialize ();
|
||||
int compute (boost::shared_ptr<ARDOUR::AudioRegion>, boost::shared_ptr<ARDOUR::AudioRegion>, CrossfadeModel);
|
||||
bool update ();
|
||||
|
||||
void member_changed (ARDOUR::Change);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1702,7 +1702,6 @@ class Session : public PBD::StatefulDestructible
|
|||
|
||||
void config_changed (const char*);
|
||||
|
||||
void add_control_protocol (const ControlProtocolInfo* const, XMLNode*);
|
||||
XMLNode& get_control_protocol_state ();
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class SndFileSource : public AudioFileSource {
|
|||
public:
|
||||
/* constructor to be called for existing external-to-session files */
|
||||
|
||||
SndFileSource (Session&, std::string path, Flag flags);
|
||||
SndFileSource (Session&, std::string path, int chn, Flag flags);
|
||||
|
||||
/* constructor to be called for new in-session files */
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ class SndFileSource : public AudioFileSource {
|
|||
mutable float *interleave_buf;
|
||||
mutable nframes_t interleave_bufsize;
|
||||
|
||||
void init (string str);
|
||||
void init ();
|
||||
int open();
|
||||
void close();
|
||||
int setup_broadcast_info (nframes_t when, struct tm&, time_t);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class SourceFactory {
|
|||
static boost::shared_ptr<Source> create (Session&, const XMLNode& node);
|
||||
|
||||
// MIDI sources will have to be hacked in here somehow
|
||||
static boost::shared_ptr<Source> createReadable (DataType type, Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
|
||||
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);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -63,20 +63,22 @@ uint64_t AudioFileSource::header_position_offset = 0;
|
|||
/* XXX maybe this too */
|
||||
char AudioFileSource::bwf_serial_number[13] = "000000000000";
|
||||
|
||||
AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags)
|
||||
: AudioSource (s, idstr), _flags (flags)
|
||||
AudioFileSource::AudioFileSource (Session& s, string path, Flag flags)
|
||||
: AudioSource (s, path), _flags (flags),
|
||||
channel (0)
|
||||
{
|
||||
/* constructor used for existing external to session files. file must exist already */
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (idstr);
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (path);
|
||||
|
||||
if (init (idstr, true)) {
|
||||
if (init (path, true)) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, SampleFormat samp_format, HeaderFormat hdr_format)
|
||||
: AudioSource (s, path), _flags (flags)
|
||||
: AudioSource (s, path), _flags (flags),
|
||||
channel (0)
|
||||
{
|
||||
/* constructor used for new internal-to-session files. file cannot exist */
|
||||
_is_embedded = false;
|
||||
|
|
@ -88,6 +90,7 @@ AudioFileSource::AudioFileSource (Session& s, std::string path, Flag flags, Samp
|
|||
|
||||
AudioFileSource::AudioFileSource (Session& s, const XMLNode& node)
|
||||
: AudioSource (s, node), _flags (Flag (Writable|CanRename))
|
||||
/* channel is set in set_state() */
|
||||
{
|
||||
/* constructor used for existing internal-to-session files. file must exist */
|
||||
|
||||
|
|
@ -195,7 +198,10 @@ XMLNode&
|
|||
AudioFileSource::get_state ()
|
||||
{
|
||||
XMLNode& root (AudioSource::get_state());
|
||||
root.add_property ("flags", enum_2_string (_flags));
|
||||
char buf[32];
|
||||
root.add_property (X_("flags"), enum_2_string (_flags));
|
||||
snprintf (buf, sizeof (buf), "%d", channel);
|
||||
root.add_property (X_("channel"), buf);
|
||||
return root;
|
||||
}
|
||||
|
||||
|
|
@ -209,15 +215,18 @@ AudioFileSource::set_state (const XMLNode& node)
|
|||
}
|
||||
|
||||
if ((prop = node.property (X_("flags"))) != 0) {
|
||||
|
||||
_flags = Flag (string_2_enum (prop->value(), _flags));
|
||||
|
||||
} else {
|
||||
|
||||
_flags = Flag (0);
|
||||
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("channel"))) != 0) {
|
||||
channel = atoi (prop->value());
|
||||
} else {
|
||||
channel = 0;
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("name"))) != 0) {
|
||||
_is_embedded = AudioFileSource::determine_embeddedness (prop->value());
|
||||
} else {
|
||||
|
|
@ -537,8 +546,7 @@ AudioFileSource::is_empty (Session& s, string path)
|
|||
{
|
||||
bool ret = false;
|
||||
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (
|
||||
SourceFactory::createReadable (DataType::AUDIO, s, path, NoPeakFile, false));
|
||||
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createReadable (DataType::AUDIO, s, path, 0, NoPeakFile, false));
|
||||
|
||||
if (afs) {
|
||||
ret = (afs->length() == 0);
|
||||
|
|
@ -579,3 +587,9 @@ AudioFileSource::safe_file_extension(string file)
|
|||
#endif // HAVE_COREAUDIO
|
||||
file.rfind(".voc") == string::npos);
|
||||
}
|
||||
|
||||
void
|
||||
AudioFileSource::mark_immutable ()
|
||||
{
|
||||
_flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include <ardour/audiofilter.h>
|
||||
#include <ardour/audiofilesource.h>
|
||||
#include <ardour/destructive_filesource.h>
|
||||
#include <ardour/region_factory.h>
|
||||
|
||||
#include "i18n.h"
|
||||
#include <locale.h>
|
||||
|
|
@ -327,7 +328,7 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff
|
|||
nframes_t position, nframes_t cnt,
|
||||
uint32_t chan_n, nframes_t read_frames, nframes_t skip_frames) const
|
||||
{
|
||||
//cerr << _name << "._read_at(" << position << ") - " << _position << endl;
|
||||
cerr << _name << "._read_at(" << position << ") - " << _position << endl;
|
||||
|
||||
nframes_t internal_offset;
|
||||
nframes_t buf_offset;
|
||||
|
|
@ -901,25 +902,44 @@ AudioRegion::recompute_at_start ()
|
|||
}
|
||||
|
||||
int
|
||||
AudioRegion::separate_by_channel (Session& session, vector<AudioRegion*>& v) const
|
||||
AudioRegion::separate_by_channel (Session& session, vector<boost::shared_ptr<AudioRegion> >& v) const
|
||||
{
|
||||
SourceList srcs;
|
||||
string new_name;
|
||||
int n;
|
||||
|
||||
for (SourceList::const_iterator i = _master_sources.begin(); i != _master_sources.end(); ++i) {
|
||||
if (_sources.size() < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
|
||||
for (SourceList::const_iterator i = _sources.begin(); i != _sources.end(); ++i) {
|
||||
|
||||
srcs.clear ();
|
||||
srcs.push_back (*i);
|
||||
|
||||
/* generate a new name */
|
||||
new_name = _name;
|
||||
|
||||
if (session.region_name (new_name, _name)) {
|
||||
return -1;
|
||||
if (_sources.size() == 2) {
|
||||
if (n == 0) {
|
||||
new_name += "-L";
|
||||
} else {
|
||||
new_name += "-R";
|
||||
}
|
||||
} else {
|
||||
new_name += '-';
|
||||
new_name += ('0' + n + 1);
|
||||
}
|
||||
|
||||
/* create a copy with just one source */
|
||||
|
||||
v.push_back (new AudioRegion (srcs, _start, _length, new_name, _layer, _flags));
|
||||
boost::shared_ptr<Region> r = RegionFactory::create (srcs, _start, _length, new_name, _layer, _flags);
|
||||
boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
|
||||
|
||||
v.push_back (ar);
|
||||
|
||||
++n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -317,3 +317,16 @@ Configuration::map_parameters (sigc::slot<void,const char*> theSlot)
|
|||
#undef CONFIG_VARIABLE
|
||||
#undef CONFIG_VARIABLE_SPECIAL
|
||||
}
|
||||
|
||||
void
|
||||
ConfigVariableBase::notify ()
|
||||
{
|
||||
// placeholder for any debugging desired when a config variable is modified
|
||||
}
|
||||
|
||||
void
|
||||
ConfigVariableBase::miss ()
|
||||
{
|
||||
// placeholder for any debugging desired when a config variable
|
||||
// is set but to the same value as it already has
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,11 +324,26 @@ ControlProtocolManager::get_state (void)
|
|||
Glib::Mutex::Lock lm (protocols_lock);
|
||||
|
||||
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
|
||||
XMLNode* child = new XMLNode (X_("Protocol"));
|
||||
child->add_property (X_("name"), (*i)->name);
|
||||
child->add_property (X_("active"), (*i)->protocol ? "yes" : "no");
|
||||
|
||||
XMLNode * child;
|
||||
|
||||
if ((*i)->protocol) {
|
||||
child = &((*i)->protocol->get_state());
|
||||
child->add_property (X_("active"), "yes");
|
||||
// should we update (*i)->state here? probably.
|
||||
root->add_child_nocopy (*child);
|
||||
}
|
||||
else if ((*i)->state) {
|
||||
// keep ownership clear
|
||||
root->add_child_copy (*(*i)->state);
|
||||
}
|
||||
else {
|
||||
child = new XMLNode (X_("Protocol"));
|
||||
child->add_property (X_("name"), (*i)->name);
|
||||
child->add_property (X_("active"), "no");
|
||||
root->add_child_nocopy (*child);
|
||||
}
|
||||
}
|
||||
|
||||
return *root;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <pbd/error.h>
|
||||
#include <ardour/coreaudiosource.h>
|
||||
#include <ardour/utils.h>
|
||||
|
||||
#include <appleutility/CAAudioFile.h>
|
||||
#include <appleutility/CAStreamBasicDescription.h>
|
||||
|
|
@ -33,33 +34,22 @@ using namespace PBD;
|
|||
CoreAudioSource::CoreAudioSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
init (_name);
|
||||
init ();
|
||||
}
|
||||
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const string& idstr, Flag flags)
|
||||
: AudioFileSource(s, idstr, flags)
|
||||
CoreAudioSource::CoreAudioSource (Session& s, const string& path, int chn, Flag flags)
|
||||
: AudioFileSource(s, path, flags),
|
||||
{
|
||||
init (idstr);
|
||||
channel = chn;
|
||||
init ();
|
||||
}
|
||||
|
||||
void
|
||||
CoreAudioSource::init (string idstr)
|
||||
CoreAudioSource::init ()
|
||||
{
|
||||
string::size_type pos;
|
||||
|
||||
tmpbuf = 0;
|
||||
tmpbufsize = 0;
|
||||
|
||||
_name = idstr;
|
||||
|
||||
if ((pos = idstr.find_last_of (':')) == string::npos) {
|
||||
channel = 0;
|
||||
_path = idstr;
|
||||
} else {
|
||||
channel = atoi (idstr.substr (pos+1).c_str());
|
||||
_path = idstr.substr (0, pos);
|
||||
}
|
||||
|
||||
cerr << "CoreAudioSource::init() " << name() << endl;
|
||||
|
||||
/* note that we temporarily truncated _id at the colon */
|
||||
|
|
|
|||
|
|
@ -225,9 +225,6 @@ Crossfade::initialize ()
|
|||
_fade_in.add (_length, 1.0);
|
||||
_fade_in.thaw ();
|
||||
|
||||
// _in->StateChanged.connect (sigc::mem_fun (*this, &Crossfade::member_changed));
|
||||
// _out->StateChanged.connect (sigc::mem_fun (*this, &Crossfade::member_changed));
|
||||
|
||||
overlap_type = _in->coverage (_out->position(), _out->last_frame());
|
||||
layer_relation = (int32_t) (_in->layer() - _out->layer());
|
||||
}
|
||||
|
|
@ -597,26 +594,6 @@ Crossfade::compute (boost::shared_ptr<AudioRegion> a, boost::shared_ptr<AudioReg
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Crossfade::member_changed (Change what_changed)
|
||||
{
|
||||
Change what_we_care_about = Change (Region::MuteChanged|
|
||||
Region::LayerChanged|
|
||||
BoundsChanged);
|
||||
|
||||
if (what_changed & what_we_care_about) {
|
||||
try {
|
||||
if (what_changed & what_we_care_about) {
|
||||
refresh ();
|
||||
}
|
||||
}
|
||||
|
||||
catch (NoCrossfadeHere& err) {
|
||||
// relax, Invalidated inside refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
Crossfade::get_state ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -410,7 +410,7 @@ DestructiveFileSource::handle_header_position_change ()
|
|||
}
|
||||
|
||||
void
|
||||
DestructiveFileSource::set_timeline_position (int64_t)
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1354,10 +1354,12 @@ IO::set_state (const XMLNode& node)
|
|||
set_automation_state (*(*iter)->children().front());
|
||||
}
|
||||
|
||||
if ((*iter)->name() == X_("gaincontrol")) {
|
||||
if ((*iter)->name() == X_("controllable")) {
|
||||
if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
|
||||
_gain_control.set_state (**iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ports_legal) {
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst,
|
|||
uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) const
|
||||
{
|
||||
|
||||
//cerr << _name << "._read_at(" << position << ") - " << _position << endl;
|
||||
cerr << _name << "._read_at(" << position << ") - " << _position << endl;
|
||||
|
||||
jack_nframes_t internal_offset = 0;
|
||||
jack_nframes_t src_offset = 0;
|
||||
|
|
|
|||
|
|
@ -545,9 +545,10 @@ EqualPowerStereoPanner::set_state (const XMLNode& node)
|
|||
|
||||
for (XMLNodeConstIterator iter = node.children().begin(); iter != node.children().end(); ++iter) {
|
||||
|
||||
if ((*iter)->name() == X_("panner")) {
|
||||
|
||||
if ((*iter)->name() == X_("controllable")) {
|
||||
if ((prop = (*iter)->property("name")) != 0 && prop->value() == "panner") {
|
||||
_control.set_state (**iter);
|
||||
}
|
||||
|
||||
} else if ((*iter)->name() == X_("Automation")) {
|
||||
|
||||
|
|
|
|||
|
|
@ -606,11 +606,15 @@ Playlist::remove_region_internal (boost::shared_ptr<Region>region)
|
|||
void
|
||||
Playlist::get_equivalent_regions (boost::shared_ptr<Region> other, vector<boost::shared_ptr<Region> >& results)
|
||||
{
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
if (Config->get_use_overlap_equivalency()) {
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
if ((*i)->overlap_equivalent (other)) {
|
||||
results.push_back ((*i));
|
||||
} else if ((*i)->equivalent (other)) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||
if ((*i)->equivalent (other)) {
|
||||
results.push_back ((*i));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1647,15 +1647,21 @@ Route::_set_state (const XMLNode& node, bool call_base)
|
|||
_comment = cmt->content();
|
||||
|
||||
} else if (child->name() == X_("extra")) {
|
||||
|
||||
_extra_xml = new XMLNode (*child);
|
||||
} else if (child->name() == X_("solo")) {
|
||||
|
||||
} else if (child->name() == X_("controllable") && (prop = child->property("name")) != 0) {
|
||||
|
||||
if (prop->value() == "solo") {
|
||||
_solo_control.set_state (*child);
|
||||
_session.add_controllable (&_solo_control);
|
||||
} else if (child->name() == X_("mute")) {
|
||||
}
|
||||
else if (prop->value() == "mute") {
|
||||
_mute_control.set_state (*child);
|
||||
_session.add_controllable (&_mute_control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((prop = node.property (X_("mix-group"))) != 0) {
|
||||
RouteGroup* mix_group = _session.mix_group_by_name(prop->value());
|
||||
|
|
|
|||
|
|
@ -382,7 +382,6 @@ Session::Session (AudioEngine &eng,
|
|||
if (master_out_channels) {
|
||||
shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
|
||||
r->set_remote_control_id (control_id);
|
||||
cerr << "master bus has remote control ID " << r->remote_control_id() << endl;
|
||||
|
||||
rl.push_back (r);
|
||||
} else {
|
||||
|
|
@ -410,6 +409,8 @@ Session::Session (AudioEngine &eng,
|
|||
|
||||
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
|
||||
|
||||
Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
|
||||
|
||||
if (was_dirty) {
|
||||
DirtyChanged (); /* EMIT SIGNAL */
|
||||
}
|
||||
|
|
@ -1794,6 +1795,10 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
|
|||
track->set_control_outs (cports);
|
||||
}
|
||||
|
||||
// assert (current_thread != RT_thread)
|
||||
|
||||
track->audio_diskstream()->non_realtime_input_change();
|
||||
|
||||
track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
|
||||
track->set_remote_control_id (control_id);
|
||||
++control_id;
|
||||
|
|
@ -3163,12 +3168,14 @@ Session::midi_path_from_name (string name)
|
|||
|
||||
for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
|
||||
|
||||
spath = (*i).path;
|
||||
|
||||
// FIXME: different directory from audio?
|
||||
spath = (*i).path + sound_dir_name + "/" + legalized;
|
||||
spath += sound_dir(false) + "/" + legalized;
|
||||
|
||||
snprintf (buf, sizeof(buf), "%s-%u.mid", spath.c_str(), cnt);
|
||||
|
||||
if (access (buf, F_OK) == 0) {
|
||||
if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
|
||||
existing++;
|
||||
}
|
||||
}
|
||||
|
|
@ -3191,6 +3198,7 @@ Session::midi_path_from_name (string name)
|
|||
|
||||
// FIXME: different directory than audio?
|
||||
spath = discover_best_sound_dir ();
|
||||
spath += '/';
|
||||
|
||||
string::size_type pos = foo.find_last_of ('/');
|
||||
|
||||
|
|
@ -3618,7 +3626,7 @@ Session::remove_redirect (Redirect* redirect)
|
|||
nframes_t
|
||||
Session::available_capture_duration ()
|
||||
{
|
||||
float sample_bytes_on_disk;
|
||||
float sample_bytes_on_disk = 4.0; // keep gcc happy
|
||||
|
||||
switch (Config->get_native_file_data_format()) {
|
||||
case FormatFloat:
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Session::memento_command_factory(XMLNode *n)
|
|||
{
|
||||
PBD::ID id;
|
||||
XMLNode *before = 0, *after = 0;
|
||||
XMLNode *child;
|
||||
XMLNode *child = 0;
|
||||
|
||||
/* get id */
|
||||
id = PBD::ID(n->property("obj_id")->value());
|
||||
|
|
|
|||
|
|
@ -1059,19 +1059,7 @@ XMLNode&
|
|||
Session::get_control_protocol_state ()
|
||||
{
|
||||
ControlProtocolManager& cpm (ControlProtocolManager::instance());
|
||||
XMLNode* node = new XMLNode (X_("ControlProtocols"));
|
||||
|
||||
cpm.foreach_known_protocol (bind (mem_fun (*this, &Session::add_control_protocol), node));
|
||||
|
||||
return *node;
|
||||
}
|
||||
|
||||
void
|
||||
Session::add_control_protocol (const ControlProtocolInfo* const cpi, XMLNode* node)
|
||||
{
|
||||
if (cpi->protocol) {
|
||||
node->add_child_nocopy (cpi->protocol->get_state());
|
||||
}
|
||||
return cpm.get_state();
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -48,30 +48,34 @@ const AudioFileSource::Flag SndFileSource::default_writable_flags = AudioFileSou
|
|||
SndFileSource::SndFileSource (Session& s, const XMLNode& node)
|
||||
: AudioFileSource (s, node)
|
||||
{
|
||||
init (_name);
|
||||
init ();
|
||||
|
||||
cerr << "SndFileSource @ " << _path << " channel = " << channel << endl;
|
||||
|
||||
if (open()) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
|
||||
SndFileSource::SndFileSource (Session& s, string path, int chn, Flag flags)
|
||||
/* files created this way are never writable or removable */
|
||||
: AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
: AudioFileSource (s, path, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
|
||||
{
|
||||
init (idstr);
|
||||
channel = chn;
|
||||
|
||||
init ();
|
||||
|
||||
if (open()) {
|
||||
throw failed_constructor ();
|
||||
}
|
||||
}
|
||||
|
||||
SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
|
||||
: AudioFileSource (s, idstr, flags, sfmt, hf)
|
||||
SndFileSource::SndFileSource (Session& s, string path, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
|
||||
: AudioFileSource (s, path, flags, sfmt, hf)
|
||||
{
|
||||
int fmt = 0;
|
||||
|
||||
init (idstr);
|
||||
init ();
|
||||
|
||||
/* this constructor is used to construct new files, not open
|
||||
existing ones.
|
||||
|
|
@ -174,9 +178,8 @@ SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, Heade
|
|||
}
|
||||
|
||||
void
|
||||
SndFileSource::init (string idstr)
|
||||
SndFileSource::init ()
|
||||
{
|
||||
string::size_type pos;
|
||||
string file;
|
||||
|
||||
// lets try to keep the object initalizations here at the top
|
||||
|
|
@ -186,20 +189,10 @@ SndFileSource::init (string idstr)
|
|||
sf = 0;
|
||||
_broadcast_info = 0;
|
||||
|
||||
string tmp_name;
|
||||
|
||||
if ((pos = idstr.find_last_of (':')) == string::npos) {
|
||||
channel = 0;
|
||||
tmp_name = idstr;
|
||||
} else {
|
||||
channel = atoi (idstr.substr (pos+1).c_str());
|
||||
tmp_name = idstr.substr (0, pos);
|
||||
}
|
||||
|
||||
if (is_embedded()) {
|
||||
_name = tmp_name;
|
||||
_name = _path;
|
||||
} else {
|
||||
_name = Glib::path_get_basename (tmp_name);
|
||||
_name = Glib::path_get_basename (_path);
|
||||
}
|
||||
|
||||
/* although libsndfile says we don't need to set this,
|
||||
|
|
@ -385,6 +378,7 @@ nframes_t
|
|||
SndFileSource::nondestructive_write_unlocked (Sample *data, nframes_t cnt)
|
||||
{
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -440,6 +434,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, nframes_t cnt)
|
|||
nframes_t old_file_pos;
|
||||
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to write a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -563,6 +558,7 @@ int
|
|||
SndFileSource::flush_header ()
|
||||
{
|
||||
if (!writable() || (sf == 0)) {
|
||||
warning << string_compose (_("attempt to flush a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE);
|
||||
|
|
@ -572,6 +568,7 @@ int
|
|||
SndFileSource::setup_broadcast_info (nframes_t when, struct tm& now, time_t tnow)
|
||||
{
|
||||
if (!writable()) {
|
||||
warning << string_compose (_("attempt to store broadcast info in a non-writable audio file source (%1)"), _path) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,14 +131,13 @@ SourceFactory::create (Session& s, const XMLNode& node)
|
|||
|
||||
#ifdef HAVE_COREAUDIO
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
SourceFactory::createReadable (DataType type, Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce)
|
||||
{
|
||||
if (type == DataType::AUDIO) {
|
||||
|
||||
if (!(flags & Destructive)) {
|
||||
|
||||
try {
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new CoreAudioSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
|
@ -149,7 +148,7 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
}
|
||||
|
||||
catch (failed_constructor& err) {
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
|
@ -161,7 +160,7 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
|
||||
} else {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
}
|
||||
|
|
@ -171,6 +170,7 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
return ret;
|
||||
}
|
||||
|
||||
return boost::shared_ptr<Source>();
|
||||
} else if (type == DataType::MIDI) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, node));
|
||||
|
|
@ -187,11 +187,11 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
#else
|
||||
|
||||
boost::shared_ptr<Source>
|
||||
SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
|
||||
SourceFactory::createReadable (DataType type, Session& s, string path, int chn, AudioFileSource::Flag flags, bool announce)
|
||||
{
|
||||
if (type == DataType::AUDIO) {
|
||||
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
|
||||
boost::shared_ptr<Source> ret (new SndFileSource (s, path, chn, flags));
|
||||
|
||||
if (setup_peakfile (ret)) {
|
||||
return boost::shared_ptr<Source>();
|
||||
|
|
@ -203,10 +203,11 @@ SourceFactory::createReadable (DataType type, Session& s, string idstr, AudioFil
|
|||
|
||||
return ret;
|
||||
|
||||
|
||||
} else if (type == DataType::MIDI) {
|
||||
|
||||
// FIXME: flags?
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, idstr, SMFSource::Flag(0)));
|
||||
boost::shared_ptr<Source> ret (new SMFSource (s, path, SMFSource::Flag(0)));
|
||||
|
||||
if (announce) {
|
||||
SourceCreated (ret);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@
|
|||
#include <fcntl.h>
|
||||
#include <cerrno>
|
||||
|
||||
#include <pbd/failed_constructor.h>
|
||||
#include <pbd/error.h>
|
||||
|
||||
#include <midi++/types.h>
|
||||
#include <midi++/alsa_sequencer.h>
|
||||
#include <midi++/port_request.h>
|
||||
|
|
@ -35,20 +38,26 @@
|
|||
#define TR_VAL(v)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace MIDI;
|
||||
using namespace PBD;
|
||||
|
||||
snd_seq_t* ALSA_SequencerMidiPort::seq = 0;
|
||||
|
||||
ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (PortRequest &req)
|
||||
: Port (req)
|
||||
, seq (0)
|
||||
, decoder (0)
|
||||
, encoder (0)
|
||||
, port_id (-1)
|
||||
{
|
||||
TR_FN();
|
||||
int err;
|
||||
|
||||
if (!seq && init_client (req.devname) < 0) {
|
||||
_ok = false;
|
||||
|
||||
} else {
|
||||
|
||||
if (0 <= (err = CreatePorts (req)) &&
|
||||
0 <= (err = snd_midi_event_new (1024, &decoder)) && // Length taken from ARDOUR::Session::midi_read ()
|
||||
0 <= (err = snd_midi_event_new (64, &encoder))) { // Length taken from ARDOUR::Session::mmc_buffer
|
||||
|
|
@ -56,21 +65,27 @@ ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (PortRequest &req)
|
|||
snd_midi_event_init (encoder);
|
||||
_ok = true;
|
||||
req.status = PortRequest::OK;
|
||||
} else
|
||||
} else {
|
||||
req.status = PortRequest::Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ALSA_SequencerMidiPort::~ALSA_SequencerMidiPort ()
|
||||
{
|
||||
if (decoder)
|
||||
if (decoder) {
|
||||
snd_midi_event_free (decoder);
|
||||
if (encoder)
|
||||
}
|
||||
if (encoder) {
|
||||
snd_midi_event_free (encoder);
|
||||
if (seq)
|
||||
snd_seq_close (seq);
|
||||
}
|
||||
if (port_id >= 0) {
|
||||
snd_seq_delete_port (seq, port_id);
|
||||
}
|
||||
}
|
||||
|
||||
int ALSA_SequencerMidiPort::selectable () const
|
||||
int
|
||||
ALSA_SequencerMidiPort::selectable () const
|
||||
{
|
||||
struct pollfd pfd[1];
|
||||
if (0 <= snd_seq_poll_descriptors (seq, pfd, 1, POLLIN | POLLOUT)) {
|
||||
|
|
@ -118,7 +133,12 @@ int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t timesta
|
|||
return totwritten;
|
||||
}
|
||||
|
||||
<<<<<<< .working
|
||||
int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp)
|
||||
=======
|
||||
int
|
||||
ALSA_SequencerMidiPort::read (byte *buf, size_t max)
|
||||
>>>>>>> .merge-right.r1393
|
||||
{
|
||||
TR_FN();
|
||||
int err;
|
||||
|
|
@ -142,27 +162,49 @@ int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp)
|
|||
return -ENOENT == err ? 0 : err;
|
||||
}
|
||||
|
||||
int ALSA_SequencerMidiPort::CreatePorts (PortRequest &req)
|
||||
int
|
||||
ALSA_SequencerMidiPort::CreatePorts (PortRequest &req)
|
||||
{
|
||||
int err;
|
||||
if (0 <= (err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX,
|
||||
(req.mode & O_NONBLOCK) ? SND_SEQ_NONBLOCK : 0))) {
|
||||
snd_seq_set_client_name (seq, req.devname);
|
||||
unsigned int caps = 0;
|
||||
|
||||
if (req.mode == O_WRONLY || req.mode == O_RDWR)
|
||||
caps |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
|
||||
if (req.mode == O_RDONLY || req.mode == O_RDWR)
|
||||
caps |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
|
||||
err = snd_seq_create_simple_port (seq, req.tagname, caps, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
|
||||
if (err >= 0) {
|
||||
|
||||
if (0 <= (err = snd_seq_create_simple_port (seq, req.tagname, caps, SND_SEQ_PORT_TYPE_MIDI_GENERIC))) {
|
||||
|
||||
port_id = err;
|
||||
|
||||
snd_seq_ev_clear (&SEv);
|
||||
snd_seq_ev_set_source (&SEv, port_id);
|
||||
snd_seq_ev_set_subs (&SEv);
|
||||
snd_seq_ev_set_direct (&SEv);
|
||||
} else
|
||||
snd_seq_close (seq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int
|
||||
ALSA_SequencerMidiPort::init_client (std::string name)
|
||||
{
|
||||
static bool called = false;
|
||||
|
||||
if (called) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
called = true;
|
||||
|
||||
if (snd_seq_open (&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) >= 0) {
|
||||
snd_seq_set_client_name (seq, name.c_str());
|
||||
return 0;
|
||||
} else {
|
||||
warning << "The ALSA MIDI system is not available. No ports based on it will be created"
|
||||
<< endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,12 +48,14 @@ class ALSA_SequencerMidiPort : public Port
|
|||
int read (byte *buf, size_t max, timestamp_t timestamp);
|
||||
|
||||
private:
|
||||
snd_seq_t *seq;
|
||||
snd_midi_event_t *decoder, *encoder;
|
||||
int port_id;
|
||||
snd_seq_event_t SEv;
|
||||
|
||||
int CreatePorts(PortRequest &req);
|
||||
|
||||
static int init_client (std::string name);
|
||||
static snd_seq_t* seq;
|
||||
};
|
||||
|
||||
}; /* namespace MIDI */
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ strip_whitespace_edges (string& str)
|
|||
{
|
||||
string::size_type i;
|
||||
string::size_type len;
|
||||
string::size_type s;
|
||||
string::size_type s = 0;
|
||||
|
||||
len = str.length();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __ardour_svn_revision_h__
|
||||
#define __ardour_svn_revision_h__
|
||||
static const char* ardour_svn_revision = "1266";
|
||||
static const char* ardour_svn_revision = "1345";
|
||||
#endif
|
||||
|
|
|
|||
75
tools/ARDOUR/SourceInfoLoader.pm
Normal file
75
tools/ARDOUR/SourceInfoLoader.pm
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package ARDOUR::SourceInfoLoader;
|
||||
|
||||
|
||||
use XML::Handler::Subs;
|
||||
|
||||
@ISA = qw( XML::Handler::Subs );
|
||||
|
||||
$VERSION = 1.0;
|
||||
|
||||
|
||||
sub new {
|
||||
my ($type, $sessionName) = @_;
|
||||
|
||||
my $self = $type->SUPER::new();
|
||||
|
||||
$self->{SessionName} = $sessionName;
|
||||
$self->{InRegions} = 0;
|
||||
%self->{Sources} = {};
|
||||
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub start_element {
|
||||
my $self = shift;
|
||||
my $element = shift;
|
||||
|
||||
my $atts = $element->{Attributes};
|
||||
|
||||
if ( $element->{Name} eq "Source") {
|
||||
if ( ! -f "interchange/".$sessionName."/audiofiles/".$atts->{name}) {
|
||||
$atts->{calculated_length} = 1;
|
||||
$self->{Sources}->{$atts->{id}} = $atts;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( $self->{InRegions} eq 1 && $element->{Name} eq "Region") {
|
||||
#print "Looking at region ".$atts->{id}."\n";
|
||||
my $num = 0;
|
||||
|
||||
my $region_length = $atts->{length};
|
||||
while ( $atts->{"source-".$num} ne "" ) {
|
||||
|
||||
if ($region_length > $self->{Sources}->{$atts->{"source-".$num}}->{calculated_length} ) {
|
||||
$self->{Sources}->{$atts->{"source-".$num}}->{calculated_length} = $region_length;
|
||||
}
|
||||
|
||||
$num++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $element->{Name} eq "Regions") {
|
||||
$self->{InRegions} = 1;
|
||||
#print "In regions\n";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
sub end_element {
|
||||
my $self = shift;
|
||||
my $element = shift;
|
||||
|
||||
if ( $element->{Name} eq "Regions") {
|
||||
$self->{InRegions} = 0;
|
||||
#print "Out of regions\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
||||
BIN
tools/Spotlight Importer/English.lproj/InfoPlist.strings
Normal file
BIN
tools/Spotlight Importer/English.lproj/InfoPlist.strings
Normal file
Binary file not shown.
BIN
tools/Spotlight Importer/English.lproj/schema.strings
Normal file
BIN
tools/Spotlight Importer/English.lproj/schema.strings
Normal file
Binary file not shown.
56
tools/Spotlight Importer/GetMetadataForFile.c
Normal file
56
tools/Spotlight Importer/GetMetadataForFile.c
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Step 1
|
||||
Set the UTI types the importer supports
|
||||
|
||||
Modify the CFBundleDocumentTypes entry in Info.plist to contain
|
||||
an array of Uniform Type Identifiers (UTI) for the LSItemContentTypes
|
||||
that your importer can handle
|
||||
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Step 2
|
||||
Implement the GetMetadataForFile function
|
||||
|
||||
Implement the GetMetadataForFile function below to scrape the relevant
|
||||
metadata from your document and return it as a CFDictionary using standard keys
|
||||
(defined in MDItem.h) whenever possible.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Step 3 (optional)
|
||||
If you have defined new attributes, update the schema.xml file
|
||||
|
||||
Edit the schema.xml file to include the metadata keys that your importer returns.
|
||||
Add them to the <allattrs> and <displayattrs> elements.
|
||||
|
||||
Add any custom types that your importer requires to the <attributes> element
|
||||
|
||||
<attribute name="com_mycompany_metadatakey" type="CFString" multivalued="true"/>
|
||||
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Get metadata attributes from file
|
||||
|
||||
This function's job is to extract useful information your file format supports
|
||||
and return it as a dictionary
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
Boolean GetMetadataForFile(void* thisInterface,
|
||||
CFMutableDictionaryRef attributes,
|
||||
CFStringRef contentTypeUTI,
|
||||
CFStringRef pathToFile)
|
||||
{
|
||||
/* Pull any available metadata from the file at the specified path */
|
||||
/* Return the attribute keys and attribute values in the dict */
|
||||
/* Return TRUE if successful, FALSE if there was no data provided */
|
||||
|
||||
#warning To complete your importer please implement the function GetMetadataForFile in GetMetadataForFile.c
|
||||
return FALSE;
|
||||
}
|
||||
87
tools/Spotlight Importer/Info.plist
Normal file
87
tools/Spotlight Importer/Info.plist
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<?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>
|
||||
|
||||
<!--
|
||||
If your application does not already define a UTI, you may want to declare it
|
||||
here, so that your documents are recognized by systems which do not have your
|
||||
application installed.
|
||||
|
||||
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>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>http://www.ardour.org</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Your Document Kind String</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
<string>public.content</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>com.apple.ostype</key>
|
||||
<string>XXXX</string>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>xxxx</string>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
-->
|
||||
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>MDImporter</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>SUPPORTED_UTI_TYPE</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.yourcfbundle</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>CFPlugInDynamicRegisterFunction</key>
|
||||
<string></string>
|
||||
<key>CFPlugInDynamicRegistration</key>
|
||||
<string>NO</string>
|
||||
<key>CFPlugInFactories</key>
|
||||
<dict>
|
||||
<key>D77F8126-18F0-4ADE-917C-4A234A5590B9</key>
|
||||
<string>MetadataImporterPluginFactory</string>
|
||||
</dict>
|
||||
<key>CFPlugInTypes</key>
|
||||
<dict>
|
||||
<key>8B08C4BF-415B-11D8-B3F9-0003936726FC</key>
|
||||
<array>
|
||||
<string>D77F8126-18F0-4ADE-917C-4A234A5590B9</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>CFPlugInUnloadFunction</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 42;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2C05A19C06CAA52B00D84F6F /* GetMetadataForFile.c in Sources */ = {isa = PBXBuildFile; fileRef = 2C05A19B06CAA52B00D84F6F /* GetMetadataForFile.c */; };
|
||||
8D576312048677EA00EA77CD /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 08FB77B6FE84183AC02AAC07 /* main.c */; settings = {ATTRIBUTES = (); }; };
|
||||
8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; };
|
||||
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; };
|
||||
C86B05270671AA6E00DD9006 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C86B05260671AA6E00DD9006 /* CoreServices.framework */; };
|
||||
C88FB7D8067446EC006EBB30 /* schema.xml in Resources */ = {isa = PBXBuildFile; fileRef = C88FB7D7067446EC006EBB30 /* schema.xml */; };
|
||||
C88FB7E40674480E006EBB30 /* schema.strings in Resources */ = {isa = PBXBuildFile; fileRef = C88FB7E30674480E006EBB30 /* schema.strings */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
08FB77B6FE84183AC02AAC07 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
|
||||
0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
|
||||
2C05A19B06CAA52B00D84F6F /* GetMetadataForFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = GetMetadataForFile.c; sourceTree = "<group>"; };
|
||||
8D576316048677EA00EA77CD /* Spotlight Importer.mdimporter */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Spotlight Importer.mdimporter"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
C86B05260671AA6E00DD9006 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
|
||||
C88FB7D7067446EC006EBB30 /* schema.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = schema.xml; sourceTree = "<group>"; };
|
||||
C88FB7DB0674470F006EBB30 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/schema.strings; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
8D576313048677EA00EA77CD /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */,
|
||||
C86B05270671AA6E00DD9006 /* CoreServices.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
089C166AFE841209C02AAC07 /* Spotlight Importer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
08FB77AFFE84173DC02AAC07 /* Source */,
|
||||
089C167CFE841241C02AAC07 /* Resources */,
|
||||
089C1671FE841209C02AAC07 /* External Frameworks and Libraries */,
|
||||
19C28FB6FE9D52B211CA2CBB /* Products */,
|
||||
);
|
||||
name = "Spotlight Importer";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
089C1671FE841209C02AAC07 /* External Frameworks and Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C86B05260671AA6E00DD9006 /* CoreServices.framework */,
|
||||
0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */,
|
||||
);
|
||||
name = "External Frameworks and Libraries";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
089C167CFE841241C02AAC07 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C88FB7E30674480E006EBB30 /* schema.strings */,
|
||||
C88FB7D7067446EC006EBB30 /* schema.xml */,
|
||||
8D576317048677EA00EA77CD /* Info.plist */,
|
||||
8D5B49A704867FD3000E48DA /* InfoPlist.strings */,
|
||||
);
|
||||
name = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
08FB77AFFE84173DC02AAC07 /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2C05A19B06CAA52B00D84F6F /* GetMetadataForFile.c */,
|
||||
08FB77B6FE84183AC02AAC07 /* main.c */,
|
||||
);
|
||||
name = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
19C28FB6FE9D52B211CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8D576316048677EA00EA77CD /* Spotlight Importer.mdimporter */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
8D57630E048677EA00EA77CD /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
8D57630D048677EA00EA77CD /* Spotlight Importer */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 70138C840896BE9A00968C2F /* Build configuration list for PBXNativeTarget "Spotlight Importer" */;
|
||||
buildPhases = (
|
||||
8D57630E048677EA00EA77CD /* Headers */,
|
||||
8D57630F048677EA00EA77CD /* Resources */,
|
||||
8D576311048677EA00EA77CD /* Sources */,
|
||||
8D576313048677EA00EA77CD /* Frameworks */,
|
||||
8D576315048677EA00EA77CD /* Rez */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "Spotlight Importer";
|
||||
productInstallPath = /Library/Spotlight;
|
||||
productName = "Spotlight Importer";
|
||||
productReference = 8D576316048677EA00EA77CD /* Spotlight Importer.mdimporter */;
|
||||
productType = "com.apple.product-type.bundle";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
089C1669FE841209C02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 70138C880896BE9A00968C2F /* Build configuration list for PBXProject "Spotlight Importer" */;
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 089C166AFE841209C02AAC07 /* Spotlight Importer */;
|
||||
projectDirPath = "";
|
||||
targets = (
|
||||
8D57630D048677EA00EA77CD /* Spotlight Importer */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
8D57630F048677EA00EA77CD /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */,
|
||||
C88FB7D8067446EC006EBB30 /* schema.xml in Resources */,
|
||||
C88FB7E40674480E006EBB30 /* schema.strings in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXRezBuildPhase section */
|
||||
8D576315048677EA00EA77CD /* Rez */ = {
|
||||
isa = PBXRezBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXRezBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
8D576311048677EA00EA77CD /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
8D576312048677EA00EA77CD /* main.c in Sources */,
|
||||
2C05A19C06CAA52B00D84F6F /* GetMetadataForFile.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
8D5B49A704867FD3000E48DA /* InfoPlist.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
089C167EFE841241C02AAC07 /* English */,
|
||||
);
|
||||
name = InfoPlist.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
C88FB7E30674480E006EBB30 /* schema.strings */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
C88FB7DB0674470F006EBB30 /* English */,
|
||||
);
|
||||
name = schema.strings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
70138C850896BE9A00968C2F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_FIX_AND_CONTINUE = YES;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = NO;
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = /Library/Spotlight;
|
||||
LIBRARY_STYLE = Bundle;
|
||||
PRODUCT_NAME = "Spotlight Importer";
|
||||
WRAPPER_EXTENSION = mdimporter;
|
||||
ZERO_LINK = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
70138C860896BE9A00968C2F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = (
|
||||
ppc,
|
||||
i386,
|
||||
);
|
||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||
GCC_MODEL_TUNING = G5;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = NO;
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = /Library/Spotlight;
|
||||
LIBRARY_STYLE = Bundle;
|
||||
PRODUCT_NAME = "Spotlight Importer";
|
||||
WRAPPER_EXTENSION = mdimporter;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
70138C890896BE9A00968C2F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
70138C8A0896BE9A00968C2F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
70138C840896BE9A00968C2F /* Build configuration list for PBXNativeTarget "Spotlight Importer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
70138C850896BE9A00968C2F /* Debug */,
|
||||
70138C860896BE9A00968C2F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
70138C880896BE9A00968C2F /* Build configuration list for PBXProject "Spotlight Importer" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
70138C890896BE9A00968C2F /* Debug */,
|
||||
70138C8A0896BE9A00968C2F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 089C1669FE841209C02AAC07 /* Project object */;
|
||||
}
|
||||
225
tools/Spotlight Importer/main.c
Normal file
225
tools/Spotlight Importer/main.c
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
//
|
||||
// main.c
|
||||
// Spotlight Importer
|
||||
//
|
||||
// Created by Taybin on 1/24/07.
|
||||
// Copyright (c) 2007 Penguin Sounds. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// DO NO MODIFY THE CONTENT OF THIS FILE
|
||||
//
|
||||
// This file contains the generic CFPlug-in code necessary for your importer
|
||||
// To complete your importer implement the function in GetMetadataForFile.c
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreFoundation/CFPlugInCOM.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// constants
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#define PLUGIN_ID "D77F8126-18F0-4ADE-917C-4A234A5590B9"
|
||||
|
||||
//
|
||||
// Below is the generic glue code for all plug-ins.
|
||||
//
|
||||
// You should not have to modify this code aside from changing
|
||||
// names if you decide to change the names defined in the Info.plist
|
||||
//
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// typedefs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// The import function to be implemented in GetMetadataForFile.c
|
||||
Boolean GetMetadataForFile(void *thisInterface,
|
||||
CFMutableDictionaryRef attributes,
|
||||
CFStringRef contentTypeUTI,
|
||||
CFStringRef pathToFile);
|
||||
|
||||
// The layout for an instance of MetaDataImporterPlugIn
|
||||
typedef struct __MetadataImporterPluginType
|
||||
{
|
||||
MDImporterInterfaceStruct *conduitInterface;
|
||||
CFUUIDRef factoryID;
|
||||
UInt32 refCount;
|
||||
} MetadataImporterPluginType;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// prototypes
|
||||
// -----------------------------------------------------------------------------
|
||||
// Forward declaration for the IUnknown implementation.
|
||||
//
|
||||
|
||||
MetadataImporterPluginType *AllocMetadataImporterPluginType(CFUUIDRef inFactoryID);
|
||||
void DeallocMetadataImporterPluginType(MetadataImporterPluginType *thisInstance);
|
||||
HRESULT MetadataImporterQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv);
|
||||
void *MetadataImporterPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID);
|
||||
ULONG MetadataImporterPluginAddRef(void *thisInstance);
|
||||
ULONG MetadataImporterPluginRelease(void *thisInstance);
|
||||
// -----------------------------------------------------------------------------
|
||||
// testInterfaceFtbl definition
|
||||
// -----------------------------------------------------------------------------
|
||||
// The TestInterface function table.
|
||||
//
|
||||
|
||||
static MDImporterInterfaceStruct testInterfaceFtbl = {
|
||||
NULL,
|
||||
MetadataImporterQueryInterface,
|
||||
MetadataImporterPluginAddRef,
|
||||
MetadataImporterPluginRelease,
|
||||
GetMetadataForFile
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// AllocMetadataImporterPluginType
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility function that allocates a new instance.
|
||||
// You can do some initial setup for the importer here if you wish
|
||||
// like allocating globals etc...
|
||||
//
|
||||
MetadataImporterPluginType *AllocMetadataImporterPluginType(CFUUIDRef inFactoryID)
|
||||
{
|
||||
MetadataImporterPluginType *theNewInstance;
|
||||
|
||||
theNewInstance = (MetadataImporterPluginType *)malloc(sizeof(MetadataImporterPluginType));
|
||||
memset(theNewInstance,0,sizeof(MetadataImporterPluginType));
|
||||
|
||||
/* Point to the function table */
|
||||
theNewInstance->conduitInterface = &testInterfaceFtbl;
|
||||
|
||||
/* Retain and keep an open instance refcount for each factory. */
|
||||
theNewInstance->factoryID = CFRetain(inFactoryID);
|
||||
CFPlugInAddInstanceForFactory(inFactoryID);
|
||||
|
||||
/* This function returns the IUnknown interface so set the refCount to one. */
|
||||
theNewInstance->refCount = 1;
|
||||
return theNewInstance;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// DeallocSpotlight_ImporterMDImporterPluginType
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility function that deallocates the instance when
|
||||
// the refCount goes to zero.
|
||||
// In the current implementation importer interfaces are never deallocated
|
||||
// but implement this as this might change in the future
|
||||
//
|
||||
void DeallocMetadataImporterPluginType(MetadataImporterPluginType *thisInstance)
|
||||
{
|
||||
CFUUIDRef theFactoryID;
|
||||
|
||||
theFactoryID = thisInstance->factoryID;
|
||||
free(thisInstance);
|
||||
if (theFactoryID){
|
||||
CFPlugInRemoveInstanceForFactory(theFactoryID);
|
||||
CFRelease(theFactoryID);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MetadataImporterQueryInterface
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation of the IUnknown QueryInterface function.
|
||||
//
|
||||
HRESULT MetadataImporterQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv)
|
||||
{
|
||||
CFUUIDRef interfaceID;
|
||||
|
||||
interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid);
|
||||
|
||||
if (CFEqual(interfaceID,kMDImporterInterfaceID)){
|
||||
/* If the Right interface was requested, bump the ref count,
|
||||
* set the ppv parameter equal to the instance, and
|
||||
* return good status.
|
||||
*/
|
||||
((MetadataImporterPluginType*)thisInstance)->conduitInterface->AddRef(thisInstance);
|
||||
*ppv = thisInstance;
|
||||
CFRelease(interfaceID);
|
||||
return S_OK;
|
||||
}else{
|
||||
if (CFEqual(interfaceID,IUnknownUUID)){
|
||||
/* If the IUnknown interface was requested, same as above. */
|
||||
((MetadataImporterPluginType*)thisInstance )->conduitInterface->AddRef(thisInstance);
|
||||
*ppv = thisInstance;
|
||||
CFRelease(interfaceID);
|
||||
return S_OK;
|
||||
}else{
|
||||
/* Requested interface unknown, bail with error. */
|
||||
*ppv = NULL;
|
||||
CFRelease(interfaceID);
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// MetadataImporterPluginAddRef
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation of reference counting for this type. Whenever an interface
|
||||
// is requested, bump the refCount for the instance. NOTE: returning the
|
||||
// refcount is a convention but is not required so don't rely on it.
|
||||
//
|
||||
ULONG MetadataImporterPluginAddRef(void *thisInstance)
|
||||
{
|
||||
((MetadataImporterPluginType *)thisInstance )->refCount += 1;
|
||||
return ((MetadataImporterPluginType*) thisInstance)->refCount;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SampleCMPluginRelease
|
||||
// -----------------------------------------------------------------------------
|
||||
// When an interface is released, decrement the refCount.
|
||||
// If the refCount goes to zero, deallocate the instance.
|
||||
//
|
||||
ULONG MetadataImporterPluginRelease(void *thisInstance)
|
||||
{
|
||||
((MetadataImporterPluginType*)thisInstance)->refCount -= 1;
|
||||
if (((MetadataImporterPluginType*)thisInstance)->refCount == 0){
|
||||
DeallocMetadataImporterPluginType((MetadataImporterPluginType*)thisInstance );
|
||||
return 0;
|
||||
}else{
|
||||
return ((MetadataImporterPluginType*) thisInstance )->refCount;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Spotlight_ImporterMDImporterPluginFactory
|
||||
// -----------------------------------------------------------------------------
|
||||
// Implementation of the factory function for this type.
|
||||
//
|
||||
void *MetadataImporterPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID)
|
||||
{
|
||||
MetadataImporterPluginType *result;
|
||||
CFUUIDRef uuid;
|
||||
|
||||
/* If correct type is being requested, allocate an
|
||||
* instance of TestType and return the IUnknown interface.
|
||||
*/
|
||||
if (CFEqual(typeID,kMDImporterTypeID)){
|
||||
uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID));
|
||||
result = AllocMetadataImporterPluginType(uuid);
|
||||
CFRelease(uuid);
|
||||
return result;
|
||||
}
|
||||
/* If the requested type is incorrect, return NULL. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
29
tools/Spotlight Importer/schema.xml
Normal file
29
tools/Spotlight Importer/schema.xml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<schema version="1.0" xmlns="http://www.apple.com/metadata"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.apple.com/metadata file:///System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/MetadataSchema.xsd">
|
||||
<note>
|
||||
Custom attributes that this metadata importer supports. Below
|
||||
is an example of a multivalued string attribute. Other types
|
||||
are CFNumber, CFDate, CFBoolean and CFData.
|
||||
</note>
|
||||
<attributes>
|
||||
<attribute name="com_Foo_YourAttrName" multivalued="true" type="CFString"/>
|
||||
</attributes>
|
||||
|
||||
<types>
|
||||
<type name="SUPPORTED_UTI_TYPE">
|
||||
<note>
|
||||
The keys that this metadata importer handles.
|
||||
</note>
|
||||
<allattrs>
|
||||
com_Foo_YourAttrName
|
||||
</allattrs>
|
||||
<displayattrs>
|
||||
com_Foo_YourAttrName
|
||||
</displayattrs>
|
||||
</type>
|
||||
</types>
|
||||
</schema>
|
||||
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
# Ruby script for pulling together a MacOSX app bundle.
|
||||
|
||||
# it will be either powerpc or i386
|
||||
versionline = `grep -m 1 '^version =' ../../SConstruct`
|
||||
versionline = `grep -m 1 '^ardour_version =' ../../SConstruct`
|
||||
version = versionline.split(" = ")[1].chomp().slice(1..-2)
|
||||
$stdout.printf("Version is %s\n", version)
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ end
|
|||
odir = Dir.getwd
|
||||
Dir.chdir("../..")
|
||||
|
||||
result = `otool -L gtk2_ardour/ardour.bin`
|
||||
result = `otool -L gtk2_ardour/ardour-#{version}`
|
||||
results = result.split("\n")
|
||||
results.delete_at(0)
|
||||
|
||||
|
|
@ -101,12 +101,12 @@ end
|
|||
|
||||
Dir.chdir(odir)
|
||||
|
||||
# copy ardour.bin to bindir/ardour
|
||||
# copy ardour binary to bindir/ardour
|
||||
|
||||
|
||||
if File.exist?("../../gtk2_ardour/ardour.bin") then
|
||||
if File.exist?("../../gtk2_ardour/ardour-#{version}") then
|
||||
$stdout.print("Copying bin to #{bindir} ...\n");
|
||||
`cp ../../gtk2_ardour/ardour.bin #{bindir}/ardour`
|
||||
`cp ../../gtk2_ardour/ardour-#{version} #{bindir}/ardour`
|
||||
end
|
||||
|
||||
`cp ../../libs/surfaces/*/*.dylib #{libdir}/surfaces`
|
||||
|
|
|
|||
|
|
@ -323,6 +323,17 @@ style "ardour_adjusters" = "default_buttons_menus"
|
|||
bg[ACTIVE] = { 0.06, 0.06, 0.06 }
|
||||
}
|
||||
|
||||
style "editor_hscrollbar" = "ardour_adjusters"
|
||||
{
|
||||
#
|
||||
# special case: we want this scrollbar to be as tall as the
|
||||
# zoom focus selector combobox. scrollbars don't expand to
|
||||
# fill the space available to them, so we have to explicitly
|
||||
# make it bigger.
|
||||
#
|
||||
GtkRange::slider_width = 27
|
||||
}
|
||||
|
||||
style "ardour_progressbars" = "default_buttons_menus"
|
||||
{
|
||||
bg[NORMAL] = { 0, 0, 0 }
|
||||
|
|
@ -658,27 +669,44 @@ style "edit_group_3"
|
|||
bg[SELECTED] = { 0.93, 0.34, 0.08 }
|
||||
}
|
||||
|
||||
style "region_list_display" = "small_bold_text"
|
||||
style "treeview_parent_node"
|
||||
{
|
||||
fg[NORMAL] = { 0.80, 0.80, 0.80 }
|
||||
fg[ACTIVE] = { 0.80, 0.80, 0.80 }
|
||||
fg[SELECTED] = { 0.70, 0.70, 0.70 }
|
||||
bg[NORMAL] = { 0, 0, 0 }
|
||||
bg[ACTIVE] = { 0, 0, 0 }
|
||||
bg[SELECTED] = { 0, 0, 0 }
|
||||
base[NORMAL] = { 0, 0, 0 }
|
||||
base[ACTIVE] = { 0, 1, 0 }
|
||||
base[INSENSITIVE] = { 0, 0, 0 }
|
||||
base[SELECTED] = { 0.80, 0.80, 0.80 }
|
||||
# specifies *just* the color used for whole file rows when not selected
|
||||
fg[NORMAL] = { 0.0, 0.6, 0.85 }
|
||||
}
|
||||
|
||||
style "treeview_display" = "small_bold_text"
|
||||
{
|
||||
# expander arrow border and DnD "icon" text
|
||||
fg[NORMAL] = { 0.8, 0.8, 0.8 }
|
||||
|
||||
# background with no rows or no selection, plus
|
||||
# expander arrow core and DnD "icon" background
|
||||
base[NORMAL] = { 0.20, 0.20, 0.25 }
|
||||
|
||||
# selected row bg when window does not have focus (including during DnD)
|
||||
base[ACTIVE] = { 0.0, 0.60, 0.60 }
|
||||
|
||||
# selected row bg when window has focus
|
||||
base[SELECTED] = { 0, 0.75, 0.75 }
|
||||
|
||||
# row text when in normal state and not a parent
|
||||
text[NORMAL] = { 0.80, 0.80, 0.80 }
|
||||
|
||||
# selected row text with window focus
|
||||
text[SELECTED] = { 0, 1.0, 1.0 }
|
||||
|
||||
# selected row text without window focus (including during DnD)
|
||||
text[ACTIVE] = { 0, 1.0, 1.0 }
|
||||
}
|
||||
|
||||
style "main_canvas_area"
|
||||
{
|
||||
bg[NORMAL] = { 0.20, 0.20, 0.25 }
|
||||
bg[ACTIVE] = { 0.20, 0.20, 0.25 }
|
||||
bg[INSENSITIVE] = { 0.20, 0.20, 0.25 }
|
||||
bg[SELECTED] = { 0.20, 0.20, 0.25 }
|
||||
bg[PRELIGHT] = { 0.20, 0.20, 0.25 }
|
||||
bg[NORMAL] = { 0.30, 0.30, 0.34 }
|
||||
bg[ACTIVE] = { 0.30, 0.30, 0.34 }
|
||||
bg[INSENSITIVE] = { 0.30, 0.30, 0.34 }
|
||||
bg[SELECTED] = { 0.30, 0.30, 0.34 }
|
||||
bg[PRELIGHT] = { 0.30, 0.30, 0.34 }
|
||||
}
|
||||
|
||||
style "track_controls_inactive"
|
||||
|
|
@ -975,17 +1003,12 @@ style "pan_slider"
|
|||
|
||||
base[NORMAL] = { 0.80, 0.80, 0.80 }
|
||||
base[ACTIVE] = { 0.80, 0.80, 0.80 }
|
||||
base[INSENSITIVE] = {0.32, 0.39, 0.45 } # matches default_base
|
||||
base[INSENSITIVE] = {0.6, 0.6, 0.6 }
|
||||
base[SELECTED] = { 0.80, 0.80, 0.80 }
|
||||
base[PRELIGHT] = { 0.80, 0.80, 0.80 }
|
||||
|
||||
}
|
||||
|
||||
style "region_list_whole_file"
|
||||
{
|
||||
fg[NORMAL] = { 0.4, 0.4, 0.9 }
|
||||
}
|
||||
|
||||
style "ardour_button" ="default_buttons_menus"
|
||||
{
|
||||
xthickness = 1
|
||||
|
|
@ -1162,7 +1185,6 @@ 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 "*EditorRegionList" style "region_list_display"
|
||||
widget "*CrossfadeEditAuditionButton" style "red_when_active"
|
||||
widget "*CrossfadeEditAuditionButton*" style "red_when_active"
|
||||
widget "*CrossfadeEditCurveButton" style "red_when_active"
|
||||
|
|
@ -1197,19 +1219,19 @@ widget "*ParameterValueDisplay" style "medium_bold_entry"
|
|||
widget "*PluginUIClickBox" style "medium_bold_entry"
|
||||
widget "*PluginUIClickBox*" style "medium_bold_entry"
|
||||
widget "*PluginSlider" style "plugin_slider"
|
||||
widget "*TrackListDisplay" style "track_list_display"
|
||||
widget "*TrackListDisplay.*" style "small_bold_text"
|
||||
widget "*EditGroupList" style "track_list_display"
|
||||
widget "*RegionListDisplay" style "small_bold_entry"
|
||||
widget "*RegionListDisplay.*" style "small_bold_text"
|
||||
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 "track_list_display"
|
||||
widget "*MixerSnapshotDisplayList" style "track_list_display"
|
||||
widget "*MixerAuxDisplayList" style "track_list_display"
|
||||
widget "*MixerGroupList" style "track_list_display"
|
||||
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"
|
||||
|
|
@ -1336,7 +1358,8 @@ 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 "region_list_whole_file"
|
||||
widget "*RegionListWholeFile" style "treeview_parent_node"
|
||||
widget "*EditorHScrollbar" style "editor_hscrollbar"
|
||||
|
||||
class "GtkWidget" style "default_base"
|
||||
class "GtkScrollbar" style "ardour_adjusters"
|
||||
|
|
|
|||
856
tools/session_exchange.py
Executable file
856
tools/session_exchange.py
Executable file
|
|
@ -0,0 +1,856 @@
|
|||
#! /usr/bin/python
|
||||
|
||||
# Session Exchange
|
||||
# By Taybin Rutkin
|
||||
# Copyright 2004-2005, under the GPL
|
||||
|
||||
VERSION='0.1.2'
|
||||
|
||||
#twisted libraries
|
||||
from twisted.internet import gtk2reactor
|
||||
gtk2reactor.install()
|
||||
from twisted.internet import reactor, protocol
|
||||
import twisted.internet.error
|
||||
|
||||
#pygtk libraries
|
||||
import gobject
|
||||
import gtk
|
||||
|
||||
#standard python2.2 libraries
|
||||
import getopt
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import shelve
|
||||
import string
|
||||
import sys
|
||||
import xml.dom.minidom
|
||||
|
||||
def get_header_size(filename):
|
||||
size = 0
|
||||
file = open(filename, 'r')
|
||||
while True:
|
||||
chunk = file.read(4)
|
||||
size += 4
|
||||
if chunk == "data":
|
||||
file.close()
|
||||
return size + 4 #include the size chunk after "data"
|
||||
if not chunk:
|
||||
file.close()
|
||||
return None
|
||||
|
||||
def append_empty_data(self, filename, size):
|
||||
file = open(filename, 'a')
|
||||
file.seek(size-1)
|
||||
file.write('\x00')
|
||||
file.close()
|
||||
|
||||
def get_sound_list(snapshot):
|
||||
doc = xml.dom.minidom.parse(snapshot)
|
||||
|
||||
regionlist = []
|
||||
playlists_tag = doc.getElementsByTagName('Playlists')
|
||||
playlists = playlists_tag[0].getElementsByTagName('Playlist')
|
||||
for play in playlists:
|
||||
regions = play.getElementsByTagName('Region')
|
||||
for region in regions:
|
||||
regionlist.append(region.getAttribute('source-0'))
|
||||
regionlist.append(region.getAttribute('source-1'))
|
||||
regionlist.append(region.getAttribute('source-2'))
|
||||
regionlist.append(region.getAttribute('source-3'))
|
||||
regionlist.append(region.getAttribute('source-4'))
|
||||
regionlist.append(region.getAttribute('source-5'))
|
||||
|
||||
sourcelist = {}
|
||||
sources = doc.getElementsByTagName('Source')
|
||||
for source in sources:
|
||||
sourcelist[source.getAttribute('id')] = str(source.getAttribute('name'))
|
||||
|
||||
soundlist = []
|
||||
for id in regionlist:
|
||||
if sourcelist.has_key(id):
|
||||
soundlist.append(sourcelist[id])
|
||||
|
||||
return soundlist
|
||||
|
||||
def raise_error(string, parent):
|
||||
dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, string)
|
||||
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
class Data(object):
|
||||
def delete_snap(self, session, collab, snap):
|
||||
sessions = self._data['sessions']
|
||||
sessions[session]['collabs'][collab]['snaps'].remove(snap)
|
||||
self._data['sessions'] = sessions
|
||||
|
||||
def delete_collab(self,session, collab):
|
||||
sessions = self._data['sessions']
|
||||
del sessions[session]['collabs'][collab]
|
||||
self._data['sessions'] = sessions
|
||||
|
||||
def delete_session(self, session):
|
||||
sessions = self._data['sessions']
|
||||
del sessions[session]
|
||||
self._data['sessions'] = sessions
|
||||
|
||||
def add_snap(self, session_name, collab_name, snap_name):
|
||||
sessions = self._data['sessions']
|
||||
sessions[session_name]['collabs'][collab_name]['snaps'].append(snap_name)
|
||||
sessions[session_name]['collabs'][collab_name]['snaps'].sort()
|
||||
self._data['sessions'] = sessions
|
||||
|
||||
g_display.update_snap_view()
|
||||
|
||||
def add_collab(self, session_name, collab_name, ip_address, port):
|
||||
sessions = self._data['sessions']
|
||||
sessions[session_name]['collabs'][collab_name] = {}
|
||||
sessions[session_name]['collabs'][collab_name]['snaps'] = []
|
||||
sessions[session_name]['collabs'][collab_name]['sounds'] = []
|
||||
sessions[session_name]['collabs'][collab_name]['ip'] = ip_address
|
||||
sessions[session_name]['collabs'][collab_name]['port'] = port
|
||||
self._data['sessions'] = sessions
|
||||
|
||||
client = ExchangeClientFactory(session_name, collab_name, None, self.debug_mode)
|
||||
reactor.connectTCP(ip_address, port, client)
|
||||
g_display.show_status("connecting")
|
||||
|
||||
g_display.update_collab_view()
|
||||
|
||||
def add_session(self, session_path):
|
||||
sessions = self._data['sessions']
|
||||
|
||||
session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: -1]
|
||||
sessions[session_name] = {}
|
||||
sessions[session_name]['path'] = session_path
|
||||
sessions[session_name]['collabs'] = {}
|
||||
sessions[session_name]['collabs'][self._data['user']] = {}
|
||||
sessions[session_name]['collabs'][self._data['user']]['snaps'] = []
|
||||
sessions[session_name]['collabs'][self._data['user']]['sounds'] = []
|
||||
|
||||
self._data['sessions'] = sessions
|
||||
|
||||
self.rescan_session(session_name)
|
||||
|
||||
def rescan_session(self, session_name):
|
||||
sessions = self._data['sessions']
|
||||
|
||||
session_path = sessions[session_name]['path']
|
||||
sessions[session_name]['collabs'][self._data['user']]['snaps'] = self._scan_snapshots(session_path)
|
||||
sessions[session_name]['collabs'][self._data['user']]['sounds'] = self._scan_sounds(session_path)
|
||||
|
||||
self._data['sessions'] = sessions
|
||||
|
||||
g_display.update_snap_view()
|
||||
|
||||
print self._data['sessions']
|
||||
|
||||
def create_session(self, session_path):
|
||||
try:
|
||||
os.mkdir(session_path)
|
||||
os.mkdir(session_path+"/sounds")
|
||||
except OSError:
|
||||
raise_error("Could not create session directory", g_display.window)
|
||||
return
|
||||
|
||||
sessions = self._data['sessions']
|
||||
|
||||
session_name = session_path[session_path.rfind('/', 0, len(session_path)-2)+1: ]
|
||||
sessions[session_name] = {}
|
||||
sessions[session_name]['path'] = session_path
|
||||
sessions[session_name]['collabs'] = {}
|
||||
sessions[session_name]['collabs'][self._data['user']] = {}
|
||||
sessions[session_name]['collabs'][self._data['user']]['snaps'] = []
|
||||
sessions[session_name]['collabs'][self._data['user']]['sounds'] = []
|
||||
|
||||
self._data['sessions'] = sessions
|
||||
print self._data['sessions']
|
||||
|
||||
def get_session_path(self, session):
|
||||
sessions = self._data['sessions']
|
||||
return sessions[session]['path']
|
||||
|
||||
def get_user(self):
|
||||
return self._data['user']
|
||||
|
||||
def set_user(self, username):
|
||||
self._data['user'] = username
|
||||
|
||||
def get_collab_ip(self, session, collab):
|
||||
sessions = self._data['sessions']
|
||||
return sessions[session]['collabs'][collab]['ip']
|
||||
|
||||
def close(self):
|
||||
self._data.close()
|
||||
|
||||
def get_sessions(self):
|
||||
sessions = self._data['sessions']
|
||||
sess = sessions.keys()
|
||||
sess.sort()
|
||||
return sess
|
||||
|
||||
def get_collabs(self, session):
|
||||
if session:
|
||||
sessions = self._data['sessions']
|
||||
collabs = sessions[session]['collabs'].keys()
|
||||
collabs.sort()
|
||||
return collabs
|
||||
else:
|
||||
return []
|
||||
|
||||
def get_snaps(self, session, collab):
|
||||
if session and collab:
|
||||
sessions = self._data['sessions']
|
||||
snaps = sessions[session]['collabs'][collab]['snaps']
|
||||
snaps.sort()
|
||||
return snaps
|
||||
else:
|
||||
return []
|
||||
|
||||
def get_sounds(self, session, collab):
|
||||
if session and collab:
|
||||
sessions = self._data['sessions']
|
||||
sounds = sessions[session]['collabs'][self._data['user']]['sounds']
|
||||
sounds.sort()
|
||||
return sounds
|
||||
else:
|
||||
return []
|
||||
|
||||
def _scan_snapshots(self, session):
|
||||
snaps = []
|
||||
files = os.listdir(session)
|
||||
pattern = re.compile(r'\.ardour$')
|
||||
for file in files:
|
||||
if pattern.search(file):
|
||||
snaps.append(file[0:-7])
|
||||
print file[0:-7]
|
||||
return snaps
|
||||
|
||||
def _scan_sounds(self, session):
|
||||
sounds = []
|
||||
files = os.listdir(session+'/sounds')
|
||||
pattern = re.compile(r'\.peak$')
|
||||
for file in files:
|
||||
if not pattern.search(file):
|
||||
sounds.append(file)
|
||||
return sounds
|
||||
|
||||
def __init__(self, *args):
|
||||
self._data = shelve.open(os.path.expanduser('~/.session_exchange'), 'c')
|
||||
self.port = 8970
|
||||
self.debug_mode = False
|
||||
if len(self._data.keys()) < 1:
|
||||
self._data['sessions'] = {}
|
||||
self._data['user'] = ''
|
||||
|
||||
self._collabs = {}
|
||||
|
||||
from twisted.protocols.basic import FileSender
|
||||
class FileSenderLimited(FileSender):
|
||||
def beginFileTransfer(self, file, consumer, limit, transform = None):
|
||||
self.file = file
|
||||
self.consumer = consumer
|
||||
self.CHUNK_SIZE = limit
|
||||
self.transform = transform
|
||||
|
||||
self.consumer.registerProducer(self, False)
|
||||
self.deferred = defer.Deferred()
|
||||
return self.deferred
|
||||
|
||||
def resumeProducing(self):
|
||||
chunk = ''
|
||||
chunk = self.file.read(self.CHUNK_SIZE)
|
||||
|
||||
if self.transform:
|
||||
chunk = self.transform(chunk)
|
||||
|
||||
self.consumer.write(chunk)
|
||||
self.lastSent = chunk[-1]
|
||||
self.file = None
|
||||
self.consumer.unregisterProducer()
|
||||
self.deferred.callback(self.lastSent)
|
||||
self.deferred = None
|
||||
|
||||
from twisted.protocols.basic import LineReceiver
|
||||
class ExchangeServer (LineReceiver):
|
||||
def __init__(self):
|
||||
self.state = "IDLE"
|
||||
|
||||
def error(self, message):
|
||||
self.sendLine("ERROR")
|
||||
self.sendLine(message)
|
||||
self.transport.loseConnection()
|
||||
|
||||
def connectionLost(self, reason):
|
||||
print "server: connection lost: ", reason
|
||||
|
||||
def connectionMade(self):
|
||||
print "server: connection made"
|
||||
|
||||
def lineReceived(self, data):
|
||||
print "server: ", data
|
||||
|
||||
if self.state == "SESSION":
|
||||
if g_data.get_sessions().count(data):
|
||||
self.session_name = data
|
||||
self.state = "IDLE"
|
||||
self.sendLine("OK")
|
||||
else:
|
||||
self.error(data + " doesn't exist on server")
|
||||
elif self.state == "SNAPSHOT":
|
||||
if g_data.get_snaps(self.session_name, g_data.get_user()).count(data):
|
||||
filename = g_data.get_session_path(self.session_name)+data+'.ardour'
|
||||
print filename
|
||||
self.sendLine(str(os.stat(filename).st_size))
|
||||
self.sendLine("OK")
|
||||
self.file = open(filename, 'r')
|
||||
file_sender = FileSender()
|
||||
cb = file_sender.beginFileTransfer(self.file, self.transport)
|
||||
cb.addCallback(self.file_done)
|
||||
else:
|
||||
self.error("snapshot: " + data + " doesn't exist on server")
|
||||
elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER":
|
||||
if g_data.get_sounds(self.session_name, g_data.get_user()).count(data):
|
||||
filename = g_data.get_session_path(self.session_name)+"/sounds/"+data
|
||||
print filename
|
||||
if self.state == "SOUNDFILE":
|
||||
self.sendLine(str(os.stat(filename).st_size))
|
||||
else: #SOUNDFILE_HEADER
|
||||
header_size = get_header_size(filename)
|
||||
if header_size:
|
||||
self.sendLine(str(header_size))
|
||||
else:
|
||||
self.error('soundfile: ' + data + 'doesn\'t have "data" chunk')
|
||||
self.sendLine("OK")
|
||||
self.file = open(filename, 'r')
|
||||
if self.state == "SOUNDFILE":
|
||||
file_sender = FileSender()
|
||||
cb = file_sender.beginFileTransfer(self.file, self.transport)
|
||||
else: # SOUNDFILE_HEADER
|
||||
file_sender = FileSenderLimited()
|
||||
cb = file_sender.beginFileTransfer(self.file, self.transport, header_size)
|
||||
cb.addCallback(self.file_done)
|
||||
else:
|
||||
self.error("soundfile: " + data + "doesn't exist on server")
|
||||
elif self.state == "SOUNDFILE_SIZE":
|
||||
if g_data.get_sounds(self.session_name, g_data.get_user()).count(data):
|
||||
filename = g_data.get_session_path(self.session_name)+"/sounds/"+data
|
||||
print filename
|
||||
self.sendLine(str(os.stat(filename).st_size))
|
||||
self.state = "IDLE"
|
||||
elif data == "SESSION":
|
||||
self.state = "SESSION"
|
||||
elif data == "SNAPS":
|
||||
self.state = "SNAPS"
|
||||
for snap in g_data.get_snaps(self.session_name, g_data.get_user()):
|
||||
self.sendLine(snap)
|
||||
self.sendLine("OK")
|
||||
self.state = "IDLE"
|
||||
elif data == "SNAPSHOT":
|
||||
self.state = "SNAPSHOT"
|
||||
elif data == "SOUNDFILE":
|
||||
self.state = "SOUNDFILE"
|
||||
elif data == "SOUNDFILE_HEADER":
|
||||
self.state = "SOUNDFILE_HEADER"
|
||||
elif data == "SOUNDFILE_SIZE":
|
||||
self.state = "SOUNDFILE_SIZE"
|
||||
|
||||
def file_done(self, data):
|
||||
print "server: file done"
|
||||
self.file.close()
|
||||
self.state = "IDLE"
|
||||
|
||||
class ExchangeServerFactory(protocol.ServerFactory):
|
||||
protocol = ExchangeServer
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
class ExchangeClient (LineReceiver):
|
||||
def __init__(self, session_name, collab_name, snap_name, debug_mode):
|
||||
self.session_name = session_name
|
||||
self.collab_name = collab_name
|
||||
self.snap_name = snap_name
|
||||
self.debug_mode = debug_mode
|
||||
self.state = "IDLE"
|
||||
|
||||
def connectionLost(self, reason):
|
||||
g_display.show_status("Connection lost")
|
||||
|
||||
def connectionMade(self):
|
||||
g_display.show_status("Connection made")
|
||||
self.state = "SESSION"
|
||||
self.sendLine("SESSION")
|
||||
self.sendLine(self.session_name)
|
||||
|
||||
def rawDataReceived(self, data):
|
||||
self.file.write(data)
|
||||
self.received += len(data)
|
||||
print self.received, self.filesize
|
||||
if self.received >= self.filesize:
|
||||
self.setLineMode()
|
||||
self.file.close()
|
||||
g_data.rescan_session(self.session_name)
|
||||
if self.state == "SNAPSHOT":
|
||||
self.sounds = get_sound_list(self.filename)
|
||||
if len(self.sounds):
|
||||
self.sound_index = 0
|
||||
if self.debug_mode:
|
||||
self.state = "SOUNDFILE_HEADER"
|
||||
self.sendLine("SOUNDFILE_HEADER")
|
||||
else:
|
||||
self.state = "SOUNDFILE"
|
||||
self.sendLine("SOUNDFILE")
|
||||
self.sendLine(self.sounds[self.sound_index])
|
||||
else:
|
||||
self.transport.loseConnection()
|
||||
elif self.state == "SOUNDFILE":
|
||||
self.sound_index += 1
|
||||
if self.sound_index > len(self.sounds)-1:
|
||||
self.transport.loseConnection()
|
||||
else:
|
||||
self.sendLine("SOUNDFILE")
|
||||
self.sendLine(self.sounds[self.sound_index])
|
||||
elif self.state == "SOUNDFILE_HEADER":
|
||||
self.state = "SOUNDFILE_SIZE"
|
||||
self.sendLine("SOUNDFILE_SIZE")
|
||||
self.sendLine(self.sounds[self.sound_index])
|
||||
|
||||
def lineReceived(self, data):
|
||||
print "client: ", data
|
||||
|
||||
if data == "ERROR":
|
||||
self.state = "ERROR"
|
||||
elif data == "OK":
|
||||
if self.state == "SESSION":
|
||||
if self.snap_name:
|
||||
self.state = "SNAPSHOT"
|
||||
self.sendLine("SNAPSHOT")
|
||||
self.sendLine(self.snap_name)
|
||||
else:
|
||||
self.state = "SNAPS"
|
||||
self.sendLine("SNAPS")
|
||||
elif self.state == "SNAPS":
|
||||
self.transport.loseConnection()
|
||||
elif self.state == "SNAPSHOT":
|
||||
self.setRawMode()
|
||||
self.filename = g_data.get_session_path(self.session_name)+'/'+self.snap_name+'.ardour'
|
||||
self.file = open(self.filename, 'w')
|
||||
self.received = 0
|
||||
elif self.state == "SOUNDFILE" or self.state == "SOUNDFILE_HEADER":
|
||||
self.setRawMode()
|
||||
self.filename = g_data.get_session_path(self.session_name)+'/sounds/'+self.sounds[self.sound_index]
|
||||
self.file = open(self.filename, 'w')
|
||||
self.received = 0
|
||||
elif self.state == "ERROR":
|
||||
raise_error(data, g_display.window)
|
||||
elif self.state == "SNAPS":
|
||||
g_data.add_snap(self.session_name, self.collab_name, data)
|
||||
elif self.state == "SNAPSHOT":
|
||||
self.filesize = int(data)
|
||||
elif self.state == "SOUNDFILE":
|
||||
self.filesize = int(data)
|
||||
elif self.state == "SOUNDFILE_HEADER":
|
||||
self.filesize = int(data)
|
||||
elif self.state == "SOUNDFILE_SIZE":
|
||||
append_empty_data(self.filename, int(data))
|
||||
self.sound_index += 1
|
||||
if self.sound_index > len(self.sounds)-1:
|
||||
self.transport.loseConnection()
|
||||
else:
|
||||
self.state = "SOUNDFILE_HEADER"
|
||||
self.sendLine("SOUNDFILE_HEADER")
|
||||
self.sendLine(self.sounds[self.sound_index])
|
||||
|
||||
class ExchangeClientFactory(protocol.ClientFactory):
|
||||
def buildProtocol(self, addr):
|
||||
return ExchangeClient(self.session_name, self.collab_name, self.snap_name, self.debug_mode)
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
raise_error('Connection failed: ' + reason.getErrorMessage(), g_display.window)
|
||||
g_display.show_status('Connection failed')
|
||||
|
||||
def __init__(self, session_name, collab_name, snap_name, debug_mode):
|
||||
self.session_name = session_name
|
||||
self.collab_name = collab_name
|
||||
self.snap_name = snap_name
|
||||
self.debug_mode = debug_mode
|
||||
|
||||
class HelperWin(object):
|
||||
def delete_me(self, window):
|
||||
self = 0
|
||||
|
||||
class Preferences(HelperWin):
|
||||
def __init__(self):
|
||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
self.window.set_title('Preferences')
|
||||
self.window.connect('destroy', self.delete_me)
|
||||
self.window.set_position(gtk.WIN_POS_MOUSE)
|
||||
|
||||
main_box = gtk.VBox()
|
||||
self.window.add(main_box)
|
||||
|
||||
hbox1 = gtk.HBox()
|
||||
label1 = gtk.Label("User")
|
||||
self.user = gtk.Entry()
|
||||
self.user.set_text(g_data.get_user())
|
||||
hbox1.pack_start(label1)
|
||||
hbox1.pack_start(self.user)
|
||||
main_box.pack_start(hbox1)
|
||||
|
||||
ok_btn = gtk.Button("Ok")
|
||||
ok_btn.connect('clicked', self.ok_clicked)
|
||||
main_box.pack_start(ok_btn)
|
||||
|
||||
self.window.show_all()
|
||||
|
||||
def ok_clicked(self, btn):
|
||||
g_data.set_user(self.user.get_text())
|
||||
self.window.hide_all()
|
||||
|
||||
def show_all(self):
|
||||
self.window.show_all()
|
||||
|
||||
class AddCollaborator(HelperWin):
|
||||
def __init__(self, session):
|
||||
self.session_name = session
|
||||
|
||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
self.window.set_title('Fetch Session')
|
||||
self.window.connect('destroy', self.delete_me)
|
||||
self.window.set_position(gtk.WIN_POS_MOUSE)
|
||||
|
||||
main_box = gtk.VBox()
|
||||
self.window.add(main_box)
|
||||
|
||||
hbox0 = gtk.HBox()
|
||||
label0 = gtk.Label("Collaborator")
|
||||
self.collab = gtk.Entry()
|
||||
self.collab.connect('key-release-event', self.key_press)
|
||||
hbox0.pack_start(label0)
|
||||
hbox0.pack_start(self.collab)
|
||||
main_box.pack_start(hbox0)
|
||||
|
||||
hbox1 = gtk.HBox()
|
||||
label1 = gtk.Label("IP Address")
|
||||
self.address = gtk.Entry()
|
||||
self.address.connect('key-release-event', self.key_press)
|
||||
hbox1.pack_start(label1)
|
||||
hbox1.pack_start(self.address)
|
||||
main_box.pack_start(hbox1)
|
||||
|
||||
hbox2 = gtk.HBox()
|
||||
label2 = gtk.Label("Port Number")
|
||||
self.port = gtk.Entry()
|
||||
self.port.connect('key-release-event', self.key_press)
|
||||
self.port.set_text(str(g_data.port))
|
||||
hbox2.pack_start(label2)
|
||||
hbox2.pack_start(self.port)
|
||||
main_box.pack_start(hbox2)
|
||||
|
||||
hbox3 = gtk.HBox()
|
||||
label3 = gtk.Label("Username")
|
||||
label3.set_sensitive(False)
|
||||
self.username = gtk.Entry()
|
||||
self.username.set_sensitive(False)
|
||||
hbox3.pack_start(label3)
|
||||
hbox3.pack_start(self.username)
|
||||
main_box.pack_start(hbox3)
|
||||
|
||||
hbox4 = gtk.HBox()
|
||||
label4 = gtk.Label("Password")
|
||||
label4.set_sensitive(False)
|
||||
self.password = gtk.Entry()
|
||||
self.password.set_sensitive(False)
|
||||
hbox4.pack_start(label4)
|
||||
hbox4.pack_start(self.password)
|
||||
main_box.pack_start(hbox4)
|
||||
|
||||
self.ok_btn = gtk.Button(gtk.STOCK_OK)
|
||||
self.ok_btn.set_use_stock(True)
|
||||
self.ok_btn.connect('clicked', self.ok_clicked)
|
||||
self.ok_btn.set_sensitive(False)
|
||||
main_box.pack_start(self.ok_btn)
|
||||
|
||||
self.window.show_all()
|
||||
|
||||
def key_press(self, event, data):
|
||||
if self.collab.get_text() and self.address.get_text() and self.port.get_text():
|
||||
self.ok_btn.set_sensitive(True)
|
||||
else:
|
||||
self.ok_btn.set_sensitive(False)
|
||||
return True
|
||||
|
||||
def ok_clicked(self, btn):
|
||||
self.window.hide_all()
|
||||
g_data.add_collab(self.session_name, self.collab.get_text(), self.address.get_text(), int(self.port.get_text()))
|
||||
self.collab.set_text('')
|
||||
self.address.set_text('')
|
||||
self.port.set_text('')
|
||||
self.username.set_text('')
|
||||
self.password.set_text('')
|
||||
|
||||
def show_all(self):
|
||||
self.window.show_all()
|
||||
|
||||
class ArdourShareWindow(object):
|
||||
def menuitem_cb(self, window, action, widget):
|
||||
print self, window, action, widget
|
||||
|
||||
def add_collaborator_cb(self, window, action, widget):
|
||||
if self.session:
|
||||
self.add_session = AddCollaborator(self.session)
|
||||
|
||||
def fetch_snapshot_cb(self, window, action, widget):
|
||||
if self.session and self.collab and self.collab != g_data.get_user():
|
||||
client = ExchangeClientFactory(self.session, self.collab, self.snap, g_data.debug_mode)
|
||||
reactor.connectTCP(g_data.get_collab_ip(self.session, self.collab), g_data.port, client)
|
||||
|
||||
def preferences_cb(self, window, action, widget):
|
||||
self.preferences = Preferences()
|
||||
|
||||
def add_session_ok_file_btn_clicked(self, w):
|
||||
filename = self.file_sel.get_filename()
|
||||
if filename.endswith(".ardour"):
|
||||
g_data.add_session(filename[0:filename.rfind("/")+1])
|
||||
self.update_session_view()
|
||||
else:
|
||||
raise_error("Not an Ardour session", self.window)
|
||||
self.file_sel.destroy()
|
||||
|
||||
def add_session_cb(self, window, action, widget):
|
||||
if g_data.get_user():
|
||||
self.file_sel = gtk.FileSelection("Add Session...")
|
||||
self.file_sel.ok_button.connect("clicked", self.add_session_ok_file_btn_clicked)
|
||||
self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy())
|
||||
self.file_sel.connect("destroy", lambda w: self.file_sel.destroy())
|
||||
self.file_sel.show()
|
||||
else:
|
||||
raise_error("Set the user name in the preferences first", self.window)
|
||||
|
||||
def create_session_cb(self, window, action, widget):
|
||||
if g_data.get_user():
|
||||
self.file_sel = gtk.FileSelection("Create Session...")
|
||||
self.file_sel.ok_button.connect("clicked", self.create_file_ok_btn_clicked)
|
||||
self.file_sel.cancel_button.connect("clicked", lambda w: self.file_sel.destroy())
|
||||
self.file_sel.connect("destroy", lambda w: self.file_sel.destroy())
|
||||
self.file_sel.show()
|
||||
else:
|
||||
raise_error("Set the user name in the preferences first", self.window)
|
||||
|
||||
def create_file_ok_btn_clicked(self, w):
|
||||
filename = self.file_sel.get_filename()
|
||||
if len(filename) > 0:
|
||||
g_data.create_session(filename)
|
||||
self.update_session_view()
|
||||
else:
|
||||
raise_error("Not an Ardour session", self.window)
|
||||
self.file_sel.destroy()
|
||||
|
||||
def update_session_view(self):
|
||||
self.session_model.clear()
|
||||
for session in g_data.get_sessions():
|
||||
self.session_model.set(self.session_model.append(), 0, session)
|
||||
|
||||
def update_collab_view(self):
|
||||
self.collab_model.clear()
|
||||
for collab in g_data.get_collabs(self.session):
|
||||
self.collab_model.set(self.collab_model.append(), 0, collab)
|
||||
|
||||
def update_snap_view(self):
|
||||
self.snap_model.clear()
|
||||
for snap in g_data.get_snaps(self.session, self.collab):
|
||||
self.snap_model.set(self.snap_model.append(), 0, snap)
|
||||
|
||||
def cb_session_selection_changed(self, selection_object):
|
||||
selected = []
|
||||
selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
|
||||
for x in selected:
|
||||
self.session = self.session_model[x][0]
|
||||
self.selected_type = "session"
|
||||
self.update_collab_view()
|
||||
|
||||
def cb_collab_selection_changed(self, selection_object):
|
||||
selected = []
|
||||
selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
|
||||
for x in selected:
|
||||
self.collab = self.collab_model[x][0]
|
||||
self.selected_type = "collab"
|
||||
self.update_snap_view()
|
||||
|
||||
def cb_snap_selection_changed(self, selection_object):
|
||||
selected = []
|
||||
selection_object.selected_foreach(lambda model, path, iter, sel = selected: sel.append(path))
|
||||
for x in selected:
|
||||
self.snap = self.snap_model[x][0]
|
||||
self.selected_type = "snap"
|
||||
|
||||
def delete_cb(self, window, action, widget):
|
||||
if self.selected_type == "session":
|
||||
g_data.delete_session(self.session)
|
||||
self.session = ""
|
||||
self.collab = ""
|
||||
self.snap = ""
|
||||
elif self.selected_type == "collab":
|
||||
g_data.delete_collab(self.session, self.collab)
|
||||
self.collab = ""
|
||||
self.snap = ""
|
||||
elif self.selected_type == "snap":
|
||||
g_data.delete_snap(self.session, self.collab, self.snap)
|
||||
self.snap = ""
|
||||
|
||||
self.update_session_view()
|
||||
self.update_collab_view()
|
||||
self.update_snap_view()
|
||||
self.selected_type = ""
|
||||
|
||||
def show_status(self, text):
|
||||
mid = self.status_bar.push(self._status_cid, text)
|
||||
if self._status_mid:
|
||||
self.status_bar.remove(self._status_cid, self._status_mid)
|
||||
self._status_mid = mid
|
||||
|
||||
def __init__(self):
|
||||
self.selected_type = ""
|
||||
self.session = ""
|
||||
self.collab = g_data.get_user()
|
||||
self.snap = ""
|
||||
|
||||
self.preferences = 0
|
||||
self.add_collab = 0
|
||||
self.add_session = 0
|
||||
|
||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
self.window.set_title('Session Exchange')
|
||||
self.window.set_size_request(400, 200)
|
||||
self.window.connect('destroy', lambda win: gtk.main_quit())
|
||||
self.window.set_position(gtk.WIN_POS_MOUSE)
|
||||
|
||||
accel_group = gtk.AccelGroup()
|
||||
self.window.add_accel_group(accel_group)
|
||||
|
||||
main_box = gtk.VBox()
|
||||
self.window.add(main_box)
|
||||
|
||||
menu_items = (
|
||||
('/_File', None, None, 0, '<Branch>'),
|
||||
('/File/_Add Session...','<control>A', self.add_session_cb, 0, ''),
|
||||
('/File/Create _Session...', '<control>S', self.create_session_cb, 0, ''),
|
||||
('/File/sep1', None, None, 0, '<Separator>'),
|
||||
('/File/_Quit', '<control>Q', gtk.main_quit, 0, '<StockItem>', gtk.STOCK_QUIT),
|
||||
('/_Edit', None, None, 0, '<Branch>' ),
|
||||
('/Edit/Cu_t', '<control>X', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_CUT),
|
||||
('/Edit/_Copy', '<control>C', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_COPY),
|
||||
('/Edit/_Paste', '<control>V', self.menuitem_cb, 0, '<StockItem>', gtk.STOCK_PASTE),
|
||||
('/Edit/_Delete', None, self.delete_cb, 0, '<StockItem>', gtk.STOCK_DELETE),
|
||||
('/Edit/sep1', None, None, 0, '<Separator>'),
|
||||
('/Edit/Add Colla_borator...','<control>B', self.add_collaborator_cb,0,''),
|
||||
('/Edit/_Fetch Snapshot','<control>F', self.fetch_snapshot_cb,0,''),
|
||||
('/Edit/sep1', None, None, 0, '<Separator>'),
|
||||
('/Edit/_Preferences...','<control>P', self.preferences_cb, 0, '')
|
||||
)
|
||||
|
||||
#need to hold a reference to the item_factory or the menubar will disappear.
|
||||
self.item_factory = gtk.ItemFactory(gtk.MenuBar, '<main>', accel_group)
|
||||
self.item_factory.create_items(menu_items, self.window)
|
||||
main_box.pack_start(self.item_factory.get_widget('<main>'), gtk.FALSE)
|
||||
|
||||
pane1 = gtk.HPaned()
|
||||
pane2 = gtk.HPaned()
|
||||
pane1.pack2(pane2, gtk.TRUE, gtk.FALSE)
|
||||
|
||||
scroll1 = gtk.ScrolledWindow()
|
||||
scroll1.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
pane1.pack1(scroll1, gtk.TRUE, gtk.FALSE)
|
||||
scroll2 = gtk.ScrolledWindow()
|
||||
scroll2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
pane2.pack1(scroll2, gtk.TRUE, gtk.FALSE)
|
||||
scroll3 = gtk.ScrolledWindow()
|
||||
scroll3.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
pane2.pack2(scroll3, gtk.TRUE, gtk.FALSE)
|
||||
|
||||
self.session_model = gtk.ListStore(gobject.TYPE_STRING)
|
||||
view1 = gtk.TreeView(self.session_model)
|
||||
column1 = gtk.TreeViewColumn('Sessions', gtk.CellRendererText(), text=0)
|
||||
view1.append_column(column1)
|
||||
self.session_selection = view1.get_selection()
|
||||
self.session_selection.connect("changed", self.cb_session_selection_changed)
|
||||
scroll1.add(view1)
|
||||
|
||||
self.update_session_view()
|
||||
|
||||
self.collab_model = gtk.ListStore(gobject.TYPE_STRING)
|
||||
view2 = gtk.TreeView(self.collab_model)
|
||||
column2 = gtk.TreeViewColumn('Collaborators', gtk.CellRendererText(), text=0)
|
||||
view2.append_column(column2)
|
||||
self.collab_selection = view2.get_selection()
|
||||
self.collab_selection.connect("changed", self.cb_collab_selection_changed)
|
||||
scroll2.add(view2)
|
||||
|
||||
self.snap_model = gtk.ListStore(gobject.TYPE_STRING)
|
||||
view3 = gtk.TreeView(self.snap_model)
|
||||
column3 = gtk.TreeViewColumn('Snapshots', gtk.CellRendererText(), text=0)
|
||||
view3.append_column(column3)
|
||||
self.snap_selection = view3.get_selection()
|
||||
self.snap_selection.connect("changed", self.cb_snap_selection_changed)
|
||||
scroll3.add(view3)
|
||||
|
||||
main_box.pack_start(pane1, gtk.TRUE, gtk.TRUE)
|
||||
|
||||
self.status_bar = gtk.Statusbar()
|
||||
main_box.pack_start(self.status_bar, gtk.FALSE)
|
||||
self._status_cid = self.status_bar.get_context_id('display')
|
||||
self._status_mid = ''
|
||||
|
||||
self.window.show_all()
|
||||
|
||||
def print_help():
|
||||
print """
|
||||
-h, --help
|
||||
-n, --no-server Only act as a client
|
||||
-p, --port <port number> Defaults to 8970
|
||||
-d, --debug Infers audio files. For debugging Ardour.
|
||||
-v, --version Version
|
||||
"""
|
||||
sys.exit(2)
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "hp:ndv", ["help", "port=", "no-server", "debug", "version"])
|
||||
except getopt.GetoptError:
|
||||
print_help()
|
||||
|
||||
server = True
|
||||
for o, a in opts:
|
||||
if o in ("-h", "--help"):
|
||||
print_help()
|
||||
if o in ("-d", "--debug"):
|
||||
g_display.window.set_title('Session Exchange: Debug Mode')
|
||||
g_data.debug_mode = True
|
||||
if o in ("-p", "--port"):
|
||||
g_data.port = int(a)
|
||||
if o in ("-n", "--no-server"):
|
||||
server = False
|
||||
if o in ("-v", "--version"):
|
||||
print VERSION
|
||||
sys.exit(2)
|
||||
|
||||
if (server):
|
||||
try:
|
||||
reactor.listenTCP(g_data.port, ExchangeServerFactory())
|
||||
except twisted.internet.error.CannotListenError:
|
||||
print "Can not listen on a port number under 1024 unless run as root"
|
||||
sys.exit(2)
|
||||
|
||||
reactor.run()
|
||||
|
||||
g_data.close()
|
||||
|
||||
# global objects
|
||||
g_data = Data()
|
||||
g_display = ArdourShareWindow()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
75
tools/synthesize_sources.pl
Executable file
75
tools/synthesize_sources.pl
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env perl
|
||||
# Ardour session synthesizer
|
||||
# (c)Sampo Savolainen 2007
|
||||
#
|
||||
# GPL
|
||||
# This reads an Ardour session file and creates zero-signal source files
|
||||
# for each missing source file. The length of each file is determined
|
||||
# by how far regions using that source file go into the sample data.
|
||||
|
||||
use XML::Parser::PerlSAX;
|
||||
use XML::Handler::XMLWriter;
|
||||
use IO::Handle;
|
||||
|
||||
use ARDOUR::SourceInfoLoader;
|
||||
|
||||
|
||||
my ($samplerate, $sessionName) = @ARGV;
|
||||
|
||||
if ( ! -d $sessionName || ! -f $sessionName."/".$sessionName.".ardour" ) {
|
||||
print "usage: synthesize_sources.pl samplerate [session name, the name must match the directory and the .ardour file in it]\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
my $sessionFile = $sessionName."/".$sessionName.".ardour";
|
||||
|
||||
|
||||
my $handler = new ARDOUR::SourceInfoLoader($sessionName);
|
||||
|
||||
my $parser = XML::Parser::PerlSAX->new( Handler => $handler );
|
||||
|
||||
$parser->parse(Source => { SystemId => $sessionFile });
|
||||
|
||||
if ( ! -d $sessionName."/interchange" ) {
|
||||
mkdir $sessionName."/interchange/" || die "couldn't create ".$sessionName."/interchange";
|
||||
}
|
||||
|
||||
if ( ! -d $sessionName."/interchange/".$sessionName ) {
|
||||
mkdir $sessionName."/interchange/".$sessionName || die "couldn't create ".$sessionName."/interchange/".$sessionName;
|
||||
}
|
||||
|
||||
if ( ! -d $sessionName."/interchange/".$sessionName."/audiofiles" ) {
|
||||
mkdir $sessionName."/interchange/".$sessionName."/audiofiles" || die "couldn't create ".$sessionName."/interchange/".$sessionName."/audiofiles";
|
||||
}
|
||||
|
||||
if ( ! -d $sessionName."/peaks") {
|
||||
mkdir $sessionName."/peaks/" || die "couldn't create ".$sessionName."/peaks";
|
||||
}
|
||||
|
||||
my $audioFileDirectory = $sessionName."/interchange/".$sessionName."/audiofiles";
|
||||
|
||||
my %sources = %{$handler->{Sources}};
|
||||
|
||||
foreach my $tmp (keys %sources) {
|
||||
|
||||
print "Generating ".$audioFileDirectory."/".$sources{$tmp}->{name}.".wav\n";
|
||||
|
||||
system("sox",
|
||||
"-t", "raw", # /dev/zero is raw :)
|
||||
"-r", $samplerate, # set sample rate
|
||||
"-c", "1", # 1 channel
|
||||
"-b", # input in bytes
|
||||
"-s", # signed
|
||||
"/dev/zero", # input signal
|
||||
|
||||
"-w", # output 16 bit
|
||||
"-t", "wav", # format wav
|
||||
$audioFileDirectory."/".$sources{$tmp}->{name}, # filename
|
||||
"trim", "0", $sources{$tmp}->{calculated_length}."s" # trim silence to wanted sample amount
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue