f19c0d8d37a80ea3a6380369ddae3f4873e9dc00
[ardour.git] / libs / ardour / recent_sessions.cc
1 /*
2     Copyright (C) 2004 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 <cstring>
21 #include <cerrno>
22 #include <fstream>
23 #include <iostream>
24 #include <sstream>
25 #include <algorithm>
26
27 #include <glib/gstdio.h>
28 #include <glibmm/miscutils.h>
29
30 #include "pbd/error.h"
31
32 #include "ardour/rc_configuration.h"
33 #include "ardour/filesystem_paths.h"
34 #include "ardour/recent_sessions.h"
35
36 #include "i18n.h"
37
38 using namespace std;
39 using namespace ARDOUR;
40 using namespace PBD;
41
42 namespace {
43
44         const char * const recent_file_name = "recent";
45         const char * const recent_templates_file_name = "recent_templates";
46
47 } // anonymous
48
49 int
50 ARDOUR::read_recent_sessions (RecentSessions& rs)
51 {
52         std::string path = Glib::build_filename (user_config_directory(), recent_file_name);
53         FILE* fin = g_fopen (path.c_str(), "rb");
54
55         if (!fin) {
56                 if (errno != ENOENT) {
57                         error << string_compose (_("cannot open recent session file %1 (%2)"), path, strerror (errno)) << endmsg;
58                         return -1;
59                 } else {
60                         return 1;
61                 }
62         }
63
64         // Read the file into a std::string
65         std::stringstream recent;
66         while (!feof (fin)) {
67                 char buf[1024];
68                 size_t charsRead = fread (buf, sizeof(char), 1024, fin);
69                 if (ferror (fin)) {
70                         error << string_compose (_("Error reading recent session file %1 (%2)"), path, strerror (errno)) << endmsg;
71                         fclose(fin);
72                         return -1;
73                 }
74                 if (charsRead == 0) {
75                         break;
76                 }
77                 recent.write (buf, charsRead);
78         }
79
80         while (true) {
81
82                 pair<string,string> newpair;
83
84                 getline(recent, newpair.first);
85
86                 if (!recent.good()) {
87                         break;
88                 }
89
90                 getline(recent, newpair.second);
91
92                 if (!recent.good()) {
93                         break;
94                 }
95
96                 rs.push_back (newpair);
97         }
98
99         /* display sorting should be done in the GUI, otherwise the
100          * natural order will be broken
101          */
102
103         fclose (fin);
104         return 0;
105 }
106
107 int
108 ARDOUR::read_recent_templates (std::deque<std::string>& rt)
109 {
110         std::string path = Glib::build_filename (user_config_directory(), recent_templates_file_name);
111
112         ifstream recent (path.c_str());
113
114         if (!recent) {
115                 if (errno != ENOENT) {
116                         error << string_compose (_("cannot open recent template file %1 (%2)"), path, strerror (errno)) << endmsg;
117                         return -1;
118                 } else {
119                         return 1;
120                 }
121         }
122
123         while (true) {
124
125                 std::string session_template_full_name;
126
127                 getline(recent, session_template_full_name);
128
129                 if (!recent.good()) {
130                         break;
131                 }
132
133                 rt.push_back (session_template_full_name);
134         }
135
136         return 0;
137 }
138
139 int
140 ARDOUR::write_recent_sessions (RecentSessions& rs)
141 {
142         FILE* fout = g_fopen (Glib::build_filename (user_config_directory(), recent_file_name).c_str(), "wb");
143
144         if (!fout) {
145                 return -1;
146         }
147
148         {
149                 stringstream recent;
150                 //ofstream recent (fout);
151
152                 // if (!recent) {
153                 //      fclose (fout);
154                 //      return -1;
155                 // }
156
157                 for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
158                         recent << (*i).first << '\n' << (*i).second << endl;
159                 }
160
161                 string recentString = recent.str();
162                 size_t writeSize = recentString.length();
163
164                 fwrite(recentString.c_str(), sizeof(char), writeSize, fout);
165
166                 if (ferror(fout))
167                 {
168                         error << string_compose (_("Error writing recent sessions file %1 (%2)"), recent_file_name, strerror (errno)) << endmsg;
169                         fclose(fout);
170                         return -1;
171                 }
172         }
173
174
175
176         fclose (fout);
177
178         return 0;
179 }
180
181 int
182 ARDOUR::write_recent_templates (std::deque<std::string>& rt)
183 {
184         std::string path = Glib::build_filename (user_config_directory(), recent_templates_file_name);
185
186         std::ofstream recent (path.c_str());
187
188         if (!recent) {
189                 return -1;
190         }
191
192         for (std::deque<std::string>::const_iterator i = rt.begin(); i != rt.end(); ++i) {
193                 recent << (*i) << std::endl;
194         }
195
196         return 0;
197 }
198
199 int
200 ARDOUR::store_recent_sessions (string name, string path)
201 {
202         RecentSessions rs;
203
204         if (ARDOUR::read_recent_sessions (rs) < 0) {
205                 return -1;
206         }
207
208         pair<string,string> newpair;
209
210         newpair.first = name;
211         newpair.second = path;
212
213         rs.erase(remove(rs.begin(), rs.end(), newpair), rs.end());
214
215         rs.push_front (newpair);
216
217         uint32_t max_recent_sessions = Config->get_max_recent_sessions();
218
219         if (rs.size() > max_recent_sessions) {
220                 rs.erase(rs.begin()+max_recent_sessions, rs.end());
221         }
222
223         return ARDOUR::write_recent_sessions (rs);
224 }
225
226 int
227 ARDOUR::store_recent_templates (const std::string& session_template_full_name)
228 {
229         std::deque<std::string> rt;
230
231         if (ARDOUR::read_recent_templates (rt) < 0) {
232                 return -1;
233         }
234
235         rt.erase(remove (rt.begin(), rt.end(), session_template_full_name), rt.end());
236
237         rt.push_front (session_template_full_name);
238
239         uint32_t max_recent_templates = Config->get_max_recent_templates ();
240
241         if (rt.size() > max_recent_templates) {
242                 rt.erase( rt.begin() + max_recent_templates, rt.end ());
243         }
244
245         return ARDOUR::write_recent_templates (rt);
246 }
247
248 int
249 ARDOUR::remove_recent_sessions (const string& path)
250 {
251         RecentSessions rs;
252         bool write = false;
253
254         if (ARDOUR::read_recent_sessions (rs) < 0) {
255                 return -1;
256         }
257
258         for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) {
259                 if (i->second == path) {
260                         rs.erase (i);
261                         write = true;
262                         break;
263                 }
264         }
265
266         if (write) {
267                 return ARDOUR::write_recent_sessions (rs);
268         } else {
269                 return 1;
270         }
271 }