summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour.menus1
-rw-r--r--gtk2_ardour/ardour_ui.h1
-rw-r--r--gtk2_ardour/ardour_ui_ed.cc3
-rw-r--r--gtk2_ardour/ardour_ui_options.cc23
-rw-r--r--gtk2_ardour/editor_audio_import.cc14
-rw-r--r--libs/ardour/ardour/audioengine.h2
-rw-r--r--libs/ardour/ardour/configuration.h6
-rw-r--r--libs/ardour/ardour/configuration_vars.h1
-rw-r--r--libs/ardour/ardour/region.h3
-rw-r--r--libs/ardour/ardour/session.h50
-rw-r--r--libs/ardour/ardour/source.h3
-rw-r--r--libs/ardour/ardour/utils.h2
-rw-r--r--libs/ardour/audio_diskstream.cc11
-rw-r--r--libs/ardour/audioengine.cc22
-rw-r--r--libs/ardour/audioregion.cc2
-rw-r--r--libs/ardour/audiosource.cc1
-rw-r--r--libs/ardour/destructive_filesource.cc26
-rw-r--r--libs/ardour/import.cc14
-rw-r--r--libs/ardour/location.cc5
-rw-r--r--libs/ardour/region.cc3
-rw-r--r--libs/ardour/session.cc25
-rw-r--r--libs/ardour/session_process.cc45
-rw-r--r--libs/ardour/session_state.cc22
-rw-r--r--libs/ardour/session_time.cc33
-rw-r--r--libs/ardour/session_transport.cc4
-rw-r--r--libs/ardour/sndfilesource.cc5
-rw-r--r--libs/ardour/utils.cc27
27 files changed, 287 insertions, 67 deletions
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus
index b1064b8e87..3aa9507d69 100644
--- a/gtk2_ardour/ardour.menus
+++ b/gtk2_ardour/ardour.menus
@@ -71,6 +71,7 @@
<menuitem action='ToggleAutoReturn'/>
<menuitem action='ToggleClick'/>
<menuitem action='toggle-follow-playhead'/>
+ <menuitem action='ToggleVideoSync'/>
</menu>
</menu>
<menu name='Edit' action='Edit'>
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index b3783140b7..5d494bc48e 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -371,6 +371,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void sync_option_changed ();
void toggle_time_master ();
+ void toggle_video_sync ();
enum ShuttleBehaviour {
Sprung,
diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
index 7b461b1d5c..ef1906f3f5 100644
--- a/gtk2_ardour/ardour_ui_ed.cc
+++ b/gtk2_ardour/ardour_ui_ed.cc
@@ -283,7 +283,8 @@ ARDOUR_UI::install_actions ()
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::transport_sensitive_actions.push_back (act);
- act = ActionManager::register_toggle_action (transport_actions, X_("ToggleTimeMaster"), _("Master"), mem_fun(*this, &ARDOUR_UI::toggle_time_master));
+ ActionManager::register_toggle_action (transport_actions, X_("ToggleVideoSync"), _("Sync startup to video"), mem_fun(*this, &ARDOUR_UI::toggle_video_sync));
+ act = ActionManager::register_toggle_action (transport_actions, X_("ToggleTimeMaster"), _("Time master"), mem_fun(*this, &ARDOUR_UI::toggle_time_master));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (common_actions, X_("ToggleRecordEnableTrack1"), _("Toggle Record Enable Track1"), bind (mem_fun(*this, &ARDOUR_UI::toggle_record_enable), 0U));
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index 665c92d264..205180a344 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -43,7 +43,8 @@ ARDOUR_UI::setup_config_options ()
std::vector<Glib::ustring> groups;
groups.push_back("options");
groups.push_back("Editor");
-
+ groups.push_back("Transport");
+
struct {
char* name;
bool (Configuration::*method)(void) const;
@@ -69,6 +70,7 @@ ARDOUR_UI::setup_config_options ()
{ "MeterHoldShort", &Configuration::get_meter_hold_short, 'r' },
{ "MeterHoldMedium", &Configuration::get_meter_hold_medium, 'r' },
{ "MeterHoldLong", &Configuration::get_meter_hold_long, 'r' },
+ { "ToggleVideoSync", &Configuration::get_use_video_sync, 't' },
{ 0, 0, 0 }
};
@@ -77,8 +79,13 @@ ARDOUR_UI::setup_config_options ()
Glib::RefPtr<Action> act = ActionManager::get_action (i->c_str(), options[n].name);
if (act) {
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
- if (options[n].act_type == 't' || (options[n].act_type == 'r' && (Config->*(options[n].method))()))
- tact->set_active ((Config->*(options[n].method))());
+ if (options[n].act_type == 't' || options[n].act_type == 'r') {
+ if ((Config->*(options[n].method))()) {
+ tact->set_active (true);
+ } else {
+ tact->set_active (false);
+ }
+ }
continue;
}
}
@@ -237,6 +244,16 @@ ARDOUR_UI::toggle_punch_out ()
toggle_session_state ("Transport", "TogglePunchOut", &Session::set_punch_out, &Session::get_punch_out);
}
+ void
+ARDOUR_UI::toggle_video_sync()
+{
+ Glib::RefPtr<Action> act = ActionManager::get_action ("Transport", "ToggleVideoSync");
+ if (act) {
+ Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+ Config->set_use_video_sync (tact->get_active());
+ }
+}
+
void
ARDOUR_UI::toggle_editing_space()
{
diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc
index fffad2e2eb..75517ec18d 100644
--- a/gtk2_ardour/editor_audio_import.cc
+++ b/gtk2_ardour/editor_audio_import.cc
@@ -82,11 +82,11 @@ Editor::bring_in_external_audio (ImportMode mode, AudioTrack* track, jack_nframe
switch (sfdb.run()) {
case SoundFileOmega::ResponseImport:
- do_import (sfdb.get_paths(), sfdb.get_split(), mode, track, pos, prompt);
+ do_import (sfdb.get_paths(), sfdb.get_split(), sfdb.get_mode(), track, pos, prompt);
break;
case SoundFileOmega::ResponseEmbed:
- do_embed (sfdb.get_paths(), sfdb.get_split(), mode, track, pos, prompt);
+ do_embed (sfdb.get_paths(), sfdb.get_split(), sfdb.get_mode(), track, pos, prompt);
break;
default:
@@ -274,12 +274,12 @@ Editor::embed_sndfile (Glib::ustring path, bool split, bool multiple_files, bool
sources.push_back(source);
}
- catch (failed_constructor& err) {
- error << string_compose(_("could not open %1"), path) << endmsg;
- goto out;
- }
+ catch (failed_constructor& err) {
+ error << string_compose(_("could not open %1"), path) << endmsg;
+ goto out;
+ }
- ARDOUR_UI::instance()->flush_pending ();
+ ARDOUR_UI::instance()->flush_pending ();
}
if (sources.empty()) {
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index d13e917ff0..36a08e237e 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -72,6 +72,8 @@ class AudioEngine : public sigc::trackable
int usecs_per_cycle () const { return _usecs_per_cycle; }
+ bool get_sync_offset (jack_nframes_t& offset) const;
+
jack_nframes_t frames_since_cycle_start () {
if (!_running || !_jack) return 0;
return jack_frames_since_cycle_start (_jack);
diff --git a/libs/ardour/ardour/configuration.h b/libs/ardour/ardour/configuration.h
index dd689e9a2d..8d51343ffb 100644
--- a/libs/ardour/ardour/configuration.h
+++ b/libs/ardour/ardour/configuration.h
@@ -63,16 +63,18 @@ class Configuration : public Stateful
XMLNode* control_protocol_state () { return _control_protocol_state; }
+ sigc::signal<void,const char*> ParameterChanged;
+
/* define accessor methods */
#undef CONFIG_VARIABLE
#undef CONFIG_VARIABLE_SPECIAL
#define CONFIG_VARIABLE(Type,var,name,value) \
Type get_##var () const { return var.get(); } \
- void set_##var (Type val) { var.set (val); var.set_is_user (user_configuration); }
+ void set_##var (Type val) { var.set (val); var.set_is_user (user_configuration); ParameterChanged (name); }
#define CONFIG_VARIABLE_SPECIAL(Type,var,name,value,mutator) \
Type get_##var () const { return var.get(); } \
- void set_##var (Type val) { var.set (val); var.set_is_user (user_configuration); }
+ void set_##var (Type val) { var.set (val); var.set_is_user (user_configuration); ParameterChanged (name); }
#include "ardour/configuration_vars.h"
#undef CONFIG_VARIABLE
#undef CONFIG_VARIABLE_SPECIAL
diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
index 85c7897026..5222eefb0a 100644
--- a/libs/ardour/ardour/configuration_vars.h
+++ b/libs/ardour/ardour/configuration_vars.h
@@ -21,6 +21,7 @@ CONFIG_VARIABLE(bool, use_hardware_monitoring, "use-hardware-monitoring", false)
CONFIG_VARIABLE(bool, use_sw_monitoring, "use-sw-monitoring", false)
CONFIG_VARIABLE(bool, use_external_monitoring, "use-external-monitoring", true)
CONFIG_VARIABLE(bool, jack_time_master, "jack-time-master", true)
+CONFIG_VARIABLE(bool, use_video_sync, "use-video-sync", false)
CONFIG_VARIABLE(bool, trace_midi_input, "trace-midi-input", false)
CONFIG_VARIABLE(bool, trace_midi_output, "trace-midi-output", false)
CONFIG_VARIABLE(bool, plugins_stop_with_transport, "plugins-stop-with-transport", false)
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index 958b4d419c..9bdf3357cf 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -22,6 +22,7 @@
#define __ardour_region_h__
#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
#include <pbd/undo.h>
#include <pbd/statefuldestructible.h>
@@ -56,7 +57,7 @@ struct RegionState : public StateManager::State
mutable RegionEditState _first_edit;
};
-class Region : public PBD::StatefulDestructible, public StateManager
+class Region : public PBD::StatefulDestructible, public StateManager, public boost::enable_shared_from_this<Region>
{
public:
enum Flag {
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index ec7deccc31..25f06c03b4 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -360,6 +360,8 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
jack_nframes_t last_transport_start() const { return _last_roll_location; }
void goto_end () { request_locate (end_location->start(), false);}
void goto_start () { request_locate (start_location->start(), false); }
+ void set_session_start (jack_nframes_t start) { start_location->set_start(start); }
+ void set_session_end (jack_nframes_t end) { end_location->set_start(end); _end_location_is_free = false; }
void use_rf_shuttle_speed ();
void request_transport_speed (float speed);
void request_overwrite_buffer (Diskstream*);
@@ -377,8 +379,9 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
jack_nframes_t current_end_frame() const { return end_location->start(); }
jack_nframes_t current_start_frame() const { return start_location->start(); }
jack_nframes_t frame_rate() const { return _current_frame_rate; }
- double frames_per_smpte_frame() const { return _frames_per_smpte_frame; }
jack_nframes_t frames_per_hour() const { return _frames_per_hour; }
+
+ double frames_per_smpte_frame() const { return _frames_per_smpte_frame; }
jack_nframes_t smpte_frames_per_hour() const { return _smpte_frames_per_hour; }
/* Locations */
@@ -417,7 +420,8 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
MidiFeedback,
MidiControl,
TranzportControl,
- Feedback
+ Feedback,
+ SmpteMode,
};
sigc::signal<void,ControlType> ControlChanged;
@@ -576,6 +580,7 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
float shuttle_speed_threshold;
float rf_speed;
float smpte_frames_per_second;
+ float video_pullup;
bool smpte_drop_frames;
AnyTime preroll;
AnyTime postroll;
@@ -585,7 +590,35 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
jack_nframes_t transport_frame () const {return _transport_frame; }
jack_nframes_t audible_frame () const;
+ enum SmpteFormat {
+ smpte_23976,
+ smpte_24,
+ smpte_24976,
+ smpte_25,
+ smpte_2997,
+ smpte_2997drop,
+ smpte_30,
+ smpte_30drop,
+ smpte_5994,
+ smpte_60,
+ };
+
+ enum PullupFormat {
+ pullup_Plus4Plus1,
+ pullup_Plus4,
+ pullup_Plus4Minus1,
+ pullup_Plus1,
+ pullup_None,
+ pullup_Minus1,
+ pullup_Minus4Plus1,
+ pullup_Minus4,
+ pullup_Minus4Minus1,
+ };
+
int set_smpte_type (float fps, bool drop_frames);
+ int set_video_pullup (float pullup);
+
+ void sync_time_vars();
void bbt_time (jack_nframes_t when, BBT_Time&);
void smpte_to_sample( SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const;
@@ -604,8 +637,11 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
jack_nframes_t convert_to_frames_at (jack_nframes_t position, AnyTime&);
+ static sigc::signal<void> StartTimeChanged;
+ static sigc::signal<void> EndTimeChanged;
static sigc::signal<void> SMPTEOffsetChanged;
- sigc::signal<void> SMPTETypeChanged;
+ static sigc::signal<void> SMPTETypeChanged;
+ static sigc::signal<void> PullupChanged;
void request_slave_source (SlaveSource, jack_nframes_t pos = 0);
SlaveSource slave_source() const { return _slave_type; }
@@ -1054,7 +1090,9 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
mutable gint processing_prohibited;
process_function_type process_function;
process_function_type last_process_function;
- jack_nframes_t _current_frame_rate;
+ bool waiting_for_sync_offset;
+ jack_nframes_t _base_frame_rate;
+ jack_nframes_t _current_frame_rate; //this includes video pullup offset
int transport_sub_state;
mutable gint _record_status;
jack_nframes_t _transport_frame;
@@ -1156,6 +1194,8 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
return false;
}
+ bool maybe_sync_start (jack_nframes_t&, jack_nframes_t&);
+
void check_declick_out ();
MIDI::MachineControl* mmc;
@@ -1800,6 +1840,8 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
void add_controllable (PBD::Controllable*);
void remove_controllable (PBD::Controllable*);
+
+ void handle_configuration_change (const char*);
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h
index 20a8190bd4..28ccd68272 100644
--- a/libs/ardour/ardour/source.h
+++ b/libs/ardour/ardour/source.h
@@ -24,7 +24,6 @@
#include <string>
#include <sigc++/signal.h>
-#include <boost/enable_shared_from_this.hpp>
#include <pbd/statefuldestructible.h>
@@ -32,7 +31,7 @@
namespace ARDOUR {
-class Source : public PBD::StatefulDestructible, public sigc::trackable, public boost::enable_shared_from_this<Source>
+class Source : public PBD::StatefulDestructible, public sigc::trackable
{
public:
Source (std::string name);
diff --git a/libs/ardour/ardour/utils.h b/libs/ardour/ardour/utils.h
index ee4482d260..5128c98a77 100644
--- a/libs/ardour/ardour/utils.h
+++ b/libs/ardour/ardour/utils.h
@@ -57,6 +57,8 @@ int touch_file(std::string path);
std::string region_name_from_path (std::string path);
std::string path_expand (std::string);
+void compute_equal_power_fades (jack_nframes_t nframes, float* in, float* out);
+
#ifdef HAVE_COREAUDIO
std::string CFStringRefToStdString(CFStringRef stringRef);
#endif // HAVE_COREAUDIO
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index c39f6ebf20..56f051890a 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -250,8 +250,7 @@ AudioDiskstream::non_realtime_input_change ()
if (speed() != 1.0f || speed() != -1.0f) {
seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()));
- }
- else {
+ } else {
seek (_session.transport_frame());
}
}
@@ -384,8 +383,12 @@ AudioDiskstream::setup_destructive_playlist ()
void
AudioDiskstream::use_destructive_playlist ()
{
- /* use the sources associated with the single full-extent region */
-
+ /* this is called from the XML-based constructor. when its done,
+ we already have a playlist and a region, but we need to
+ set up our sources for write. we use the sources associated
+ with the (presumed single, full-extent) region.
+ */
+
Playlist::RegionList* rl = _playlist->regions_at (0);
if (rl->empty()) {
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 13feb3f3f3..40d10f30d4 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -163,18 +163,32 @@ AudioEngine::stop ()
}
+
+bool
+AudioEngine::get_sync_offset (jack_nframes_t& offset) const
+{
+ jack_position_t pos;
+
+ (void) jack_transport_query (_jack, &pos);
+
+ if (pos.valid & JackVideoFrameOffset) {
+ offset = pos.video_offset;
+ return true;
+ }
+
+ return false;
+}
+
void
AudioEngine::_jack_timebase_callback (jack_transport_state_t state, jack_nframes_t nframes,
-
- jack_position_t* pos, int new_position, void *arg)
+ jack_position_t* pos, int new_position, void *arg)
{
static_cast<AudioEngine*> (arg)->jack_timebase_callback (state, nframes, pos, new_position);
}
void
AudioEngine::jack_timebase_callback (jack_transport_state_t state, jack_nframes_t nframes,
-
- jack_position_t* pos, int new_position)
+ jack_position_t* pos, int new_position)
{
if (session && session->synced_to_jack()) {
session->jack_timebase_callback (state, nframes, pos, new_position);
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index 659d638ad6..4cd45c5d99 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -218,8 +218,6 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
save_state ("initial state");
_envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed));
-
- /* NOTE: no CheckNewRegion signal emitted here. This is the copy constructor */
}
AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& node)
diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc
index 19f6de5c64..e3a064bb09 100644
--- a/libs/ardour/audiosource.cc
+++ b/libs/ardour/audiosource.cc
@@ -66,7 +66,6 @@ AudioSource::AudioSource (string name)
AudioSource::AudioSource (const XMLNode& node)
: Source (node)
{
- cerr << "audiosource from XML\n";
if (pending_peak_sources_lock == 0) {
pending_peak_sources_lock = new Glib::Mutex;
}
diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc
index 7bf47e84a0..bf16b40005 100644
--- a/libs/ardour/destructive_filesource.cc
+++ b/libs/ardour/destructive_filesource.cc
@@ -56,6 +56,7 @@ typedef off_t off64_t;
#include <pbd/error.h>
#include <ardour/destructive_filesource.h>
+#include <ardour/utils.h>
#include "i18n.h"
@@ -124,13 +125,7 @@ DestructiveFileSource::setup_standard_crossfades (jack_nframes_t rate)
out_coefficient = new gain_t[xfade_frames];
in_coefficient = new gain_t[xfade_frames];
- for (jack_nframes_t n = 0; n < xfade_frames; ++n) {
-
- /* XXXX THIS IS NOT THE RIGHT XFADE CURVE: USE A PROPER VOLUMETRIC EQUAL POWER CURVE */
-
- in_coefficient[n] = n/(gain_t) (xfade_frames-1); /* 0 .. 1 */
- out_coefficient[n] = 1.0 - in_coefficient[n]; /* 1 .. 0 */
- }
+ compute_equal_power_fades (xfade_frames, in_coefficient, out_coefficient);
}
void
@@ -195,7 +190,7 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in)
}
if (file_cnt) {
- if ((retval = write_float (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
+ if ((retval = read_unlocked (xfade_buf, fade_position, file_cnt)) != (ssize_t) file_cnt) {
if (retval >= 0 && errno == EAGAIN) {
/* XXX - can we really trust that errno is meaningful here? yes POSIX, i'm talking to you.
* short or no data there */
@@ -213,7 +208,7 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in)
}
if (nofade && !fade_in) {
- if (write_float (data, file_pos, nofade) != nofade) {
+ if (write_float (data, file_pos - timeline_position, nofade) != nofade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
@@ -245,24 +240,27 @@ DestructiveFileSource::crossfade (Sample* data, jack_nframes_t cnt, int fade_in)
} else if (xfade) {
+ gain_t in[xfade];
+ gain_t out[xfade];
+
/* short xfade, compute custom curve */
- /* XXX COMPUTE THE CURVE, DAMMIT! */
+ compute_equal_power_fades (xfade, in, out);
for (jack_nframes_t n = 0; n < xfade; ++n) {
- xfade_buf[n] = (xfade_buf[n] * out_coefficient[n]) + (fade_data[n] * in_coefficient[n]);
+ xfade_buf[n] = (xfade_buf[n] * out[n]) + (fade_data[n] * in[n]);
}
}
if (xfade) {
- if (write_float (xfade_buf, fade_position, xfade) != xfade) {
+ if (write_float (xfade_buf, fade_position - timeline_position, xfade) != xfade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
}
if (fade_in && nofade) {
- if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
+ if (write_float (data + xfade, file_pos + xfade - timeline_position, nofade) != nofade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
@@ -345,7 +343,7 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt)
/* in the middle of recording */
- if (write_float (data, file_pos, cnt) != cnt) {
+ if (write_float (data, file_pos - timeline_position, cnt) != cnt) {
return 0;
}
}
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index dc9819af8e..2fd38bf0a6 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -305,14 +305,18 @@ Session::sample_rate_convert (import_status& status, string infile, string& outf
sf_count_t input_count = 0;
SNDFILE* in = sf_open(infile.c_str(), SFM_READ, &sf_info);
+ if (!in) {
+ error << string_compose(_("Import/SRC: could not open input file: %1"), outfile) << endmsg;
+ return false;
+ }
sf_count_t total_input_frames = sf_info.frames;
outfile = build_tmp_convert_name(infile);
SNDFILE* out = sf_open(outfile.c_str(), SFM_RDWR, &sf_info);
- if(!out) {
- error << string_compose(_("Import: could not open temp file: %1"), outfile) << endmsg;
- return false;
- }
+ if (!out) {
+ error << string_compose(_("Import/SRC: could not open output file: %1"), outfile) << endmsg;
+ return false;
+ }
sf_seek (in, 0, SEEK_SET) ;
sf_seek (out, 0, SEEK_SET) ;
@@ -371,8 +375,6 @@ Session::sample_rate_convert (import_status& status, string infile, string& outf
sf_close(in);
sf_close(out);
- status.done = true;
-
if (status.cancel) {
return false;
} else {
diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc
index 58ef812d2e..30b28c6abe 100644
--- a/libs/ardour/location.cc
+++ b/libs/ardour/location.cc
@@ -30,6 +30,7 @@
#include <pbd/xml++.h>
#include <ardour/location.h>
+#include <ardour/session.h>
#include <ardour/audiofilesource.h>
#include "i18n.h"
@@ -84,8 +85,12 @@ Location::set_start (jack_nframes_t s)
_end = s;
start_changed(this); /* EMIT SIGNAL */
if ( is_start() ) {
+ Session::StartTimeChanged (); /* EMIT SIGNAL */
AudioFileSource::set_header_position_offset ( s );
}
+ if ( is_end() ) {
+ Session::EndTimeChanged (); /* EMIT SIGNAL */
+ }
}
return 0;
}
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index f81cb3bed5..e8353ac529 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -32,6 +32,7 @@
#include <ardour/region.h>
#include <ardour/playlist.h>
#include <ardour/session.h>
+#include <ardour/region_factory.h>
#include "i18n.h"
@@ -274,7 +275,7 @@ Region::first_edit ()
_first_edit = EditChangesNothing;
send_change (NameChanged);
- /// XXX CheckNewRegion (boost::shared_ptr<Region>(this));
+ RegionFactory::CheckNewRegion (shared_from_this());
}
}
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 9b8397e467..b9888dfd30 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -92,9 +92,13 @@ Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0;
Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0;
sigc::signal<int> Session::AskAboutPendingState;
-sigc::signal<void> Session::SMPTEOffsetChanged;
sigc::signal<void> Session::SendFeedback;
+sigc::signal<void> Session::SMPTEOffsetChanged;
+sigc::signal<void> Session::SMPTETypeChanged;
+sigc::signal<void> Session::PullupChanged;
+sigc::signal<void> Session::StartTimeChanged;
+sigc::signal<void> Session::EndTimeChanged;
int
Session::find_session (string str, string& path, string& snapshot, bool& isnew)
@@ -288,6 +292,8 @@ Session::Session (AudioEngine &eng,
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
+ Config->ParameterChanged.connect (mem_fun (*this, &Session::handle_configuration_change));
+
if (was_dirty) {
DirtyChanged (); /* EMIT SIGNAL */
}
@@ -1423,8 +1429,9 @@ Session::set_frame_rate (jack_nframes_t frames_per_second)
here.
*/
- _current_frame_rate = frames_per_second;
- _frames_per_smpte_frame = (double) _current_frame_rate / (double) smpte_frames_per_second;
+ _base_frame_rate = frames_per_second;
+
+ sync_time_vars();
Route::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * 0.25));
@@ -2717,8 +2724,6 @@ Session::add_source (boost::shared_ptr<Source> source)
{
boost::shared_ptr<AudioFileSource> afs;
- cerr << "add new source " << source->name() << endl;
-
if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
pair<AudioSourceList::key_type, AudioSourceList::mapped_type> entry;
@@ -3873,6 +3878,16 @@ Session::set_xfade_model (CrossfadeModel xm)
}
void
+Session::handle_configuration_change (const char* parameter)
+{
+ if (!strcmp (parameter, "use-video-sync")) {
+ if (_transport_speed == 0.0f) {
+ waiting_for_sync_offset = true;
+ }
+ }
+}
+
+void
Session::add_curve(Curve *curve)
{
curves[curve->id()] = curve;
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 68ad11cf42..43849793d4 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -728,7 +728,8 @@ Session::process_without_events (jack_nframes_t nframes)
bool session_needs_butler = false;
jack_nframes_t stop_limit;
long frames_moved;
-
+ jack_nframes_t offset = 0;
+
{
if (post_transport_work & (PostTransportLocate|PostTransportStop)) {
no_roll (nframes, 0);
@@ -761,16 +762,20 @@ Session::process_without_events (jack_nframes_t nframes)
return;
}
- click (_transport_frame, nframes, 0);
+ if (maybe_sync_start (nframes, offset)) {
+ return;
+ }
+
+ click (_transport_frame, nframes, offset);
prepare_diskstreams ();
frames_moved = (long) floor (_transport_speed * nframes);
- if (process_routes (nframes, 0)) {
- no_roll (nframes, 0);
- return;
- }
+ if (process_routes (nframes, offset)) {
+ no_roll (nframes, offset);
+ return;
+ }
commit_diskstreams (nframes, session_needs_butler);
@@ -836,3 +841,31 @@ Session::process_audition (jack_nframes_t nframes)
}
}
+bool
+Session::maybe_sync_start (jack_nframes_t& nframes, jack_nframes_t& offset)
+{
+ jack_nframes_t sync_offset;
+
+ if (!waiting_for_sync_offset) {
+ return false;
+ }
+
+ if (_engine.get_sync_offset (sync_offset) && sync_offset < nframes) {
+
+ no_roll (sync_offset, 0);
+ nframes -= sync_offset;
+ offset += sync_offset;
+ waiting_for_sync_offset = false;
+
+ if (nframes == 0) {
+ return true; // done
+ }
+
+ } else {
+ no_roll (nframes, 0);
+ return true; // done
+ }
+
+ return false;
+}
+
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 6cddfb026a..9f1c6baf4a 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -222,6 +222,18 @@ Session::first_stage_init (string fullpath, string snapshot_name)
process_function = &Session::process_with_events;
+ if (Config->get_use_video_sync()) {
+ waiting_for_sync_offset = true;
+ } else {
+ waiting_for_sync_offset = false;
+ }
+
+ _current_frame_rate = 48000;
+ _base_frame_rate = 48000;
+
+ smpte_frames_per_second = 30;
+ video_pullup = 0.0;
+ smpte_drop_frames = false;
last_smpte_when = 0;
_smpte_offset = 0;
_smpte_offset_negative = true;
@@ -257,6 +269,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
/* default SMPTE type is 30 FPS, non-drop */
set_smpte_type (30.0, false);
+ set_video_pullup (0.0);
_engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
@@ -910,6 +923,11 @@ Session::load_options (const XMLNode& node)
rf_speed = atof (prop->value().c_str());
}
}
+ if ((child = find_named_node (node, "video-pullup")) != 0) {
+ if ((prop = child->property ("val")) != 0) {
+ set_video_pullup( atof (prop->value().c_str()) );
+ }
+ }
if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
if ((prop = child->property ("val")) != 0) {
set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
@@ -1164,6 +1182,10 @@ Session::get_options () const
child = opthead->add_child ("rf-speed");
child->add_property ("val", buf);
+ snprintf (buf, sizeof(buf)-1, "%.4f", video_pullup);
+ child = opthead->add_child ("video-pullup");
+ child->add_property ("val", buf);
+
snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
child = opthead->add_child ("smpte-frames-per-second");
child->add_property ("val", buf);
diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc
index bd2c992ff5..6229857f72 100644
--- a/libs/ardour/session_time.cc
+++ b/libs/ardour/session_time.cc
@@ -48,15 +48,20 @@ Session::bbt_time (jack_nframes_t when, BBT_Time& bbt)
/* SMPTE TIME */
+void
+Session::sync_time_vars ()
+{
+ _current_frame_rate = _base_frame_rate * (1.0 + (video_pullup/100.0) );
+ _frames_per_hour = _current_frame_rate * 3600;
+ _frames_per_smpte_frame = (double) _current_frame_rate / (double) smpte_frames_per_second;
+ _smpte_frames_per_hour = (unsigned long) (smpte_frames_per_second * 3600.0);
+}
+
int
Session::set_smpte_type (float fps, bool drop_frames)
{
smpte_frames_per_second = fps;
smpte_drop_frames = drop_frames;
- _frames_per_smpte_frame = (double) _current_frame_rate / (double) smpte_frames_per_second;
- _frames_per_hour = _current_frame_rate * 3600;
- _smpte_frames_per_hour = (unsigned long) (smpte_frames_per_second * 3600.0);
-
last_smpte_valid = false;
// smpte type bits are the middle two in the upper nibble
@@ -79,6 +84,8 @@ Session::set_smpte_type (float fps, bool drop_frames)
break;
};
+ sync_time_vars();
+
SMPTETypeChanged (); /* EMIT SIGNAL */
set_dirty();
@@ -86,6 +93,20 @@ Session::set_smpte_type (float fps, bool drop_frames)
return 0;
}
+int
+Session::set_video_pullup (float pull)
+{
+ video_pullup = pull;
+
+ sync_time_vars();
+
+ PullupChanged (); /* EMIT SIGNAL */
+
+ set_dirty();
+
+ return 0;
+}
+
void
Session::set_smpte_offset (jack_nframes_t off)
{
@@ -407,6 +428,10 @@ Session::jack_timebase_callback (jack_transport_state_t state,
pos->valid = jack_position_bits_t (pos->valid | JackPositionBBT);
}
+ //poke audio video ratio so Ardour can track Video Sync
+ pos->audio_frames_per_video_frame = frame_rate() / smpte_frames_per_second;
+ pos->valid = jack_position_bits_t (pos->valid | JackAudioVideoRatio);
+
#if 0
/* SMPTE info */
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index 8e0522c19d..1138d97664 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -186,6 +186,10 @@ Session::realtime_stop (bool abort)
_transport_speed = 0;
+ if (Config->get_use_video_sync()) {
+ waiting_for_sync_offset = true;
+ }
+
transport_sub_state = (auto_return ? AutoReturning : 0);
}
diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
index 699522c2ad..faed2409e5 100644
--- a/libs/ardour/sndfilesource.cc
+++ b/libs/ardour/sndfilesource.cc
@@ -292,6 +292,11 @@ SndFileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t
uint32_t real_cnt;
jack_nframes_t file_cnt;
+ //destructive (tape) tracks need to offset reads and writes by the timeline position
+ if (_flags && ARDOUR::Destructive == ARDOUR::Destructive) {
+ start -= timeline_position;
+ }
+
if (start > _length) {
/* read starts beyond end of data, just memset to zero */
diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc
index 78e5572a3d..5f676964d2 100644
--- a/libs/ardour/utils.cc
+++ b/libs/ardour/utils.cc
@@ -271,3 +271,30 @@ CFStringRefToStdString(CFStringRef stringRef)
return result;
}
#endif // HAVE_COREAUDIO
+
+void
+compute_equal_power_fades (jack_nframes_t nframes, float* in, float* out)
+{
+ double step;
+
+ step = 1.0/nframes;
+
+ in[0] = 0.0f;
+
+ for (int i = 1; i < nframes - 1; ++i) {
+ in[i] = in[i-1] + step;
+ }
+
+ in[nframes-1] = 1.0;
+
+ const float pan_law_attenuation = -3.0f;
+ const float scale = 2.0f - 4.0f * powf (10.0f,pan_law_attenuation/20.0f);
+
+ for (unsigned long n = 0; n < nframes; ++n) {
+ float inVal = in[n];
+ float outVal = 1 - inVal;
+ out[n] = outVal * (scale * outVal + 1.0f - scale);
+ in[n] = inVal * (scale * inVal + 1.0f - scale);
+ }
+}
+