Skip to content

Conversation

phw
Copy link
Member

@phw phw commented Mar 5, 2025

Summary

  • This is a…
    • Bug fix
    • Feature addition
    • Refactoring
    • Minor / simple change (like a typo)
    • Other
  • Describe this change in 1-2 sentences:

Problem

This PR implements a custom URL handler in an attempt to provide a solution for PICARD-3040. This PR focuses on adding the ability to handle the protocol to Picard and register the handler on various systems.

The handler allows opening URIs like org.musicbrainz.picard:openalbum?id=3fd4b04a-28fa-45b7-89d7-bcb883be287c.

Solution

  • Implement the protocol handler based on the existing browser integration
  • Enable support for handling the custom URLs via command line (Linux and Windows) and via a handler registered with QDesktopServices.setUrlHandler (macOS).
  • Register the handler on macOS, Linux and Windows. This depends both on the system and the installation method.

Action

  • Test on different systems
  • This PR does not in any way actually use the handler. For OAuth this would require setting the callback URL accordingly (which currently requires us to register a separate "App" on MusicBrainz.org with the custom handler). For tagger buttons this would need some changes on MusicBrainz.org itself.

@phw
Copy link
Member Author

phw commented Mar 5, 2025

To test this on Linux, run python setup.py build_desktop_file and copy the generated org.musicbrainz.Picard.desktop file to ~/.local/share/applications.

Edit the Exec line in the file to open Picard from the source. I have set it to:

Exec=/home/phw/devel/musicbrainz/picard/tagger.py -c /home/phw/devel/musicbrainz/picard/picard3.ini --no-plugins %U

Afterwards run:

update-desktop-database ~/.local/share/applications

It should now be possible to run xdg-open with a custom protocol URI:

xdg-open "org.musicbrainz.picard:openalbum?id=3fd4b04a-28fa-45b7-89d7-bcb883be287c"

It also works from within browsers, but at least with Firefox and Chrome it is a bit special. Pasting the custom URI into the address bar just triggers web searches. But if it is part of a link (e.g. <a href="org.musicbrainz.picard:openalbum?id=3fd4b04a-28fa-45b7-89d7-bcb883be287c">Tagger</a>, it is being used and the browser will ask whether the handler shall be called.

@phw phw force-pushed the custom-protocol branch 2 times, most recently from b1dcda6 to 9aad628 Compare March 6, 2025 07:58
@phw
Copy link
Member Author

phw commented Mar 6, 2025

The URL handler on macOS is not called. The app is started and brought to the foreground, but the handler never receives the URL. There is a bug report https://bugreports.qt.io/browse/QTBUG-131741 for Qt 6.
8.0 and 6.8.1 which looks related. But it is marked as fixed in 6.8.2, which we already use for the macOS builds.

@phw phw force-pushed the custom-protocol branch 6 times, most recently from 7b64040 to 281b1c7 Compare March 6, 2025 15:12
@phw phw force-pushed the custom-protocol branch from 281b1c7 to 92a148e Compare March 7, 2025 17:09
@phw
Copy link
Member Author

phw commented Mar 7, 2025

I tested this on Windows and macOS.

On Windows using the installer everything works as expected. Windows, like Linux, passes the custom URL via command line (hooray for single instance mode), and it gets processed as expected. The installer registers the protocol handler via registry and this also gets cleaned up again on uninstalling.

I still need to test this with the appx package (as used for the store). Theoretically this works the same, but protocol registration happens via the appxmanifest metadata. Testing this needs code signing to work (only signed appx packages can be installed), and I need to do the proper setup for this on my machine.

Unfortunately the macOS test results are a bit mixed. Registering the protocol handler via the app package metadata (info.plist) works as expected. The handler works (tried with Safari and command line open command) and the app gets started or raised.

But event processing is not working as expected in Qt. Like with file open macOS handles the protocol by sending an event to the app. The Qt documentation for QDesktopServices suggest that it should work when registering the handler via QDesktopServices.setUrlHandler. But the handler was never invoked.

I first assumed our custom event handling in https://github.com/metabrainz/picard/blob/master/picard/tagger.py#L792-L804 is interfering, so I made sure no event is processed there and super() gets called. But made no difference.

Then I figured out that with Qt 6.7 the event with the custom protocol URL ends up as a FileOpen event. So I patched our even handling to handle URLs with our scheme explicitly in https://github.com/metabrainz/picard/pull/2596/files#diff-754164b29034aa27e27d501630b16fe491c78108500b10caeab6b272bc240fbdR814 and call the handler directly. This feels like a workaround, though.

Unfortunately with Qt 6.8.2 the event neither shows up as a FileOpen event nor does it call the registered handler.

So far I think this is a Qt bug. As mentioned above there is the suspicious bug https://bugreports.qt.io/browse/QTBUG-131741 , but it is marked as resolved for 6.8.2. I'll see that I can create a small reproducer and report this to Qt.

@phw phw force-pushed the custom-protocol branch from 472666d to 74a70ec Compare March 11, 2025 06:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants