Commit read-only stack security fix for 64bit processors.
[ardour.git] / libs / ardour / sndfilesource.cc
index 1374d9bd31263645701e425859520ecab8d548bf..1e408e12bc701c1b80944831d353920f2653db0f 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <pwd.h>
 #include <sys/utsname.h>
+#include <sys/stat.h>
 
 #include <glibmm/miscutils.h>
 
@@ -34,55 +35,40 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-SndFileSource::SndFileSource (const XMLNode& node)
-       : AudioFileSource (node)
+SndFileSource::SndFileSource (Session& s, const XMLNode& node)
+       : AudioFileSource (s, node)
 {
        init (_name);
 
        if (open()) {
                throw failed_constructor ();
        }
-
-       if (_build_peakfiles) {
-               if (initialize_peakfile (false, _path)) {
-                       sf_close (sf);
-                       sf = 0;
-                       throw failed_constructor ();
-               }
-       }
-
-       AudioSourceCreated (this); /* EMIT SIGNAL */
 }
 
-SndFileSource::SndFileSource (string idstr, Flag flags)
+SndFileSource::SndFileSource (Session& s, string idstr, Flag flags)
                                        /* files created this way are never writable or removable */
-       : AudioFileSource (idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
+       : AudioFileSource (s, idstr, Flag (flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy)))
 {
        init (idstr);
 
        if (open()) {
                throw failed_constructor ();
        }
-
-       if (!(_flags & NoPeakFile) && _build_peakfiles) {
-               if (initialize_peakfile (false, _path)) {
-                       sf_close (sf);
-                       sf = 0;
-                       throw failed_constructor ();
-               }
-       }
-
-
-       AudioSourceCreated (this); /* EMIT SIGNAL */
 }
 
-SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf, jack_nframes_t rate, Flag flags)
-       : AudioFileSource(idstr, flags, sfmt, hf)
+SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags)
+       : AudioFileSource (s, idstr, flags, sfmt, hf)
 {
        int fmt = 0;
 
        init (idstr);
 
+       /* this constructor is used to construct new files, not open
+          existing ones.
+       */
+
+       file_is_new = true;
+       
        switch (hf) {
        case CAF:
                fmt = SF_FORMAT_CAF;
@@ -156,6 +142,8 @@ SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf,
                          utsinfo.version);
                
                _broadcast_info->version = 1;  
+               _broadcast_info->time_reference_low = 0;  
+               _broadcast_info->time_reference_high = 0;  
                
                /* XXX do something about this field */
                
@@ -173,16 +161,6 @@ SndFileSource::SndFileSource (string idstr, SampleFormat sfmt, HeaderFormat hf,
                }
                
        }
-       
-       if (!(_flags & NoPeakFile) && _build_peakfiles) {
-               if (initialize_peakfile (true, _path)) {
-                       sf_close (sf);
-                       sf = 0;
-                       throw failed_constructor ();
-               }
-       }
-
-       AudioSourceCreated (this); /* EMIT SIGNAL */
 }
 
 void 
@@ -231,8 +209,8 @@ SndFileSource::open ()
 
        _length = _info.frames;
 
-
-       _broadcast_info = (SF_BROADCAST_INFO*) calloc (1, sizeof (SF_BROADCAST_INFO));
+       _broadcast_info = new SF_BROADCAST_INFO;
+       memset (_broadcast_info, 0, sizeof (*_broadcast_info));
        
        /* lookup broadcast info */
        
@@ -241,28 +219,24 @@ SndFileSource::open ()
                /* if the file has data but no broadcast info, then clearly, there is no broadcast info */
 
                if (_length) {
-                       free (_broadcast_info);
+                       delete _broadcast_info;
                        _broadcast_info = 0;
                        _flags = Flag (_flags & ~Broadcast);
                }
 
