diff --git a/gtk2_ardour/ardour-menus.xml b/gtk2_ardour/ardour-menus.xml index 6521753bea..57be502461 100644 --- a/gtk2_ardour/ardour-menus.xml +++ b/gtk2_ardour/ardour-menus.xml @@ -59,6 +59,16 @@ + + + + + + + + + + diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 30f57a9d13..7b2dfcdf44 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -652,92 +652,6 @@ ARDOUR_UI::update_wall_clock () return TRUE; } - -void -ARDOUR_UI::toggle_auto_play () - -{ - toggle_some_session_state (auto_play_button, - &Session::get_auto_play, - &Session::set_auto_play); -} - -void -ARDOUR_UI::toggle_auto_return () - -{ - toggle_some_session_state (auto_return_button, - &Session::get_auto_return, - &Session::set_auto_return); -} - -void -ARDOUR_UI::toggle_click () -{ - toggle_some_session_state (click_button, - &Session::get_clicking, - &Session::set_clicking); -} - -void -ARDOUR_UI::toggle_session_auto_loop () -{ - if (session) { - if (session->get_auto_loop()) { - if (session->transport_rolling()) { - transport_roll(); - } - else { - session->request_auto_loop (false); - } - } - else { - session->request_auto_loop (true); - } - } -} - -void -ARDOUR_UI::toggle_session_punch_in () -{ - if (session) { - session->set_punch_in (!session->get_punch_in()); - } -} - -void -ARDOUR_UI::toggle_punch_out () -{ - toggle_some_session_state (punch_out_button, - &Session::get_punch_out, - &Session::set_punch_out); -} - -void -ARDOUR_UI::toggle_punch_in () -{ - toggle_some_session_state (punch_in_button, - &Session::get_punch_in, - &Session::set_punch_in); -} - -void -ARDOUR_UI::map_button_state () -{ - map_some_session_state (auto_return_button, - &Session::get_auto_return); - map_some_session_state (auto_play_button, - &Session::get_auto_play); - map_some_session_state (auto_input_button, - &Session::get_auto_input); - map_some_session_state (punch_in_button, - &Session::get_punch_in); - map_some_session_state (punch_out_button, - &Session::get_punch_out); - map_some_session_state (click_button, - &Session::get_clicking); -} - void ARDOUR_UI::control_methods_adjusted () @@ -789,38 +703,6 @@ ARDOUR_UI::map_some_session_state (ToggleButton& button, } } -void -ARDOUR_UI::toggle_some_session_state (ToggleButton& button, - bool (Session::*get)() const, - void (Session::*set)(bool)) - -{ - bool button_state; - bool session_state; - - if (session == 0) { - return; - } - - button_state = button.get_active (); - session_state = (session->*get)(); - - if (button_state != session_state) { - (session->*set) (button_state); -#if 0 - - /* check that it worked, and reverse - the button state if it didn't - */ - - if ((session->*get)() != button_state) { - button->set_active (!button_state); - } -#endif - - } -} - gint ARDOUR_UI::session_menu (GdkEventButton *ev) { diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index 284a89ab21..2b6cf1f565 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -299,14 +299,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI void engine_stopped (); void engine_running (); - void map_some_session_state (Gtk::ToggleButton& button, - bool (ARDOUR::Session::*get)() const); - - void toggle_some_session_state (Gtk::ToggleButton& button, - bool (ARDOUR::Session::*get)() const, - void (ARDOUR::Session::*set)(bool)); - void map_button_state (); - void clear_meters (); static gint _blink (void *); diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc index ab4a0e9b53..3ce826ca82 100644 --- a/gtk2_ardour/ardour_ui2.cc +++ b/gtk2_ardour/ardour_ui2.cc @@ -381,14 +381,12 @@ ARDOUR_UI::setup_transport () ARDOUR_UI::instance()->tooltips().set_tip (primary_clock, _("Primary clock")); ARDOUR_UI::instance()->tooltips().set_tip (secondary_clock, _("secondary clock")); - /* options: XXX these should all be actions with the buttons as proxies */ - - auto_return_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_auto_return)); - auto_play_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_auto_play)); - auto_input_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_auto_input)); - click_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_click)); - punch_in_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_punch_in)); - punch_out_button.signal_toggled().connect (mem_fun(*this,&ARDOUR_UI::toggle_punch_out)); + ActionManager::get_action ("Transport", "ToggleAutoReturn")->connect_proxy (auto_return_button); + ActionManager::get_action ("Transport", "ToggleAutoPlay")->connect_proxy (auto_play_button); + ActionManager::get_action ("Transport", "ToggleAutoInput")->connect_proxy (auto_input_button); + ActionManager::get_action ("Transport", "ToggleClick")->connect_proxy (click_button); + ActionManager::get_action ("Transport", "TogglePunchIn")->connect_proxy (punch_in_button); + ActionManager::get_action ("Transport", "TogglePunchOut")->connect_proxy (punch_out_button); preroll_button.unset_flags (CAN_FOCUS); preroll_button.set_events (preroll_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK)); diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc index 6c8b5b540e..84900e702a 100644 --- a/gtk2_ardour/ardour_ui_dialogs.cc +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -110,8 +110,6 @@ ARDOUR_UI::connect_to_session (Session *s) /* Clocks are on by default after we are connected to a session, so show that here. */ - map_button_state (); - connect_dependents_to_session (s); start_clocking (); @@ -258,15 +256,6 @@ ARDOUR_UI::toggle_options_window () } } -void -ARDOUR_UI::toggle_auto_input () - -{ - toggle_some_session_state (auto_input_button, - &Session::get_auto_input, - &Session::set_auto_input); -} - int ARDOUR_UI::create_location_ui () { diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 753aa6a667..e2e24f5bd8 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -70,6 +70,7 @@ ARDOUR_UI::install_actions () ActionManager::register_action (main_actions, X_("Cleanup"), _("Cleanup")); ActionManager::register_action (main_actions, X_("Sync"), _("Sync")); ActionManager::register_action (main_actions, X_("Options"), _("Options")); + ActionManager::register_action (main_actions, X_("TransportOptions"), _("Options")); /* the real actions */ @@ -242,19 +243,31 @@ 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_("TogglePunchIn"), _("punch in"), mem_fun(*this, &ARDOUR_UI::toggle_punch_in)); - ActionManager::session_sensitive_actions.push_back (act); - ActionManager::transport_sensitive_actions.push_back (act); - act = ActionManager::register_toggle_action (transport_actions, X_("TogglePunchOut"), _("punch out"), mem_fun(*this, &ARDOUR_UI::toggle_punch_out)); - ActionManager::session_sensitive_actions.push_back (act); - ActionManager::transport_sensitive_actions.push_back (act); - - /* XXX the newline in the displayed name of this action is really wrong, but its because we want the button - that proxies for this action to be more compact. It would be nice to find a way to override the action - name appearance on the button. + /* XXX the newline in the displayed names of these action is really wrong, but its because we want the button + that proxies for these action to be more compact. It would be nice to find a way to override the action + name appearance on the buttons. */ - act = ActionManager::register_action (transport_actions, X_("ToggleTimeMaster"), _("time\nmaster"), mem_fun(*this, &ARDOUR_UI::toggle_time_master)); + act = ActionManager::register_toggle_action (transport_actions, X_("TogglePunchIn"), _("punch\nin"), mem_fun(*this, &ARDOUR_UI::toggle_punch_in)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::transport_sensitive_actions.push_back (act); + act = ActionManager::register_toggle_action (transport_actions, X_("TogglePunchOut"), _("punch\nout"), mem_fun(*this, &ARDOUR_UI::toggle_punch_out)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::transport_sensitive_actions.push_back (act); + act = ActionManager::register_toggle_action (transport_actions, X_("ToggleClick"), _("click"), mem_fun(*this, &ARDOUR_UI::toggle_click)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::transport_sensitive_actions.push_back (act); + act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoInput"), _("auto\ninput"), mem_fun(*this, &ARDOUR_UI::toggle_auto_input)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::transport_sensitive_actions.push_back (act); + act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoPlay"), _("auto\nplay"), mem_fun(*this, &ARDOUR_UI::toggle_auto_play)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::transport_sensitive_actions.push_back (act); + act = ActionManager::register_toggle_action (transport_actions, X_("ToggleAutoReturn"), _("auto\nreturn"), mem_fun(*this, &ARDOUR_UI::toggle_auto_return)); + ActionManager::session_sensitive_actions.push_back (act); + ActionManager::transport_sensitive_actions.push_back (act); + + act = ActionManager::register_toggle_action (transport_actions, X_("ToggleTimeMaster"), _("time\nmaster"), mem_fun(*this, &ARDOUR_UI::toggle_time_master)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (common_actions, X_("SendAllMidiFeedback"), _("send all midi feedback"), mem_fun(*this, &ARDOUR_UI::send_all_midi_feedback)); @@ -391,6 +404,7 @@ ARDOUR_UI::install_actions () act = ActionManager::register_action (option_actions, X_("UnmuteNewFullCrossfades"), _("Unmute new full crossfades"), mem_fun (*this, &ARDOUR_UI::toggle_UnmuteNewFullCrossfades)); ActionManager::session_sensitive_actions.push_back (act); + #ifdef NEW_ACTIONS act = ActionManager::register_action (option_actions, X_("SetRegionLayerMode", _("SetRegionLayerMode"), mem_fun (*this, &ARDOUR_UI::toggle_SetRegionLayerMode))); ActionManager::session_sensitive_actions.push_back (act); diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc index 2fbec5d9a1..a45a820c8e 100644 --- a/gtk2_ardour/ardour_ui_options.cc +++ b/gtk2_ardour/ardour_ui_options.cc @@ -134,6 +134,58 @@ ARDOUR_UI::toggle_ManuallyConnectNewTrackOutputs() toggle_session_state ("options", "AutoConnectNewTrackOutputsToHardware", bind (mem_fun (session, &Session::set_output_auto_connect), Session::AutoConnectOption (0))); } +void +ARDOUR_UI::toggle_auto_input () +{ + toggle_session_state ("Transport", "ToggleAutoInput", &Session::set_auto_input, &Session::get_auto_input); +} + +void +ARDOUR_UI::toggle_auto_play () +{ + toggle_session_state ("Transport", "ToggleAutoPlay", &Session::set_auto_play, &Session::get_auto_play); +} + +void +ARDOUR_UI::toggle_auto_return () +{ + toggle_session_state ("Transport", "ToggleAutoReturn", &Session::set_auto_return, &Session::get_auto_return); +} + +void +ARDOUR_UI::toggle_click () +{ + toggle_session_state ("Transport", "ToggleClick", &Session::set_clicking, &Session::get_clicking); +} + +void +ARDOUR_UI::toggle_session_auto_loop () +{ + if (session) { + if (session->get_auto_loop()) { + if (session->transport_rolling()) { + transport_roll(); + } else { + session->request_auto_loop (false); + } + } else { + session->request_auto_loop (true); + } + } +} + +void +ARDOUR_UI::toggle_punch_in () +{ + toggle_session_state ("Transport", "TogglePunchIn", &Session::set_punch_in, &Session::get_punch_in); +} + +void +ARDOUR_UI::toggle_punch_out () +{ + toggle_session_state ("Transport", "TogglePunchOut", &Session::set_punch_out, &Session::get_punch_out); +} + void ARDOUR_UI::toggle_UseHardwareMonitoring() { @@ -313,6 +365,12 @@ ARDOUR_UI::setup_options () session_control_changed (Session::SoloingModel); session_control_changed (Session::LayeringModel); session_control_changed (Session::CrossfadingModel); + session_control_changed (Session::PunchOut); + session_control_changed (Session::PunchIn); + session_control_changed (Session::AutoPlay); + session_control_changed (Session::AutoReturn); + session_control_changed (Session::AutoInput); + session_control_changed (Session::Clicking); session->ControlChanged.connect (mem_fun (*this, &ARDOUR_UI::queue_session_control_changed)); } @@ -406,34 +464,31 @@ ARDOUR_UI::session_control_changed (Session::ControlType t) break; - // BUTTON STATE: fix me in the future to use actions - - case Session::AutoPlay: - map_some_session_state (auto_play_button, &Session::get_auto_play); + map_some_session_state ("Transport", "ToggleAutoPlay", &Session::get_auto_play); break; case Session::AutoLoop: break; case Session::AutoReturn: - map_some_session_state (auto_return_button, &Session::get_auto_return); + map_some_session_state ("Transport", "ToggleAutoReturn", &Session::get_auto_return); break; case Session::AutoInput: - map_some_session_state (auto_input_button, &Session::get_auto_input); + map_some_session_state ("Transport", "ToggleAutoInput", &Session::get_auto_input); break; case Session::PunchOut: - map_some_session_state (punch_in_button, &Session::get_punch_out); + map_some_session_state ("Transport", "TogglePunchOut", &Session::get_punch_out); break; case Session::PunchIn: - map_some_session_state (punch_in_button, &Session::get_punch_in); + map_some_session_state ("Transport", "TogglePunchIn", &Session::get_punch_in); break; case Session::Clicking: - map_some_session_state (click_button, &Session::get_clicking); + map_some_session_state ("Transport", "ToggleClick", &Session::get_clicking); break; default: diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 6ac880939d..2b74a8d979 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -35,6 +35,7 @@ crossfade.cc curve.cc cycle_timer.cc default_click.cc +destructive_filesource.cc diskstream.cc filesource.cc gain.cc diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index e7ba315e45..81ca8834b3 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002 Paul Davis + Copyright (C) 2002-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,6 +56,10 @@ class AudioTrack : public Route int use_diskstream (string name); int use_diskstream (id_t id); + bool destructive() const { return _destructive; } + void set_destructive (bool yn); + sigc::signal DestructiveChanged; + jack_nframes_t update_total_latency(); void set_latency_delay (jack_nframes_t); @@ -155,6 +159,8 @@ class AudioTrack : public Route }; MIDIRecEnableControl _midi_rec_enable_control; + + bool _destructive; }; }; /* namespace ARDOUR*/ diff --git a/libs/ardour/ardour/destructive_filesource.h b/libs/ardour/ardour/destructive_filesource.h new file mode 100644 index 0000000000..7f816a9e6b --- /dev/null +++ b/libs/ardour/ardour/destructive_filesource.h @@ -0,0 +1,52 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_destructive_file_source_h__ +#define __ardour_destructive_file_source_h__ + +#include + +#include + +struct tm; + +namespace ARDOUR { + +class DestructiveFileSource : public FileSource { + public: + DestructiveFileSource (std::string path, jack_nframes_t rate, bool repair_first = false); + DestructiveFileSource (const XMLNode&, jack_nframes_t rate); + ~DestructiveFileSource (); + + int seek (jack_nframes_t frame); + void mark_capture_start (); + void mark_capture_end (); + void clear_capture_marks(); + + jack_nframes_t write (Sample *src, jack_nframes_t cnt); + + private: + bool _capture_start; + bool _capture_end; +}; + +} + +#endif /* __ardour_destructive_file_source_h__ */ diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 0cdbfd1724..5b63cfad28 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -60,7 +60,8 @@ class DiskStream : public Stateful, public sigc::trackable public: enum Flag { Recordable = 0x1, - Hidden = 0x2 + Hidden = 0x2, + Destructive = 0x4 }; DiskStream (Session &, const string& name, Flag f = Recordable); @@ -92,6 +93,9 @@ class DiskStream : public Stateful, public sigc::trackable bool hidden() const { return _flags & Hidden; } bool recordable() const { return _flags & Recordable; } + bool destructive() const { return _flags & Destructive; } + + void set_destructive (bool yn); jack_nframes_t roll_delay() const { return _roll_delay; } void set_roll_delay (jack_nframes_t); @@ -150,11 +154,6 @@ class DiskStream : public Stateful, public sigc::trackable AudioPlaylist *playlist () { return _playlist; } - FileSource *fades_source (uint32_t n=0) { - if (n < channels.size()) - return channels[n].fades_source; - return 0; - } FileSource *write_source (uint32_t n=0) { if (n < channels.size()) return channels[n].write_source; @@ -245,7 +244,7 @@ class DiskStream : public Stateful, public sigc::trackable void set_block_size (jack_nframes_t); int internal_playback_seek (jack_nframes_t distance); int can_internal_playback_seek (jack_nframes_t distance); - void reset_write_sources (bool); + void reset_write_sources (bool, bool force = false); void non_realtime_input_change (); uint32_t read_data_count() const { return _read_data_count; } diff --git a/libs/ardour/ardour/filesource.h b/libs/ardour/ardour/filesource.h index 75f454f554..fc86656c2e 100644 --- a/libs/ardour/ardour/filesource.h +++ b/libs/ardour/ardour/filesource.h @@ -72,7 +72,7 @@ class FileSource : public Source { static void set_search_path (string); - private: + protected: int fd; string _path; bool remove_at_unref; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 0b13cf5f30..775dbc8ea9 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -686,7 +686,7 @@ class Session : public sigc::trackable, public Stateful sigc::signal SourceAdded; sigc::signal SourceRemoved; - FileSource *create_file_source (ARDOUR::DiskStream&, int32_t chan); + FileSource *create_file_source (ARDOUR::DiskStream&, int32_t chan, bool destructive); Source *get_source (ARDOUR::id_t); /* playlist management */ diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 4a922d631d..1a2137ea6f 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -1096,3 +1096,15 @@ AudioTrack::MIDIRecEnableControl::write_feedback (MIDI::byte* buf, int32_t& bufs return buf; } + +void +AudioTrack::set_destructive (bool yn) +{ + if (diskstream) { + if (_destructive != yn) { + diskstream->set_destructive (yn); + _destructive = yn; + DestructiveChanged(); + } + } +} diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc new file mode 100644 index 0000000000..f0813f61dc --- /dev/null +++ b/libs/ardour/destructive_filesource.cc @@ -0,0 +1,155 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +/* This is is very hacky way to get pread and pwrite declarations. + First, include so that we can avoid its #undef __USE_UNIX98. + Then define __USE_UNIX98, include , and then undef it + again. If #define _XOPEN_SOURCE actually worked, I'd use that, but + despite claims in the header that it does, it doesn't. + + features.h isn't available on osx and it compiles fine without it. +*/ + +#ifdef HAVE_FEATURES_H +#include +#endif + +#if __GNUC__ >= 3 +// #define _XOPEN_SOURCE 500 +#include +#else +#define __USE_UNIX98 +#include +#undef __USE_UNIX98 +#endif + +// darwin supports 64 by default and doesn't provide wrapper functions. +#if defined (__APPLE__) +typedef off_t off64_t; +#define open64 open +#define close64 close +#define lseek64 lseek +#define pread64 pread +#define pwrite64 pwrite +#endif + +#include + +#include +#include + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; + +DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first) + : FileSource (path, rate, repair_first) +{ + _capture_start = false; + _capture_end = false; +} + +DestructiveFileSource::DestructiveFileSource (const XMLNode& node, jack_nframes_t rate) + : FileSource (node, rate) +{ + _capture_start = false; + _capture_end = false; +} + +DestructiveFileSource::~DestructiveFileSource() +{ +} + +int +DestructiveFileSource::seek (jack_nframes_t frame) +{ + return 0; +} + +void +DestructiveFileSource::mark_capture_start () +{ + _capture_start = true; +} + +void +DestructiveFileSource::mark_capture_end() +{ + _capture_end = true; +} + +void +DestructiveFileSource::clear_capture_marks () +{ + _capture_start = false; + _capture_end = false; +} + +jack_nframes_t +DestructiveFileSource::write (Sample* data, jack_nframes_t cnt) +{ + { + LockMonitor lm (_lock, __LINE__, __FILE__); + + int32_t byte_cnt = cnt * sizeof (Sample); + int32_t byte_pos = data_offset + (_length * sizeof (Sample)); + jack_nframes_t oldlen; + + if (::pwrite64 (fd, (char *) data, byte_cnt, byte_pos) != (off64_t) byte_cnt) { + error << string_compose(_("FileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg; + return 0; + } + + oldlen = _length; + _length += cnt; + _write_data_count = byte_cnt; + + if (_build_peakfiles) { + PeakBuildRecord *pbr = 0; + + if (pending_peak_builds.size()) { + pbr = pending_peak_builds.back(); + } + + if (pbr && pbr->frame + pbr->cnt == oldlen) { + + /* the last PBR extended to the start of the current write, + so just extend it again. + */ + + pbr->cnt += cnt; + } else { + pending_peak_builds.push_back (new PeakBuildRecord (oldlen, cnt)); + } + + _peaks_built = false; + } + + } + + + if (_build_peakfiles) { + queue_for_peaks (*this); + } + + return cnt; +} + diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index d0b0415c8c..b19f25be72 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -99,7 +100,6 @@ DiskStream::init_channel (ChannelInfo &chan) chan.capture_wrap_buffer = 0; chan.speed_buffer = 0; chan.peak_power = 0.0f; - chan.fades_source = 0; chan.write_source = 0; chan.source = 0; chan.current_capture_buffer = 0; @@ -1060,8 +1060,12 @@ DiskStream::seek (jack_nframes_t frame, bool complete_refill) for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) { (*chan).playback_buf->reset (); (*chan).capture_buf->reset (); + if (destructive()) { + DestructiveFileSource* dfs = dynamic_cast ((*chan).write_source); + dfs->seek (frame); + } } - + playback_sample = frame; file_frame = frame; @@ -1775,6 +1779,10 @@ DiskStream::get_state () char buf[64]; LocaleGuard lg (X_("POSIX")); + if (destructive()) { + node->add_property ("destructive", "true"); + } + snprintf (buf, sizeof(buf), "%zd", channels.size()); node->add_property ("channels", buf); @@ -1849,6 +1857,12 @@ DiskStream::set_state (const XMLNode& node) _name = prop->value(); } + if ((prop = node.property ("destructive")) != 0) { + if (prop->value() == "true") { + _flags |= Destructive; + } + } + if (deprecated_io_node) { if ((prop = deprecated_io_node->property ("id")) != 0) { sscanf (prop->value().c_str(), "%" PRIu64, &_id); @@ -1966,7 +1980,7 @@ DiskStream::use_new_write_source (uint32_t n) } try { - if ((chan.write_source = _session.create_file_source (*this, n)) == 0) { + if ((chan.write_source = _session.create_file_source (*this, n, destructive())) == 0) { throw failed_constructor(); } } @@ -1983,7 +1997,7 @@ DiskStream::use_new_write_source (uint32_t n) } void -DiskStream::reset_write_sources (bool mark_write_complete) +DiskStream::reset_write_sources (bool mark_write_complete, bool force) { ChannelList::iterator chan; uint32_t n; @@ -1991,6 +2005,10 @@ DiskStream::reset_write_sources (bool mark_write_complete) if (!recordable()) { return; } + + if (!force && destructive()) { + return; + } capturing_sources.clear (); @@ -2310,3 +2328,16 @@ DiskStream::set_roll_delay (jack_nframes_t nframes) { _roll_delay = nframes; } + +void +DiskStream::set_destructive (bool yn) +{ + if (yn != destructive()) { + reset_write_sources (true, true); + if (yn) { + _flags |= Destructive; + } else { + _flags &= ~Destructive; + } + } +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 726d3070bb..63439bf969 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -2619,7 +2620,7 @@ Session::get_source (ARDOUR::id_t id) } FileSource * -Session::create_file_source (DiskStream& ds, int32_t chan) +Session::create_file_source (DiskStream& ds, int32_t chan, bool destructive) { string spath; uint32_t cnt; @@ -2693,7 +2694,11 @@ Session::create_file_source (DiskStream& ds, int32_t chan) /* this might throw failed_constructor(), which is OK */ - return new FileSource (spath, frame_rate()); + if (destructive) { + return new DestructiveFileSource (spath, frame_rate()); + } else { + return new FileSource (spath, frame_rate()); + } } /* Playlist management */ diff --git a/libs/pbd3/undo.cc b/libs/pbd3/undo.cc index 482cb5cf37..0af1cc2e7a 100644 --- a/libs/pbd3/undo.cc +++ b/libs/pbd3/undo.cc @@ -77,7 +77,6 @@ UndoCommand::clear () void UndoCommand::undo () { - cerr << "There are " << undo_actions.size() << " actions to undo\n"; for (list::reverse_iterator i = undo_actions.rbegin(); i != undo_actions.rend(); ++i) { (*i)(); } @@ -100,14 +99,12 @@ UndoHistory::add (UndoCommand uc) void UndoHistory::undo (unsigned int n) { - cerr << "Undo history undoing " << n << " with a list of " << UndoList.size() << endl; while (n--) { if (UndoList.size() == 0) { return; } UndoCommand uc = UndoList.back (); UndoList.pop_back (); - cerr << "undoing command called " << uc.name() << endl; uc.undo (); RedoList.push_back (uc); }