re-apply roll-delay after seek - fixes #5781
[ardour.git] / libs / ardour / find_session.cc
1 /*
2     Copyright (C) 2012 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 #include <unistd.h>
21 #include <sys/stat.h>
22
23 #include <cstring>
24 #include <climits>
25 #include <cerrno>
26
27 #include <glibmm/miscutils.h>
28
29 #include "pbd/compose.h"
30 #include "pbd/pathexpand.h"
31 #include "pbd/error.h"
32
33 #include "ardour/filename_extensions.h"
34 #include "ardour/utils.h"
35 #include "ardour/session_utils.h"
36
37 #include "i18n.h"
38
39 using namespace std;
40 using namespace PBD;
41
42 namespace ARDOUR {
43
44 int
45 find_session (string str, string& path, string& snapshot, bool& isnew)
46 {
47         struct stat statbuf;
48
49         isnew = false;
50
51         str = canonical_path (str);
52
53         /* check to see if it exists, and what it is */
54
55         if (stat (str.c_str(), &statbuf)) {
56                 if (errno == ENOENT) {
57                         isnew = true;
58                 } else {
59                         error << string_compose (_("cannot check session path %1 (%2)"), str, strerror (errno))
60                               << endmsg;
61                         return -1;
62                 }
63         }
64
65         if (!isnew) {
66
67                 /* it exists, so it must either be the name
68                    of the directory, or the name of the statefile
69                    within it.
70                 */
71
72                 if (S_ISDIR (statbuf.st_mode)) {
73
74                         string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
75
76                         if (slash == string::npos) {
77
78                                 /* a subdirectory of cwd, so statefile should be ... */
79
80                                 string tmp = Glib::build_filename (str, str+statefile_suffix);
81
82                                 /* is it there ? */
83
84                                 if (stat (tmp.c_str(), &statbuf)) {
85                                         error << string_compose (_("cannot check statefile %1 (%2)"), tmp, strerror (errno))
86                                               << endmsg;
87                                         return -1;
88                                 }
89
90                                 path = str;
91                                 snapshot = str;
92
93                         } else {
94
95                                 /* some directory someplace in the filesystem.
96                                    the snapshot name is the directory name
97                                    itself.
98                                 */
99
100                                 path = str;
101                                 snapshot = str.substr (slash+1);
102
103                         }
104
105                 } else if (S_ISREG (statbuf.st_mode)) {
106
107                         string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
108                         string::size_type suffix;
109
110                         /* remove the suffix */
111
112                         if (slash != string::npos) {
113                                 snapshot = str.substr (slash+1);
114                         } else {
115                                 snapshot = str;
116                         }
117
118                         suffix = snapshot.find (statefile_suffix);
119
120                         const string::size_type start_pos_of_extension = snapshot.size () - strlen (statefile_suffix);
121                         // we should check the start of extension position
122                         // because files '*.ardour.bak' are possible
123                         if (suffix != start_pos_of_extension) {
124                                 error << string_compose (_("%1 is not a snapshot file"), str) << endmsg;
125                                 return -1;
126                         }
127
128                         /* remove suffix */
129
130                         snapshot = snapshot.substr (0, suffix);
131
132                         if (slash == string::npos) {
133
134                                 /* we must be in the directory where the
135                                    statefile lives. get it using cwd().
136                                 */
137
138                                 char cwd[PATH_MAX+1];
139
140                                 if (getcwd (cwd, sizeof (cwd)) == 0) {
141                                         error << string_compose (_("cannot determine current working directory (%1)"), strerror (errno))
142                                               << endmsg;
143                                         return -1;
144                                 }
145
146                                 path = cwd;
147
148                         } else {
149
150                                 /* full path to the statefile */
151
152                                 path = str.substr (0, slash);
153                         }
154
155                 } else {
156
157                         /* what type of file is it? */
158                         error << string_compose (_("unknown file type for session %1"), str) << endmsg;
159                         return -1;
160                 }
161
162         } else {
163
164                 /* its the name of a new directory. get the name
165                    as "dirname" does.
166                 */
167
168                 string::size_type slash = str.find_last_of (G_DIR_SEPARATOR);
169
170                 if (slash == string::npos) {
171
172                         /* no slash, just use the name, but clean it up */
173
174                         path = legalize_for_path (str);
175                         snapshot = path;
176
177                 } else {
178
179                         path = str;
180                         snapshot = str.substr (slash+1);
181                 }
182         }
183
184         return 0;
185 }
186
187 }  // namespace ARDOUR