From b83ddbe3d659045222866d1c73b7b7d6276b0d40 Mon Sep 17 00:00:00 2001 From: Al Crate Date: Mon, 7 Aug 2023 07:44:58 +0100 Subject: [PATCH] Bug fixes (#51) * Bug fixes Signed-off-by: Al Crate --- CHANGELOG.md | 9 --- CMakeLists.txt | 2 +- docs/build_guides/centos_7.md | 2 +- docs/build_guides/rocky_linux_9_1.md | 2 +- include/xstudio/ui/qml/session_model_ui.hpp | 2 +- src/media/src/media_source_actor.cpp | 3 +- .../dneg/shotgun/src/data_source_shotgun.cpp | 7 +- .../src/qml/Shotgun.1/ShotgunPublishNotes.qml | 2 - .../shotgun/src/qml/Shotgun.1/ShotgunRoot.qml | 19 +++--- .../media_reader/openexr/src/openexr.cpp | 11 ++-- .../src/plugin_manager_actor.cpp | 66 +++++++++---------- .../session/src/session_model_handler_ui.cpp | 44 +++++++++++-- .../session/src/session_model_methods_ui.cpp | 2 +- src/ui/qml/session/src/session_model_ui.cpp | 8 +++ ui/qml/xstudio/menus/XsMediaMenu.qml | 3 + .../panels/playlist/XsPlaylistsPanelNew.qml | 28 ++++++-- 16 files changed, 136 insertions(+), 74 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 584ba8795..8b1378917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1 @@ - - - - - - - - - diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ecc79b52..ba40ec9b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.12 FATAL_ERROR) -set(XSTUDIO_GLOBAL_VERSION "0.11.0" CACHE STRING "Version string") +set(XSTUDIO_GLOBAL_VERSION "0.11.2" CACHE STRING "Version string") set(XSTUDIO_GLOBAL_NAME xStudio) project(${XSTUDIO_GLOBAL_NAME} VERSION ${XSTUDIO_GLOBAL_VERSION} LANGUAGES CXX) diff --git a/docs/build_guides/centos_7.md b/docs/build_guides/centos_7.md index 60a435958..32fc7a494 100644 --- a/docs/build_guides/centos_7.md +++ b/docs/build_guides/centos_7.md @@ -46,7 +46,7 @@ Install 5.15 dev tools, using Qt5 online installer, requires login account (free wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.2.tar.gz tar -xf v3.11.2.tar.gz mkdir json-3.11.2/build - cd json-3.7.3/build + cd json-3.11.2/build cmake .. -DJSON_BuildTests=Off make -j $JOBS sudo make install diff --git a/docs/build_guides/rocky_linux_9_1.md b/docs/build_guides/rocky_linux_9_1.md index 1db2a0803..09f9a21e4 100644 --- a/docs/build_guides/rocky_linux_9_1.md +++ b/docs/build_guides/rocky_linux_9_1.md @@ -28,7 +28,7 @@ wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.2.tar.gz tar -xf v3.11.2.tar.gz mkdir json-3.11.2/build - cd json-3.7.3/build + cd json-3.11.2/build cmake .. -DJSON_BuildTests=Off make -j $JOBS sudo make install diff --git a/include/xstudio/ui/qml/session_model_ui.hpp b/include/xstudio/ui/qml/session_model_ui.hpp index fd1805297..67e143506 100644 --- a/include/xstudio/ui/qml/session_model_ui.hpp +++ b/include/xstudio/ui/qml/session_model_ui.hpp @@ -210,6 +210,7 @@ class SessionModel : public caf::mixin::actor_object { Q_INVOKABLE void relinkMedia(const QModelIndexList &indexes, const QUrl &path); Q_INVOKABLE void decomposeMedia(const QModelIndexList &indexes); Q_INVOKABLE void rescanMedia(const QModelIndexList &indexes); + Q_INVOKABLE QModelIndex getPlaylistIndex(const QModelIndex &index) const; signals: void bookmarkActorAddrChanged(); @@ -296,7 +297,6 @@ class SessionModel : public caf::mixin::actor_object { const utility::JsonTree &tree, const QPersistentModelIndex &search_hint = QModelIndex()); utility::Uuid refreshId(nlohmann::json &ij); - QModelIndex getPlaylistIndex(const QModelIndex &index) const; QFuture> handleMediaIdDropFuture( const int proposedAction, const utility::JsonStore &drop, const QModelIndex &index); diff --git a/src/media/src/media_source_actor.cpp b/src/media/src/media_source_actor.cpp index c46440838..805c8eb35 100644 --- a/src/media/src/media_source_actor.cpp +++ b/src/media/src/media_source_actor.cpp @@ -129,7 +129,8 @@ MediaSourceActor::MediaSourceActor( base_.set_media_reference(mr); - anon_send(actor_cast(this), acquire_media_detail_atom_v, media_reference.rate()); + // special case , when duplicating, as that'll suppy streams. + // anon_send(actor_cast(this), acquire_media_detail_atom_v, media_reference.rate()); init(); } diff --git a/src/plugin/data_source/dneg/shotgun/src/data_source_shotgun.cpp b/src/plugin/data_source/dneg/shotgun/src/data_source_shotgun.cpp index 890e275d6..199325d7b 100644 --- a/src/plugin/data_source/dneg/shotgun/src/data_source_shotgun.cpp +++ b/src/plugin/data_source/dneg/shotgun/src/data_source_shotgun.cpp @@ -757,7 +757,12 @@ ShotgunDataSourceActor::ShotgunDataSourceActor( // do we need the UI to have spun up before we can issue calls to shotgun... // erm... - [=](use_data_atom, const caf::uri &uri) -> result { + [=](use_data_atom atom, const caf::uri &uri) { + delegate(actor_cast(this), atom, uri, FrameRate()); + }, + [=](use_data_atom, + const caf::uri &uri, + const FrameRate &media_rate) -> result { // check protocol == shotgun.. if (uri.scheme() != "shotgun") return UuidActorVector(); diff --git a/src/plugin/data_source/dneg/shotgun/src/qml/Shotgun.1/ShotgunPublishNotes.qml b/src/plugin/data_source/dneg/shotgun/src/qml/Shotgun.1/ShotgunPublishNotes.qml index ceed5d469..b7b5c3ce7 100644 --- a/src/plugin/data_source/dneg/shotgun/src/qml/Shotgun.1/ShotgunPublishNotes.qml +++ b/src/plugin/data_source/dneg/shotgun/src/qml/Shotgun.1/ShotgunPublishNotes.qml @@ -181,9 +181,7 @@ XsWindow { ) publishNotesDialog.payload = tmp - // console.log(tmp) publish_func(tmp, playlist_uuid) - // onAccepted: push_playlist_note_promise(data_source, payload, playlist, playlist_uuid, error) } } diff --git a/src/plugin/data_source/dneg/shotgun/src/qml/Shotgun.1/ShotgunRoot.qml b/src/plugin/data_source/dneg/shotgun/src/qml/Shotgun.1/ShotgunRoot.qml index 9f0e5d961..d558186b3 100644 --- a/src/plugin/data_source/dneg/shotgun/src/qml/Shotgun.1/ShotgunRoot.qml +++ b/src/plugin/data_source/dneg/shotgun/src/qml/Shotgun.1/ShotgunRoot.qml @@ -992,16 +992,15 @@ Item { let inds = app_window.sessionSelectionModel.selectedIndexes inds.forEach( function (item, index) { - let type = item.model.get(item, "typeRole") - if(type == "Playlist") { - // get playlist name - let uuid = item.model.get(item, "actorUuidRole") - - push_notes_dialog.publishSelected = selected_media - push_notes_dialog.playlist_uuid = uuid - push_notes_dialog.updatePublish() - push_notes_dialog.show() - } + // find playlist.. + let plind = app_window.sessionModel.getPlaylistIndex(item) + // get playlist name + let uuid = item.model.get(plind, "actorUuidRole") + + push_notes_dialog.publishSelected = selected_media + push_notes_dialog.playlist_uuid = uuid + push_notes_dialog.updatePublish() + push_notes_dialog.show() } ) } diff --git a/src/plugin/media_reader/openexr/src/openexr.cpp b/src/plugin/media_reader/openexr/src/openexr.cpp index 04fab4fd8..582f16c15 100644 --- a/src/plugin/media_reader/openexr/src/openexr.cpp +++ b/src/plugin/media_reader/openexr/src/openexr.cpp @@ -580,22 +580,23 @@ xstudio::media::MediaDetail OpenEXRMediaReader::detail(const caf::uri &uri) cons else if (timecode_rate) fr = static_cast(timecode_rate->value()); - if (fr == 0.0) - fr = 24.0; - if (timecode) { + // note if frame rate is no known from metadata we use 24pfs + // as a default tc = utility::Timecode( timecode->value().hours(), timecode->value().minutes(), timecode->value().seconds(), timecode->value().frame(), - fr, + fr == 0.0 ? 24.0 : fr, timecode->value().dropFrame()); } else if (rate) { tc = utility::Timecode("00:00:00:00", fr); } - frd.set_rate(utility::FrameRate(1.0 / fr)); + // if frame rate is not known, return null frame rate so xSTUDIO will + // apply its global frame rate + frd.set_rate(fr == 0.0 ? utility::FrameRate() : utility::FrameRate(1.0 / fr)); std::vector stream_ids; for (int prt = 0; prt < parts; ++prt) { diff --git a/src/plugin_manager/src/plugin_manager_actor.cpp b/src/plugin_manager/src/plugin_manager_actor.cpp index a73027ce3..9ca48dc1e 100644 --- a/src/plugin_manager/src/plugin_manager_actor.cpp +++ b/src/plugin_manager/src/plugin_manager_actor.cpp @@ -46,6 +46,39 @@ PluginManagerActor::PluginManagerActor(caf::actor_config &cfg) : caf::event_base delegate(actor_cast(this), json_store::update_atom_v, full); }, + // helper for dealing with URI's + [=](data_source::use_data_atom, + const caf::uri &uri, + const FrameRate &media_rate) -> result { + // send to resident enabled datasource plugins + auto actors = std::vector(); + + for (const auto &i : manager_.factories()) { + if (i.second.factory()->type() == PluginType::PT_DATA_SOURCE and + resident_.count(i.first)) + actors.push_back(resident_[i.first]); + } + + if (actors.empty()) + return UuidActorVector(); + + auto rp = make_response_promise(); + + fan_out_request( + actors, infinite, data_source::use_data_atom_v, uri, media_rate) + .then( + [=](const std::vector results) mutable { + for (const auto &i : results) { + if (not i.empty()) + return rp.deliver(i); + } + rp.deliver(UuidActorVector()); + }, + [=](error &err) mutable { rp.deliver(std::move(err)); }); + + return rp; + }, + // helper for dealing with Media sources back population's [=](data_source::use_data_atom, const caf::actor &media, @@ -166,39 +199,6 @@ PluginManagerActor::PluginManagerActor(caf::actor_config &cfg) : caf::event_base return rp; }, - // helper for dealing with URI's - [=](data_source::use_data_atom, - const caf::uri &uri, - const FrameRate &media_rate) -> result { - // send to resident enabled datasource plugins - auto actors = std::vector(); - - for (const auto &i : manager_.factories()) { - if (i.second.factory()->type() == PluginType::PT_DATA_SOURCE and - resident_.count(i.first)) - actors.push_back(resident_[i.first]); - } - - if (actors.empty()) - return UuidActorVector(); - - auto rp = make_response_promise(); - - fan_out_request( - actors, infinite, data_source::use_data_atom_v, uri, media_rate) - .then( - [=](const std::vector results) mutable { - for (const auto &i : results) { - if (not i.empty()) - return rp.deliver(i); - } - rp.deliver(UuidActorVector()); - }, - [=](error &err) mutable { rp.deliver(std::move(err)); }); - - return rp; - }, - [=](json_store::update_atom, const JsonStore &js) { try { // this will trash manually enabled/disabled plugins. diff --git a/src/ui/qml/session/src/session_model_handler_ui.cpp b/src/ui/qml/session/src/session_model_handler_ui.cpp index 4acd2eaca..52cf27944 100644 --- a/src/ui/qml/session/src/session_model_handler_ui.cpp +++ b/src/ui/qml/session/src/session_model_handler_ui.cpp @@ -643,7 +643,39 @@ void SessionModel::init(caf::actor_system &_system) { } }, - [=](utility::event_atom, media::add_media_stream_atom, const UuidActor &) {}, + + // NEVER TRIGGERS ? NOT TESTED ! + [=](utility::event_atom, media::add_media_stream_atom, const UuidActor &) { + // spdlog::warn("media::add_media_stream_atom"); + try { + auto src = caf::actor_cast(self()->current_sender()); + auto src_str = actorToString(system(), src); + + auto indexes = search_recursive_list( + QVariant::fromValue(QStringFromStd(src_str)), + actorRole, + QModelIndex(), + 0, + 1); + + if (not indexes.empty() and indexes[0].isValid()) { + const nlohmann::json &j = indexToData(indexes[0]); + + // spdlog::warn("media::add_media_stream_atom REQUEST"); + + requestData( + QVariant::fromValue(QStringFromStd(src_str)), + actorRole, + getPlaylistIndex(indexes[0]), + j, + childrenRole); + } else { + spdlog::warn("FAIELD"); + } + } catch (const std::exception &err) { + spdlog::warn("{} {}", __PRETTY_FUNCTION__, err.what()); + } + }, [=](utility::event_atom, playlist::move_media_atom, @@ -656,18 +688,22 @@ void SessionModel::init(caf::actor_system &_system) { auto index = search_recursive( QVariant::fromValue(QStringFromStd(src_str)), actorRole); - spdlog::info("utility::event_atom, utility::move_media_atom {}", src_str); + // spdlog::info("utility::event_atom, utility::move_media_atom {}", + // src_str); // trigger update of model.. if (index.isValid()) { const nlohmann::json &j = indexToData(index); + // spdlog::warn("{}", j.dump(2)); if (j.at("type") == "Subset" or j.at("type") == "Timeline") { - auto media_id = j.at("children").at(0).at("id"); + const auto tree = *(indexToTree(index)->child(0)); + auto media_id = tree.data().at("id"); + requestData( QVariant::fromValue(QUuidFromUuid(media_id)), idRole, index, - j.at("children").at(0), + tree.data(), childrenRole); } } diff --git a/src/ui/qml/session/src/session_model_methods_ui.cpp b/src/ui/qml/session/src/session_model_methods_ui.cpp index 9f17f0830..f65f864b5 100644 --- a/src/ui/qml/session/src/session_model_methods_ui.cpp +++ b/src/ui/qml/session/src/session_model_methods_ui.cpp @@ -24,7 +24,7 @@ QVariant SessionModel::playlists() const { auto data = R"([])"_json; try { auto value = R"({"text": null, "uuid":null})"_json; - for (const auto &i : data_) { + for (const auto &i : *(data_.child(0))) { value["text"] = i.data().at("name"); value["uuid"] = i.data().at("actor_uuid"); data.push_back(value); diff --git a/src/ui/qml/session/src/session_model_ui.cpp b/src/ui/qml/session/src/session_model_ui.cpp index 0686c4300..f5ac923eb 100644 --- a/src/ui/qml/session/src/session_model_ui.cpp +++ b/src/ui/qml/session/src/session_model_ui.cpp @@ -194,6 +194,14 @@ void SessionModel::processChildren(const nlohmann::json &rj, const QModelIndex & // spdlog::warn("processChildren {} {} {}", type, ptree->data().dump(2), rj.dump(2)); // spdlog::warn("processChildren {}", tree_to_json( *ptree,"children").dump(2)); // spdlog::warn("processChildren {}", rj.dump(2)); + if (type == "MediaSource" and rj.at(0).at("children").empty() and + rj.at(1).at("children").empty()) { + // spdlog::warn("RETRY {}", rj.dump(2)); + // force retry + emit dataChanged(parent_index, parent_index, roles); + return; + } + try { if (type == "Session" or type == "Container List" or type == "Media" or diff --git a/ui/qml/xstudio/menus/XsMediaMenu.qml b/ui/qml/xstudio/menus/XsMediaMenu.qml index ad3d31816..7d024a774 100644 --- a/ui/qml/xstudio/menus/XsMediaMenu.qml +++ b/ui/qml/xstudio/menus/XsMediaMenu.qml @@ -116,6 +116,9 @@ XsMenu { fakeDisabled: false Repeater { model: app_window.mediaImageSource.streams + onItemAdded: stream_menu.insertItem(index, item) + onItemRemoved: stream_menu.removeItem(item) + XsMenuItem { mytext: modelData.name enabled: true diff --git a/ui/qml/xstudio/panels/playlist/XsPlaylistsPanelNew.qml b/ui/qml/xstudio/panels/playlist/XsPlaylistsPanelNew.qml index 4721f1f22..aa0bf2289 100644 --- a/ui/qml/xstudio/panels/playlist/XsPlaylistsPanelNew.qml +++ b/ui/qml/xstudio/panels/playlist/XsPlaylistsPanelNew.qml @@ -11,6 +11,7 @@ import QuickFuture 1.0 import QuickPromise 1.0 import xStudio 1.1 +import xstudio.qml.helpers 1.0 Rectangle { id: panel @@ -132,14 +133,33 @@ Rectangle { } if("xstudio/media-ids" in data) { - media_move_copy_dialog.data = data + let before = null + let internal_copy = false if(previousItem) { - media_move_copy_dialog.index = previousItem.modelIndex() + before = previousItem.modelIndex() + } + + // does media exist in our parent. + if(before) { + let mi = app_window.sessionModel.search_recursive( + helpers.QVariantFromUuidString(data["xstudio/media-ids"].split("\n")[0]), "idRole" + ) + + if(app_window.sessionModel.getPlaylistIndex(before) == app_window.sessionModel.getPlaylistIndex(mi)) { + internal_copy = true + } + } + + if(internal_copy) { + Future.promise( + app_window.sessionModel.handleDropFuture(Qt.CopyAction, data, before) + ).then(function(quuids){}) } else { - media_move_copy_dialog.index = null + media_move_copy_dialog.data = data + media_move_copy_dialog.index = before + media_move_copy_dialog.open() } - media_move_copy_dialog.open() } else { if(previousItem) {