-               set_timeline_position (0);
+               set_timeline_position (header_position_offset);
 
        } else {
        
                /* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits
                   of the time reference.
                */
-               
-               set_timeline_position (_broadcast_info->time_reference_low);
+
+               set_timeline_position ( _broadcast_info->time_reference_low );
        }
 
        if (writable()) {
                sf_command (sf, SFC_SET_UPDATE_HEADER_AUTO, 0, SF_FALSE);
-
-               /* update header if header offset info changes */
-               
-               AudioFileSource::HeaderPositionOffsetChanged.connect (mem_fun (*this, &AudioFileSource::handle_header_position_change));
        }
 
        return 0;
@@ -270,11 +244,19 @@ SndFileSource::open ()
 
 SndFileSource::~SndFileSource ()
 {
-       GoingAway (this); /* EMIT SIGNAL */
+       GoingAway (); /* EMIT SIGNAL */
 
        if (sf) {
                sf_close (sf);
                sf = 0;
+
+               /* stupid libsndfile updated the headers on close,
+                  so touch the peakfile if it exists and has data
+                  to make sure its time is as new as the audio
+                  file.
+               */
+
+               touch_peakfile ();
        }
 
        if (interleave_buf) {
@@ -292,13 +274,13 @@ SndFileSource::sample_rate () const
        return _info.samplerate;
 }
 
-jack_nframes_t
-SndFileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
+nframes_t
+SndFileSource::read_unlocked (Sample *dst, nframes_t start, nframes_t cnt) const
 {
        int32_t nread;
        float *ptr;
        uint32_t real_cnt;
-       jack_nframes_t file_cnt;
+       nframes_t file_cnt;
 
        if (start > _length) {
 
@@ -329,14 +311,14 @@ SndFileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t
                }
                
                if (_info.channels == 1) {
-                       jack_nframes_t ret = sf_read_float (sf, dst, file_cnt);
+                       nframes_t ret = sf_read_float (sf, dst, file_cnt);
                        _read_data_count = cnt * sizeof(float);
                        return ret;
                }
        }
 
        if (file_cnt != cnt) {
-               jack_nframes_t delta = cnt - file_cnt;
+               nframes_t delta = cnt - file_cnt;
                memset (dst+file_cnt, 0, sizeof (Sample) * delta);
        }
 
@@ -367,8 +349,8 @@ SndFileSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t
        return nread;
 }
 
