musescore / MuseScore

MuseScore is an open source and free music notation software. For support, contribution, bug reports, visit MuseScore.org. Fork and make pull requests!
https://musescore.org
Other
12.26k stars 2.65k forks source link

Compatibility Issues with QtWebSockets Module in MuseScore 4.4 for ODLA #24360

Closed andreoid87 closed 1 month ago

andreoid87 commented 2 months ago

Issue type

Other type of issue

Description with steps to reproduce

Issue Summary

I’m the developer of ODLA, a device that helps visually impaired people write music through a keyboard with a raised staff. We've successfully integrated ODLA with MuseScore (until 4.3) using a QML plugin that communicates via WebSockets.

Background

Problem

Since updating to MuseScore 4.4 and transitioning to Qt 6.2.4, the plugin no longer works on Windows. Despite the following attempts, the QtWebSockets module is not found:

Error message:

17:16:29.999 | ERROR | main_thread | ExtPluginRunner::run | "file:///C:/Users/[Your_Username]/Documents/MuseScore4/Plugins/ODLA/ODLA.qml:2 module \"QtWebSockets\" is not installed\n"

Steps to Reproduce

  1. Create a plugin with:
    import QtWebSockets 1.2
  2. Copy the qml plugin file to plugin directory.
  3. Go to the MuseScore4/bin/ folder.
  4. Copy Qt6WebSocket.dll from the Qt 6.2.4 kit into this folder.
  5. Launch MuseScore 4.4.
  6. Load the ODLA plugin from the Plugins menu.
  7. Check the output console for the error:
    17:16:29.999 | ERROR | main_thread | ExtPluginRunner::run | "file:///C:/Users/[Your_Username]/Documents/MuseScore4/Plugins/ODLA/ODLA.qml:2 module \"QtWebSockets\" is not installed\n"

Questions

  1. Was disabling this module a deliberate design choice, perhaps for security reasons?
  2. Is it possible to request that this module be made available? I’m willing to submit a pull request and implement the necessary changes.
  3. Despite including references to the library in the CMakeList files, why does the error persist?

Impact

This issue is critical as it undermines months of work and affects hundreds of visually impaired users who rely on ODLA for music composition.

Your support is greatly appreciated in resolving this issue.

Supporting files, videos and screenshots

image

What is the latest version of MuseScore Studio where this issue is present?

4.4

Regression

Yes, this used to work in a previous version of MuseScore 4.x

Operating system

Windows 11, MacOS

Additional context

No response

Checklist

cbjeukendrup commented 2 months ago

Maybe the problem is that in Qt 6 it's not enough to package just the dll, but also some QML files, or some auxiliary DLL. I can't check this at the moment because I don't have a Windows machine handy. Sometimes it is not enough to add a module to FindQt6.cmake, but something might need to be added here too: https://github.com/musescore/MuseScore/blob/186c925cb4255e38b6f609868ad4049eff77c0c0/src/app/CMakeLists.txt#L358-L368

Besides the switch to Qt 6, we cleaned up the packaging scripts on macOS; now, instead of packaging Qt modules in bulk without really knowing which ones we are packaging, we let macdeployqt figure out which ones are necessary and package only those. This mainly saves disk space (which is quite welcome because the app size is already almost doubled since we support Apple Silicon). However, if plugin authors strongly want certain Qt modules to be packaged, we can consider doing that. That change only affects macOS though, so on Windows something else must be going on.

Jojo-Schmitz commented 2 months ago

There is a Qt6WebSockets.dll in ${QT_INSTALL_BINS} on Windows, once the Qt WebSockets component is installed In 5.15.2 Qt5WebSockets.dll seems to have been installed by default

andreoid87 commented 2 months ago

Thank you for the quick response!

I attempted to resolve the issue by making the following changes:

  1. In MuseScore/src/app/CMakeLists.txt, I added:
 ${QT_INSTALL_BINS}/Qt6QuickControls2Impl.dll
+${QT_INSTALL_BINS}/Qt6WebSockets.dll
 ${QT_INSTALL_BINS}/Qt6QuickLayouts.dll
  1. In Musescore/buildscripts/cmake/FindQt6.cmake, I included:
     Core5Compat
+    WebSockets
     # Note: only used in ExampleView class.
     # When that class is removed, don't forget to remove this dependency.
     StateMachine

However, even after performing a clean build, I'm still encountering the following error:

16:51:21.632 | ERROR | main_thread     | ExtPluginRunner::run | Failed to load QML file: C:/Users/Accordino/Documents/MuseScore4/Plugins/ODLA/ODLA.qml

16:51:21.632 | ERROR | main_thread     | ExtPluginRunner::run | "file:///C:/Users/Accordino/Documents/MuseScore4/Plugins/ODLA/ODLA.qml:2 module \"QtWebSockets\" is not installed\n" 

