+
+int MWindow::copy_target(const char *path, const char *target)
+{
+ int ifd = ::open(path, O_RDONLY);
+ if( ifd < 0 ) {
+ eprintf("Cannot open asset: %s", path);
+ return 1;
+ }
+ int ret = 0;
+ int ofd = ::open(target, O_CREAT+O_TRUNC+O_WRONLY, 0777);
+ if( ofd >= 0 ) {
+ struct stat st;
+ int64_t total_bytes = !fstat(ifd, &st) ? st.st_size : 0;
+ char progress_title[BCTEXTLEN];
+ sprintf(progress_title, _("Copying: %s\n"), target);
+ BC_ProgressBox progress(-1, -1, progress_title, total_bytes);
+
+ int64_t count = 0, len = -1;
+ int bfrsz = 0x100000;
+ uint8_t *bfr = new uint8_t[bfrsz];
+ while( (len=::read(ifd, bfr, bfrsz)) > 0 ) {
+ if( len != ::write(ofd, bfr, len) ) {
+ eprintf("Error writing: %s", target);
+ break;
+ }
+ if( progress.is_cancelled() ) {
+ ret = 1;
+ break;
+ }
+ progress.update(count += len, 1);
+ }
+ delete [] bfr;
+ ::close(ofd);
+
+ progress.stop_progress();
+ if( len < 0 ) {
+ eprintf("Error reading: %s", path);
+ ret = 1;
+ }
+ }
+ else
+ eprintf("Cannot create asset target: %s", target);
+ ::close(ifd);
+ return ret;
+}
+
+int MWindow::link_target(const char *real_path, const char *link_path, int relative)
+{
+ char target[BCTEXTLEN];
+ if( relative ) {
+ const char *bp = real_path, *cp = bp;
+ const char *lp = link_path, *np = lp;
+ char *tp = target, *ep = tp+sizeof(target)-1, lch;
+ while( *lp && *bp && (lch=*lp++) == *bp++ ) {
+ if( lch == '/' ) { np = lp; cp = bp; }
+ }
+ while( tp<ep && *np ) {
+ if( *np++ != '/' ) continue;
+ *tp++ = '.'; *tp++ = '.'; *tp++ = '/';
+ }
+ while( tp<ep && *cp ) *tp++ = *cp++;
+ *tp = 0;
+ }
+ else
+ strcpy(target, real_path);
+ if( symlink(target, link_path) ) {
+ eprintf("Cannot create symlink: %s", link_path);
+ return 1;
+ }
+ return 0;
+}
+
+void MWindow::save_project(const char *dir, int save_mode, int overwrite, int reload)
+{
+ char dir_path[BCTEXTLEN];
+ strcpy(dir_path, dir);
+ FileSystem fs;
+ fs.complete_path(dir_path);
+
+ struct stat st;
+ if( !stat(dir_path, &st) ) {
+ if( !S_ISDIR(st.st_mode) ) {
+ eprintf("Path exists and is not a directory\n%s", dir_path);
+ return;
+ }
+ }
+ else {
+ if( mkdir(dir_path, S_IRWXU | S_IRWXG | S_IRWXO) ) {
+ eprintf("Cannot create directory\n%s", dir_path);
+ return;
+ }
+ }
+ char *real_dir = realpath(dir_path, 0);
+ strcpy(dir_path, real_dir);
+ free(real_dir);
+
+ EDL *save_edl = new EDL;
+ save_edl->create_objects();
+ save_edl->copy_all(edl);
+
+ char progress_title[BCTEXTLEN];
+ sprintf(progress_title, _("Saving to %s:\n"), dir);
+ int total_assets = save_edl->assets->total();
+ MainProgressBar *progress = mainprogress->start_progress(progress_title, total_assets);
+ int ret = 0;
+ Asset *current = save_edl->assets->first;
+ for( int i=0; !ret && current; ++i, current=NEXT ) {
+ char *path = current->path;
+ if( ::stat(path, &st) ) {
+ eprintf("Asset not found: %s", path);
+ continue;
+ }
+ char *real_path = realpath(path, 0);
+ const char *cp = strrchr(path, '/'), *bp = !cp ? path : cp+1;
+ char link_path[BCTEXTLEN];
+ snprintf(link_path, sizeof(link_path), "%s/%s", dir_path, bp);
+ int skip = 0;
+ if( strcmp(real_path, link_path) ) {
+ if( !::lstat(link_path, &st) ) {
+ if( overwrite )
+ ::remove(link_path);
+ else
+ skip = 1;
+ }
+ }
+ else {
+ eprintf("copy/link to self, skippped: %s", path);
+ skip = 1;
+ }
+ if( !skip ) {
+ if( save_mode == SAVE_PROJECT_COPY ) {
+ if( copy_target(real_path, link_path) )
+ ret = 1;
+ }
+ else {
+ link_target(real_path, link_path,
+ save_mode == SAVE_PROJECT_RELLINK ? 1 : 0);
+ }
+ }
+ free(real_path);
+ strcpy(path, link_path);
+
+ if( progress->is_cancelled() ) break;
+ progress->update(i);
+ }
+
+ progress->stop_progress();
+ delete progress;
+
+ char *cp = strrchr(dir_path,'/');
+ char *bp = cp ? cp+1 : dir_path;
+ char filename[BCTEXTLEN];
+ snprintf(filename, sizeof(filename), "%s/%s.xml", dir_path, bp);
+ save_edl->set_path(filename);
+ FileXML file;
+ save_edl->save_xml(&file, filename);
+ file.terminate_string();
+
+ if( !file.write_to_file(filename) ) {
+ char string[BCTEXTLEN];
+ sprintf(string, _("\"%s\" %dC written"), filename, (int)strlen(file.string()));
+ gui->lock_window("SaveProject::run 2");
+ gui->show_message(string);
+ gui->unlock_window();
+ gui->mainmenu->add_load(filename);
+ }
+ else
+ eprintf(_("Couldn't open %s."), filename);
+
+ save_edl->remove_user();
+
+ if( reload ) {
+ gui->lock_window("MWindow::save_project");
+ ArrayList<char*> filenames;
+ filenames.append(filename);
+ load_filenames(&filenames, LOADMODE_REPLACE);
+ gui->unlock_window();
+ }
+}
+
+