Merged with trunk R879
authorDavid Robillard <d@drobilla.net>
Thu, 31 Aug 2006 19:17:00 +0000 (19:17 +0000)
committerDavid Robillard <d@drobilla.net>
Thu, 31 Aug 2006 19:17:00 +0000 (19:17 +0000)
git-svn-id: svn://localhost/ardour2/branches/midi@880 d708f5d6-7413-0410-9779-e7cbd77b26cf

40 files changed:
SConstruct
gtk2_ardour/SConscript
gtk2_ardour/ardour.menus
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/ardour_ui_options.cc
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/plugin_selector.cc
gtk2_ardour/plugin_selector.h
gtk2_ardour/redirect_box.cc
gtk2_ardour/sfdb_ui.cc
libs/ardour/SConscript
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/configuration.h
libs/ardour/ardour/configuration_vars.h
libs/ardour/ardour/port.h
libs/ardour/ardour/region.h
libs/ardour/ardour/session.h
libs/ardour/ardour/source.h
libs/ardour/ardour/utils.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_library.cc
libs/ardour/audio_unit.cc
libs/ardour/audioengine.cc
libs/ardour/audiosource.cc
libs/ardour/coreaudiosource.cc
libs/ardour/destructive_filesource.cc
libs/ardour/import.cc
libs/ardour/insert.cc
libs/ardour/location.cc
libs/ardour/plugin.cc
libs/ardour/region.cc
libs/ardour/session.cc
libs/ardour/session_process.cc
libs/ardour/session_state.cc
libs/ardour/session_time.cc
libs/ardour/session_transport.cc
libs/ardour/sndfilesource.cc
libs/ardour/source_factory.cc
libs/ardour/utils.cc

