using namespace std;
using namespace ARDOUR;
+using namespace PBD;
gain_t* DestructiveFileSource::out_coefficient = 0;
gain_t* DestructiveFileSource::in_coefficient = 0;
jack_nframes_t DestructiveFileSource::xfade_frames = 64;
-DestructiveFileSource::DestructiveFileSource (string path, jack_nframes_t rate, bool repair_first, SampleFormat samp_format)
- : FileSource (path, rate, repair_first, samp_format)
+DestructiveFileSource::DestructiveFileSource (string path, SampleFormat samp_format, HeaderFormat hdr_format, jack_nframes_t rate, Flag flags)
+ : SndFileSource (path, samp_format, hdr_format, rate, flags)
{
- if (out_coefficient == 0) {
- setup_standard_crossfades (rate);
- }
+ init ();
+}
- xfade_buf = new Sample[xfade_frames];
- _capture_start = false;
- _capture_end = false;
+DestructiveFileSource::DestructiveFileSource (string path, Flag flags)
+ : SndFileSource (path, flags)
+{
+ init ();
}
-DestructiveFileSource::DestructiveFileSource (const XMLNode& node, jack_nframes_t rate)
- : FileSource (node, rate)
+DestructiveFileSource::DestructiveFileSource (const XMLNode& node)
+ : SndFileSource (node)
{
- if (out_coefficient == 0) {
- setup_standard_crossfades (rate);
- }
+ init ();
+}
+void
+DestructiveFileSource::init ()
+{
xfade_buf = new Sample[xfade_frames];
_capture_start = false;
_capture_end = false;
+ file_pos = 0;
+
+ timeline_position = header_position_offset;
+ AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &DestructiveFileSource::handle_header_position_change));
}
DestructiveFileSource::~DestructiveFileSource()
void
DestructiveFileSource::setup_standard_crossfades (jack_nframes_t rate)
{
- xfade_frames = (jack_nframes_t) floor ((/*Config->get_destructive_crossfade_msecs()*/ 64 / 1000.0) * rate);
+ /* This static method is assumed to have been called by the Session
+ before any DFS's are created.
+ */
+
+ xfade_frames = (jack_nframes_t) floor ((Config->get_destructive_xfade_msecs () / 1000.0) * rate);
+
+ if (out_coefficient) {
+ delete [] out_coefficient;
+ }
+
+ if (in_coefficient) {
+ delete [] in_coefficient;
+ }
out_coefficient = new gain_t[xfade_frames];
in_coefficient = new gain_t[xfade_frames];
}
}
-int
-DestructiveFileSource::seek (jack_nframes_t frame)
-{
- return 0;
-}
-
void
DestructiveFileSource::mark_capture_start (jack_nframes_t pos)
{
- _capture_start = true;
- capture_start_frame = pos;
+ if (pos < timeline_position) {
+ _capture_start = false;
+ } else {
+ _capture_start = true;
+ capture_start_frame = pos;
+ }
}
void
jack_nframes_t xfade = min (xfade_frames, cnt);
jack_nframes_t nofade = cnt - xfade;
Sample* fade_data = 0;
- off_t fade_position = 0; // in frames
+ jack_nframes_t fade_position = 0; // in frames
ssize_t retval;
-
+ jack_nframes_t file_cnt;
+
if (fade_in) {
fade_position = file_pos;
fade_data = data;
fade_data = data + nofade;
}
- if ((retval = file_read (xfade_buf, fade_position, xfade, workbuf)) != (ssize_t) xfade) {
- 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 */
+ if (fade_position > _length) {
+
+ /* read starts beyond end of data, just memset to zero */
+
+ file_cnt = 0;
- xfade = retval;
- nofade = cnt - xfade;
- } else {
- error << string_compose(_("DestructiveFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"), _path, retval, errno, strerror (errno), xfade) << endmsg;
- return 0;
+ } else if (fade_position + xfade > _length) {
+
+ /* read ends beyond end of data, read some, memset the rest */
+
+ file_cnt = _length - fade_position;
+
+ } else {
+
+ /* read is entirely within data */
+
+ file_cnt = xfade;
+ }
+
+ if (file_cnt) {
+ if ((retval = write_float (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 */
+ memset (xfade_buf, 0, xfade * sizeof(Sample));
+ } else {
+ error << string_compose(_("DestructiveFileSource: \"%1\" bad read retval: %2 of %5 (%3: %4)"), _path, retval, errno, strerror (errno), xfade) << endmsg;
+ return 0;
+ }
}
+ }
+
+ if (file_cnt != xfade) {
+ jack_nframes_t delta = xfade - file_cnt;
+ memset (xfade_buf+file_cnt, 0, sizeof (Sample) * delta);
}
if (nofade && !fade_in) {
- cerr << "write " << nofade << " frames of prefade OUT data to " << file_pos << " .. " << file_pos + nofade << endl;
- if (file_write (data, file_pos, nofade, workbuf) != (ssize_t) nofade) {
+ if (write_float (data, file_pos, nofade) != nofade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
}
if (xfade) {
- cerr << "write " << xfade << " frames of xfade data to " << fade_position << " .. " << fade_position + xfade << endl;
-
- if (file_write (xfade_buf, fade_position, xfade, workbuf) != (ssize_t) xfade) {
+ if (write_float (xfade_buf, fade_position, xfade) != xfade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
}
if (fade_in && nofade) {
- cerr << "write " << nofade << " frames of postfade IN data to " << file_pos + xfade << " .. "
- << file_pos + xfade + nofade << endl;
- if (file_write (data + xfade, file_pos + xfade, nofade, workbuf) != (ssize_t) nofade) {
+ if (write_float (data + xfade, file_pos + xfade, nofade) != nofade) {
error << string_compose(_("DestructiveFileSource: \"%1\" bad write (%2)"), _path, strerror (errno)) << endmsg;
return 0;
}
}
jack_nframes_t
-DestructiveFileSource::write (Sample* data, jack_nframes_t cnt, char * workbuf)
+DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char * workbuf)
{
- cerr << _name << ": write " << cnt << " to " << file_pos << " start ? " << _capture_start << " end ? " << _capture_end << endl;
+ jack_nframes_t old_file_pos;
- {
- LockMonitor lm (_lock, __LINE__, __FILE__);
-
- jack_nframes_t oldlen;
+ if (!writable()) {
+ return 0;
+ }
- if (_capture_start) {
- _capture_start = false;
- _capture_end = false;
+ if (_capture_start && _capture_end) {
- /* move to the correct location place */
- //file_pos = data_offset + (capture_start_frame * sizeof (Sample));
- file_pos = capture_start_frame;
-
- cerr << "First frame of capture will be at " << file_pos << endl;
-
- if (crossfade (data, cnt, 1, workbuf) != cnt) {
- return 0;
- }
+ /* start and end of capture both occur within the data we are writing,
+ so do both crossfades.
+ */
+
+ _capture_start = false;
+ _capture_end = false;
+
+ /* move to the correct location place */
+ file_pos = capture_start_frame;
+
+ // split cnt in half
+ jack_nframes_t subcnt = cnt / 2;
+ jack_nframes_t ofilepos = file_pos;
+
+ // fade in
+ if (crossfade (data, subcnt, 1, workbuf) != subcnt) {
+ return 0;
+ }
+
+ file_pos += subcnt;
+ Sample * tmpdata = data + subcnt;
+
+ // fade out
+ subcnt = cnt - subcnt;
+ if (crossfade (tmpdata, subcnt, 0, workbuf) != subcnt) {
+ return 0;
+ }
+
+ file_pos = ofilepos; // adjusted below
- } else if (_capture_end) {
- _capture_start = false;
- _capture_end = false;
+ } else if (_capture_start) {
- if (crossfade (data, cnt, 0, workbuf) != cnt) {
- return 0;
- }
- } else {
- if (file_write(data, file_pos, cnt, workbuf) != (ssize_t) cnt) {
- return 0;
- }
+ /* start of capture both occur within the data we are writing,
+ so do the fade in
+ */
+
+ _capture_start = false;
+ _capture_end = false;
+
+ /* move to the correct location place */
+ file_pos = capture_start_frame;
+
+ if (crossfade (data, cnt, 1, workbuf) != cnt) {
+ return 0;
}
+
+ } else if (_capture_end) {
- oldlen = _length;
- if (file_pos + cnt > _length) {
- _length += cnt;
+ /* end of capture both occur within the data we are writing,
+ so do the fade out
+ */
+
+ _capture_start = false;
+ _capture_end = false;
+
+ if (crossfade (data, cnt, 0, workbuf) != cnt) {
+ return 0;
}
- file_pos += cnt;
- cerr << "at end of write, file_pos = " << file_pos << endl;
+ } else {
- if (_build_peakfiles) {
- PeakBuildRecord *pbr = 0;
-
- if (pending_peak_builds.size()) {
- pbr = pending_peak_builds.back();
- }
+ /* in the middle of recording */
+
+ if (write_float (data, file_pos, cnt) != cnt) {
+ return 0;
+ }
+ }
+
+ old_file_pos = file_pos;
+ update_length (file_pos, cnt);
+ file_pos += cnt;
+
+ if (_build_peakfiles) {
+ PeakBuildRecord *pbr = 0;
+
+ if (pending_peak_builds.size()) {
+ pbr = pending_peak_builds.back();
+ }
+
+ if (pbr && pbr->frame + pbr->cnt == old_file_pos) {
- 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));
- }
+ /* the last PBR extended to the start of the current write,
+ so just extend it again.
+ */
- _peaks_built = false;
+ pbr->cnt += cnt;
+ } else {
+ pending_peak_builds.push_back (new PeakBuildRecord (old_file_pos, cnt));
}
-
+
+ _peaks_built = false;
}
-
if (_build_peakfiles) {
queue_for_peaks (*this);
}
-
+
return cnt;
}
{
return capture_start_frame;
}
+
+XMLNode&
+DestructiveFileSource::get_state ()
+{
+ XMLNode& node = AudioFileSource::get_state ();
+ node.add_property (X_("destructive"), "true");
+ return node;
+}
+
+void
+DestructiveFileSource::handle_header_position_change ()
+{
+ if ( _length != 0 ) {
+ error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
+ //in the future, pop up a dialog here that allows user to regenerate file with new start offset
+ } else if (writable()) {
+ timeline_position = header_position_offset;
+ set_header_timeline_position (); //this will get flushed if/when the file is recorded to
+ }
+}
+
+void
+DestructiveFileSource::set_timeline_position (jack_nframes_t pos)
+{
+ //destructive track timeline postion does not change except at instantion or when header_position_offset (session start) changes
+}