Is there something else that needs to be configured in the plugin engine code? Or do you have any suggestions on how to debug this issue to determine which modules are being loaded and why QtWebSockets isn't?

cbjeukendrup commented 2 months ago

When you open your Qt installation folder, i.e. C:\Qt\6.2.4\msvc2019_64, and you look in the bin, lib, plugins, and qml folders, can you find anything else that seems related to WebSockets? Perhaps that will need to be packaged with MuseScore too.

andreoid87 commented 2 months ago

Yes, I installed WebSocket using the maintenance tool. Here are the DLLs I have:

  1. D:\Qt\6.2.4\msvc2019_64\bin\Qt6WebSockets.dll
  2. D:\Qt\6.2.4\msvc2019_64\qml\QtWebSockets\qmlwebsocketsplugin.dll
  3. D:\Qt\6.2.4\msvc2019_64\mkspecs\modules\qt_lib_websockets.pri
  4. D:\Qt\6.2.4\msvc2019_64\mkspecs\modules\qt_lib_websockets_private.pri
  5. D:\Qt\6.2.4\msvc2019_64\modules\WebSockets.json

There are probably other files as well, which makes me think the module was successfully installed.

cbjeukendrup commented 2 months ago

That means they are correctly installed in your Qt installation, but they will also need to be installed into your (self-built) MuseScore installation, so basically copied into the respective subfolders of CMAKE_INSTALL_PREFIX. This is what install(… DESTINATION …) does in CMake. I'd start with qml\QtWebSockets\qmlwebsocketsplugin.dll, and try if copying that into your MuseScore installation helps.

andreoid87 commented 2 months ago

I’ve already done that, but it looks like there might be an issue with loading the DLL(s). All the files seem fine, and it worked correctly in the previous version (I mean Qt5Websockets... etc.).

Can you suggest a way to investigate more deeply with debug messages to see if there's any issue during the loading of these modules? I’ve been looking everywhere but can’t find anything.

shoogle commented 1 month ago
Files added to C:\Qt\6.2.4\msvc2019_64 when you install Qt WebSockets via the Maintenance Tool ``` bin/Qt6WebSockets.dll bin/Qt6WebSocketsd.dll include/QtWebSockets/6.2.4/QtWebSockets/private/qdefaultmaskgenerator_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qsslserver_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qwebsocketcorsauthenticator_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qwebsocketdataprocessor_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qwebsocketframe_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qwebsockethandshakerequest_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qwebsockethandshakeresponse_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qwebsocketprotocol_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qwebsocketserver_p.h include/QtWebSockets/6.2.4/QtWebSockets/private/qwebsocket_p.h include/QtWebSockets/QMaskGenerator include/QtWebSockets/qmaskgenerator.h include/QtWebSockets/QtWebSockets include/QtWebSockets/QtWebSocketsDepends include/QtWebSockets/QtWebSocketsVersion include/QtWebSockets/qtwebsocketsversion.h include/QtWebSockets/QWebSocket include/QtWebSockets/qwebsocket.h include/QtWebSockets/QWebSocketCorsAuthenticator include/QtWebSockets/qwebsocketcorsauthenticator.h include/QtWebSockets/QWebSocketProtocol include/QtWebSockets/qwebsocketprotocol.h include/QtWebSockets/QWebSocketServer include/QtWebSockets/qwebsocketserver.h include/QtWebSockets/qwebsockets_global.h lib/cmake/Qt6BuildInternals/StandaloneTests/QtWebSocketsTestsConfig.cmake lib/cmake/Qt6Qml/QmlPlugins/Qt6qmlwebsocketsAdditionalTargetInfo.cmake lib/cmake/Qt6Qml/QmlPlugins/Qt6qmlwebsocketsConfig.cmake lib/cmake/Qt6Qml/QmlPlugins/Qt6qmlwebsocketsConfigVersion.cmake lib/cmake/Qt6Qml/QmlPlugins/Qt6qmlwebsocketsConfigVersionImpl.cmake lib/cmake/Qt6Qml/QmlPlugins/Qt6qmlwebsocketsTargets-debug.cmake lib/cmake/Qt6Qml/QmlPlugins/Qt6qmlwebsocketsTargets-relwithdebinfo.cmake lib/cmake/Qt6Qml/QmlPlugins/Qt6qmlwebsocketsTargets.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsAdditionalTargetInfo.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsConfig.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsConfigVersion.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsConfigVersionImpl.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsDependencies.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsTargets-debug.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsTargets-relwithdebinfo.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsTargets.cmake lib/cmake/Qt6WebSockets/Qt6WebSocketsVersionlessTargets.cmake lib/metatypes/qt6websockets_metatypes.json lib/Qt6WebSockets.lib lib/Qt6WebSockets.prl lib/Qt6WebSocketsd.lib lib/Qt6WebSocketsd.prl mkspecs/modules/qt_lib_websockets.pri mkspecs/modules/qt_lib_websockets_private.pri modules/WebSockets.json qml/QtWebSockets/plugins.qmltypes qml/QtWebSockets/qmldir qml/QtWebSockets/qmlwebsocketsplugin.dll qml/QtWebSockets/qmlwebsocketsplugind.dll ``` Found by running these commands in Git Bash: ```Bash cd /c/Qt/6.2.4 find msvc2019_64/ -type f > WithoutQtWebSockets.txt # Now install Qt WebSockets via Maintenance Tool. find msvc2019_64/ -type f > WithQtWebSockets.txt diff WithoutQtWebSockets.txt WithQtWebSockets.txt | sed -En 's|^> msvc2019_64/||p' | less ```