-jack_nframes_t 
-SndFileSource::write_unlocked (Sample *data, jack_nframes_t cnt, char * workbuf)
+nframes_t 
+SndFileSource::write_unlocked (Sample *data, nframes_t cnt)
 {
        if (!writable()) {
                return 0;
@@ -380,7 +362,7 @@ SndFileSource::write_unlocked (Sample *data, jack_nframes_t cnt, char * workbuf)
                return 0;
        }
        
-       jack_nframes_t oldlen;
+       nframes_t oldlen;
        int32_t frame_pos = _length;
        
        if (write_float (data, frame_pos, cnt) != cnt) {
@@ -413,7 +395,7 @@ SndFileSource::write_unlocked (Sample *data, jack_nframes_t cnt, char * workbuf)
        
        
        if (_build_peakfiles) {
-               queue_for_peaks (*this);
+               queue_for_peaks (shared_from_this ());
        }
 
        _write_data_count = cnt;
@@ -422,7 +404,7 @@ SndFileSource::write_unlocked (Sample *data, jack_nframes_t cnt, char * workbuf)
 }
 
 int
-SndFileSource::update_header (jack_nframes_t when, struct tm& now, time_t tnow)
+SndFileSource::update_header (nframes_t when, struct tm& now, time_t tnow)
 {      
        set_timeline_position (when);
 
@@ -441,12 +423,11 @@ SndFileSource::flush_header ()
        if (!writable() || (sf == 0)) {
                return -1;
        }
-
        return (sf_command (sf, SFC_UPDATE_HEADER_NOW, 0, 0) != SF_TRUE);
 }
 
 int
-SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t tnow)
+SndFileSource::setup_broadcast_info (nframes_t when, struct tm& now, time_t tnow)
 {
        if (!writable()) {
                return -1;
@@ -461,8 +442,8 @@ SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t
        int random_code = random() % 999999999;
        
        snprintf (_broadcast_info->originator_reference, sizeof (_broadcast_info->originator_reference), "%2s%3s%12s%02d%02d%02d%9d",
-                 bwf_country_code,
-                 bwf_organization_code,
+                 Config->get_bwf_country_code().c_str(),
+                 Config->get_bwf_organization_code().c_str(),
                  bwf_serial_number,
                  now.tm_hour,
                  now.tm_min,
@@ -474,7 +455,7 @@ SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t
                  now.tm_mon,
                  now.tm_mday);
        
-       snprintf (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d-%02d-%02d",
+       snprintf (_broadcast_info->origination_time, sizeof (_broadcast_info->origination_time), "%02d:%02d:%02d",
                  now.tm_hour,
                  now.tm_min,
                  now.tm_sec);
@@ -486,7 +467,7 @@ SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t
        if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
                error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
                _flags = Flag (_flags & ~Broadcast);
-               free (_broadcast_info);
+               delete _broadcast_info;
                _broadcast_info = 0;
                return -1;
        }
@@ -497,48 +478,26 @@ SndFileSource::setup_broadcast_info (jack_nframes_t when, struct tm& now, time_t
 void
 SndFileSource::set_header_timeline_position ()
 {
-       uint64_t pos;
-
        if (!(_flags & Broadcast)) {
                return;
        }
 
-       cerr << "timeline pos = " << timeline_position << " offset = " << header_position_offset << endl;
-
-       _broadcast_info->time_reference_high = 0;
-
-       if (header_position_negative) {
-
-               if (ULONG_LONG_MAX - header_position_offset < timeline_position) {
-                       pos = ULONG_LONG_MAX; // impossible
-               } else {
-                       pos = timeline_position + header_position_offset;
-               }
-
-       } else {
-
-               if (timeline_position < header_position_offset) {
-                       pos = 0;
-               } else {
-                       pos = timeline_position - header_position_offset;
-               }
-       }
-
-       _broadcast_info->time_reference_high = (pos >> 32);
-       _broadcast_info->time_reference_low = (pos & 0xffffffff);
-
-       cerr << "set binfo pos to " << _broadcast_info->time_reference_high << " + " << _broadcast_info->time_reference_low << endl;
+       _broadcast_info->time_reference_high = (timeline_position >> 32);
+       _broadcast_info->time_reference_low = (timeline_position & 0xffffffff);
 
        if (sf_command (sf, SFC_SET_BROADCAST_INFO, _broadcast_info, sizeof (*_broadcast_info)) != SF_TRUE) {
                error << string_compose (_("cannot set broadcast info for audio file %1; Dropping broadcast info for this file"), _path) << endmsg;
                _flags = Flag (_flags & ~Broadcast);
-               free (_broadcast_info);
+               delete _broadcast_info;
                _broadcast_info = 0;
        }
+
+       
+
 }
 
-jack_nframes_t
-SndFileSource::write_float (Sample* data, jack_nframes_t frame_pos, jack_nframes_t cnt)
+nframes_t
+SndFileSource::write_float (Sample* data, nframes_t frame_pos, nframes_t cnt)
 {
        if (sf_seek (sf, frame_pos, SEEK_SET|SFM_WRITE) != frame_pos) {
                error << string_compose (_("%1: cannot seek to %2"), _path, frame_pos) << endmsg;
@@ -551,3 +510,9 @@ SndFileSource::write_float (Sample* data, jack_nframes_t frame_pos, jack_nframes
        
        return cnt;
 }
+
+nframes_t
+SndFileSource::natural_position() const
+{
+       return timeline_position;
+}