2 Copyright (C) 2010 Paul Davis
3 Author: Robin Gareus <robin@gareus.org>
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.
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.
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.
20 #ifdef WITH_VIDEOTIMELINE
28 #include <sys/types.h>
32 #include <sigc++/bind.h>
35 #include "pbd/error.h"
36 #include "pbd/convert.h"
37 #include "gtkmm2ext/utils.h"
38 #include "ardour/session_directory.h"
39 #include "ardour/profile.h"
40 #include "ardour/template_utils.h"
41 #include "ardour/session.h"
42 #include "ardour_ui.h"
43 #include "gui_thread.h"
45 #include "utils_videotl.h"
48 #include "video_copy_dialog.h"
54 using namespace ARDOUR;
56 VideoCopyDialog::VideoCopyDialog (Session* s, std::string infile)
57 : ArdourDialog (_("Import Video File "))
59 , path_label (_("Output File:"), Gtk::ALIGN_LEFT)
60 , browse_button (_("Browse"))
61 , copy_button (_("Copy/Embed"))
62 , abort_button (_("Abort"))
68 set_name ("VideoCopyDialog");
69 set_position (Gtk::WIN_POS_MOUSE);
71 set_skip_taskbar_hint (true);
72 set_resizable (false);
73 p_connection = sigc::connection();
75 std::string dstdir = video_dest_dir(_session->session_directory().video_path(), Config->get_video_server_docroot());
76 std::string dstfn = dstdir + G_DIR_SEPARATOR + Glib::path_get_basename(infile);
77 path_entry.set_text (dstfn);
79 path_hbox = manage (new HBox);
80 path_hbox->pack_start (path_label, false, false, 3);
81 path_hbox->pack_start (path_entry, true, true, 3);
82 path_hbox->pack_start (browse_button, false, false, 3);
83 browse_button.set_name ("PaddedButton");
84 path_entry.set_width_chars(38);
86 browse_button.signal_clicked().connect (sigc::mem_fun (*this, &VideoCopyDialog::open_browse_dialog));
87 copy_button.signal_clicked().connect (sigc::mem_fun (*this, &VideoCopyDialog::launch_copy));
88 abort_button.signal_clicked().connect (sigc::mem_fun (*this, &VideoCopyDialog::abort_clicked));
90 progress_box = manage (new VBox);
91 progress_box->pack_start (progress_label, false, false);
92 progress_box->pack_start (pbar, false, false);
93 progress_box->pack_start (abort_button, false, false);
95 get_vbox()->pack_start (*path_hbox, false, false);
96 get_vbox()->pack_start (*progress_box, false, false);
99 cancel_button = add_button (Stock::CANCEL, RESPONSE_CANCEL);
100 get_action_area()->pack_start (copy_button, false, false);
101 show_all_children ();
102 progress_box->hide();
105 VideoCopyDialog::~VideoCopyDialog ()
110 VideoCopyDialog::setup_non_interactive_copy (std::string destfn)
112 if (destfn.empty()) {
113 std::string dstdir = video_dest_dir(_session->session_directory().video_path(), Config->get_video_server_docroot());
114 outfn= dstdir + G_DIR_SEPARATOR + Glib::path_get_basename(infn);
122 VideoCopyDialog::on_show ()
125 Glib::signal_timeout().connect_once (sigc::mem_fun(*this, &VideoCopyDialog::launch_copy), 200);
131 VideoCopyDialog::abort_clicked ()
137 VideoCopyDialog::progress_timeout ()
140 pbar.set_pulse_step(.5);
144 pbar.set_fraction ((double)p_cur / (double) p_tot);
149 video_copy_thread (void *arg)
151 VideoCopyDialog *cvd = static_cast<VideoCopyDialog*>(arg);
158 VideoCopyDialog::launch_copy ()
161 outfn = path_entry.get_text();
163 if (!confirm_video_outfn(outfn)) { return; }
164 p_cur = 0; p_tot = 0;
166 p_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &VideoCopyDialog::progress_timeout), 80);
168 pbar.set_size_request(300,-1);
169 progress_box->show();
171 cancel_button->hide();
176 pthread_create(&thread, NULL, video_copy_thread ,this);
178 if (gtk_events_pending()) {
179 gtk_main_iteration ();
184 pthread_join(thread, NULL);
186 p_connection.disconnect();
189 Gtk::Dialog::response(RESPONSE_CANCEL);
191 Gtk::Dialog::response(RESPONSE_ACCEPT);
196 VideoCopyDialog::do_copy ()
198 progress_label.set_text (_("Linking File."));
200 unlink (outfn.c_str());
202 bool try_hardlink = false; // Config->get_try_link_for_embed(); /* XXX */
204 if (lstat (infn.c_str(), &sb) == 0) {
206 /* don't hardlink a symlink */
207 if ((sb.st_mode&S_IFMT) == S_IFLNK) {
208 try_hardlink = false;
209 if (stat (infn.c_str(), &sb) == 0) {
214 /* Can not stat() input file */
215 warning << _("Can not read input file.") << endmsg;
221 if ( !try_hardlink || link(infn.c_str(), outfn.c_str()) ) {
222 /* hard-link failed , try copy */
223 progress_label.set_text (_("Copying File."));
224 int infd = open (infn.c_str(), O_RDONLY);
225 int outfd = open (outfn.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
226 if (infd <0 || outfd <0) {
227 if (infd != -1) close(infd);
228 warning << _("Can not open files for copy.") << endmsg;
235 while ((nrb = read(infd, buffer, BUFSIZ)) > 0 && nrb != -1 ) {
236 ret = write(outfd, buffer, nrb);
237 if(ret != nrb || aborted) {
238 warning << _("File copy failed.") << endmsg;
239 unlink(outfn.c_str());
252 VideoCopyDialog::open_browse_dialog ()
254 Gtk::FileChooserDialog dialog(_("Video File Copy Destination"), Gtk::FILE_CHOOSER_ACTION_SAVE);
255 dialog.set_filename (path_entry.get_text());
257 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
258 dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
260 int result = dialog.run();
262 if (result == Gtk::RESPONSE_OK) {
263 std::string filename = dialog.get_filename();
265 if (filename.length()) {
266 path_entry.set_text (filename);
270 #endif /* WITH_VIDEOTIMELINE */