Move FileManager code into libpbd. Use it for SMF read/write.

git-svn-id: svn://localhost/ardour2/branches/3.0@7108 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2010-05-16 20:54:50 +00:00
parent 50615cd17c
commit f1114dedee
16 changed files with 153 additions and 75 deletions

View File

@ -32,7 +32,7 @@
#include "ardour/source.h"
#include "ardour/ardour.h"
#include "ardour/readable.h"
#include "ardour/file_manager.h"
#include "pbd/file_manager.h"
#include "pbd/stateful.h"
#include "pbd/xml++.h"
@ -141,7 +141,7 @@ class AudioSource : virtual public Source,
framecnt_t frames_per_peak);
private:
FdFileDescriptor* _peakfile_descriptor;
PBD::FdFileDescriptor* _peakfile_descriptor;
int _peakfile_fd;
framecnt_t peak_leftover_cnt;
framecnt_t peak_leftover_size;

View File

@ -46,7 +46,6 @@ namespace PBD {
extern uint64_t MidiClock;
extern uint64_t Monitor;
extern uint64_t Solo;
extern uint64_t FileManager;
}
}

View File

@ -24,7 +24,7 @@
#include "ardour/audiofilesource.h"
#include "ardour/broadcast_info.h"
#include "ardour/file_manager.h"
#include "pbd/file_manager.h"
namespace ARDOUR {
@ -73,7 +73,7 @@ class SndFileSource : public AudioFileSource {
framecnt_t write_float (Sample* data, framepos_t pos, framecnt_t cnt);
private:
SndFileDescriptor* _descriptor;
PBD::SndFileDescriptor* _descriptor;
SF_INFO _info;
BroadcastInfo *_broadcast_info;

View File

@ -43,5 +43,4 @@ uint64_t PBD::DEBUG::MackieControl = PBD::new_debug_bit ("mackiecontrol");
uint64_t PBD::DEBUG::MidiClock = PBD::new_debug_bit ("midiclock");
uint64_t PBD::DEBUG::Monitor = PBD::new_debug_bit ("monitor");
uint64_t PBD::DEBUG::Solo = PBD::new_debug_bit ("solo");
uint64_t PBD::DEBUG::FileManager = PBD::new_debug_bit ("filemanager");

View File

@ -32,7 +32,6 @@
#include <glibmm/miscutils.h>
#include "evoral/SMFReader.hpp"
#include "evoral/Control.hpp"
#include "ardour/audioengine.h"

View File

@ -92,7 +92,6 @@ libardour_sources = [
'export_profile_manager.cc',
'export_status.cc',
'export_timespan.cc',
'file_manager.cc',
'file_source.cc',
'filename_extensions.cc',
'filesystem_paths.cc',

View File

@ -26,6 +26,7 @@
#include "evoral/Event.hpp"
#include "evoral/SMF.hpp"
#include "evoral/midi_util.h"
#include "pbd/file_manager.h"
using namespace std;
@ -82,7 +83,14 @@ SMF::open(const std::string& path, int track) THROW_FILE_ERROR
}
_file_path = path;
_smf = smf_load(_file_path.c_str());
PBD::StdioFileDescriptor d (_file_path, "r");
FILE* f = d.allocate ();
if (f == 0) {
return -1;
}
_smf = smf_load (f);
if (_smf == NULL) {
return -1;
}
@ -149,7 +157,13 @@ void
SMF::close() THROW_FILE_ERROR
{
if (_smf) {
if (smf_save(_smf, _file_path.c_str()) != 0) {
PBD::StdioFileDescriptor d (_file_path, "w+");
FILE* f = d.allocate ();
if (f == 0) {
throw FileError ();
}
if (smf_save(_smf, f) != 0) {
throw FileError();
}
smf_delete(_smf);
@ -259,8 +273,15 @@ SMF::begin_write()
void
SMF::end_write() THROW_FILE_ERROR
{
if (smf_save(_smf, _file_path.c_str()) != 0)
PBD::StdioFileDescriptor d (_file_path, "w+");
FILE* f = d.allocate ();
if (f == 0) {
throw FileError ();
}
if (smf_save(_smf, f) != 0) {
throw FileError();
}
}
double

View File

@ -387,11 +387,11 @@ char *smf_event_decode(const smf_event_t *event) WARN_UNUSED_RESULT;
char *smf_event_extract_text(const smf_event_t *event) WARN_UNUSED_RESULT;
/* Routines for loading SMF files. */
smf_t *smf_load(const char *file_name) WARN_UNUSED_RESULT;
smf_t *smf_load(FILE *) WARN_UNUSED_RESULT;
smf_t *smf_load_from_memory(const void *buffer, const size_t buffer_length) WARN_UNUSED_RESULT;
/* Routine for writing SMF files. */
int smf_save(smf_t *smf, const char *file_name) WARN_UNUSED_RESULT;
int smf_save(smf_t *smf, FILE *file) WARN_UNUSED_RESULT;
/* Routines for manipulating smf_tempo_t. */
smf_tempo_t *smf_get_tempo_by_pulses(const smf_t *smf, size_t pulses) WARN_UNUSED_RESULT;

View File

@ -794,12 +794,11 @@ parse_mtrk_chunk(smf_track_t *track)
}
/**
* Allocate buffer of proper size and read file contents into it. Close file afterwards.
* Allocate buffer of proper size and read file contents into it.
*/
static int
load_file_into_buffer(void **file_buffer, size_t *file_buffer_length, const char *file_name)
load_file_into_buffer(void **file_buffer, size_t *file_buffer_length, FILE* stream)
{
FILE *stream = fopen(file_name, "r");
long offset;
if (stream == NULL) {
@ -841,12 +840,6 @@ load_file_into_buffer(void **file_buffer, size_t *file_buffer_length, const char
return (-6);
}
if (fclose(stream)) {
g_critical("fclose(3) failed: %s", strerror(errno));
return (-7);
}
return (0);
}
@ -903,17 +896,17 @@ smf_load_from_memory(const void *buffer, const size_t buffer_length)
/**
* Loads SMF file.
*
* \param file_name Path to the file.
* \param file Open file.
* \return SMF or NULL, if loading failed.
*/
smf_t *
smf_load(const char *file_name)
smf_load(FILE *file)
{
size_t file_buffer_length;
void *file_buffer;
smf_t *smf;
if (load_file_into_buffer(&file_buffer, &file_buffer_length, file_name))
if (load_file_into_buffer(&file_buffer, &file_buffer_length, file))
return (NULL);
smf = smf_load_from_memory(file_buffer, file_buffer_length);

View File

@ -391,29 +391,14 @@ write_track(smf_track_t *track)
* Takes smf->file_buffer and saves it to the file.
*/
static int
write_file(smf_t *smf, const char *file_name)
write_file(smf_t *smf, FILE* stream)
{
FILE *stream;
stream = fopen(file_name, "w+");
if (stream == NULL) {
g_critical("Cannot open input file: %s", strerror(errno));
return (-1);
}
if (fwrite(smf->file_buffer, 1, smf->file_buffer_length, stream) != smf->file_buffer_length) {
g_critical("fwrite(3) failed: %s", strerror(errno));
return (-2);
}
if (fclose(stream)) {
g_critical("fclose(3) failed: %s", strerror(errno));
return (-3);
}
return (0);
}
@ -593,11 +578,11 @@ assert_smf_is_identical(const smf_t *a, const smf_t *b)
}
static void
assert_smf_saved_correctly(const smf_t *smf, const char *file_name)
assert_smf_saved_correctly(const smf_t *smf, FILE* file)
{
smf_t *saved;
saved = smf_load(file_name);
saved = smf_load (file);
assert(saved != NULL);
assert_smf_is_identical(smf, saved);
@ -610,11 +595,11 @@ assert_smf_saved_correctly(const smf_t *smf, const char *file_name)
/**
* Writes the contents of SMF to the file given.
* \param smf SMF.
* \param file_name Path to the file.
* \param file File descriptor.
* \return 0, if saving was successfull.
*/
int
smf_save(smf_t *smf, const char *file_name)
smf_save(smf_t *smf, FILE* file)
{
int i, error;
smf_track_t *track;
@ -641,7 +626,7 @@ smf_save(smf_t *smf, const char *file_name)
}
}
error = write_file(smf, file_name);
error = write_file(smf, file);
free_buffer(smf);
@ -649,7 +634,7 @@ smf_save(smf_t *smf, const char *file_name)
return (error);
#ifndef NDEBUG
assert_smf_saved_correctly(smf, file_name);
assert_smf_saved_correctly(smf, file);
#endif
return (0);

View File

@ -91,7 +91,7 @@ def build(bld):
obj.name = 'libevoral'
obj.target = 'evoral'
obj.uselib = 'GLIBMM GTHREAD SMF'
obj.uselib_local = 'libsmf'
obj.uselib_local = 'libsmf libpbd'
obj.vnum = EVORAL_LIB_VERSION
obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3')

View File

@ -32,6 +32,7 @@ static std::map<const char*,uint64_t> _debug_bit_map;
uint64_t PBD::DEBUG::Stateful = PBD::new_debug_bit ("stateful");
uint64_t PBD::DEBUG::Properties = PBD::new_debug_bit ("properties");
uint64_t PBD::DEBUG::FileManager = PBD::new_debug_bit ("filemanager");
uint64_t PBD::debug_bits = 0x0;

View File

@ -25,16 +25,15 @@
#include <cassert>
#include <iostream>
#include "pbd/compose.h"
#include "ardour/file_manager.h"
#include "ardour/debug.h"
#include "pbd/file_manager.h"
#include "pbd/debug.h"
using namespace std;
using namespace PBD;
using namespace ARDOUR;
FileManager* FileDescriptor::_manager;
namespace ARDOUR {
namespace PBD {
/** Class to limit the number of files held open */
class FileManager
@ -103,9 +102,9 @@ FileManager::allocate (FileDescriptor* d)
list<FileDescriptor*>::iterator oldest = _files.end ();
for (list<FileDescriptor*>::iterator i = _files.begin(); i != _files.end(); ++i) {
if ((*i)->is_open() && (*i)->refcount == 0) {
if ((*i)->last_used < lowest_last_used) {
lowest_last_used = (*i)->last_used;
if ((*i)->is_open() && (*i)->_refcount == 0) {
if ((*i)->_last_used < lowest_last_used) {
lowest_last_used = (*i)->_last_used;
oldest = i;
}
}
@ -121,25 +120,26 @@ FileManager::allocate (FileDescriptor* d)
DEBUG::FileManager,
string_compose (
"closed file for %1 to release file handle; now have %2 of %3 open\n",
(*oldest)->name, _open, _max_open
(*oldest)->_name, _open, _max_open
)
);
}
if (d->open ()) {
DEBUG_TRACE (DEBUG::FileManager, string_compose ("open of %1 failed.\n", d->_name));
return true;
}
_open++;
DEBUG_TRACE (DEBUG::FileManager, string_compose ("opened file for %1; now have %2 of %3 open.\n", d->name, _open, _max_open));
DEBUG_TRACE (DEBUG::FileManager, string_compose ("opened file for %1; now have %2 of %3 open.\n", d->_name, _open, _max_open));
}
struct timespec t;
clock_gettime (CLOCK_MONOTONIC, &t);
d->last_used = t.tv_sec + (double) t.tv_nsec / 10e9;
d->_last_used = t.tv_sec + (double) t.tv_nsec / 10e9;
d->refcount++;
d->_refcount++;
return false;
}
@ -150,8 +150,8 @@ FileManager::release (FileDescriptor* d)
{
Glib::Mutex::Lock lm (_mutex);
d->refcount--;
assert (d->refcount >= 0);
d->_refcount--;
assert (d->_refcount >= 0);
}
/** Remove a file from our lists. It will be closed if it is currently open. */
@ -164,7 +164,7 @@ FileManager::remove (FileDescriptor* d)
close (d);
DEBUG_TRACE (
DEBUG::FileManager,
string_compose ("closed file for %1; file is being removed; now have %2 of %3 open\n", d->name, _open, _max_open)
string_compose ("closed file for %1; file is being removed; now have %2 of %3 open\n", d->_name, _open, _max_open)
);
}
@ -182,10 +182,10 @@ FileManager::close (FileDescriptor* d)
}
FileDescriptor::FileDescriptor (string const & n, bool w)
: refcount (0)
, last_used (0)
, name (n)
, writeable (w)
: _refcount (0)
, _last_used (0)
, _name (n)
, _writeable (w)
{
}
@ -262,7 +262,7 @@ SndFileDescriptor::open ()
{
/* we must have a lock on the FileManager's mutex */
_sndfile = sf_open (name.c_str(), writeable ? SFM_RDWR : SFM_READ, _info);
_sndfile = sf_open (_name.c_str(), _writeable ? SFM_RDWR : SFM_READ, _info);
return (_sndfile == 0);
}
@ -298,7 +298,7 @@ FdFileDescriptor::open ()
{
/* we must have a lock on the FileManager's mutex */
_fd = ::open (name.c_str(), writeable ? (O_RDWR | O_CREAT) : O_RDONLY, _mode);
_fd = ::open (_name.c_str(), _writeable ? (O_RDWR | O_CREAT) : O_RDONLY, _mode);
return (_fd == -1);
}
@ -325,3 +325,62 @@ FdFileDescriptor::allocate ()
*/
return _fd;
}
/** @param n Filename.
* @param w true to open writeable, otherwise false.
*/
StdioFileDescriptor::StdioFileDescriptor (string const & n, std::string const & m)
: FileDescriptor (n, false)
, _file (0)
, _mode (m)
{
manager()->add (this);
}
StdioFileDescriptor::~StdioFileDescriptor ()
{
manager()->remove (this);
}
bool
StdioFileDescriptor::is_open () const
{
/* we must have a lock on the FileManager's mutex */
return _file != 0;
}
bool
StdioFileDescriptor::open ()
{
/* we must have a lock on the FileManager's mutex */
_file = fopen (_name.c_str(), _mode.c_str());
return (_file == 0);
}
void
StdioFileDescriptor::close ()
{
/* we must have a lock on the FileManager's mutex */
fclose (_file);
_file = 0;
}
/** @return FILE*, or 0 on error */
FILE*
StdioFileDescriptor::allocate ()
{
bool const f = manager()->allocate (this);
if (f) {
return 0;
}
/* this is ok thread-wise because allocate () has incremented
the Descriptor's refcount, so the file will not be closed
*/
return _file;
}

View File

@ -39,6 +39,7 @@ namespace PBD {
extern uint64_t Stateful;
extern uint64_t Properties;
extern uint64_t FileManager;
}
}

View File

@ -17,8 +17,8 @@
*/
#ifndef __file_manager_h__
#define __file_manager_h__
#ifndef __pbd_file_manager_h__
#define __pbd_file_manager_h__
#include <sys/types.h>
#include <string>
@ -27,7 +27,7 @@
#include <glibmm/thread.h>
#include "pbd/signals.h"
namespace ARDOUR {
namespace PBD {
class FileManager;
@ -69,10 +69,10 @@ protected:
virtual void close () = 0;
virtual bool is_open () const = 0;
int refcount; ///< number of active users of this file
double last_used; ///< monotonic time that this file was last allocated
std::string name; ///< filename
bool writeable; ///< true if it should be opened writeable, otherwise false
int _refcount; ///< number of active users of this file
double _last_used; ///< monotonic time that this file was last allocated
std::string _name; ///< filename
bool _writeable; ///< true if it should be opened writeable, otherwise false
FileManager* manager ();
@ -123,6 +123,27 @@ private:
mode_t _mode; ///< mode to use when creating files
};
/** FileDescriptor for a file opened using stdio */
class StdioFileDescriptor : public FileDescriptor
{
public:
StdioFileDescriptor (std::string const &, std::string const &);
~StdioFileDescriptor ();
FILE* allocate ();
private:
friend class FileManager;
bool open ();
void close ();
bool is_open () const;
FILE* _file;
std::string _mode;
};
}
#endif

View File

@ -67,6 +67,7 @@ def build(bld):
error.cc
filesystem.cc
filesystem_paths.cc
file_manager.cc
file_utils.cc
fpu.cc
id.cc