X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsndfilesource.cc;h=4522e8a54dc794cd106ea0a362297625a0c932a5;hb=cf52d6e4b40111eb04b244ec054055a4ec15dbe0;hp=27c91c8c2705662fb7d8284c7ca4551a7a0b66d6;hpb=294b99aabf3eb96323a3159b7a5e1b4bfc1ff04a;p=ardour.git diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index 27c91c8c27..4522e8a54d 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -25,12 +25,14 @@ #include #include #include +#include #include -#ifdef PLATFORM_WINDOWS +#include +#include "pbd/gstdio_compat.h" + #include -#endif #include #include @@ -39,7 +41,7 @@ #include "ardour/utils.h" #include "ardour/session.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace ARDOUR; @@ -76,7 +78,7 @@ SndFileSource::SndFileSource (Session& s, const XMLNode& node) } /** Constructor for existing external-to-session files. - Files created this way are never writable or removable + Files created this way are never writable or removable */ SndFileSource::SndFileSource (Session& s, const string& path, int chn, Flag flags) : Source(s, DataType::AUDIO, path, flags) @@ -101,8 +103,8 @@ SndFileSource::SndFileSource (Session& s, const string& path, int chn, Flag flag } } -/** This constructor is used to construct new internal-to-session files, - not open existing ones. +/** This constructor is used to construct new internal-to-session files, + not open existing ones. */ SndFileSource::SndFileSource (Session& s, const string& path, const string& origin, SampleFormat sfmt, HeaderFormat hf, framecnt_t rate, Flag flags) @@ -150,6 +152,23 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig _flags = Flag (_flags & ~Broadcast); break; + case RF64_WAV: + fmt = SF_FORMAT_RF64; + _flags = Flag (_flags & ~Broadcast); + _flags = Flag (_flags | RF64_RIFF); + break; + + case MBWF: + fmt = SF_FORMAT_RF64; + _flags = Flag (_flags | Broadcast); + _flags = Flag (_flags | RF64_RIFF); + break; + + case RF64: + fmt = SF_FORMAT_RF64; + _flags = Flag (_flags & ~Broadcast); + break; + default: fatal << string_compose (_("programming error: %1"), X_("unsupported audio header format requested")) << endmsg; abort(); /*NOTREACHED*/ @@ -180,7 +199,7 @@ SndFileSource::SndFileSource (Session& s, const string& path, const string& orig throw failed_constructor(); } } else { - /* normal mode: do not open the file here - do that in write_unlocked() as needed + /* normal mode: do not open the file here - do that in {read,write}_unlocked() as needed */ } } @@ -230,22 +249,43 @@ SndFileSource::init_sndfile () AudioFileSource::HeaderPositionOffsetChanged.connect_same_thread (header_position_connection, boost::bind (&SndFileSource::handle_header_position_change, this)); } +void +SndFileSource::close () +{ + if (_sndfile) { + sf_close (_sndfile); + _sndfile = 0; + file_closed (); + } +} + int SndFileSource::open () { - string path_to_open; - if (_sndfile) { return 0; } - + +// We really only want to use g_open for all platforms but because of this +// method(SndfileSource::open), the compiler(or at least GCC) is confused +// because g_open will expand to "open" on non-POSIX systems and needs the +// global namespace qualifer. The problem is since since C99 ::g_open will +// apparently expand to ":: open" #ifdef PLATFORM_WINDOWS - path_to_open = Glib::locale_from_utf8(_path); + int fd = g_open (_path.c_str(), writable() ? O_CREAT | O_RDWR : O_RDONLY, writable() ? 0644 : 0444); #else - path_to_open = _path; + int fd = ::open (_path.c_str(), writable() ? O_CREAT | O_RDWR : O_RDONLY, writable() ? 0644 : 0444); #endif - _sndfile = sf_open (path_to_open.c_str(), writable() ? SFM_RDWR : SFM_READ, &_info); + if (fd == -1) { + error << string_compose ( + _ ("SndFileSource: cannot open file \"%1\" for %2"), + _path, + (writable () ? "read+write" : "reading")) << endmsg; + return -1; + } + + _sndfile = sf_open_fd (fd, writable() ? SFM_RDWR : SFM_READ, &_info, true); if (_sndfile == 0) { char errbuf[1024]; @@ -255,10 +295,10 @@ SndFileSource::open () so we don't want to see this message. */ - cerr << "failed to open " << path_to_open << " with name " << _name << endl; + cerr << "failed to open " << _path << " with name " << _name << endl; error << string_compose(_("SndFileSource: cannot open file \"%1\" for %2 (%3)"), - path_to_open, (writable() ? "read+write" : "reading"), errbuf) << endmsg; + _path, (writable() ? "read+write" : "reading"), errbuf) << endmsg; #endif return -1; } @@ -274,6 +314,19 @@ SndFileSource::open () _length = _info.frames; +#ifdef HAVE_RF64_RIFF + if (_file_is_new && _length == 0 && writable()) { + if (_flags & RF64_RIFF) { + if (sf_command (_sndfile, SFC_RF64_AUTO_DOWNGRADE, 0, 0) != SF_TRUE) { + char errbuf[256]; + sf_error_str (_sndfile, errbuf, sizeof (errbuf) - 1); + error << string_compose (_("Cannot mark RF64 audio file for automatic downgrade to WAV: %1"), errbuf) + << endmsg; + } + } + } +#endif + if (!_broadcast_info) { _broadcast_info = new BroadcastInfo; } @@ -296,12 +349,12 @@ SndFileSource::open () delete _broadcast_info; _broadcast_info = 0; _flags = Flag (_flags & ~Broadcast); - } + } /* Set the broadcast flag if the BWF info is already there. We need * this when recovering or using existing files. */ - + if (bwf_info_exists) { _flags = Flag (_flags | Broadcast); } @@ -320,7 +373,7 @@ SndFileSource::open () if (!_broadcast_info->write_to_file (_sndfile)) { error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"), - path_to_open, _broadcast_info->get_error()) + _path, _broadcast_info->get_error()) << endmsg; _flags = Flag (_flags & ~Broadcast); delete _broadcast_info; @@ -328,16 +381,13 @@ SndFileSource::open () } } } - + return 0; } SndFileSource::~SndFileSource () { - if (_sndfile) { - sf_close (_sndfile); - _sndfile = 0; - } + close (); delete _broadcast_info; delete [] xfade_buf; } @@ -352,10 +402,10 @@ framecnt_t SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) const { assert (cnt >= 0); - - int32_t nread; + + framecnt_t nread; float *ptr; - uint32_t real_cnt; + framecnt_t real_cnt; framepos_t file_cnt; if (writable() && !_sndfile) { @@ -364,10 +414,10 @@ SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) con return cnt; } - if (_sndfile == 0) { - error << string_compose (_("could not allocate file %1 for reading."), _path) << endmsg; + if (const_cast(this)->open()) { + error << string_compose (_("could not open file %1 for reading."), _path) << endmsg; return 0; - } + } if (start > _length) { @@ -425,7 +475,7 @@ SndFileSource::read_unlocked (Sample *dst, framepos_t start, framecnt_t cnt) con /* stride through the interleaved data */ - for (int32_t n = 0; n < nread; ++n) { + for (framecnt_t n = 0; n < nread; ++n) { dst[n] = *ptr; ptr += _info.channels; } @@ -461,7 +511,7 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, framecnt_t cnt) return 0; } - int32_t frame_pos = _length; + framepos_t frame_pos = _length; if (write_float (data, frame_pos, cnt) != cnt) { return 0; @@ -470,7 +520,7 @@ SndFileSource::nondestructive_write_unlocked (Sample *data, framecnt_t cnt) update_length (_length + cnt); if (_build_peakfiles) { - compute_and_write_peaks (data, frame_pos, cnt, false, true); + compute_and_write_peaks (data, frame_pos, cnt, true, true); } return cnt; @@ -557,7 +607,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, framecnt_t cnt) update_length (file_pos + cnt); if (_build_peakfiles) { - compute_and_write_peaks (data, file_pos, cnt, false, true); + compute_and_write_peaks (data, file_pos, cnt, true, true); } file_pos += cnt; @@ -638,15 +688,6 @@ SndFileSource::setup_broadcast_info (framepos_t /*when*/, struct tm& now, time_t set_header_timeline_position (); - if (!_broadcast_info->write_to_file (_sndfile)) { - error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"), - _path, _broadcast_info->get_error()) - << endmsg; - _flags = Flag (_flags & ~Broadcast); - delete _broadcast_info; - _broadcast_info = 0; - } - return 0; } @@ -656,6 +697,7 @@ SndFileSource::set_header_timeline_position () if (!(_flags & Broadcast)) { return; } + assert (_broadcast_info); _broadcast_info->set_time_reference (_timeline_position); @@ -926,8 +968,23 @@ SndFileSource::get_soundfile_info (const string& path, SoundFileInfo& info, stri sf_info.format = 0; // libsndfile says to clear this before sf_open(). - if ((sf = sf_open (const_cast(path.c_str()), SFM_READ, &sf_info)) == 0) { - char errbuf[256]; + if (path.empty() || Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) { + return false; + } + +#ifdef PLATFORM_WINDOWS + int fd = g_open (path.c_str(), O_RDONLY, 0444); +#else + int fd = ::open (path.c_str(), O_RDONLY, 0444); +#endif + + if (fd == -1) { + error << string_compose ( _("SndFileSource: cannot open file \"%1\" for reading"), path) + << endmsg; + return false; + } + if ((sf = sf_open_fd (fd, SFM_READ, &sf_info, true)) == 0) { + char errbuf[1024]; error_msg = sf_error_str (0, errbuf, sizeof (errbuf) - 1); return false; }