diff --git a/io/loadthread.cpp b/io/loadthread.cpp index 65bdc50f4..e343369d8 100644 --- a/io/loadthread.cpp +++ b/io/loadthread.cpp @@ -20,621 +20,623 @@ #include struct TransitionData { - int id; - QString name; - long length; - Clip* otc; - Clip* ctc; + int id; + QString name; + long length; + Clip* otc; + Clip* ctc; }; LoadThread::LoadThread(LoadDialog* l, bool a) : ld(l), autorecovery(a), cancelled(false) { - connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); - connect(this, SIGNAL(success()), this, SLOT(success_func())); + connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); + connect(this, SIGNAL(success()), this, SLOT(success_func())); connect(this, SIGNAL(error()), this, SLOT(error_func())); connect(this, SIGNAL(start_create_dual_transition(const TransitionData*,Clip*,Clip*,const EffectMeta*)), this, SLOT(create_dual_transition(const TransitionData*,Clip*,Clip*,const EffectMeta*))); - connect(this, SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const EffectMeta*, long, bool)), this, SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const EffectMeta*, long, bool))); + connect(this, SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const EffectMeta*, long, bool)), this, SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const EffectMeta*, long, bool))); } const EffectMeta* get_meta_from_name(const QString& name) { - for (int j=0;jtrack < 0) ? "Transform" : "Volume"; break; - case 1: effect_name = (c->track < 0) ? "Shake" : "Pan"; break; - case 2: effect_name = (c->track < 0) ? "Text" : "Noise"; break; - case 3: effect_name = (c->track < 0) ? "Solid" : "Tone"; break; - case 4: effect_name = "Invert"; break; - case 5: effect_name = "Chroma Key"; break; - case 6: effect_name = "Gaussian Blur"; break; - case 7: effect_name = "Crop"; break; - case 8: effect_name = "Flip"; break; - case 9: effect_name = "Box Blur"; break; - case 10: effect_name = "Wave"; break; - case 11: effect_name = "Temperature"; break; - } - } + // backwards compatibility with 180820 + if (stream.name() == "effect" && effect_id != -1) { + switch (effect_id) { + case 0: effect_name = (c->track < 0) ? "Transform" : "Volume"; break; + case 1: effect_name = (c->track < 0) ? "Shake" : "Pan"; break; + case 2: effect_name = (c->track < 0) ? "Text" : "Noise"; break; + case 3: effect_name = (c->track < 0) ? "Solid" : "Tone"; break; + case 4: effect_name = "Invert"; break; + case 5: effect_name = "Chroma Key"; break; + case 6: effect_name = "Gaussian Blur"; break; + case 7: effect_name = "Crop"; break; + case 8: effect_name = "Flip"; break; + case 9: effect_name = "Box Blur"; break; + case 10: effect_name = "Wave"; break; + case 11: effect_name = "Temperature"; break; + } + } - // wait for effects to be loaded - effects_loaded.lock(); + // wait for effects to be loaded + effects_loaded.lock(); - const EffectMeta* meta = NULL; + const EffectMeta* meta = NULL; - // find effect with this name - if (!effect_name.isEmpty()) { - meta = get_meta_from_name(effect_name); - } + // find effect with this name + if (!effect_name.isEmpty()) { + meta = get_meta_from_name(effect_name); + } - effects_loaded.unlock(); + effects_loaded.unlock(); - if (meta == NULL) { - dout << "[WARNING] An effect used by this project is missing. It was not loaded."; - } else { - QString tag = stream.name().toString(); + if (meta == NULL) { + dout << "[WARNING] An effect used by this project is missing. It was not loaded."; + } else { + QString tag = stream.name().toString(); - int type; - if (tag == "opening") { - type = TA_OPENING_TRANSITION; - } else if (tag == "closing") { - type = TA_CLOSING_TRANSITION; - } else { - type = TA_NO_TRANSITION; - } + int type; + if (tag == "opening") { + type = TA_OPENING_TRANSITION; + } else if (tag == "closing") { + type = TA_CLOSING_TRANSITION; + } else { + type = TA_NO_TRANSITION; + } - emit start_create_effect_ui(&stream, c, type, meta, effect_length, effect_enabled); + emit start_create_effect_ui(&stream, c, type, meta, effect_length, effect_enabled); - waitCond.wait(&mutex); - } + waitCond.wait(&mutex); + } } void LoadThread::read_next(QXmlStreamReader &stream) { - stream.readNext(); - update_current_element_count(stream); + stream.readNext(); + update_current_element_count(stream); } void LoadThread::read_next_start_element(QXmlStreamReader &stream) { - stream.readNextStartElement(); - update_current_element_count(stream); + stream.readNextStartElement(); + update_current_element_count(stream); } void LoadThread::update_current_element_count(QXmlStreamReader &stream) { - if (is_element(stream)) { - current_element_count++; - report_progress((current_element_count * 100) / total_element_count); - } + if (is_element(stream)) { + current_element_count++; + report_progress((current_element_count * 100) / total_element_count); + } } bool LoadThread::is_element(QXmlStreamReader &stream) { - return stream.isStartElement() - && (stream.name() == "folder" - || stream.name() == "footage" - || stream.name() == "sequence" - || stream.name() == "clip" - || stream.name() == "effect"); + return stream.isStartElement() + && (stream.name() == "folder" + || stream.name() == "footage" + || stream.name() == "sequence" + || stream.name() == "clip" + || stream.name() == "effect"); } bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) { - f.seek(0); - stream.setDevice(stream.device()); + f.seek(0); + stream.setDevice(stream.device()); - QString root_search; - QString child_search; + QString root_search; + QString child_search; - switch (type) { - case LOAD_TYPE_VERSION: - root_search = "version"; - break; - case LOAD_TYPE_URL: - root_search = "url"; - break; - case MEDIA_TYPE_FOLDER: - root_search = "folders"; - child_search = "folder"; - break; - case MEDIA_TYPE_FOOTAGE: - root_search = "media"; - child_search = "footage"; - break; - case MEDIA_TYPE_SEQUENCE: - root_search = "sequences"; - child_search = "sequence"; - break; - } + switch (type) { + case LOAD_TYPE_VERSION: + root_search = "version"; + break; + case LOAD_TYPE_URL: + root_search = "url"; + break; + case MEDIA_TYPE_FOLDER: + root_search = "folders"; + child_search = "folder"; + break; + case MEDIA_TYPE_FOOTAGE: + root_search = "media"; + child_search = "footage"; + break; + case MEDIA_TYPE_SEQUENCE: + root_search = "sequences"; + child_search = "sequence"; + break; + } - show_err = true; + show_err = true; - while (!stream.atEnd() && !cancelled) { - read_next_start_element(stream); - if (stream.name() == root_search) { - if (type == LOAD_TYPE_VERSION) { - int proj_version = stream.readElementText().toInt(); - if (proj_version < MIN_SAVE_VERSION && proj_version > SAVE_VERSION) { - if (QMessageBox::warning(mainWindow, "Version Mismatch", "This project was saved in a different version of Olive and may not be fully compatible with this version. Would you like to attempt loading it anyway?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) { - show_err = false; - return false; - } - } - } else if (type == LOAD_TYPE_URL) { - internal_proj_url = stream.readElementText(); - internal_proj_dir = QFileInfo(internal_proj_url).absoluteDir(); - } else { - while (!cancelled && !(stream.name() == root_search && stream.isEndElement())) { - read_next(stream); - if (stream.name() == child_search && stream.isStartElement()) { - switch (type) { - case MEDIA_TYPE_FOLDER: - { - Media* folder = panel_project->new_folder(0); - folder->temp_id2 = 0; - for (int j=0;jtemp_id = attr.value().toInt(); - } else if (attr.name() == "name") { - folder->set_name(attr.value().toString()); - } else if (attr.name() == "parent") { - folder->temp_id2 = attr.value().toInt(); - } - } - loaded_folders.append(folder); - } - break; - case MEDIA_TYPE_FOOTAGE: - { - int folder = 0; + while (!stream.atEnd() && !cancelled) { + read_next_start_element(stream); + if (stream.name() == root_search) { + if (type == LOAD_TYPE_VERSION) { + int proj_version = stream.readElementText().toInt(); + if (proj_version < MIN_SAVE_VERSION && proj_version > SAVE_VERSION) { + if (QMessageBox::warning(mainWindow, "Version Mismatch", "This project was saved in a different version of Olive and may not be fully compatible with this version. Would you like to attempt loading it anyway?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) { + show_err = false; + return false; + } + } + } else if (type == LOAD_TYPE_URL) { + internal_proj_url = stream.readElementText(); + internal_proj_dir = QFileInfo(internal_proj_url).absoluteDir(); + } else { + while (!cancelled && !(stream.name() == root_search && stream.isEndElement())) { + read_next(stream); + if (stream.name() == child_search && stream.isStartElement()) { + switch (type) { + case MEDIA_TYPE_FOLDER: + { + Media* folder = panel_project->new_folder(0); + folder->temp_id2 = 0; + for (int j=0;jtemp_id = attr.value().toInt(); + } else if (attr.name() == "name") { + folder->set_name(attr.value().toString()); + } else if (attr.name() == "parent") { + folder->temp_id2 = attr.value().toInt(); + } + } + loaded_folders.append(folder); + } + break; + case MEDIA_TYPE_FOOTAGE: + { + int folder = 0; - Media* item = new Media(0); - Footage* m = new Footage(); + Media* item = new Media(0); + Footage* m = new Footage(); - m->using_inout = false; + m->using_inout = false; - for (int j=0;jsave_id = attr.value().toInt(); - } else if (attr.name() == "folder") { - folder = attr.value().toInt(); - } else if (attr.name() == "name") { - m->name = attr.value().toString(); - } else if (attr.name() == "url") { - m->url = attr.value().toString(); + for (int j=0;jsave_id = attr.value().toInt(); + } else if (attr.name() == "folder") { + folder = attr.value().toInt(); + } else if (attr.name() == "name") { + m->name = attr.value().toString(); + } else if (attr.name() == "url") { + m->url = attr.value().toString(); - if (!QFileInfo::exists(m->url)) { // if path is not absolute - QString proj_dir_test = proj_dir.absoluteFilePath(m->url); - QString internal_proj_dir_test = internal_proj_dir.absoluteFilePath(m->url); + if (!QFileInfo::exists(m->url)) { // if path is not absolute + QString proj_dir_test = proj_dir.absoluteFilePath(m->url); + QString internal_proj_dir_test = internal_proj_dir.absoluteFilePath(m->url); - if (QFileInfo::exists(proj_dir_test)) { // if path is relative to the project's current dir - m->url = proj_dir_test; - dout << "[INFO] Matched" << attr.value().toString() << "relative to project's current directory"; - } else if (QFileInfo::exists(internal_proj_dir_test)) { // if path is relative to the last directory the project was saved in - m->url = internal_proj_dir_test; - dout << "[INFO] Matched" << attr.value().toString() << "relative to project's internal directory"; - } else if (m->url.contains('%')) { - // hack for image sequences (qt won't be able to find the URL with %, but ffmpeg may) - m->url = internal_proj_dir_test; - dout << "[INFO] Guess image sequence" << attr.value().toString() << "path to project's internal directory"; - } else { - dout << "[INFO] Failed to match" << attr.value().toString() << "to file"; - } - } else { - dout << "[INFO] Matched" << attr.value().toString() << "with absolute path"; - } - } else if (attr.name() == "duration") { - m->length = attr.value().toLongLong(); - } else if (attr.name() == "using_inout") { - m->using_inout = (attr.value() == "1"); - } else if (attr.name() == "in") { - m->in = attr.value().toLong(); - } else if (attr.name() == "out") { - m->out = attr.value().toLong(); - } - } + if (QFileInfo::exists(proj_dir_test)) { // if path is relative to the project's current dir + m->url = proj_dir_test; + dout << "[INFO] Matched" << attr.value().toString() << "relative to project's current directory"; + } else if (QFileInfo::exists(internal_proj_dir_test)) { // if path is relative to the last directory the project was saved in + m->url = internal_proj_dir_test; + dout << "[INFO] Matched" << attr.value().toString() << "relative to project's internal directory"; + } else if (m->url.contains('%')) { + // hack for image sequences (qt won't be able to find the URL with %, but ffmpeg may) + m->url = internal_proj_dir_test; + dout << "[INFO] Guess image sequence" << attr.value().toString() << "path to project's internal directory"; + } else { + dout << "[INFO] Failed to match" << attr.value().toString() << "to file"; + } + } else { + dout << "[INFO] Matched" << attr.value().toString() << "with absolute path"; + } + } else if (attr.name() == "duration") { + m->length = attr.value().toLongLong(); + } else if (attr.name() == "using_inout") { + m->using_inout = (attr.value() == "1"); + } else if (attr.name() == "in") { + m->in = attr.value().toLong(); + } else if (attr.name() == "out") { + m->out = attr.value().toLong(); + } else if (attr.name() == "speed") { + m->speed = attr.value().toDouble(); + } + } - item->set_footage(m); + item->set_footage(m); - project_model.appendChild(find_loaded_folder_by_id(folder), item); + project_model.appendChild(find_loaded_folder_by_id(folder), item); - // analyze media to see if it's the same - loaded_media_items.append(item); - } - break; - case MEDIA_TYPE_SEQUENCE: - { - Media* parent = NULL; - Sequence* s = new Sequence(); + // analyze media to see if it's the same + loaded_media_items.append(item); + } + break; + case MEDIA_TYPE_SEQUENCE: + { + Media* parent = NULL; + Sequence* s = new Sequence(); - // load attributes about sequence - for (int j=0;jname = attr.value().toString(); - } else if (attr.name() == "folder") { - int folder = attr.value().toInt(); - if (folder > 0) parent = find_loaded_folder_by_id(folder); - } else if (attr.name() == "id") { - s->save_id = attr.value().toInt(); - } else if (attr.name() == "width") { - s->width = attr.value().toInt(); - } else if (attr.name() == "height") { - s->height = attr.value().toInt(); - } else if (attr.name() == "framerate") { - s->frame_rate = attr.value().toDouble(); - } else if (attr.name() == "afreq") { - s->audio_frequency = attr.value().toInt(); - } else if (attr.name() == "alayout") { - s->audio_layout = attr.value().toInt(); - } else if (attr.name() == "open") { - open_seq = s; - } else if (attr.name() == "workarea") { - s->using_workarea = (attr.value() == "1"); - } else if (attr.name() == "workareaIn") { - s->workarea_in = attr.value().toLong(); - } else if (attr.name() == "workareaOut") { - s->workarea_out = attr.value().toLong(); - } - } + // load attributes about sequence + for (int j=0;jname = attr.value().toString(); + } else if (attr.name() == "folder") { + int folder = attr.value().toInt(); + if (folder > 0) parent = find_loaded_folder_by_id(folder); + } else if (attr.name() == "id") { + s->save_id = attr.value().toInt(); + } else if (attr.name() == "width") { + s->width = attr.value().toInt(); + } else if (attr.name() == "height") { + s->height = attr.value().toInt(); + } else if (attr.name() == "framerate") { + s->frame_rate = attr.value().toDouble(); + } else if (attr.name() == "afreq") { + s->audio_frequency = attr.value().toInt(); + } else if (attr.name() == "alayout") { + s->audio_layout = attr.value().toInt(); + } else if (attr.name() == "open") { + open_seq = s; + } else if (attr.name() == "workarea") { + s->using_workarea = (attr.value() == "1"); + } else if (attr.name() == "workareaIn") { + s->workarea_in = attr.value().toLong(); + } else if (attr.name() == "workareaOut") { + s->workarea_out = attr.value().toLong(); + } + } - QVector transition_data; + QVector transition_data; - // load all clips and clip information - while (!cancelled && !(stream.name() == child_search && stream.isEndElement()) && !stream.atEnd()) { - read_next_start_element(stream); - if (stream.name() == "marker" && stream.isStartElement()) { - Marker m; - for (int j=0;jmarkers.append(m); - } else if (stream.name() == "transition" && stream.isStartElement()) { - TransitionData td; - td.otc = NULL; - td.ctc = NULL; - for (int j=0;jmarkers.append(m); + } else if (stream.name() == "transition" && stream.isStartElement()) { + TransitionData td; + td.otc = NULL; + td.ctc = NULL; + for (int j=0;jautoscale = false; + // backwards compatibility code + c->autoscale = false; - c->media = NULL; + c->media = NULL; - for (int j=0;jname = attr.value().toString(); - } else if (attr.name() == "enabled") { - c->enabled = (attr.value() == "1"); - } else if (attr.name() == "id") { - c->load_id = attr.value().toInt(); - } else if (attr.name() == "clipin") { - c->clip_in = attr.value().toLong(); - } else if (attr.name() == "in") { - c->timeline_in = attr.value().toLong(); - } else if (attr.name() == "out") { - c->timeline_out = attr.value().toLong(); - } else if (attr.name() == "track") { - c->track = attr.value().toInt(); - } else if (attr.name() == "r") { - c->color_r = attr.value().toInt(); - } else if (attr.name() == "g") { - c->color_g = attr.value().toInt(); - } else if (attr.name() == "b") { - c->color_b = attr.value().toInt(); - } else if (attr.name() == "autoscale") { - c->autoscale = (attr.value() == "1"); - } else if (attr.name() == "media") { - media_type = MEDIA_TYPE_FOOTAGE; - media_id = attr.value().toInt(); - } else if (attr.name() == "stream") { - stream_id = attr.value().toInt(); - } else if (attr.name() == "speed") { - c->speed = attr.value().toDouble(); - } else if (attr.name() == "maintainpitch") { - c->maintain_audio_pitch = (attr.value() == "1"); - } else if (attr.name() == "reverse") { - c->reverse = (attr.value() == "1"); - } else if (attr.name() == "opening") { - c->opening_transition = attr.value().toInt(); - } else if (attr.name() == "closing") { - c->closing_transition = attr.value().toInt(); - } else if (attr.name() == "sequence") { - media_type = MEDIA_TYPE_SEQUENCE; + for (int j=0;jname = attr.value().toString(); + } else if (attr.name() == "enabled") { + c->enabled = (attr.value() == "1"); + } else if (attr.name() == "id") { + c->load_id = attr.value().toInt(); + } else if (attr.name() == "clipin") { + c->clip_in = attr.value().toLong(); + } else if (attr.name() == "in") { + c->timeline_in = attr.value().toLong(); + } else if (attr.name() == "out") { + c->timeline_out = attr.value().toLong(); + } else if (attr.name() == "track") { + c->track = attr.value().toInt(); + } else if (attr.name() == "r") { + c->color_r = attr.value().toInt(); + } else if (attr.name() == "g") { + c->color_g = attr.value().toInt(); + } else if (attr.name() == "b") { + c->color_b = attr.value().toInt(); + } else if (attr.name() == "autoscale") { + c->autoscale = (attr.value() == "1"); + } else if (attr.name() == "media") { + media_type = MEDIA_TYPE_FOOTAGE; + media_id = attr.value().toInt(); + } else if (attr.name() == "stream") { + stream_id = attr.value().toInt(); + } else if (attr.name() == "speed") { + c->speed = attr.value().toDouble(); + } else if (attr.name() == "maintainpitch") { + c->maintain_audio_pitch = (attr.value() == "1"); + } else if (attr.name() == "reverse") { + c->reverse = (attr.value() == "1"); + } else if (attr.name() == "opening") { + c->opening_transition = attr.value().toInt(); + } else if (attr.name() == "closing") { + c->closing_transition = attr.value().toInt(); + } else if (attr.name() == "sequence") { + media_type = MEDIA_TYPE_SEQUENCE; - // since we haven't finished loading sequences, we defer linking this until later - c->media = NULL; - c->media_stream = attr.value().toInt(); - loaded_clips.append(c); - } - } + // since we haven't finished loading sequences, we defer linking this until later + c->media = NULL; + c->media_stream = attr.value().toInt(); + loaded_clips.append(c); + } + } - // set media and media stream - switch (media_type) { - case MEDIA_TYPE_FOOTAGE: - if (media_id >= 0) { - for (int j=0;jto_footage(); - if (m->save_id == media_id) { - c->media = loaded_media_items.at(j); - c->media_stream = stream_id; - break; - } - } - } - break; - } + // set media and media stream + switch (media_type) { + case MEDIA_TYPE_FOOTAGE: + if (media_id >= 0) { + for (int j=0;jto_footage(); + if (m->save_id == media_id) { + c->media = loaded_media_items.at(j); + c->media_stream = stream_id; + break; + } + } + } + break; + } - // load links and effects - while (!cancelled && !(stream.name() == "clip" && stream.isEndElement()) && !stream.atEnd()) { - read_next(stream); - if (stream.isStartElement()) { - if (stream.name() == "linked") { - while (!cancelled && !(stream.name() == "linked" && stream.isEndElement()) && !stream.atEnd()) { - read_next(stream); - if (stream.name() == "link" && stream.isStartElement()) { - for (int k=0;klinked.append(link_attr.value().toInt()); - break; - } - } - } - } - if (cancelled) return false; - } else if (stream.isStartElement() && (stream.name() == "effect" || stream.name() == "opening" || stream.name() == "closing")) { - // "opening" and "closing" are backwards compatibility code - load_effect(stream, c); - } - } - } - if (cancelled) return false; + // load links and effects + while (!cancelled && !(stream.name() == "clip" && stream.isEndElement()) && !stream.atEnd()) { + read_next(stream); + if (stream.isStartElement()) { + if (stream.name() == "linked") { + while (!cancelled && !(stream.name() == "linked" && stream.isEndElement()) && !stream.atEnd()) { + read_next(stream); + if (stream.name() == "link" && stream.isStartElement()) { + for (int k=0;klinked.append(link_attr.value().toInt()); + break; + } + } + } + } + if (cancelled) return false; + } else if (stream.isStartElement() && (stream.name() == "effect" || stream.name() == "opening" || stream.name() == "closing")) { + // "opening" and "closing" are backwards compatibility code + load_effect(stream, c); + } + } + } + if (cancelled) return false; - s->clips.append(c); - } - } - if (cancelled) return false; + s->clips.append(c); + } + } + if (cancelled) return false; - // correct links, clip IDs, transitions - for (int i=0;iclips.size();i++) { - // correct links - Clip* correct_clip = s->clips.at(i); - for (int j=0;jlinked.size();j++) { - bool found = false; - for (int k=0;kclips.size();k++) { - if (s->clips.at(k)->load_id == correct_clip->linked.at(j)) { - correct_clip->linked[j] = k; - found = true; - break; - } - } - if (!found) { - correct_clip->linked.removeAt(j); - j--; - if (QMessageBox::warning(mainWindow, "Invalid Clip Link", "This project contains an invalid clip link. It may be corrupt. Would you like to continue loading it?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) { - delete s; - return false; - } - } - } + // correct links, clip IDs, transitions + for (int i=0;iclips.size();i++) { + // correct links + Clip* correct_clip = s->clips.at(i); + for (int j=0;jlinked.size();j++) { + bool found = false; + for (int k=0;kclips.size();k++) { + if (s->clips.at(k)->load_id == correct_clip->linked.at(j)) { + correct_clip->linked[j] = k; + found = true; + break; + } + } + if (!found) { + correct_clip->linked.removeAt(j); + j--; + if (QMessageBox::warning(mainWindow, "Invalid Clip Link", "This project contains an invalid clip link. It may be corrupt. Would you like to continue loading it?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) { + delete s; + return false; + } + } + } - // re-link clips to transitions - if (correct_clip->opening_transition > -1) { - for (int j=0;jopening_transition) { - transition_data[j].otc = correct_clip; - } - } - } - if (correct_clip->closing_transition > -1) { - for (int j=0;jclosing_transition) { - transition_data[j].ctc = correct_clip; - } - } - } - } + // re-link clips to transitions + if (correct_clip->opening_transition > -1) { + for (int j=0;jopening_transition) { + transition_data[j].otc = correct_clip; + } + } + } + if (correct_clip->closing_transition > -1) { + for (int j=0;jclosing_transition) { + transition_data[j].ctc = correct_clip; + } + } + } + } - // create transitions - for (int i=0;iopening_transition = -1; - if (td.ctc != NULL) td.ctc->closing_transition = -1; + // create transitions + for (int i=0;iopening_transition = -1; + if (td.ctc != NULL) td.ctc->closing_transition = -1; } else { emit start_create_dual_transition(&td, primary, secondary, meta); waitCond.wait(&mutex); - } - } - } + } + } + } - Media* m = panel_project->new_sequence(NULL, s, false, parent); + Media* m = panel_project->new_sequence(NULL, s, false, parent); - loaded_sequences.append(m); - } - break; - } - } - } - if (cancelled) return false; - } - break; - } - } - return !cancelled; + loaded_sequences.append(m); + } + break; + } + } + } + if (cancelled) return false; + } + break; + } + } + return !cancelled; } Media* LoadThread::find_loaded_folder_by_id(int id) { - if (id == 0) return NULL; - for (int j=0;jtemp_id == id) { - return parent_item; - } - } - return NULL; + if (id == 0) return NULL; + for (int j=0;jtemp_id == id) { + return parent_item; + } + } + return NULL; } void LoadThread::run() { - mutex.lock(); + mutex.lock(); - QFile file(project_url); - if (!file.open(QIODevice::ReadOnly)) { - dout << "[ERROR] Could not open file"; - return; - } + QFile file(project_url); + if (!file.open(QIODevice::ReadOnly)) { + dout << "[ERROR] Could not open file"; + return; + } - /* set up directories to search for media - * most of the time, these will be the same but in - * case the project file has moved without the footage, - * we check both - */ - proj_dir = QFileInfo(project_url).absoluteDir(); - internal_proj_dir = QFileInfo(project_url).absoluteDir(); - internal_proj_url = project_url; + /* set up directories to search for media + * most of the time, these will be the same but in + * case the project file has moved without the footage, + * we check both + */ + proj_dir = QFileInfo(project_url).absoluteDir(); + internal_proj_dir = QFileInfo(project_url).absoluteDir(); + internal_proj_url = project_url; - QXmlStreamReader stream(&file); + QXmlStreamReader stream(&file); - bool cont = false; - error_str.clear(); - show_err = true; + bool cont = false; + error_str.clear(); + show_err = true; - // temp variables for loading (unnecessary?) - open_seq = NULL; - loaded_folders.clear(); - loaded_media_items.clear(); - loaded_clips.clear(); - loaded_sequences.clear(); + // temp variables for loading (unnecessary?) + open_seq = NULL; + loaded_folders.clear(); + loaded_media_items.clear(); + loaded_clips.clear(); + loaded_sequences.clear(); - // get "element" count - current_element_count = 0; - total_element_count = 0; - while (!cancelled && !stream.atEnd()) { - stream.readNextStartElement(); - if (is_element(stream)) { - total_element_count++; - } - } - cont = !cancelled; + // get "element" count + current_element_count = 0; + total_element_count = 0; + while (!cancelled && !stream.atEnd()) { + stream.readNextStartElement(); + if (is_element(stream)) { + total_element_count++; + } + } + cont = !cancelled; - // find project file version - cont = load_worker(file, stream, LOAD_TYPE_VERSION); + // find project file version + cont = load_worker(file, stream, LOAD_TYPE_VERSION); - // find project's internal URL + // find project's internal URL cont = load_worker(file, stream, LOAD_TYPE_URL); - // load folders first - if (cont) { - cont = load_worker(file, stream, MEDIA_TYPE_FOLDER); - } + // load folders first + if (cont) { + cont = load_worker(file, stream, MEDIA_TYPE_FOLDER); + } - // load media - if (cont) { - // since folders loaded correctly, organize them appropriately - for (int i=0;itemp_id2; - project_model.appendChild(find_loaded_folder_by_id(parent), folder); - } + // load media + if (cont) { + // since folders loaded correctly, organize them appropriately + for (int i=0;itemp_id2; + project_model.appendChild(find_loaded_folder_by_id(parent), folder); + } - cont = load_worker(file, stream, MEDIA_TYPE_FOOTAGE); - } + cont = load_worker(file, stream, MEDIA_TYPE_FOOTAGE); + } - // load sequences - if (cont) { - cont = load_worker(file, stream, MEDIA_TYPE_SEQUENCE); - } + // load sequences + if (cont) { + cont = load_worker(file, stream, MEDIA_TYPE_SEQUENCE); + } - if (!cancelled) { - if (!cont) { + if (!cancelled) { + if (!cont) { xml_error = false; if (show_err) emit error(); - } else if (stream.hasError()) { + } else if (stream.hasError()) { error_str = stream.errorString(); xml_error = true; emit error(); - cont = false; + cont = false; - } else { - // attach nested sequence clips to their sequences - for (int i=0;imedia == NULL && loaded_clips.at(i)->media_stream == loaded_sequences.at(j)->to_sequence()->save_id) { - loaded_clips.at(i)->media = loaded_sequences.at(j); - loaded_clips.at(i)->refresh(); - break; - } - } - } - } - } - - if (cont) { - emit success(); // run in main thread - - for (int i=0;istart_preview_generator(loaded_media_items.at(i), true); - } + } else { + // attach nested sequence clips to their sequences + for (int i=0;imedia == NULL && loaded_clips.at(i)->media_stream == loaded_sequences.at(j)->to_sequence()->save_id) { + loaded_clips.at(i)->media = loaded_sequences.at(j); + loaded_clips.at(i)->refresh(); + break; + } + } + } + } } - file.close(); + if (cont) { + emit success(); // run in main thread - mutex.unlock(); + for (int i=0;istart_preview_generator(loaded_media_items.at(i), true); + } + } + + file.close(); + + mutex.unlock(); } void LoadThread::cancel() { - waitCond.wakeAll(); + waitCond.wakeAll(); cancelled = true; } @@ -663,64 +665,64 @@ void LoadThread::success_func() { counter++; } mainWindow->updateTitle(orig_filename); - } else { - panel_project->add_recent_project(project_url); - } + } else { + panel_project->add_recent_project(project_url); + } - mainWindow->setWindowModified(autorecovery); - if (open_seq != NULL) set_sequence(open_seq); - update_ui(false); + mainWindow->setWindowModified(autorecovery); + if (open_seq != NULL) set_sequence(open_seq); + update_ui(false); } void LoadThread::create_effect_ui( - QXmlStreamReader* stream, - Clip* c, - int type, - const EffectMeta* meta, - long effect_length, - bool effect_enabled) + QXmlStreamReader* stream, + Clip* c, + int type, + const EffectMeta* meta, + long effect_length, + bool effect_enabled) { - /* This is extremely hacky - prepare yourself. - * - * When moving project loading to a separate thread, it was soon discovered - * that effects wouldn't load correctly anymore. They were actually still - * "functional", but there were no controls appearing in EffectControls. - * - * Turns out since Effect creates its UI in its constructor, the UI was - * created in this thread rather than the main GUI thread, which is a big - * no-no. Unfortunately the design of Effect does not separate UI and data, - * so having the UI set up was integral to creating annd loading the effect. - * - * Therefore, rather than rewrite the class (I just rewrote QTreeWidget to - * QTreeView with a custom model/item so I'm exhausted), for - * quick-n-dirty-ness, I made LoadThread offload the effect creation to the - * main thread (and since the effect loads data from the same XML stream, - * the LoadThread has to wait for the effect to finish before it can - * continue. - * - * Sorry. I'll fix it one day. - */ + /* This is extremely hacky - prepare yourself. + * + * When moving project loading to a separate thread, it was soon discovered + * that effects wouldn't load correctly anymore. They were actually still + * "functional", but there were no controls appearing in EffectControls. + * + * Turns out since Effect creates its UI in its constructor, the UI was + * created in this thread rather than the main GUI thread, which is a big + * no-no. Unfortunately the design of Effect does not separate UI and data, + * so having the UI set up was integral to creating annd loading the effect. + * + * Therefore, rather than rewrite the class (I just rewrote QTreeWidget to + * QTreeView with a custom model/item so I'm exhausted), for + * quick-n-dirty-ness, I made LoadThread offload the effect creation to the + * main thread (and since the effect loads data from the same XML stream, + * the LoadThread has to wait for the effect to finish before it can + * continue. + * + * Sorry. I'll fix it one day. + */ - if (cancelled) return; - if (type == TA_NO_TRANSITION) { - Effect* e = create_effect(c, meta); - e->set_enabled(effect_enabled); - e->load(*stream); + if (cancelled) return; + if (type == TA_NO_TRANSITION) { + Effect* e = create_effect(c, meta); + e->set_enabled(effect_enabled); + e->load(*stream); - c->effects.append(e); - } else { - int transition_index = create_transition(c, NULL, meta); - Transition* t = c->sequence->transitions.at(transition_index); - if (effect_length > -1) t->set_length(effect_length); - t->set_enabled(effect_enabled); - t->load(*stream); + c->effects.append(e); + } else { + int transition_index = create_transition(c, NULL, meta); + Transition* t = c->sequence->transitions.at(transition_index); + if (effect_length > -1) t->set_length(effect_length); + t->set_enabled(effect_enabled); + t->load(*stream); - if (type == TA_OPENING_TRANSITION) { - c->opening_transition = transition_index; - } else { - c->closing_transition = transition_index; - } - } + if (type == TA_OPENING_TRANSITION) { + c->opening_transition = transition_index; + } else { + c->closing_transition = transition_index; + } + } waitCond.wakeAll(); } diff --git a/panels/project.cpp b/panels/project.cpp index 3c924b933..b2ee221b2 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -852,6 +852,7 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, stream.writeAttribute("using_inout", QString::number(f->using_inout)); stream.writeAttribute("in", QString::number(f->in)); stream.writeAttribute("out", QString::number(f->out)); + stream.writeAttribute("speed", QString::number(f->speed)); for (int j=0;jvideo_tracks.size();j++) { const FootageStream& ms = f->video_tracks.at(j); stream.writeStartElement("video");