You can probably ignore the d.dll file as well as all files in include and lib/cmake, so that just leaves:

bin/Qt6WebSockets.dll
lib/metatypes/qt6websockets_metatypes.json
lib/Qt6WebSockets.lib
lib/Qt6WebSockets.prl
lib/Qt6WebSocketsd.lib
lib/Qt6WebSocketsd.prl
mkspecs/modules/qt_lib_websockets.pri
mkspecs/modules/qt_lib_websockets_private.pri
modules/WebSockets.json
qml/QtWebSockets/plugins.qmltypes
qml/QtWebSockets/qmldir
qml/QtWebSockets/qmlwebsocketsplugin.dll
qml/QtWebSockets/qmlwebsocketsplugind.dll

These will need to be placed correctly relative to MuseScore's execuable.

andreoid87 commented 1 month ago

Files added to C:\Qt\6.2.4\msvc2019_64 when you install Qt WebSockets via the Maintenance Tool You can probably ignore the d.dll file as well as all files in include and lib/cmake, so that just leaves:

bin/Qt6WebSockets.dll
lib/metatypes/qt6websockets_metatypes.json
lib/Qt6WebSockets.lib
lib/Qt6WebSockets.prl
lib/Qt6WebSocketsd.lib
lib/Qt6WebSocketsd.prl
mkspecs/modules/qt_lib_websockets.pri
mkspecs/modules/qt_lib_websockets_private.pri
modules/WebSockets.json
qml/QtWebSockets/plugins.qmltypes
qml/QtWebSockets/qmldir
qml/QtWebSockets/qmlwebsocketsplugin.dll
qml/QtWebSockets/qmlwebsocketsplugind.dll

These will need to be placed correctly relative to MuseScore's execuable.

Thank you for the suggestion. I’ve already installed Qt WebSockets via the Maintenance Tool, and I’m currently building MuseScore 4 in Qt Creator. I added the following missing files:

lib/metatypes/qt6websockets_metatypes.json
lib/Qt6WebSockets.lib
lib/Qt6WebSockets.prl
lib/Qt6WebSocketsd.lib
lib/Qt6WebSocketsd.prl

However, this didn't resolve the issue. I suspect the problem is not due to missing files but rather an internal call that hasn't been made.

cbjeukendrup commented 1 month ago

As far as I know there is really no such function call for all other Qt modules that we use, so I really wouldn't know what it should be for WebSockets. You can try #including one WebSockets header in some cpp file (probably doesn't matter which one, maybe main.cpp); maybe that's what required to make the module register its QML files.

Also, did you add that qmldir file (and those other four in qml/QtWebSockets)? That might be crucial.

shoogle commented 1 month ago

This page suggests:

find_package(Qt6 REQUIRED COMPONENTS WebSockets)
target_link_libraries(mytarget PRIVATE Qt6::WebSockets)

I think you have find_package already, but what about target_link_libraries?

andreoid87 commented 1 month ago

This page suggests:

find_package(Qt6 REQUIRED COMPONENTS WebSockets)
target_link_libraries(mytarget PRIVATE Qt6::WebSockets)

I think you have find_package already, but what about target_link_libraries?

Hi shoogle

I noticed that in the MuseScore/src/app/CMakeLists.txt file, we already have:

target_link_libraries(mscore ${LINK_LIB}) 

To be more certain of what libraries are being linked, I also added the following snippet to print all the linked libraries:

get_target_property(LINKED_LIBRARIES mscore INTERFACE_LINK_LIBRARIES)
message(STATUS "Librerie linkate al target mscore:")
foreach(LIB ${LINKED_LIBRARIES})
    message(STATUS " - ${LIB}")
endforeach()

And indeed, the following libraries are listed:

[cmake] -- - Qt6::Svg 
[cmake] -- - Qt6::PrintSupport 
[cmake] -- - Qt6::OpenGL 
[cmake] -- - Qt6::Core5Compat 
>>> [cmake] -- - Qt6::WebSockets 
[cmake] -- - Qt6::StateMachine 

