Merged with trunk R1393.

git-svn-id: svn://localhost/ardour2/branches/midi@1395 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2007-01-28 17:44:13 +00:00
parent cd37c36326
commit f9f5ec85fb
85 changed files with 5136 additions and 2848 deletions

View file

@ -1,7 +0,0 @@
.sconf_temp
.sconsign.dblite
ardour.rc
config.log
scache.conf
.gdb_history
docs/

View file

@ -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:

View file

@ -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"/>

View file

@ -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'

View file

@ -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)

View file

@ -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

View file

@ -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" "")

View file

@ -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'/>

View file

@ -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"

View file

@ -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 ();

View file

@ -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);

View file

@ -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
}

View file

@ -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;
}

View file

@ -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 ()
{

View file

@ -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 ();

View file

@ -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);

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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;

View file

@ -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);
}

View file

@ -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*);

View file

@ -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();
}

View file

@ -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

View file

@ -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?
}

View file

@ -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;

View file

@ -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;

View file

@ -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 ();

View file

@ -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));
}
}

View file

@ -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 ();
}

File diff suppressed because it is too large Load diff

View file

@ -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();
}
}
}

View file

@ -196,7 +196,7 @@ LadspaPluginUI::build ()
frame->add (*box);
hpacker.pack_start(*frame,true,true);
x = 0;
x = 1;
}
}

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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*);

View file

@ -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 ();

View file

@ -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);

View file

@ -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) {

View file

@ -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

View file

@ -44,7 +44,6 @@ buffer_set.cc
meter.cc
amp.cc
panner.cc
destructive_filesource.cc
audiofilesource.cc
audiofilter.cc
audioregion.cc

View file

@ -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);

View file

@ -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 */

View file

@ -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());

View file

@ -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 */

View file

@ -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;

View file

@ -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);
};

View file

@ -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 ();
};

View file

@ -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);

View file

@ -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:

View file

@ -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));
}

View file

@ -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;

View file

@ -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
}

View file

@ -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;
}

View file

@ -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 */

View file

@ -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 ()
{

View file

@ -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
}

View file

@ -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) {

View file

@ -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;

View file

@ -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")) {

View file

@ -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));
}
}

View file

@ -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());

View file

@ -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:

View file

@ -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());

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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 */

View file

@ -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();

View file

@ -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

View 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;

Binary file not shown.

View 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;
}

View 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>

View file

@ -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 */;
}

View 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;
}

View 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>

View file

@ -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`

View file

@ -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
View 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
View 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
);
}