index b6a2ed64c5131b70208e77938aa8ec2428fcdd92..be4b6ce0b8be9d29b045e246aab21c9551234a32 100644 (file)
@@ -26,6 +26,7 @@ subst_dict = { }
 opts = Options('scache.conf')
 opts.AddOptions(
   ('ARCH', 'Set architecture-specific compilation flags by hand (all flags as 1 argument)',''),
+    BoolOption('AUDIOUNITS', 'Compile with Apple\'s AudioUnit library. (experimental)', 0),
     BoolOption('COREAUDIO', 'Compile with Apple\'s CoreAudio library', 0),
     BoolOption('DEBUG', 'Set to build with debugging information and no optimizations', 0),
     PathOption('DESTDIR', 'Set the intermediate install "prefix"', '/'),
@@ -467,6 +468,17 @@ if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == 0:
     
 libraries['boost'] = conf.Finish ()
 
+conf = env.Configure ()
+
+# jack_port_ensure_monitor available
+
+if conf.CheckFunc('jack_port_ensure_monitor'):
+    env.Append(CCFLAGS='-DWITH_JACK_PORT_ENSURE_MONITOR')
+else:
+    print '\nWARNING: You need at least svn revision 985 of jack for hardware monitoring to work correctly.\n'
+
+env = conf.Finish()
+
 #
 # Check for liblo
 
@@ -497,8 +509,6 @@ else:
 
 libraries['dmalloc'] = conf.Finish ()
 
-#
-
 #
 # Audio/MIDI library (needed for MIDI, since audio is all handled via JACK)
 #
index aaa686d246cba8294b867ea0d730ad44e3c3cefc..8a1fd22ff2ba7f15ae0bb9b96c79c702324ca36c 100644 (file)
@@ -61,7 +61,7 @@ skipped_files=Split("""
 connection_editor.cc
 """)
 
-coreaudio_files=Split("""
+audiounit_files=Split("""
 au_pluginui.cc
 """)
 
@@ -224,9 +224,9 @@ if env['VST']:
        extra_sources += vst_files
        gtkardour.Append (CCFLAGS="-DVST_SUPPORT", CPPPATH="#libs/fst")
 
-if gtkardour['COREAUDIO']:
-    extra_sources += coreaudio_files
-    gtkardour.Append(CCFLAGS='-DHAVE_COREAUDIO')
+if gtkardour['AUDIOUNITS']:
+    extra_sources += audiounit_files
+    gtkardour.Append(CCFLAGS='-DHAVE_AUDIOUNITS')
     gtkardour.Append(LINKFLAGS='-framework Carbon')
     gtkardour.Merge([libraries['appleutility']])
  
index ab87fbb3ef7c2105ec7069f6ccbdcb79fe7a62ab..0f1f741c30d3eacc700668198096d9f345225b96 100644 (file)
@@ -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'>
index d0e90c42bebc9ff75785df00e5c6d935aa51e0b1..fdaa2d74ca9df334dd770526958b91ac1a0ad933 100644 (file)
@@ -377,6 +377,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
 
        void sync_option_changed ();
        void toggle_time_master ();
+       void toggle_video_sync ();
 
        enum ShuttleBehaviour {
                Sprung,
index 2fe34127dc2c6f4d1b716b66bcb63dfb17344d0d..5af62db99ff26ae6762413921633bc8beffd9e6e 100644 (file)
@@ -287,7 +287,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));
index 665c92d264b2725fd1bedecb24d7ca19749661db..205180a344be66ba5510eddb1f8bd0df5ea8b3ba 100644 (file)
@@ -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()
 {
index 8efdca2dd48ea6c26d554f0f4abcd16fb3ae7906..fdd680beb2bb3ec81174fb5ab7ccefd3c38cdc35 100644 (file)
@@ -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()) {
index 69f6f56690d696d1a365c452bf62ca4fce9ddd6b..8a52e8587f673e738bbb0b358ac5f846459e00fe 100644 (file)
@@ -92,7 +92,7 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        }
 #endif
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
        aumodel = ListStore::create(aucols);
        au_display.set_model (aumodel);
        au_display.append_column (_("Available plugins"), aucols.name);
@@ -151,7 +151,7 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        }
 #endif
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
        notebook.pages().push_back (TabElem (auscroller, _("AudioUnit")));
 #endif
 
@@ -171,7 +171,7 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        }
 #endif
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
        au_display.signal_button_press_event().connect_notify (mem_fun(*this, &PluginSelector::row_clicked));
        au_display.get_selection()->signal_changed().connect (mem_fun(*this, &PluginSelector::au_display_selection_changed));
 #endif
@@ -187,7 +187,7 @@ PluginSelector::PluginSelector (PluginManager *mgr)
        vst_refiller ();
 #endif
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
        au_refiller ();
 #endif
 
@@ -219,7 +219,7 @@ PluginSelector::set_correct_focus()
        }
 #endif
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
        cp--;
 
        if (cp == 0) {
@@ -330,7 +330,7 @@ PluginSelector::vst_display_selection_changed()
 
 #endif //VST_SUPPORT
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
 
 void
 PluginSelector::_au_refiller (void *arg)
@@ -374,7 +374,7 @@ PluginSelector::au_display_selection_changed()
        current_selection = ARDOUR::AudioUnit;
 }
 
-#endif //HAVE_COREAUDIO
+#endif //HAVE_AUDIOUNIT
 
 void
 PluginSelector::use_plugin (PluginInfoPtr pi)
@@ -413,7 +413,7 @@ PluginSelector::btn_add_clicked()
 #endif
                        break;
                case ARDOUR::AudioUnit:
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
                        row = *(au_display.get_selection()->get_selected());
                        name = row[aucols.name];
                        pi = row[aucols.plugin];
@@ -451,7 +451,7 @@ PluginSelector::btn_update_clicked()
 #ifdef VST_SUPPORT
        vst_refiller ();
 #endif 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
        au_refiller ();
 #endif
 }
index d71203131c3a7bb647cb6d9d3491b45c8e0b5fa2..73c3008e642bfd5e3b3b029739056b223f35a67d 100644 (file)
@@ -110,7 +110,7 @@ class PluginSelector : public ArdourDialog
        void vst_display_selection_changed();
 #endif // VST_SUPPORT
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
        // page 3
        struct AUColumns : public Gtk::TreeModel::ColumnRecord {
                AUColumns () {
@@ -131,7 +131,7 @@ class PluginSelector : public ArdourDialog
        static void _au_refiller (void *);
        void au_refiller ();
        void au_display_selection_changed();
-#endif //HAVE_COREAUDIO
+#endif //HAVE_AUDIOUNIT
 
        ARDOUR::PluginManager *manager;
 
index 642e863ddbbd38eea5c85c401242e79b77afc800..a7b709682977f757ec6d8b87764e5153bc7df75a 100644 (file)
@@ -62,7 +62,7 @@
 
 #include "i18n.h"
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
 #include "au_pluginui.h"
 #endif
 
@@ -1001,7 +1001,7 @@ RedirectBox::edit_redirect (boost::shared_ptr<Redirect> redirect)
                                } else {
                                        plugin_ui->show_all ();
                                }
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNIT
                        } else if (type == ARDOUR::AudioUnit) {
                                AUPluginUI* plugin_ui;
                                if (plugin_insert->get_gui() == 0) {
index 6858b8442dfd58a91af9a6e430089a9a718166a7..b0601704c89adc27229c0fb04e9d1c8a1e2e6a9b 100644 (file)
@@ -269,7 +269,11 @@ SoundFileBox::remove_field_clicked ()
 void
 SoundFileBox::field_edited (const Glib::ustring& str1, const Glib::ustring& str2)
 {
-       cout << "field_edited" << endl;
+       Gtk::TreeModel::Children rows(fields->children());
+       Gtk::TreeModel::Row row(rows[atoi(str1.c_str())]);
+       
+       Library->set_field (path, row[label_columns.field], str2);
+       
        Library->save_changes ();
 }
 
index 254f5a0560ee1e6ca8845a8fbd032cf6e13cadec..c15897d8be8c08b8c83e0914eb16bb56a8614a73 100644 (file)
@@ -116,7 +116,8 @@ arch_specific_objects = [ ]
 
 osc_files = [ 'osc.cc' ]
 vst_files = [ 'vst_plugin.cc', 'session_vst.cc' ]
-coreaudio_files = [ 'audio_unit.cc', 'coreaudiosource.cc' ]
+audiounit_files = [ 'audio_unit.cc' ]
+coreaudio_files = [ 'coreaudiosource.cc' ]
 extra_sources = [ ]
 
 if ardour['VST']:
@@ -194,11 +195,15 @@ if conf.CheckCHeader('sys/vfs.h'):
 if conf.CheckCHeader('/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h'):
     ardour.Append(LINKFLAGS="-framework CoreMIDI")
 
-if conf.CheckCHeader('/System/Library/Frameworks/AudioToolbox.framework/Headers/ExtendedAudioFile.h') and ardour['COREAUDIO'] == 1:
+if conf.CheckCHeader('/System/Library/Frameworks/AudioUnit.framework/Headers/AudioUnit.h') and ardour['AUDIOUNITS']:
+    ardour.Append(CXXFLAGS="-DHAVE_AUDIOUNITS")
+    ardour.Append(LINKFLAGS="-framework AudioUnit")
+    extra_sources += audiounit_files
+if conf.CheckCHeader('/System/Library/Frameworks/AudioToolbox.framework/Headers/ExtendedAudioFile.h') and ardour['COREAUDIO']:
     ardour.Append(CXXFLAGS="-DHAVE_COREAUDIO")    
     ardour.Append(LINKFLAGS="-framework AudioToolbox")
     extra_sources += coreaudio_files
-    
 
 if env['CONFIG_ARCH'] == 'apple':
     # this next line avoids issues with circular dependencies between libardour and libardour_cp.
@@ -226,7 +231,7 @@ ardour.Merge ([
 if ardour['LIBLO']:
     ardour.Merge ([ libraries['lo'] ])
 
-if ardour['COREAUDIO']:
+if ardour['COREAUDIO'] or ardour['AUDIOUNITS']:
     ardour.Merge ([ libraries['appleutility'] ])
 
 ardour.VersionBuild(['version.cc', 'ardour/version.h'], 'SConscript')
@@ -256,12 +261,12 @@ libardour = ardour.SharedLibrary('ardour', ardour_files + extra_sources + arch_s
 Default(libardour)
 
 if env['NLS']:
-       i18n (ardour, ardour_files + vst_files + coreaudio_files, env)
+       i18n (ardour, ardour_files + vst_files + coreaudio_files + audiounit_files, env)
 
 
 env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libardour))
              
 env.Alias('tarball', env.Distribute (env['DISTTREE'],
                                     [ 'SConscript', 'i18n.h', 'gettext.h', 'sse_functions.s', 'sse_functions_64bit.s' ] +
-                                    ardour_files + vst_files + coreaudio_files +
+                                    ardour_files + vst_files + coreaudio_files + audiounit_files +
                                     glob.glob('po/*.po') + glob.glob('ardour/*.h')))
index db814bbb5fce39f93a09047eda03149a23d5b4d8..5f9e53380f049215f2119506af359c5e391546a6 100644 (file)
@@ -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);
index dd689e9a2d350dae6823a419c313a7977aadd17f..8d51343ffbd1bad6a48c117aedd66c688d550bb6 100644 (file)
@@ -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
index 85c78970260fb91e063044e89bcd6408b903dc0c..5222eefb0a4da087eabee287c86feecae216eb77 100644 (file)
@@ -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)
index 5da254b6df31e02d61c5e9ae7b7e62271bdfce66..a436722cb04cf6d11d23f55b2e691e4964a3bdec 100644 (file)
@@ -106,7 +106,13 @@ class Port : public sigc::trackable {
        }
        
        void ensure_monitor_input (bool yn) {
+
+#ifdef WITH_JACK_PORT_ENSURE_MONITOR
                jack_port_ensure_monitor (_port, yn);
+#else
+               jack_port_request_monitor(_port, yn);
+#endif
+
        }
 
        /*XXX completely bloody useless imho*/
index 1abba574f1980a7f2c35bd84e1108de64fe012bc..c3e93fc7ae51ea7880d6cb2e152b777310edcc60 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <vector>
 #include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
 
 #include <pbd/undo.h>
 #include <pbd/statefuldestructible.h> 
@@ -58,7 +59,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:
        typedef std::vector<boost::shared_ptr<Source> > SourceList;
index 47b6c163ef383f0e9e158a18e1f5a0c4cf9bcd3b..09fd01baec4667f260cb18d06d942ae27014229b 100644 (file)
@@ -374,6 +374,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*);
@@ -392,8 +394,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 */
@@ -432,7 +435,8 @@ class Session : public sigc::trackable, public PBD::StatefulDestructible
                MidiFeedback,
                MidiControl,
                TranzportControl,
-               Feedback
+               Feedback,
+               SmpteMode,
        };
 
        sigc::signal<void,ControlType> ControlChanged;
@@ -593,6 +597,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;
@@ -602,7 +607,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;
@@ -621,8 +654,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; }
@@ -1074,7 +1110,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;
@@ -1176,6 +1214,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;
@@ -1817,6 +1857,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
index 1728cdb4779ea36e6b1fceae87b21abaa6f1c940..a18250fff25b927ebeef8acd33cba84e703b37eb 100644 (file)
@@ -24,7 +24,6 @@
 #include <string>
 
 #include <sigc++/signal.h>
-#include <boost/enable_shared_from_this.hpp>
 
 #include <pbd/statefuldestructible.h> 
 
@@ -33,7 +32,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, DataType type);
index ee4482d26061cf8c880862cd7ea4c7b7c7d31b58..214e74156c6732cb1fe42848e64bc172758dfa06 100644 (file)
@@ -25,7 +25,7 @@
 #include <string>
 #include <cmath>
 
-#ifdef HAVE_COREAUDIO
+#if defined(HAVE_COREAUDIO) || defined(HAVE_AUDIOUNITS)
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
@@ -57,8 +57,11 @@ int touch_file(std::string path);
 std::string region_name_from_path (std::string path);
 std::string path_expand (std::string);
 
-#ifdef HAVE_COREAUDIO
+void compute_equal_power_fades (jack_nframes_t nframes, float* in, float* out);
+
+#if defined(HAVE_COREAUDIO) || defined(HAVE_AUDIOUNITS)
 std::string CFStringRefToStdString(CFStringRef stringRef);
 #endif // HAVE_COREAUDIO
 
 #endif /* __ardour_utils_h__ */
+
index 7f062880b26584398bfef9406c1f2fe47674ea78..7b77aad8f5e0e75a3618ebb98f4447cf721c2b33 100644 (file)
@@ -251,8 +251,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());
        }
 }
@@ -386,8 +385,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()) {
index ad008f6312d4463444fe2db8b3929bcdb1184d02..3aa6d05be1fea88bc087318d349829c1583e8ab8 100644 (file)
@@ -432,9 +432,9 @@ AudioLibrary::safe_file_extension(string file)
         file.rfind(".vwe") == string::npos &&
         file.rfind(".paf") == string::npos &&
 #ifdef HAVE_COREAUDIO
-               file.rfind(".mp3") == string::npos &&
-               file.rfind(".aac") == string::npos &&
-               file.rfind(".mp4") == string::npos &&
+       file.rfind(".mp3") == string::npos &&
+       file.rfind(".aac") == string::npos &&
+       file.rfind(".mp4") == string::npos &&
 #endif // HAVE_COREAUDIO
         file.rfind(".voc") == string::npos);
 }
index ad9862181407fe0ba9389fae42d817756b5df266..57d5505a0f3c22331c3403c3a6b33a8904fd6977 100644 (file)
@@ -394,3 +394,4 @@ AUPluginInfo::setup_nchannels (CAComponentDescription& comp_desc)
                                              0, &cinfo, &info_size);
        }
 }
+
index fe29037cb737725c035db5d4350f8653b9bc08c6..027a6233017b215ac376d57cc878de91b281c35b 100644 (file)
@@ -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);
index b9d21223e3e5e826644accc8b7850836e6b5f58f..d74a38097cda8428557f7d708bf54e9dfea537ce 100644 (file)
@@ -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;
        }
index 652ca1e4f2d09bbf783b31da416e15078368a63e..0d7e690a25b2f343e1811398f4518ca951c1f1f5 100644 (file)
@@ -31,16 +31,12 @@ CoreAudioSource::CoreAudioSource (const XMLNode& node)
        : AudioFileSource (node)
 {
        init (_name);
-       
-       SourceCreated (this); /* EMIT SIGNAL */
 }
 
 CoreAudioSource::CoreAudioSource (const string& idstr, Flag flags)
        : AudioFileSource(idstr, flags)
 {
        init (idstr);
-
-       SourceCreated (this); /* EMIT SIGNAL */
 }
 
 void 
index 7bf47e84a07266dd9b7510d975a1c1876ea6e9b2..bf16b40005c7e7247f15d3ca1e3a0a42791ee893 100644 (file)
@@ -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;
                }
        }
index 14f67245fdc954ac01390b224588309523ff818f..01c7182e141f50fbec60f39917b588b756153381 100644 (file)
@@ -306,14 +306,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) ;
@@ -372,8 +376,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 {
index 55938ab2409324cb805ead0ab03e465acf488d8d..c74c81f7e39d90939feb6926cb1a6f2f4403721b 100644 (file)
@@ -36,7 +36,7 @@
 #include <ardour/vst_plugin.h>
 #endif
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNITS
 #include <ardour/audio_unit.h>
 #endif
 
@@ -523,7 +523,7 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
 #ifdef VST_SUPPORT
        boost::shared_ptr<VSTPlugin> vp;
 #endif
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNITS
        boost::shared_ptr<AUPlugin> ap;
 #endif
 
@@ -533,7 +533,7 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
        } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
                return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
 #endif
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNITS
        } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
                return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
 #endif
@@ -839,7 +839,7 @@ PluginInsert::type ()
 #ifdef VST_SUPPORT
        boost::shared_ptr<VSTPlugin> vp;
 #endif
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNITS
        boost::shared_ptr<AUPlugin> ap;
 #endif
        
@@ -851,7 +851,7 @@ PluginInsert::type ()
        } else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
                return ARDOUR::VST;
 #endif
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNITS
        } else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
                return ARDOUR::AudioUnit;
 #endif
index 58ef812d2e51a009ca745dde98032dbf3b3cad4a..30b28c6abee73a937e76d9eec31988ab66f3d5c9 100644 (file)
@@ -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;
        }
index bedc32a0b359f53e951ef1f344458fea05b05b71..8d200b0ee413b30a273de56d59d90e81335bd72e 100644 (file)
@@ -261,7 +261,7 @@ ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginType ty
                break;
 #endif
 
-#ifdef HAVE_COREAUDIO
+#ifdef HAVE_AUDIOUNITS
        case ARDOUR::AudioUnit:
                plugs = AUPluginInfo::discover ();
                unique_id = 0; // Neither do AU.
@@ -282,3 +282,4 @@ ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginType ty
        
        return PluginPtr ((Plugin*) 0);
 }
+
index 48431087ae87f293a1db24ce70c9ee7b0ea0cfed..c420649ef25514e01b2ca685efe834f51b5d7d5c 100644 (file)
@@ -33,6 +33,7 @@
 #include <ardour/playlist.h>
 #include <ardour/session.h>
 #include <ardour/source.h>
+#include <ardour/region_factory.h>
 
 #include "i18n.h"
 
@@ -400,7 +401,7 @@ Region::first_edit ()
                _first_edit = EditChangesNothing;
 
                send_change (NameChanged);
-               /// XXX CheckNewRegion (boost::shared_ptr<Region>(this));
+               RegionFactory::CheckNewRegion (shared_from_this());
        }
 }
 
index 3c325ee5385b7d6aa5e92a910d8262ca4714872c..ebdbea1fc499ab79e59de102d10629be6cb15a6e 100644 (file)
@@ -98,9 +98,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)
@@ -298,6 +302,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 */
        }
@@ -1435,8 +1441,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));
 
@@ -2759,8 +2766,6 @@ Session::remove_region_from_region_list (boost::shared_ptr<Region> r)
 void
 Session::add_source (boost::shared_ptr<Source> source)
 {
-       cerr << "add new source " << source->name() << endl;
-
        pair<SourceMap::key_type, SourceMap::mapped_type> entry;
        pair<SourceMap::iterator,bool> result;
 
@@ -4083,6 +4088,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)
 {
index e99478e0b40e73aa63f3ab353ef955e1754bdf36..8379b93e8357be12c511355c1a4680f9ffdac8c8 100644 (file)
@@ -742,7 +742,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);
@@ -777,16 +778,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);
 
@@ -845,3 +850,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;
+}
+
index c3eee04de4e03a568c6690854fdb3f430a7e8ae4..eaaa723a0c107bd1b8139f070b944e915b9f9d03 100644 (file)
@@ -229,6 +229,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;
@@ -264,6 +276,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));
 
@@ -926,6 +939,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 );
@@ -1180,6 +1198,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);
index 945dfbe48bafbcf8f31efb0a8550fd8c24dc35ce..c74d3021cb66a31e3bf869e146a4d8dad436cb03 100644 (file)
@@ -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
@@ -83,6 +88,8 @@ Session::set_smpte_type (float fps, bool drop_frames)
                break;
        };
 
+       sync_time_vars();
+
        SMPTETypeChanged (); /* EMIT SIGNAL */
 
        set_dirty();
@@ -90,6 +97,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)
 {
@@ -411,6 +432,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 */
 
index 85e2dd391f31ab23dfec420c1eee60b520dbcd79..561d63fe781fcbb3fa47ddc85894377f3fe0f46e 100644 (file)
@@ -191,6 +191,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);
 }
 
index 2bdcdc5a02e25181a3b9b362c8faf6b88b9a5cb5..b6ded6d6173b27bda0b1995a2d44e5a3da3bcfa8 100644 (file)
@@ -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 */
index 2fcdd290334f07fd3557dff32e3bcc9063eba31c..61a7659a5edf08e460a2b63708c4e88f3799d4ff 100644 (file)
 #include <ardour/destructive_filesource.h>
 #include <ardour/configuration.h>
 
+#ifdef HAVE_COREAUDIO
+#include <ardour/coreaudiosource.h>
+#endif
+
 #include "i18n.h"
 
 using namespace ARDOUR;
@@ -32,8 +36,6 @@ using namespace std;
 sigc::signal<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
 
 #ifdef HAVE_COREAUDIO
-
-
 boost::shared_ptr<Source>
 SourceFactory::create (const XMLNode& node)
 {
index 26b5966086f8cf58c33e9de0aeee188cd95c2e6a..8d9d799a4427aa4d5eb2a1b7534c83c447447a21 100644 (file)
@@ -259,7 +259,7 @@ path_expand (string path)
 #endif
 }
 
-#ifdef HAVE_COREAUDIO
+#if defined(HAVE_COREAUDIO) || defined(HAVE_AUDIOUNITS)
 string 
 CFStringRefToStdString(CFStringRef stringRef)
 {
@@ -277,3 +277,29 @@ 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);
+       }
+}