So I'm certain that the library has been linked, or at least, the command was issued. However, I still have no idea how to confirm if the operation was successful.

igorkorsukov commented 1 month ago

@andreoid87 Would you agree to we add our own API for working with a web socket, and you would rewrite your plugin a little? Strategically, it would be more useful for us..., and your problem would be solved. The only inconvenience is that you need two versions of the plugin, for 4.3 and below and for 4.4 and above

andreoid87 commented 1 month ago

@andreoid87 Would you agree to we add our own API for working with a web socket, and you would rewrite your plugin a little? Strategically, it would be more useful for us..., and your problem would be solved. The only inconvenience is that you need two versions of the plugin, for 4.3 and below and for 4.4 and above

Of course, I’m open to the idea of using a new API for WebSockets, and I can modify my plugin to align with it.

Considering that 4.4 has already been released and I haven’t managed to get it working yet, I’m assuming you’re talking about implementing this in 4.5 or next?

I’m not very familiar with MuseScore’s workflow, so if it’s not too much trouble, could you clarify what I should do next to seriously discuss and contribute to this?

Let me know how I can assist in making this happen.

igorkorsukov commented 1 month ago

I hope to have time to add this API in 4.4.1 (it will be only for you, we will not talk about it widely).

Please provide a sample code from your plugin for working with a socket

Jojo-Schmitz commented 1 month ago

I'll pretend to haven't seen this ;-)

andreoid87 commented 1 month ago

I hope to have time to add this API in 4.4.1 (it will be only for you, we will not talk about it widely).

Please provide a sample code from your plugin for working with a socket

I want to sincerely thank everyone for their collaboration; you’ve all been very kind.

I’ve just made the repository for the plugin I’ve been working on public. Please note that it’s not very organized, and there are definitely some parts of the code that could be improved. I know I still have a lot to learn about programming.

https://github.com/kemoniariverOrganization/ODLA_Musescore_Plugin.git

igorkorsukov commented 1 month ago

We decided to release 4.4.1 as soon as possible because there is a very important fix that affects many.

The websocket improvement will be included in 4.4.2

andreoid87 commented 1 month ago

thanks for letting me know @igorkorsukov

igorkorsukov commented 1 month ago

@andreoid87 We have added an API for working with a websocket. You can see an example here https://github.com/musescore/MuseScore/pull/24470/files#diff-cfe9933d2556d9e42dd4c66eb0b6d9537b7498c7b2e311cecfc60d1c3e141dde It is now in 4.4.2 (you can build it now to check) and will be added to the master

andreoid87 commented 1 month ago

Thank you very much @igorkorsukov!

I have tested it, and I'm happy to confirm that it works correctly!

However, I noticed that I needed to set the variable -DMUSE_MODULE_NETWORK_WEBSOCKET:BOOL=ON during the build process, as the default setting is OFF.

I modified this setting through Qt Creator by going to the "Projects" pane as as shown below:

image

Could you please let me know if the team compiling version 4.4.2 of MuseScore will include this change? Without it, the API cannot be used.

cbjeukendrup commented 1 month ago

This build option is enabled on CI (GitHub Actions). The reason for disabling it by default, is that we didn't want to require all contributors to install QtWebSockets.

Jojo-Schmitz commented 1 month ago

How would you enable it with MSVC?

cbjeukendrup commented 1 month ago

You'd just set the MUSE_MODULE_NETWORK_WEBSOCKET CMake option to ON, just like how you set other CMake options

Jojo-Schmitz commented 1 month ago

Well, I just don't see where, short of editing the CMakeLists.txt

Jojo-Schmitz commented 1 month ago

Actually I asked the wrong question, I meant to ask how to set this in Visual Studio

igorkorsukov commented 1 month ago

I have no experience with the VS I can advise you to do it this way main CMakeList.txt

###########################################
# Setup Configure
###########################################

if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/SetupConfigure.local.cmake")
    include(${CMAKE_CURRENT_LIST_DIR}/SetupConfigure.local.cmake)
else()
    include(SetupConfigure)
endif()

i.e. we can use our local configuration during development we can create a SetupConfigure.local.cmake file in the root of the project we can either copy the standard one or do it like this

SetupConfigure.local.cmake

include(${CMAKE_CURRENT_LIST_DIR}/buildscripts/cmake/SetupConfigure.cmake)

set(MUSE_MODULE_NETWORK_WEBSOCKET ON)
Jojo-Schmitz commented 1 month ago

Thanks, almost there, but with SetupConfigure.local.cmake:

include(SetupConfigure)

set(MUSE_MODULE_NETWORK_WEBSOCKET ON)
Jojo-Schmitz commented 1 month ago

(and having to ignore that file on Mu3 builds)