1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-06 09:42:55 +08:00

Handle osu:// scheme links via IPC in desktop game

This commit is contained in:
Bartłomiej Dach 2022-06-20 21:21:16 +02:00
parent 92011124d1
commit 330af7ec74
No known key found for this signature in database
GPG Key ID: BCECCD4FA41F6497
3 changed files with 65 additions and 23 deletions

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
#nullable disable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -22,23 +20,26 @@ using osu.Game.Updater;
using osu.Desktop.Windows; using osu.Desktop.Windows;
using osu.Framework.Threading; using osu.Framework.Threading;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.IPC;
namespace osu.Desktop namespace osu.Desktop
{ {
internal class OsuGameDesktop : OsuGame internal class OsuGameDesktop : OsuGame
{ {
public OsuGameDesktop(string[] args = null) private OsuSchemeLinkIPCChannel? osuSchemeLinkIPCChannel;
public OsuGameDesktop(string[]? args = null)
: base(args) : base(args)
{ {
} }
public override StableStorage GetStorageForStableInstall() public override StableStorage? GetStorageForStableInstall()
{ {
try try
{ {
if (Host is DesktopGameHost desktopHost) if (Host is DesktopGameHost desktopHost)
{ {
string stablePath = getStableInstallPath(); string? stablePath = getStableInstallPath();
if (!string.IsNullOrEmpty(stablePath)) if (!string.IsNullOrEmpty(stablePath))
return new StableStorage(stablePath, desktopHost); return new StableStorage(stablePath, desktopHost);
} }
@ -51,11 +52,11 @@ namespace osu.Desktop
return null; return null;
} }
private string getStableInstallPath() private string? getStableInstallPath()
{ {
static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")) || File.Exists(Path.Combine(p, "osu!.cfg")); static bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs")) || File.Exists(Path.Combine(p, "osu!.cfg"));
string stableInstallPath; string? stableInstallPath;
if (OperatingSystem.IsWindows()) if (OperatingSystem.IsWindows())
{ {
@ -83,15 +84,15 @@ namespace osu.Desktop
} }
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
private string getStableInstallPathFromRegistry() private string? getStableInstallPathFromRegistry()
{ {
using (RegistryKey key = Registry.ClassesRoot.OpenSubKey("osu")) using (RegistryKey? key = Registry.ClassesRoot.OpenSubKey("osu"))
return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", ""); return key?.OpenSubKey(@"shell\open\command")?.GetValue(string.Empty)?.ToString()?.Split('"')[1].Replace("osu!.exe", "");
} }
protected override UpdateManager CreateUpdateManager() protected override UpdateManager CreateUpdateManager()
{ {
string packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER"); string? packageManaged = Environment.GetEnvironmentVariable("OSU_EXTERNAL_UPDATE_PROVIDER");
if (!string.IsNullOrEmpty(packageManaged)) if (!string.IsNullOrEmpty(packageManaged))
return new NoActionUpdateManager(); return new NoActionUpdateManager();
@ -118,6 +119,8 @@ namespace osu.Desktop
LoadComponentAsync(new GameplayWinKeyBlocker(), Add); LoadComponentAsync(new GameplayWinKeyBlocker(), Add);
LoadComponentAsync(new ElevatedPrivilegesChecker(), Add); LoadComponentAsync(new ElevatedPrivilegesChecker(), Add);
osuSchemeLinkIPCChannel = new OsuSchemeLinkIPCChannel(Host, this);
} }
public override void SetHost(GameHost host) public override void SetHost(GameHost host)
@ -135,7 +138,7 @@ namespace osu.Desktop
} }
private readonly List<string> importableFiles = new List<string>(); private readonly List<string> importableFiles = new List<string>();
private ScheduledDelegate importSchedule; private ScheduledDelegate? importSchedule;
private void fileDrop(string[] filePaths) private void fileDrop(string[] filePaths)
{ {
@ -168,5 +171,11 @@ namespace osu.Desktop
Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning); Task.Factory.StartNew(() => Import(paths), TaskCreationOptions.LongRunning);
} }
} }
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
osuSchemeLinkIPCChannel?.Dispose();
}
} }
} }

View File

@ -11,6 +11,7 @@ using osu.Framework;
using osu.Framework.Development; using osu.Framework.Development;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Game;
using osu.Game.IPC; using osu.Game.IPC;
using osu.Game.Tournament; using osu.Game.Tournament;
using Squirrel; using Squirrel;
@ -65,19 +66,8 @@ namespace osu.Desktop
{ {
if (!host.IsPrimaryInstance) if (!host.IsPrimaryInstance)
{ {
if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args if (trySendIPCMessage(host, cwd, args))
{
var importer = new ArchiveImportIPCChannel(host);
foreach (string file in args)
{
Console.WriteLine(@"Importing {0}", file);
if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000))
throw new TimeoutException(@"IPC took too long to send");
}
return; return;
}
// we want to allow multiple instances to be started when in debug. // we want to allow multiple instances to be started when in debug.
if (!DebugUtils.IsDebugBuild) if (!DebugUtils.IsDebugBuild)
@ -108,6 +98,34 @@ namespace osu.Desktop
} }
} }
private static bool trySendIPCMessage(IIpcHost host, string cwd, string[] args)
{
if (args.Length == 1 && args[0].StartsWith(OsuGameBase.OSU_PROTOCOL, StringComparison.Ordinal))
{
var osuSchemeLinkHandler = new OsuSchemeLinkIPCChannel(host);
if (!osuSchemeLinkHandler.HandleLinkAsync(args[0]).Wait(3000))
throw new IPCTimeoutException(osuSchemeLinkHandler.GetType());
return true;
}
if (args.Length > 0 && args[0].Contains('.')) // easy way to check for a file import in args
{
var importer = new ArchiveImportIPCChannel(host);
foreach (string file in args)
{
Console.WriteLine(@"Importing {0}", file);
if (!importer.ImportAsync(Path.GetFullPath(file, cwd)).Wait(3000))
throw new IPCTimeoutException(importer.GetType());
}
return true;
}
return false;
}
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]
private static void setupSquirrel() private static void setupSquirrel()
{ {

View File

@ -0,0 +1,15 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
namespace osu.Game.IPC
{
public class IPCTimeoutException : TimeoutException
{
public IPCTimeoutException(Type channelType)
: base($@"IPC took too long to send message via channel {channelType}")
{
}
}
}