Compare commits
12 Commits
de1a99c501
...
1.1
Author | SHA1 | Date | |
---|---|---|---|
28752c83f3 | |||
4ce20fff51 | |||
7733308120 | |||
0e2fa5f81a | |||
7478741ba2 | |||
b1a3d2685c | |||
5601f76124 | |||
364c1e9ee5 | |||
1b6d562ee8 | |||
e62e6a4af0 | |||
b87cd50b0c | |||
5b08f9138b |
27
DiscordMediaRP/Config.cs
Normal file
27
DiscordMediaRP/Config.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace DiscordMediaRP;
|
||||||
|
|
||||||
|
public struct Config
|
||||||
|
{
|
||||||
|
public required string DiscordKey;
|
||||||
|
public LogLevel? LogLevel;
|
||||||
|
public string? LargeImageKey;
|
||||||
|
public bool? UseSpotify;
|
||||||
|
public string[]? WebbrowserIgnoreSites;
|
||||||
|
|
||||||
|
public Config WithDiscordKey(string key)
|
||||||
|
{
|
||||||
|
return this with { DiscordKey = key };
|
||||||
|
}
|
||||||
|
|
||||||
|
public Config WithLargeImageKey(string key)
|
||||||
|
{
|
||||||
|
return this with { LargeImageKey = key };
|
||||||
|
}
|
||||||
|
|
||||||
|
public Config WithLogLevel(LogLevel level)
|
||||||
|
{
|
||||||
|
return this with { LogLevel = level };
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using System.Reflection;
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
using Windows.Media;
|
using Windows.Media;
|
||||||
using Windows.Media.Control;
|
using Windows.Media.Control;
|
||||||
using DiscordRPC;
|
using DiscordRPC;
|
||||||
@ -18,25 +19,32 @@ public class DisMediaRP : IDisposable
|
|||||||
private readonly ILogger? _logger;
|
private readonly ILogger? _logger;
|
||||||
private readonly MediaManager _mediaManager = new();
|
private readonly MediaManager _mediaManager = new();
|
||||||
private readonly DiscordRpcClient _discordRpcClient;
|
private readonly DiscordRpcClient _discordRpcClient;
|
||||||
private readonly RichPresence _currentStatus = new()
|
private RichPresence _currentStatus;
|
||||||
{
|
|
||||||
Assets = new()
|
|
||||||
{
|
|
||||||
LargeImageText = "C9Glax/DiscordMediaRichPresence",
|
|
||||||
SmallImageText = "https://www.flaticon.com/de/autoren/alfanz"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private bool _running = true;
|
private bool _running = true;
|
||||||
|
private Config config;
|
||||||
|
|
||||||
public DisMediaRP(string applicationId, LogLevel? logLevel, string? largeImageKey = null) : this(applicationId, new Logger(logLevel ?? LogLevel.Information), largeImageKey)
|
private static RichPresence DefaultPresence(string? largeImageKey)
|
||||||
{
|
{
|
||||||
|
return new RichPresence()
|
||||||
|
{
|
||||||
|
Details = "hewwo :3",
|
||||||
|
State = "https://github.com/C9Glax/DiscordMediaRichPresence",
|
||||||
|
Assets = new()
|
||||||
|
{
|
||||||
|
LargeImageKey = largeImageKey ?? "",
|
||||||
|
SmallImageKey = "music",
|
||||||
|
LargeImageText = "C9Glax/DiscordMediaRichPresence",
|
||||||
|
SmallImageText = "https://www.flaticon.com/de/autoren/alfanz"
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public DisMediaRP(string applicationId, ILogger? logger = null, string? largeImageKey = null)
|
public DisMediaRP(Config config)
|
||||||
{
|
{
|
||||||
this._logger = logger;
|
this.config = config;
|
||||||
this._currentStatus.Assets.LargeImageKey = largeImageKey ?? "cat";
|
this._logger = new Logger(config.LogLevel ?? LogLevel.Information);
|
||||||
this._discordRpcClient = new DiscordRpcClient(applicationId, logger: new DisLogger(this._logger));
|
this._currentStatus = DefaultPresence(config.LargeImageKey);
|
||||||
|
this._discordRpcClient = new DiscordRpcClient(config.DiscordKey, logger: new DisLogger(this._logger));
|
||||||
this._discordRpcClient.Initialize();
|
this._discordRpcClient.Initialize();
|
||||||
this._discordRpcClient.OnError += (sender, args) =>
|
this._discordRpcClient.OnError += (sender, args) =>
|
||||||
{
|
{
|
||||||
@ -48,14 +56,32 @@ public class DisMediaRP : IDisposable
|
|||||||
this._mediaManager.OnAnyMediaPropertyChanged += MediaPropertyChanged;
|
this._mediaManager.OnAnyMediaPropertyChanged += MediaPropertyChanged;
|
||||||
this._mediaManager.OnAnyPlaybackStateChanged += PlaybackStateChanged;
|
this._mediaManager.OnAnyPlaybackStateChanged += PlaybackStateChanged;
|
||||||
this._mediaManager.OnAnyTimelinePropertyChanged += TimelinePropertyChanged;
|
this._mediaManager.OnAnyTimelinePropertyChanged += TimelinePropertyChanged;
|
||||||
|
this._mediaManager.OnFocusedSessionChanged += mediaSession =>
|
||||||
|
{
|
||||||
|
if (mediaSession is null)
|
||||||
|
{
|
||||||
|
this._currentStatus = DefaultPresence(config.LargeImageKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._discordRpcClient.SetPresence(this._currentStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
if (this._mediaManager.GetFocusedSession() is not null)
|
if (this._mediaManager.GetFocusedSession() is not null)
|
||||||
{
|
{
|
||||||
this.MediaPropertyChanged(this._mediaManager.GetFocusedSession(), this._mediaManager.GetFocusedSession().ControlSession.TryGetMediaPropertiesAsync().GetResults());
|
try
|
||||||
|
{
|
||||||
|
this.MediaPropertyChanged(this._mediaManager.GetFocusedSession(),
|
||||||
|
this._mediaManager.GetFocusedSession().ControlSession.TryGetMediaPropertiesAsync().GetResults());
|
||||||
|
}
|
||||||
|
catch (System.Runtime.InteropServices.COMException e)
|
||||||
|
{
|
||||||
|
this._logger?.LogError("Could not fetch MediaProperties\n{e}", e);
|
||||||
|
}
|
||||||
this.PlaybackStateChanged(this._mediaManager.GetFocusedSession(), this._mediaManager.GetFocusedSession().ControlSession.GetPlaybackInfo());
|
this.PlaybackStateChanged(this._mediaManager.GetFocusedSession(), this._mediaManager.GetFocusedSession().ControlSession.GetPlaybackInfo());
|
||||||
this.TimelinePropertyChanged(this._mediaManager.GetFocusedSession(), this._mediaManager.GetFocusedSession().ControlSession.GetTimelineProperties());
|
this.TimelinePropertyChanged(this._mediaManager.GetFocusedSession(), this._mediaManager.GetFocusedSession().ControlSession.GetTimelineProperties());
|
||||||
}
|
}else
|
||||||
|
this._discordRpcClient.SetPresence(this._currentStatus);
|
||||||
|
|
||||||
while(_running)
|
while(_running)
|
||||||
Thread.Sleep(50);
|
Thread.Sleep(50);
|
||||||
@ -65,9 +91,9 @@ public class DisMediaRP : IDisposable
|
|||||||
{
|
{
|
||||||
this._logger?.LogDebug(ObjectToString(mediaSession));
|
this._logger?.LogDebug(ObjectToString(mediaSession));
|
||||||
this._logger?.LogDebug(ObjectToString(mediaProperties));
|
this._logger?.LogDebug(ObjectToString(mediaProperties));
|
||||||
if (mediaSession != this._mediaManager.GetFocusedSession())
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (!UseMediaSession(mediaSession))
|
||||||
|
return;
|
||||||
|
|
||||||
string details = $"{mediaProperties.Title}";
|
string details = $"{mediaProperties.Title}";
|
||||||
if (mediaProperties.Artist.Length > 0)
|
if (mediaProperties.Artist.Length > 0)
|
||||||
@ -76,16 +102,16 @@ public class DisMediaRP : IDisposable
|
|||||||
details += $" - Album: {mediaProperties.AlbumTitle}";
|
details += $" - Album: {mediaProperties.AlbumTitle}";
|
||||||
this._currentStatus.Details = details;
|
this._currentStatus.Details = details;
|
||||||
|
|
||||||
this._discordRpcClient.SetPresence(this._currentStatus);
|
this.PlaybackStateChanged(mediaSession, mediaSession.ControlSession.GetPlaybackInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)
|
private void PlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)
|
||||||
{
|
{
|
||||||
this._logger?.LogDebug(ObjectToString(mediaSession));
|
this._logger?.LogDebug(ObjectToString(mediaSession));
|
||||||
this._logger?.LogDebug(ObjectToString(playbackInfo));
|
this._logger?.LogDebug(ObjectToString(playbackInfo));
|
||||||
if (mediaSession != this._mediaManager.GetFocusedSession())
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (!UseMediaSession(mediaSession))
|
||||||
|
return;
|
||||||
|
|
||||||
string playbackState = playbackInfo.PlaybackStatus switch
|
string playbackState = playbackInfo.PlaybackStatus switch
|
||||||
{
|
{
|
||||||
@ -114,18 +140,60 @@ public class DisMediaRP : IDisposable
|
|||||||
{
|
{
|
||||||
this._logger?.LogDebug(ObjectToString(mediaSession));
|
this._logger?.LogDebug(ObjectToString(mediaSession));
|
||||||
this._logger?.LogDebug(ObjectToString(timelineProperties));
|
this._logger?.LogDebug(ObjectToString(timelineProperties));
|
||||||
if (mediaSession != this._mediaManager.GetFocusedSession())
|
|
||||||
|
if (!UseMediaSession(mediaSession))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (timelineProperties.LastUpdatedTime < DateTimeOffset.UnixEpoch)
|
if (timelineProperties.LastUpdatedTime < DateTimeOffset.UnixEpoch)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this._currentStatus.Timestamps = new Timestamps(DateTime.Now.Subtract(timelineProperties.Position),
|
GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo =
|
||||||
DateTime.Now.Add(timelineProperties.EndTime - timelineProperties.Position));
|
mediaSession.ControlSession.GetPlaybackInfo();
|
||||||
|
|
||||||
|
string? repeatMode = playbackInfo.AutoRepeatMode switch
|
||||||
|
{
|
||||||
|
MediaPlaybackAutoRepeatMode.Track => "\ud83d\udd02",
|
||||||
|
MediaPlaybackAutoRepeatMode.List => "\ud83d\udd01",
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
string? shuffle = (playbackInfo.IsShuffleActive ?? false) ? "\ud83d\udd00" : null;
|
||||||
|
|
||||||
|
this._currentStatus.State = string.Join(' ', repeatMode, shuffle, $"{timelineProperties.Position:hh\\:mm\\:ss}/{timelineProperties.EndTime:hh\\:mm\\:ss}");
|
||||||
|
|
||||||
|
if (mediaSession.ControlSession.GetPlaybackInfo().PlaybackStatus is
|
||||||
|
GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing)
|
||||||
|
this._currentStatus.Timestamps = new Timestamps()
|
||||||
|
{
|
||||||
|
End = DateTime.UtcNow.Add(timelineProperties.EndTime - timelineProperties.Position)
|
||||||
|
};
|
||||||
|
else
|
||||||
|
this._currentStatus.Timestamps = new Timestamps();
|
||||||
|
|
||||||
this._discordRpcClient.SetPresence(this._currentStatus);
|
this._discordRpcClient.SetPresence(this._currentStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool UseMediaSession(MediaManager.MediaSession mediaSession)
|
||||||
|
{
|
||||||
|
string processId = mediaSession.ControlSession.SourceAppUserModelId;
|
||||||
|
if (processId == "spotify.exe")
|
||||||
|
return config.UseSpotify ?? true;
|
||||||
|
|
||||||
|
if (processId == "firefox.exe")
|
||||||
|
{
|
||||||
|
string[] windowNames = Process.GetProcesses().Where(proc => processId.Contains(proc.ProcessName, StringComparison.InvariantCultureIgnoreCase)).Select(proc => proc.MainWindowTitle).ToArray();
|
||||||
|
return !windowNames.Any(name =>
|
||||||
|
{
|
||||||
|
foreach (string site in config.WebbrowserIgnoreSites ?? Array.Empty<string>())
|
||||||
|
if (name.Contains(site, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_mediaManager.Dispose();
|
_mediaManager.Dispose();
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
|
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
|
||||||
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.3" />
|
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.3" />
|
||||||
<PackageReference Include="GlaxLogger" Version="1.0.6" />
|
<PackageReference Include="GlaxLogger" Version="1.0.6" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -2,31 +2,40 @@
|
|||||||
|
|
||||||
using DiscordMediaRP;
|
using DiscordMediaRP;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
Config? c = null;
|
||||||
|
if (File.Exists("config.json"))
|
||||||
|
c = JsonConvert.DeserializeObject<Config>(File.ReadAllText("config.json"));
|
||||||
|
|
||||||
|
int discordKeyIndex = Array.IndexOf(args, "-d");
|
||||||
|
if (discordKeyIndex > -1)
|
||||||
|
if (discordKeyIndex + 1 < args.Length)
|
||||||
|
if (c is null)
|
||||||
|
c = new Config()
|
||||||
|
{
|
||||||
|
DiscordKey = args[discordKeyIndex + 1]
|
||||||
|
};
|
||||||
|
else
|
||||||
|
c = c.Value.WithDiscordKey(args[discordKeyIndex + 1]);
|
||||||
|
else
|
||||||
|
throw new IndexOutOfRangeException("No Discord ApplicationKey provided");
|
||||||
|
else if(c is null)
|
||||||
|
throw new ArgumentNullException(nameof(Config.DiscordKey));
|
||||||
|
|
||||||
|
|
||||||
int loglevelIndex = Array.IndexOf(args, "-l");
|
int loglevelIndex = Array.IndexOf(args, "-l");
|
||||||
LogLevel? level = null;
|
|
||||||
if(loglevelIndex > -1)
|
if(loglevelIndex > -1)
|
||||||
if(loglevelIndex + 1 < args.Length)
|
if (loglevelIndex + 1 < args.Length)
|
||||||
level = loglevelIndex < args.Length ? Enum.Parse<LogLevel>(args[loglevelIndex + 1]) : null;
|
c = c.Value.WithLogLevel(Enum.Parse<LogLevel>(args[loglevelIndex + 1]));
|
||||||
else
|
else
|
||||||
throw new IndexOutOfRangeException(nameof(loglevelIndex));
|
throw new IndexOutOfRangeException(nameof(loglevelIndex));
|
||||||
|
|
||||||
int discordKeyIndex = Array.IndexOf(args, "-d");
|
|
||||||
string discordKey;
|
|
||||||
if (loglevelIndex > -1)
|
|
||||||
if(discordKeyIndex + 1 < args.Length)
|
|
||||||
discordKey = args[discordKeyIndex + 1];
|
|
||||||
else
|
|
||||||
throw new IndexOutOfRangeException("No Discord ApplicationKey provided");
|
|
||||||
else
|
|
||||||
throw new ArgumentNullException(nameof(discordKey));
|
|
||||||
|
|
||||||
int imageKeyIndex = Array.IndexOf(args, "-i");
|
int imageKeyIndex = Array.IndexOf(args, "-i");
|
||||||
string? imageKey = null;
|
|
||||||
if(imageKeyIndex > -1)
|
if(imageKeyIndex > -1)
|
||||||
if (imageKeyIndex + 1 < args.Length)
|
if (imageKeyIndex + 1 < args.Length)
|
||||||
imageKey = args[imageKeyIndex + 1];
|
c = c.Value.WithLargeImageKey(args[imageKeyIndex + 1]);
|
||||||
else
|
else
|
||||||
throw new IndexOutOfRangeException(nameof(imageKeyIndex));
|
throw new IndexOutOfRangeException(nameof(imageKeyIndex));
|
||||||
|
|
||||||
DisMediaRP _ = new (discordKey, level, imageKey);
|
DisMediaRP _ = new (c.Value);
|
23
README.md
23
README.md
@ -1,2 +1,25 @@
|
|||||||
# DiscordMediaRichPresence
|
# DiscordMediaRichPresence
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
`DiscordMediaRP.exe [-d <Your ApplicationKey>] [-l Debug]`
|
||||||
|
|
||||||
|
If you omit the ApplicationKey as argument, you need to use a `config.json`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"DiscordKey": "<Your ApplicationKey>",
|
||||||
|
"UseSpotify": false,
|
||||||
|
"WebbrowserIgnoreSites": [
|
||||||
|
"Youtube",
|
||||||
|
"Reddit"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Your Discord-Application should have 5 Assets:
|
||||||
|
* cat
|
||||||
|
* play
|
||||||
|
* pause
|
||||||
|
* stop
|
||||||
|
* music
|
||||||
|
|
||||||
|

|
||||||
|
Reference in New Issue
Block a user