Merge branch 'master' of git.ardour.org:ardour/ardour
[ardour.git] / libs / pbd / sndfile_manager.cc
1 /*
2     Copyright (C) 2010 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file libs/pbd/sndfile_manager.cc
21  *  @brief A FileDescriptor for files opened using libsndfile.
22  */
23
24 #include <sys/time.h>
25 #include <sys/resource.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <cassert>
30 #include "pbd/compose.h"
31 #include "pbd/sndfile_manager.h"
32 #include "pbd/debug.h"
33
34 using namespace std;
35 using namespace PBD;
36
37 /** @param file_name Filename.
38  *  @param writeable true to open writeable, otherwise false.
39  *  @param info SF_INFO for the file.
40  */
41
42 SndFileDescriptor::SndFileDescriptor (string const & file_name, bool writeable, SF_INFO* info)
43         : FileDescriptor (file_name, writeable)
44         , _sndfile (0)
45         , _info (info)
46 {
47         manager()->add (this);
48 }
49
50 SndFileDescriptor::~SndFileDescriptor ()
51 {
52         manager()->remove (this);
53 }
54
55 /** @return SNDFILE*, or 0 on error */
56 SNDFILE*
57 SndFileDescriptor::allocate ()
58 {
59         bool const f = manager()->allocate (this);
60         if (f) {
61                 return 0;
62         }
63
64         /* this is ok thread-wise because allocate () has incremented
65            the Descriptor's refcount, so the file will not be closed
66         */
67         return _sndfile;
68 }
69
70 void
71 SndFileDescriptor::close ()
72 {
73         /* we must have a lock on the FileManager's mutex */
74
75         assert (_sndfile);
76         sf_close (_sndfile);
77         _sndfile = 0;
78 }
79
80 bool
81 SndFileDescriptor::is_open () const
82 {
83         /* we must have a lock on the FileManager's mutex */
84
85         return _sndfile != 0;
86 }
87
88 bool
89 SndFileDescriptor::open ()
90 {
91         /* we must have a lock on the FileManager's mutex */
92         
93         int fd = ::open(_path.c_str(), O_LARGEFILE | (_writeable ? (O_RDWR) : O_RDONLY));
94         if (fd == -1) return false;
95         fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
96
97         _sndfile = sf_open_fd (fd, _writeable ? SFM_RDWR : SFM_READ, _info, 1);
98
99         return (_sndfile == 0);
100 }
101