LCOV - code coverage report
Current view: top level - src/musesounds/internal - musesamplercheckstatusscenario.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 87.8 % 74 65
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2025 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "musesamplercheckstatusscenario.h"
      24              : 
      25              : #include "rcommand/commandtypes.h"
      26              : #include "translation.h"
      27              : #include "ui/view/iconcodes.h"
      28              : 
      29              : using namespace mu::musesounds;
      30              : 
      31            8 : bool MuseSamplerCheckStatusScenario::alreadyChecked() const
      32              : {
      33            8 :     return m_alreadyChecked;
      34              : }
      35              : 
      36           14 : void MuseSamplerCheckStatusScenario::checkAndShowStatusIfNeed()
      37              : {
      38           14 :     if (!multiwindowsProvider()->isFirstWindow()) {
      39           10 :         return;
      40              :     }
      41              : 
      42           13 :     if (service()->libInitFailed()) {
      43            7 :         m_alreadyChecked = true;
      44            7 :         if (configuration()->showLoadingFailedWarning()) {
      45            6 :             showLoadingFailedNotification();
      46              :         }
      47            7 :         return;
      48              :     }
      49              : 
      50            6 :     if (!service()->canCheckForUpdate()) {
      51            1 :         return;
      52              :     }
      53              : 
      54            5 :     LOGI() << "Checking for MuseSampler update...";
      55            5 :     m_alreadyChecked = true;
      56              : 
      57            5 :     if (service()->incompatibleLocalVersion()) {
      58            1 :         showCriticalUpdateNotification();
      59            1 :         return;
      60              :     }
      61              : 
      62            4 :     auto promise = service()->checkForUpdate();
      63            4 :     promise.onResolve(this, [this](const muse::RetVal<bool>& res) {
      64            4 :         if (!res.ret) {
      65            1 :             LOGE() << "Unable to check for MuseSampler update: " << res.ret.toString();
      66            1 :             return;
      67              :         }
      68              : 
      69            3 :         if (res.val) {
      70            2 :             showNewVersionNotification();
      71              :         }
      72              :     });
      73            4 : }
      74              : 
      75            6 : void MuseSamplerCheckStatusScenario::showLoadingFailedNotification()
      76              : {
      77            6 :     muse::IInteractive::ButtonData closeBtn = interactive()->buttonData(muse::IInteractive::Button::Close);
      78              :     muse::IInteractive::ButtonData troubleshootBtn(int(muse::IInteractive::Button::CustomButton) + 1,
      79            6 :                                                    muse::trc("musesounds", "Troubleshoot"));
      80            6 :     troubleshootBtn.icon = int(muse::ui::IconCode::Code::OPEN_LINK);
      81              : 
      82              : #ifdef Q_OS_LINUX
      83              :     muse::IInteractive::ButtonData openBtn(int(muse::IInteractive::Button::CustomButton) + 2,
      84            6 :                                            muse::trc("musesounds", "Open MuseSounds Manager"), true /*accent*/);
      85              : 
      86              :     std::string msg = muse::trc("musesounds", "To load MuseSounds, open MuseSounds Manager and check that you’re running the latest version. "
      87              :                                               "Update if needed and restart your machine.\n\n"
      88            6 :                                               "If the issue persists, follow the steps at the troubleshooting link below.");
      89              : #else
      90              :     muse::IInteractive::ButtonData openBtn(int(muse::IInteractive::Button::CustomButton) + 2,
      91              :                                            muse::trc("musesounds", "Open MuseHub"), true /*accent*/);
      92              : 
      93              :     std::string msg = muse::trc("musesounds", "To load MuseSounds, open MuseHub and check that you’re running the latest version. "
      94              :                                               "Update if needed and restart your machine.\n\n"
      95              :                                               "If the issue persists, follow the steps at the troubleshooting link below.");
      96              : #endif
      97              : 
      98              : #ifdef Q_OS_WIN
      99              :     const muse::IInteractive::ButtonDatas buttons { openBtn, troubleshootBtn, closeBtn };
     100              : #else
     101           30 :     const muse::IInteractive::ButtonDatas buttons { closeBtn, troubleshootBtn, openBtn };
     102              : #endif
     103              : 
     104           18 :     interactive()->warning(muse::trc("musesounds", "MuseSounds could not be loaded"), msg,
     105              :                            buttons, openBtn.btn,
     106           12 :                            muse::IInteractive::Option::WithIcon | muse::IInteractive::Option::WithDontShowAgainCheckBox)
     107            6 :     .onResolve(this, [this, troubleshootBtn, openBtn](const muse::IInteractive::Result& res) {
     108            6 :         if (!res.showAgain()) {
     109            2 :             configuration()->setShowLoadingFailedWarning(false);
     110              :         }
     111              : 
     112            6 :         if (res.isButton(troubleshootBtn.btn)) {
     113            2 :             platformInteractive()->openUrl(configuration()->museSoundsTroubleshootUrl());
     114            4 :         } else if (res.isButton(openBtn.btn)) {
     115            1 :             openMuseHub(false /*quit*/);
     116              :         }
     117            6 :     });
     118           12 : }
     119              : 
     120            1 : void MuseSamplerCheckStatusScenario::showCriticalUpdateNotification()
     121              : {
     122              :     muse::IInteractive::ButtonData notNowBtn(int(muse::IInteractive::Button::CustomButton) + 1,
     123            1 :                                              muse::trc("musesounds", "Not now"));
     124              : 
     125              : #ifdef Q_OS_LINUX
     126              :     muse::IInteractive::ButtonData launchBtn(int(muse::IInteractive::Button::CustomButton) + 2,
     127            1 :                                              muse::trc("musesounds", "Quit & launch MuseSounds Manager"), true /*accent*/);
     128              : 
     129              :     std::string msg = muse::trc("musesounds", "To apply this update, MuseScore Studio will need to close briefly and MuseSounds Manager will open. "
     130            1 :                                               "Your MuseSounds libraries won’t work until the update is complete.");
     131              : #else
     132              :     muse::IInteractive::ButtonData launchBtn(int(muse::IInteractive::Button::CustomButton) + 2,
     133              :                                              muse::trc("musesounds", "Quit & launch MuseHub"), true /*accent*/);
     134              : 
     135              :     std::string msg = muse::trc("musesounds", "To apply this update, MuseScore Studio will need to close briefly and MuseHub will open. "
     136              :                                               "Your MuseSounds libraries won’t work until the update is complete.");
     137              : #endif
     138              : 
     139            6 :     interactive()->info(muse::trc("musesounds", "MuseSounds needs an update"), msg,
     140              :                         { notNowBtn, launchBtn }, launchBtn.btn, muse::IInteractive::Option::WithIcon)
     141            1 :     .onResolve(this, [this, launchBtn](const muse::IInteractive::Result& res) {
     142            1 :         if (res.isButton(launchBtn.btn)) {
     143            0 :             openMuseHub(true /*quit*/);
     144              :         }
     145            1 :     });
     146            2 : }
     147              : 
     148            2 : void MuseSamplerCheckStatusScenario::showNewVersionNotification()
     149              : {
     150              :     muse::IInteractive::ButtonData notNowBtn(int(muse::IInteractive::Button::CustomButton) + 1,
     151            2 :                                              muse::trc("musesounds", "Not now"));
     152              : 
     153              : #ifdef Q_OS_LINUX
     154              :     muse::IInteractive::ButtonData launchBtn(int(muse::IInteractive::Button::CustomButton) + 2,
     155            2 :                                              muse::trc("musesounds", "Quit & launch MuseSounds Manager"), true /*accent*/);
     156              : 
     157              :     std::string msg = muse::trc("musesounds", "To keep MuseSounds running smoothly, "
     158              :                                               "MuseScore Studio needs to close briefly so MuseSounds Manager can apply the update. "
     159            2 :                                               "You’ll need to restart MuseScore Studio when the update is complete.");
     160              : #else
     161              :     muse::IInteractive::ButtonData launchBtn(int(muse::IInteractive::Button::CustomButton) + 2,
     162              :                                              muse::trc("musesounds", "Quit & launch MuseHub"), true /*accent*/);
     163              : 
     164              :     std::string msg = muse::trc("musesounds", "To keep MuseSounds running smoothly, "
     165              :                                               "MuseScore Studio needs to close briefly so MuseHub can apply the update. "
     166              :                                               "You’ll be prompted to relaunch MuseScore Studio when it’s ready.");
     167              : #endif
     168              : 
     169           12 :     interactive()->info(muse::trc("musesounds", "An update for MuseSounds is available"), msg,
     170              :                         { notNowBtn, launchBtn }, launchBtn.btn, muse::IInteractive::Option::WithIcon)
     171            2 :     .onResolve(this, [this, launchBtn](const muse::IInteractive::Result& res) {
     172            2 :         if (res.isButton(launchBtn.btn)) {
     173            0 :             openMuseHub(true /*quit*/);
     174              :         }
     175            2 :     });
     176            4 : }
     177              : 
     178            1 : void MuseSamplerCheckStatusScenario::openMuseHub(bool quit)
     179              : {
     180              : #ifdef Q_OS_LINUX
     181            5 :     if (process()->startDetached("muse-sounds-manager",
     182              :                                  { "--show-sampler-update", "--show-hidden-statuses" })) {
     183            1 :         if (quit) {
     184            0 :             commandDispatcher()->dispatch(muse::rcommand::Command("command://app/quit"));
     185              :         }
     186              :     } else {
     187            0 :         openMuseHubWebsite(quit);
     188              :     }
     189              : #else
     190              :     const muse::UriQuery MUSEHUB_URI("musehub://requestUpdateCheck?from=musescore-studio");
     191              : 
     192              : #ifdef Q_OS_MACOS
     193              :     if (!platformInteractive()->canOpenApp(MUSEHUB_URI)) {
     194              :         openMuseHubWebsite(quit);
     195              :         return;
     196              :     }
     197              : #endif
     198              : 
     199              :     auto promise = platformInteractive()->openApp(MUSEHUB_URI);
     200              : 
     201              :     promise.onResolve(this, [this, quit](const muse::Ret& ret) {
     202              :         if (!ret) {
     203              :             openMuseHubWebsite(quit);
     204              :         } else if (quit) {
     205              :             commandDispatcher()->dispatch(muse::rcommand::Command("command://app/quit"));
     206              :         }
     207              :     });
     208              : 
     209              :     promise.onReject(this, [this, quit](int, const std::string&) {
     210              :         openMuseHubWebsite(quit);
     211              :     });
     212              : #endif
     213            1 : }
     214              : 
     215            0 : void MuseSamplerCheckStatusScenario::openMuseHubWebsite(bool quit)
     216              : {
     217              : #ifdef Q_OS_LINUX
     218            0 :     platformInteractive()->openUrl(updateConfiguration()->appWebSiteUrl());
     219              : #else
     220              :     platformInteractive()->openUrl(globalConfiguration()->museHubWebUrl());
     221              : #endif
     222              : 
     223            0 :     if (quit) {
     224            0 :         commandDispatcher()->dispatch(muse::rcommand::Command("command://app/quit"));
     225              :     }
     226            0 : }
        

Generated by: LCOV version 2.0-1