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