diff --git a/src/appshell/appshellmodule.cpp b/src/appshell/appshellmodule.cpp index da2fa717fbe0f..8cc018ede3a90 100644 --- a/src/appshell/appshellmodule.cpp +++ b/src/appshell/appshellmodule.cpp @@ -200,6 +200,14 @@ void AppShellModule::onInit(const IApplication::RunMode&) #endif } +void AppShellModule::onAllInited(const framework::IApplication::RunMode&) +{ + //! NOTE: process QEvent::FileOpen as early as possible if it was postponed +#ifdef Q_OS_MACOS + qApp->processEvents(); +#endif +} + void AppShellModule::onDeinit() { s_sessionsManager->deinit(); diff --git a/src/appshell/appshellmodule.h b/src/appshell/appshellmodule.h index ac201c856eeaf..c0514c6c31620 100644 --- a/src/appshell/appshellmodule.h +++ b/src/appshell/appshellmodule.h @@ -41,6 +41,7 @@ class AppShellModule : public modularity::IModuleSetup void onPreInit(const framework::IApplication::RunMode& mode) override; void onInit(const framework::IApplication::RunMode& mode) override; + void onAllInited(const framework::IApplication::RunMode& mode) override; void onDeinit() override; }; } diff --git a/src/engraving/libmscore/engravingobject.cpp b/src/engraving/libmscore/engravingobject.cpp index 0b3be1debe5f6..a5ca9e27c4e2c 100644 --- a/src/engraving/libmscore/engravingobject.cpp +++ b/src/engraving/libmscore/engravingobject.cpp @@ -676,6 +676,22 @@ bool EngravingObject::isLinked(EngravingObject* se) const return _links->contains(se); } +//--------------------------------------------------------- +// findLinkedInScore +/// if exists, returns the linked object in the required +/// score, else returns null +//--------------------------------------------------------- + +EngravingObject* EngravingObject::findLinkedInScore(Score* score) const +{ + if (score == this || !_links || _links->empty()) { + return nullptr; + } + auto findElem = std::find_if(_links->begin(), _links->end(), + [score](EngravingObject* engObj) { return engObj && engObj->score() == score; }); + return findElem != _links->end() ? *findElem : nullptr; +} + //--------------------------------------------------------- // undoUnlink //--------------------------------------------------------- diff --git a/src/engraving/libmscore/engravingobject.h b/src/engraving/libmscore/engravingobject.h index 4d5f5bcce3d0d..212a76a835c15 100644 --- a/src/engraving/libmscore/engravingobject.h +++ b/src/engraving/libmscore/engravingobject.h @@ -295,6 +295,7 @@ class EngravingObject void linkTo(EngravingObject*); void unlink(); bool isLinked(EngravingObject* se = nullptr) const; + EngravingObject* findLinkedInScore(Score* score) const; virtual void undoUnlink(); LinkedObjects* links() const { return _links; } diff --git a/src/engraving/libmscore/excerpt.cpp b/src/engraving/libmscore/excerpt.cpp index 1eb7984650c69..ee316ce67faf5 100644 --- a/src/engraving/libmscore/excerpt.cpp +++ b/src/engraving/libmscore/excerpt.cpp @@ -771,7 +771,8 @@ static MeasureBase* cloneMeasure(MeasureBase* mb, Score* score, const Score* osc if (e->generated()) { continue; } - if ((e->track() == srcTrack && strack != mu::nidx) || (e->systemFlag() && srcTrack == 0)) { + if ((e->track() == srcTrack && strack != mu::nidx && !e->systemFlag()) + || (e->systemFlag() && srcTrack == 0 && e->track() == srcTrack)) { EngravingItem* ne = e->linkedClone(); processLinkedClone(ne, score, strack); if (!ns) { @@ -1479,8 +1480,8 @@ void Excerpt::cloneStaff2(Staff* srcStaff, Staff* dstStaff, const Fraction& star for (EngravingItem* e : oseg->annotations()) { if (e->generated() - || (e->track() != srcTrack && !e->systemFlag()) // system items must be cloned even if they are on different tracks - || (e->systemFlag() && score->nstaves() > 1)) { // ...but only once! + || (e->track() != srcTrack && !(e->systemFlag() && e->track() == 0)) // system items must be cloned even if they are on different tracks + || (e->track() != srcTrack && e->systemFlag() && e->findLinkedInScore(score))) { // ...but only once! continue; } diff --git a/src/framework/audio/internal/platform/win/wasapiaudioclient.cpp b/src/framework/audio/internal/platform/win/wasapiaudioclient.cpp index 2d05ab2f81806..1af58db0d3bd9 100644 --- a/src/framework/audio/internal/platform/win/wasapiaudioclient.cpp +++ b/src/framework/audio/internal/platform/win/wasapiaudioclient.cpp @@ -29,8 +29,9 @@ using namespace winrt::Windows::Foundation; using namespace winrt::Windows::Media::Devices; using namespace winrt::Windows::Devices::Enumeration; -WasapiAudioClient::WasapiAudioClient(HANDLE clientStartedEvent, HANDLE clientStoppedEvent) - : m_clientStartedEvent(clientStartedEvent), m_clientStoppedEvent(clientStoppedEvent) +WasapiAudioClient::WasapiAudioClient(HANDLE clientStartedEvent, HANDLE clientFailedToStartEvent, HANDLE clientStoppedEvent) + : m_clientStartedEvent(clientStartedEvent), m_clientFailedToStartEvent(clientFailedToStartEvent), m_clientStoppedEvent( + clientStoppedEvent) { check_hresult(MFStartup(MF_VERSION, MFSTARTUP_LITE)); } @@ -218,6 +219,8 @@ HRESULT WasapiAudioClient::ActivateCompleted(IActivateAudioInterfaceAsyncOperati m_audioRenderClient = nullptr; m_sampleReadyAsyncResult = nullptr; + SetEvent(m_clientFailedToStartEvent); + // Must return S_OK even on failure. return S_OK; } @@ -370,6 +373,8 @@ void WasapiAudioClient::startPlayback() noexcept } catch (...) { hresult error = to_hresult(); setStateAndNotify(DeviceState::Error, error); + + SetEvent(m_clientFailedToStartEvent); } } @@ -398,6 +403,9 @@ HRESULT WasapiAudioClient::onStartPlayback(IMFAsyncResult*) noexcept return S_OK; } catch (...) { setStateAndNotify(DeviceState::Error, to_hresult()); + + SetEvent(m_clientFailedToStartEvent); + // Must return S_OK. return S_OK; } diff --git a/src/framework/audio/internal/platform/win/wasapiaudioclient.h b/src/framework/audio/internal/platform/win/wasapiaudioclient.h index 97993d2b0532b..4edab29a4a34c 100644 --- a/src/framework/audio/internal/platform/win/wasapiaudioclient.h +++ b/src/framework/audio/internal/platform/win/wasapiaudioclient.h @@ -29,7 +29,7 @@ namespace winrt { struct WasapiAudioClient : implements { public: - WasapiAudioClient(HANDLE clientStartedEvent, HANDLE clientStoppedEvent); + WasapiAudioClient(HANDLE clientStartedEvent, HANDLE clientFailedToStartEvent, HANDLE clientStoppedEvent); ~WasapiAudioClient(); void setHardWareOffload(bool value); @@ -99,6 +99,7 @@ struct WasapiAudioClient : implements wasapiClient; @@ -54,6 +55,7 @@ static WasapiData s_data; WasapiAudioDriver::WasapiAudioDriver() { s_data.clientStartedEvent = CreateEvent(NULL, FALSE, FALSE, L"WASAPI_Client_Started"); + s_data.clientFailedToStartEvent = CreateEvent(NULL, FALSE, FALSE, L"WASAPI_Client_Failed_To_Start"); s_data.clientStoppedEvent = CreateEvent(NULL, FALSE, FALSE, L"WASAPI_Client_Stopped"); m_devicesListener.startWithCallback([this]() { @@ -77,7 +79,8 @@ std::string WasapiAudioDriver::name() const bool WasapiAudioDriver::open(const Spec& spec, Spec* activeSpec) { if (!s_data.wasapiClient.get()) { - s_data.wasapiClient = make_self(s_data.clientStartedEvent, s_data.clientStoppedEvent); + s_data.wasapiClient + = make_self(s_data.clientStartedEvent, s_data.clientFailedToStartEvent, s_data.clientStoppedEvent); } m_desiredSpec = spec; @@ -102,7 +105,15 @@ bool WasapiAudioDriver::open(const Spec& spec, Spec* activeSpec) s_data.wasapiClient->asyncInitializeAudioDevice(deviceId); - WaitForSingleObject(s_data.clientStartedEvent, INFINITE); + static constexpr DWORD handleCount = 2; + const HANDLE handles[handleCount] = { s_data.clientStartedEvent, s_data.clientFailedToStartEvent }; + + DWORD waitResult = WaitForMultipleObjects(handleCount, handles, false, INFINITE); + if (waitResult != WAIT_OBJECT_0) { + // Either the event was the second event (namely s_data.clientFailedToStartEvent) + // Or some wait error occurred + return false; + } m_activeSpec = m_desiredSpec; m_activeSpec.sampleRate = s_data.wasapiClient->sampleRate(); diff --git a/src/notation/internal/masternotation.cpp b/src/notation/internal/masternotation.cpp index 94981f719b46a..5585c5d4574f8 100644 --- a/src/notation/internal/masternotation.cpp +++ b/src/notation/internal/masternotation.cpp @@ -431,6 +431,12 @@ void MasterNotation::applyOptions(mu::engraving::MasterScore* score, const Score tt->setFollowText(true); tt->setTrack(0); seg->add(tt); + for (auto staff : score->getSystemObjectStaves()) { + TempoText* linkedTt = toTempoText(tt->linkedClone()); + linkedTt->setScore(score); + linkedTt->setTrack(staff->idx() * VOICES); + seg->add(linkedTt); + } } score->setUpTempoMap(); diff --git a/src/notation/internal/notationparts.cpp b/src/notation/internal/notationparts.cpp index 6b67c025d5f3e..8e533885a3703 100644 --- a/src/notation/internal/notationparts.cpp +++ b/src/notation/internal/notationparts.cpp @@ -941,10 +941,6 @@ void NotationParts::appendStaves(Part* part, const InstrumentTemplate& templ, co } initStaff(staff, templ, staffType, staffIndex); - if (lastStaffIndex > 0) { - staff->setBarLineSpan(score()->staff(lastStaffIndex - 1)->barLineSpan()); - } - insertStaff(staff, staffIndex); }