Fixed some valgrind errors from using uninitialized variables in
[ardour.git] / gtk2_ardour / export_range_markers_dialog.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3     Author: Andre Raue
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <sys/stat.h>
22
23 #include <sstream>
24
25 #include <ardour/audioengine.h>
26 #include <ardour/sndfile_helpers.h>
27
28 #include <pbd/dirname.h>
29
30 #include "ardour_ui.h"
31 #include "export_range_markers_dialog.h"
32
33 #include "i18n.h"
34
35 using namespace Gtk;
36 using namespace ARDOUR;
37 using namespace std;
38
39 ExportRangeMarkersDialog::ExportRangeMarkersDialog (PublicEditor& editor) 
40         : ExportDialog(editor)
41
42         do_not_allow_export_cd_markers();
43         
44         total_duration = 0;
45         current_range_marker_index = 0;
46 }
47         
48         
49 void 
50 ExportRangeMarkersDialog::export_audio_data ()
51 {
52         getSession().locations()->apply(*this, &ExportRangeMarkersDialog::process_range_markers_export);
53 }
54
55 void
56 ExportRangeMarkersDialog::process_range_markers_export(Locations::LocationList& locations)
57 {
58         Locations::LocationList::iterator locationIter;
59         current_range_marker_index = 0;
60         init_progress_computing(locations);
61         
62         for (locationIter = locations.begin(); locationIter != locations.end(); ++locationIter) {
63                 Location *currentLocation = (*locationIter);
64
65                 if(currentLocation->is_range_marker()){
66                         // init filename
67                         string filepath = get_target_filepath(
68                                 get_selected_file_name(),
69                                 currentLocation->name(),
70                                 sndfile_file_ending_from_string(get_selected_header_format()));
71                         
72                         initSpec(filepath);
73                         
74                         spec.start_frame = currentLocation->start();
75                         spec.end_frame = currentLocation->end();
76
77                         getSession().request_locate(spec.start_frame, false);
78
79                         if (getSession().start_audio_export(spec)){
80                                 // if export fails                      
81                                 return;
82                         }
83
84                         // wait until export of this range finished
85                         gtk_main_iteration();
86                         while(spec.running){
87                                 if(gtk_events_pending()){
88                                         gtk_main_iteration();
89                                 }else {
90                                         usleep(10000);
91                                 }
92                         }
93                         
94                         getSession().engine().freewheel (false);
95                         current_range_marker_index++;
96                 }
97         }
98         
99         spec.running = false;
100 }
101
102
103 string
104 ExportRangeMarkersDialog::get_target_filepath(string path, string filename, string postfix)
105 {
106         string target_path = path;
107         if ((target_path.find_last_of ('/')) != string::npos) {
108                 target_path += '/';
109         }
110
111         string target_filepath = target_path + filename + postfix;
112         struct stat statbuf;
113         
114         for(int counter=1; (stat (target_filepath.c_str(), &statbuf) == 0); counter++){
115                 // while file exists    
116                 ostringstream scounter;
117                 scounter.flush();
118                 scounter << counter;
119                 
120                 target_filepath = 
121                         target_path + filename + "_" + scounter.str() + postfix;
122         }
123         
124         return target_filepath;
125 }
126
127
128 bool
129 ExportRangeMarkersDialog::is_filepath_valid(string &filepath)
130 {
131         // sanity check file name first
132         struct stat statbuf;
133   
134         if (filepath.empty()) {
135                 // warning dialog
136                 string txt = _("Please enter a valid target directory.");
137                 MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
138                 msg.run();
139                 return false;
140         }
141         
142         if ( (stat (filepath.c_str(), &statbuf) != 0) || 
143                 (!S_ISDIR (statbuf.st_mode)) ) {
144                         string txt = _("Please select an existing target directory. Files\n"
145                                 "are not allowed!");
146                         MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
147                         msg.run();
148                         return false;
149         }
150         
151         // directory needs to exist and be writable
152         string dirpath = PBD::dirname (filepath);
153         if (::access (dirpath.c_str(), W_OK) != 0) {
154                 string txt = _("Cannot write file in: ") + dirpath;
155                 MessageDialog msg (*this, txt, false, MESSAGE_ERROR, BUTTONS_OK, true);
156                 msg.run();
157                 return false;
158         }
159         
160         return true;
161 }
162
163
164 void
165 ExportRangeMarkersDialog::init_progress_computing(Locations::LocationList& locations)
166 {
167         // flush vector
168         range_markers_durations_aggregated.resize(0);
169         
170         jack_nframes_t duration_before_current_location = 0;
171         Locations::LocationList::iterator locationIter;
172                 
173         for (locationIter = locations.begin(); locationIter != locations.end(); ++locationIter) {
174                 Location *currentLocation = (*locationIter);
175                 
176                 if(currentLocation->is_range_marker()){
177                         range_markers_durations_aggregated.push_back(
178                                 duration_before_current_location);
179                         
180                         jack_nframes_t duration = 
181                                 currentLocation->end() - currentLocation->start();
182                         
183                         range_markers_durations.push_back(duration);
184                         duration_before_current_location += duration;   
185                 }
186         }
187
188         total_duration = duration_before_current_location;      
189 }
190
191
192 gint
193 ExportRangeMarkersDialog::progress_timeout ()
194 {
195         double progress = 0.0;
196         
197         if(current_range_marker_index >= range_markers_durations.size()){
198                 progress = 1.0;
199         }
200         else{
201                 progress = 
202                         ((double) range_markers_durations_aggregated[current_range_marker_index] +
203                         (spec.progress * (double) range_markers_durations[current_range_marker_index])) /
204                         (double) total_duration;
205         }
206         
207         set_progress_fraction( progress );
208         return TRUE;
209 }