2020-12-03 10:10:25 +00:00
using AudioSwitcher.AudioApi.CoreAudio ;
using DisplayMagician.GameLibraries ;
2020-12-02 08:11:23 +00:00
using DisplayMagician.InterProcess ;
2020-12-20 07:42:04 +00:00
using DisplayMagicianShared ;
2020-12-26 03:59:45 +00:00
using Microsoft.Toolkit.Uwp.Notifications ;
2020-06-01 10:25:52 +00:00
using Newtonsoft.Json ;
using System ;
using System.Collections.Generic ;
2020-10-13 09:02:46 +00:00
using System.ComponentModel ;
2020-07-23 06:31:00 +00:00
using System.Diagnostics ;
2020-06-01 10:25:52 +00:00
using System.IO ;
using System.Linq ;
using System.Text ;
2020-06-15 09:57:46 +00:00
using System.Text.RegularExpressions ;
2020-07-23 06:31:00 +00:00
using System.Threading ;
2020-06-01 10:25:52 +00:00
using System.Threading.Tasks ;
using System.Windows.Forms ;
2020-12-26 03:59:45 +00:00
using Windows.Data.Xml.Dom ;
using Windows.UI.Notifications ;
2020-06-01 10:25:52 +00:00
2020-12-02 08:11:23 +00:00
namespace DisplayMagician
2020-06-01 10:25:52 +00:00
{
2020-07-21 07:50:41 +00:00
public static class ShortcutRepository
2020-06-01 10:25:52 +00:00
{
#region Class Variables
// Common items to the class
2020-08-07 03:59:23 +00:00
private static List < ShortcutItem > _allShortcuts = new List < ShortcutItem > ( ) ;
private static bool _shortcutsLoaded = false ;
2020-06-01 10:25:52 +00:00
// Other constants that are useful
2020-08-18 22:16:04 +00:00
private static string AppShortcutStoragePath = Path . Combine ( Program . AppDataPath , $"Shortcuts" ) ;
private static string _shortcutStorageJsonFileName = Path . Combine ( AppShortcutStoragePath , $"Shortcuts_{Version.ToString(2)}.json" ) ;
2020-07-21 11:40:33 +00:00
private static string uuidV4Regex = @"(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$" ;
2020-12-03 10:10:25 +00:00
private static CoreAudioController _audioController = null ;
2020-12-09 07:47:30 +00:00
private static readonly NLog . Logger logger = NLog . LogManager . GetCurrentClassLogger ( ) ;
2020-06-01 10:25:52 +00:00
#endregion
#region Class Constructors
2020-07-21 07:50:41 +00:00
static ShortcutRepository ( )
2020-06-01 10:25:52 +00:00
{
2020-08-18 22:16:04 +00:00
try
{
NvAPIWrapper . NVIDIA . Initialize ( ) ;
2020-12-03 10:10:25 +00:00
_audioController = new CoreAudioController ( ) ;
2020-08-18 22:16:04 +00:00
// Create the Profile Storage Path if it doesn't exist so that it's avilable for all the program
if ( ! Directory . Exists ( AppShortcutStoragePath ) )
{
Directory . CreateDirectory ( AppShortcutStoragePath ) ;
}
}
catch ( Exception ex )
{
2020-12-09 07:47:30 +00:00
//Console.WriteLine($"ShortcutItem/Instansiation exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
logger . Error ( ex , $"ShortcutRepository/Instansiation exception during class construction" ) ;
2020-08-18 22:16:04 +00:00
// ignored
}
2020-06-01 10:25:52 +00:00
// Load the Shortcuts from storage
2020-06-15 09:57:46 +00:00
LoadShortcuts ( ) ;
2020-06-01 10:25:52 +00:00
}
2020-07-21 07:50:41 +00:00
2020-06-01 10:25:52 +00:00
#endregion
#region Class Properties
2020-06-07 08:48:45 +00:00
public static List < ShortcutItem > AllShortcuts
2020-06-01 10:25:52 +00:00
{
get
{
2020-08-07 03:59:23 +00:00
if ( ! _shortcutsLoaded )
2020-06-01 10:25:52 +00:00
// Load the Shortcuts from storage
2020-06-15 09:57:46 +00:00
LoadShortcuts ( ) ;
2020-08-07 03:59:23 +00:00
2020-06-01 10:25:52 +00:00
return _allShortcuts ;
}
}
public static int ShortcutCount
{
get
{
2020-08-07 03:59:23 +00:00
if ( ! _shortcutsLoaded )
// Load the Shortcuts from storage
LoadShortcuts ( ) ;
2020-06-01 10:25:52 +00:00
return _allShortcuts . Count ;
}
}
2020-12-03 10:10:25 +00:00
public static CoreAudioController AudioController
{
get
{
return _audioController ;
}
}
2020-07-23 23:06:33 +00:00
public static Version Version
{
get = > new Version ( 1 , 0 , 0 ) ;
}
2020-06-01 10:25:52 +00:00
#endregion
#region Class Methods
2020-06-07 08:48:45 +00:00
public static bool AddShortcut ( ShortcutItem shortcut )
2020-06-01 10:25:52 +00:00
{
2020-06-07 08:48:45 +00:00
if ( ! ( shortcut is ShortcutItem ) )
2020-06-01 10:25:52 +00:00
return false ;
2020-11-28 04:55:34 +00:00
// Add the shortcut to the list of shortcuts
_allShortcuts . Add ( shortcut ) ;
2020-06-01 10:25:52 +00:00
//Doublecheck it's been added
if ( ContainsShortcut ( shortcut ) )
{
// Generate the Shortcut Icon ready to be used
2020-10-18 10:04:08 +00:00
//shortcut.SaveShortcutIconToCache();
2020-06-01 10:25:52 +00:00
// Save the shortcuts JSON as it's different
SaveShortcuts ( ) ;
return true ;
}
else
return false ;
}
2020-06-07 08:48:45 +00:00
public static bool RemoveShortcut ( ShortcutItem shortcut )
2020-06-01 10:25:52 +00:00
{
2020-06-07 08:48:45 +00:00
if ( ! ( shortcut is ShortcutItem ) )
2020-06-01 10:25:52 +00:00
return false ;
// Remove the Shortcut Icons from the Cache
2020-12-26 08:46:32 +00:00
List < ShortcutItem > shortcutsToRemove = _allShortcuts . FindAll ( item = > item . UUID . Equals ( shortcut . UUID , StringComparison . OrdinalIgnoreCase ) ) ;
2020-06-07 08:48:45 +00:00
foreach ( ShortcutItem shortcutToRemove in shortcutsToRemove )
2020-06-01 10:25:52 +00:00
{
try
{
File . Delete ( shortcutToRemove . SavedShortcutIconCacheFilename ) ;
}
2020-07-15 08:11:38 +00:00
catch ( Exception ex )
2020-06-01 10:25:52 +00:00
{
2020-07-24 04:51:48 +00:00
Console . WriteLine ( $"ShortcutRepository/RemoveShortcut exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-07-15 08:11:38 +00:00
2020-06-01 10:25:52 +00:00
// TODO check and report
}
}
// Remove the shortcut from the list.
2020-12-26 08:46:32 +00:00
int numRemoved = _allShortcuts . RemoveAll ( item = > item . UUID . Equals ( shortcut . UUID , StringComparison . OrdinalIgnoreCase ) ) ;
2020-06-01 10:25:52 +00:00
if ( numRemoved = = 1 )
{
SaveShortcuts ( ) ;
return true ;
}
else if ( numRemoved = = 0 )
return false ;
else
throw new ShortcutRepositoryException ( ) ;
}
2020-06-15 09:57:46 +00:00
public static bool RemoveShortcut ( string shortcutNameOrUuid )
2020-06-01 10:25:52 +00:00
{
2020-06-15 09:57:46 +00:00
if ( String . IsNullOrWhiteSpace ( shortcutNameOrUuid ) )
2020-06-01 10:25:52 +00:00
return false ;
2020-06-15 09:57:46 +00:00
List < ShortcutItem > shortcutsToRemove ;
int numRemoved ;
2020-06-01 10:25:52 +00:00
2020-07-21 11:40:33 +00:00
//string uuidV4Regex = @"/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i";
2020-06-15 09:57:46 +00:00
Match match = Regex . Match ( shortcutNameOrUuid , uuidV4Regex , RegexOptions . IgnoreCase ) ;
if ( match . Success )
2020-06-01 10:25:52 +00:00
{
2020-12-26 08:46:32 +00:00
shortcutsToRemove = _allShortcuts . FindAll ( item = > item . UUID . Equals ( shortcutNameOrUuid , StringComparison . OrdinalIgnoreCase ) ) ;
numRemoved = _allShortcuts . RemoveAll ( item = > item . UUID . Equals ( shortcutNameOrUuid , StringComparison . OrdinalIgnoreCase ) ) ;
2020-06-01 10:25:52 +00:00
}
else
2020-06-15 09:57:46 +00:00
{
2020-12-26 08:46:32 +00:00
shortcutsToRemove = _allShortcuts . FindAll ( item = > item . Name . Equals ( shortcutNameOrUuid , StringComparison . OrdinalIgnoreCase ) ) ;
numRemoved = _allShortcuts . RemoveAll ( item = > item . Name . Equals ( shortcutNameOrUuid , StringComparison . OrdinalIgnoreCase ) ) ;
2020-06-15 09:57:46 +00:00
}
2020-06-01 10:25:52 +00:00
// Remove the Shortcut Icons from the Cache
2020-06-07 08:48:45 +00:00
foreach ( ShortcutItem shortcutToRemove in shortcutsToRemove )
2020-06-01 10:25:52 +00:00
{
try
{
File . Delete ( shortcutToRemove . SavedShortcutIconCacheFilename ) ;
}
2020-07-15 08:11:38 +00:00
catch ( Exception ex )
2020-06-01 10:25:52 +00:00
{
2020-07-24 04:51:48 +00:00
Console . WriteLine ( $"ShortcutRepository/RemoveShortcut exception 2: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-07-15 08:11:38 +00:00
2020-06-01 10:25:52 +00:00
// TODO check and report
}
}
if ( numRemoved = = 1 )
{
SaveShortcuts ( ) ;
return true ;
2020-06-15 09:57:46 +00:00
}
2020-06-01 10:25:52 +00:00
else if ( numRemoved = = 0 )
return false ;
else
throw new ShortcutRepositoryException ( ) ;
2020-06-15 09:57:46 +00:00
2020-06-01 10:25:52 +00:00
}
2020-06-07 08:48:45 +00:00
public static bool ContainsShortcut ( ShortcutItem shortcut )
2020-06-01 10:25:52 +00:00
{
2020-06-07 08:48:45 +00:00
if ( ! ( shortcut is ShortcutItem ) )
2020-06-01 10:25:52 +00:00
return false ;
2020-06-07 08:48:45 +00:00
foreach ( ShortcutItem testShortcut in _allShortcuts )
2020-06-01 10:25:52 +00:00
{
2020-12-26 08:46:32 +00:00
if ( testShortcut . UUID . Equals ( shortcut . UUID , StringComparison . OrdinalIgnoreCase ) )
2020-06-01 10:25:52 +00:00
return true ;
}
return false ;
}
2020-06-15 09:57:46 +00:00
public static bool ContainsShortcut ( string shortcutNameOrUuid )
2020-06-01 10:25:52 +00:00
{
2020-06-15 09:57:46 +00:00
if ( String . IsNullOrWhiteSpace ( shortcutNameOrUuid ) )
2020-06-01 10:25:52 +00:00
return false ;
2020-07-21 11:40:33 +00:00
//string uuidV4Regex = @"(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$";
2020-06-15 09:57:46 +00:00
Match match = Regex . Match ( shortcutNameOrUuid , uuidV4Regex , RegexOptions . IgnoreCase ) ;
if ( match . Success )
{
foreach ( ShortcutItem testShortcut in _allShortcuts )
{
2020-12-26 08:46:32 +00:00
if ( testShortcut . UUID . Equals ( shortcutNameOrUuid , StringComparison . OrdinalIgnoreCase ) )
2020-06-15 09:57:46 +00:00
return true ;
}
2020-06-01 10:25:52 +00:00
2020-06-15 09:57:46 +00:00
}
else
2020-06-01 10:25:52 +00:00
{
2020-06-15 09:57:46 +00:00
foreach ( ShortcutItem testShortcut in _allShortcuts )
{
2020-12-26 08:46:32 +00:00
if ( testShortcut . Name . Equals ( shortcutNameOrUuid , StringComparison . OrdinalIgnoreCase ) )
2020-06-15 09:57:46 +00:00
return true ;
}
2020-06-01 10:25:52 +00:00
}
return false ;
}
2020-06-15 09:57:46 +00:00
public static ShortcutItem GetShortcut ( string shortcutNameOrUuid )
2020-06-01 10:25:52 +00:00
{
2020-06-15 09:57:46 +00:00
if ( String . IsNullOrWhiteSpace ( shortcutNameOrUuid ) )
2020-06-01 10:25:52 +00:00
return null ;
2020-07-21 11:40:33 +00:00
//string uuidV4Regex = @"/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i";
2020-06-15 09:57:46 +00:00
Match match = Regex . Match ( shortcutNameOrUuid , uuidV4Regex , RegexOptions . IgnoreCase ) ;
if ( match . Success )
2020-06-01 10:25:52 +00:00
{
2020-06-15 09:57:46 +00:00
foreach ( ShortcutItem testShortcut in _allShortcuts )
{
2020-12-26 08:46:32 +00:00
if ( testShortcut . UUID . Equals ( shortcutNameOrUuid , StringComparison . OrdinalIgnoreCase ) )
2020-06-15 09:57:46 +00:00
return testShortcut ;
}
}
else
{
foreach ( ShortcutItem testShortcut in _allShortcuts )
{
2020-12-26 08:46:32 +00:00
if ( testShortcut . Name . Equals ( shortcutNameOrUuid , StringComparison . OrdinalIgnoreCase ) )
2020-06-15 09:57:46 +00:00
return testShortcut ;
}
2020-06-01 10:25:52 +00:00
}
return null ;
2020-06-15 09:57:46 +00:00
2020-06-01 10:25:52 +00:00
}
2020-06-15 09:57:46 +00:00
public static bool RenameShortcutProfile ( ProfileItem newProfile )
2020-06-01 10:25:52 +00:00
{
2020-06-15 09:57:46 +00:00
if ( ! ( newProfile is ProfileItem ) )
return false ;
2020-06-01 10:25:52 +00:00
2020-06-15 09:57:46 +00:00
foreach ( ShortcutItem testShortcut in ShortcutRepository . AllShortcuts )
2020-06-01 10:25:52 +00:00
{
2020-12-26 08:46:32 +00:00
if ( testShortcut . ProfileUUID . Equals ( newProfile . UUID , StringComparison . OrdinalIgnoreCase ) & & testShortcut . AutoName )
2020-06-15 09:57:46 +00:00
{
testShortcut . ProfileToUse = newProfile ;
testShortcut . AutoSuggestShortcutName ( ) ;
}
2020-06-01 10:25:52 +00:00
}
2020-06-15 09:57:46 +00:00
SaveShortcuts ( ) ;
2020-06-01 10:25:52 +00:00
2020-06-15 09:57:46 +00:00
return true ;
2020-06-01 10:25:52 +00:00
}
private static bool LoadShortcuts ( )
{
if ( File . Exists ( _shortcutStorageJsonFileName ) )
{
var json = File . ReadAllText ( _shortcutStorageJsonFileName , Encoding . Unicode ) ;
if ( ! string . IsNullOrWhiteSpace ( json ) )
{
2020-06-07 08:48:45 +00:00
List < ShortcutItem > shortcuts = new List < ShortcutItem > ( ) ;
2020-06-01 10:25:52 +00:00
try
{
2020-06-07 08:48:45 +00:00
_allShortcuts = JsonConvert . DeserializeObject < List < ShortcutItem > > ( json , new JsonSerializerSettings
2020-06-01 10:25:52 +00:00
{
MissingMemberHandling = MissingMemberHandling . Ignore ,
NullValueHandling = NullValueHandling . Ignore ,
DefaultValueHandling = DefaultValueHandling . Include ,
TypeNameHandling = TypeNameHandling . Auto
} ) ;
}
catch ( Exception ex )
{
// ignored
Console . WriteLine ( $"Unable to load Shortcuts from JSON file {_shortcutStorageJsonFileName}: " + ex . Message ) ;
}
// Lookup all the Profile Names in the Saved Profiles
2020-06-07 08:48:45 +00:00
foreach ( ShortcutItem updatedShortcut in _allShortcuts )
2020-06-01 10:25:52 +00:00
{
2020-06-14 04:20:52 +00:00
foreach ( ProfileItem profile in ProfileRepository . AllProfiles )
2020-06-01 10:25:52 +00:00
{
2020-06-15 09:57:46 +00:00
if ( profile . Equals ( updatedShortcut . ProfileToUse ) )
2020-06-01 10:25:52 +00:00
{
// And assign the matching Profile if we find it.
updatedShortcut . ProfileToUse = profile ;
updatedShortcut . IsPossible = true ;
break ;
}
}
}
2020-10-26 01:30:00 +00:00
// Sort the shortcuts alphabetically
_allShortcuts . Sort ( ) ;
2020-06-01 10:25:52 +00:00
}
}
2020-08-07 03:59:23 +00:00
_shortcutsLoaded = true ;
2020-06-01 10:25:52 +00:00
return true ;
}
2020-10-20 08:22:07 +00:00
public static bool SaveShortcuts ( )
2020-06-01 10:25:52 +00:00
{
2020-08-18 22:16:04 +00:00
if ( ! Directory . Exists ( AppShortcutStoragePath ) )
2020-06-01 10:25:52 +00:00
{
try
{
2020-08-18 22:16:04 +00:00
Directory . CreateDirectory ( AppShortcutStoragePath ) ;
2020-06-01 10:25:52 +00:00
}
catch ( Exception ex )
{
2020-07-24 04:51:48 +00:00
Console . WriteLine ( $"ShortcutRepository/SaveShortcuts exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-07-15 08:11:38 +00:00
2020-08-18 22:16:04 +00:00
Console . WriteLine ( $"Unable to create Shortcut folder {AppShortcutStoragePath}: " + ex . Message ) ;
2020-06-01 10:25:52 +00:00
}
}
2020-10-18 10:04:08 +00:00
2020-06-01 10:25:52 +00:00
try
{
var json = JsonConvert . SerializeObject ( _allShortcuts , Formatting . Indented , new JsonSerializerSettings
{
NullValueHandling = NullValueHandling . Include ,
DefaultValueHandling = DefaultValueHandling . Populate ,
TypeNameHandling = TypeNameHandling . Auto
} ) ;
if ( ! string . IsNullOrWhiteSpace ( json ) )
{
File . WriteAllText ( _shortcutStorageJsonFileName , json , Encoding . Unicode ) ;
return true ;
}
}
catch ( Exception ex )
{
2020-07-24 04:51:48 +00:00
Console . WriteLine ( $"ShortcutRepository/SaveShortcuts exception 2: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-07-15 08:11:38 +00:00
2020-06-01 10:25:52 +00:00
Console . WriteLine ( $"Unable to save Shortcut JSON file {_shortcutStorageJsonFileName}: " + ex . Message ) ;
}
return false ;
}
2020-07-23 06:31:00 +00:00
// ReSharper disable once CyclomaticComplexity
2020-11-19 09:40:08 +00:00
public static void RunShortcut ( ShortcutItem shortcutToUse , NotifyIcon notifyIcon = null )
2020-07-23 06:31:00 +00:00
{
// Do some validation to make sure the shortcut is sensible
// And that we have enough to try and action within the shortcut
2020-07-23 23:06:33 +00:00
// including checking the Profile in the shortcut is possible
2020-07-23 06:31:00 +00:00
// (in other words check everything in the shortcut is still valid)
2020-07-23 23:06:33 +00:00
if ( ! ( shortcutToUse is ShortcutItem ) )
return ;
2020-07-23 06:31:00 +00:00
( bool valid , string reason ) = shortcutToUse . IsValid ( ) ;
if ( ! valid )
{
2020-12-09 07:47:30 +00:00
logger . Error ( $"ShortcutRepository/RunShortcut error. shortcutToUse isn't valid" ) ;
2020-12-05 04:41:15 +00:00
MessageBox . Show (
$"Unable to run the shortcut '{shortcutToUse.Name}': {reason}" ,
@"Cannot run the Shortcut" ,
MessageBoxButtons . OK ,
MessageBoxIcon . Exclamation ) ;
return ;
//throw new Exception(string.Format("ShortcutRepository/SaveShortcutIconToCache exception: Unable to run the shortcut '{0}': {1}", shortcutToUse.Name, reason));
2020-07-23 06:31:00 +00:00
}
// Remember the profile we are on now
2020-10-11 08:12:52 +00:00
bool needToChangeProfiles = false ;
2020-07-23 06:31:00 +00:00
ProfileItem rollbackProfile = ProfileRepository . CurrentProfile ;
2020-10-11 08:12:52 +00:00
if ( ! rollbackProfile . Equals ( shortcutToUse . ProfileToUse ) )
needToChangeProfiles = true ;
2020-07-23 06:31:00 +00:00
2020-10-02 05:10:34 +00:00
// Tell the IPC Service we are busy right now, and keep the previous status for later
InstanceStatus rollbackInstanceStatus = IPCService . GetInstance ( ) . Status ;
IPCService . GetInstance ( ) . Status = InstanceStatus . Busy ;
2020-10-11 08:12:52 +00:00
// Only change profiles if we have to
if ( needToChangeProfiles )
2020-07-23 06:31:00 +00:00
{
2020-10-11 08:12:52 +00:00
// Apply the Profile!
2020-10-22 08:46:36 +00:00
Console . WriteLine ( $"Changing to '{shortcutToUse.ProfileToUse.Name}' Display Profile" ) ;
2020-10-11 08:12:52 +00:00
if ( ! Program . ApplyProfile ( shortcutToUse . ProfileToUse ) )
{
2020-10-22 08:46:36 +00:00
Console . WriteLine ( $"ERROR - Cannot apply '{shortcutToUse.ProfileToUse.Name}' Display Profile" ) ;
2020-12-09 07:47:30 +00:00
logger . Error ( $"ShortcutRepository/RunShortcut cannot apply '{shortcutToUse.ProfileToUse.Name}' Display Profile" ) ;
2020-10-11 08:12:52 +00:00
}
2020-07-23 06:31:00 +00:00
}
2020-12-03 10:10:25 +00:00
// record the old audio device
2020-12-07 08:11:51 +00:00
bool needToChangeAudio = false ;
2020-12-03 10:10:25 +00:00
CoreAudioDevice rollbackAudioDevice = _audioController . DefaultPlaybackDevice ;
2020-12-05 04:41:15 +00:00
double rollbackAudioVolume = _audioController . DefaultPlaybackDevice . Volume ;
2020-12-07 08:11:51 +00:00
if ( ! rollbackAudioDevice . FullName . Equals ( shortcutToUse . AudioDevice ) )
needToChangeAudio = true ;
2020-12-03 10:10:25 +00:00
// Change Audio Device (if one specified)
if ( shortcutToUse . ChangeAudioDevice )
{
IEnumerable < CoreAudioDevice > audioDevices = _audioController . GetPlaybackDevices ( ) ;
foreach ( CoreAudioDevice audioDevice in audioDevices )
{
if ( audioDevice . FullName . Equals ( shortcutToUse . AudioDevice ) )
{
// use the Audio Device
audioDevice . SetAsDefault ( ) ;
2020-12-05 04:41:15 +00:00
if ( shortcutToUse . SetAudioVolume )
{
Task myTask = new Task ( ( ) = >
{
audioDevice . SetVolumeAsync ( Convert . ToDouble ( shortcutToUse . AudioVolume ) ) ;
} ) ;
myTask . Start ( ) ;
myTask . Wait ( 2000 ) ;
}
2020-12-03 10:10:25 +00:00
}
}
}
2020-12-12 08:29:38 +00:00
// record the old microphone device
bool needToChangeCaptureDevice = false ;
CoreAudioDevice rollbackCaptureDevice = _audioController . DefaultCaptureDevice ;
double rollbackCaptureVolume = _audioController . DefaultCaptureDevice . Volume ;
if ( ! rollbackCaptureDevice . FullName . Equals ( shortcutToUse . CaptureDevice ) )
needToChangeCaptureDevice = true ;
// Change capture Device (if one specified)
if ( shortcutToUse . ChangeCaptureDevice )
{
IEnumerable < CoreAudioDevice > captureDevices = _audioController . GetCaptureDevices ( ) ;
foreach ( CoreAudioDevice captureDevice in captureDevices )
{
if ( captureDevice . FullName . Equals ( shortcutToUse . CaptureDevice ) )
{
// use the Audio Device
captureDevice . SetAsDefault ( ) ;
if ( shortcutToUse . SetCaptureVolume )
{
Task myTask = new Task ( ( ) = >
{
captureDevice . SetVolumeAsync ( Convert . ToDouble ( shortcutToUse . CaptureVolume ) ) ;
} ) ;
myTask . Start ( ) ;
myTask . Wait ( 2000 ) ;
}
}
}
}
2020-10-02 05:10:34 +00:00
// Set the IP Service status back to what it was
IPCService . GetInstance ( ) . Status = rollbackInstanceStatus ;
2020-07-23 06:31:00 +00:00
// Now run the pre-start applications
2020-10-11 08:12:52 +00:00
List < Process > startProgramsToStop = new List < Process > ( ) ;
2020-11-04 05:47:41 +00:00
List < StartProgram > startProgramsToStart = shortcutToUse . StartPrograms . Where ( program = > program . Enabled = = true ) . OrderBy ( program = > program . Priority ) . ToList ( ) ;
if ( startProgramsToStart . Count > 0 )
2020-10-11 08:12:52 +00:00
{
2020-11-04 05:47:41 +00:00
foreach ( StartProgram processToStart in startProgramsToStart )
2020-10-11 08:12:52 +00:00
{
// Start the executable
2020-11-04 05:47:41 +00:00
Console . WriteLine ( "Starting programs before main game/executable:" ) ;
2020-10-22 08:46:36 +00:00
Console . WriteLine ( $" - Starting process {processToStart.Executable}" ) ;
2020-10-11 08:12:52 +00:00
Process process = null ;
2020-10-13 07:22:42 +00:00
if ( processToStart . ExecutableArgumentsRequired )
process = System . Diagnostics . Process . Start ( processToStart . Executable , processToStart . Arguments ) ;
2020-10-11 08:12:52 +00:00
else
2020-10-13 07:22:42 +00:00
process = System . Diagnostics . Process . Start ( processToStart . Executable ) ;
2020-10-11 08:12:52 +00:00
// Record t
2020-10-13 09:02:46 +00:00
if ( processToStart . CloseOnFinish )
startProgramsToStop . Add ( process ) ;
2020-10-11 08:12:52 +00:00
}
}
2020-07-23 06:31:00 +00:00
2020-11-19 09:40:08 +00:00
// Add a status notification icon in the status area
// but only if we are going to wait for a process to finish
string oldNotifyText = "" ;
bool temporaryNotifyIcon = false ;
ContextMenuStrip oldContextMenuStrip = null ;
// If we're running the shortcut from the ShortcutLibrary
// then we get given the NotifyIcon through the function
// parameters i.e. if temporaryIcon is false in that case.
// This means we need to save the state if the temporaryIcon
// is false.
// Conversely, if temporaryIcon is true, then we need
2020-12-09 07:47:30 +00:00
// to create a NotifyIncon as MainForm isn't running to create
2020-11-19 09:40:08 +00:00
// one for us already!
if ( notifyIcon = = null )
temporaryNotifyIcon = true ;
if ( temporaryNotifyIcon )
{
if ( ! shortcutToUse . Category . Equals ( ShortcutCategory . NoGame ) )
{
try
{
notifyIcon = new NotifyIcon
{
2020-12-02 08:11:23 +00:00
Icon = Properties . Resources . DisplayMagician ,
2020-11-19 09:40:08 +00:00
Visible = true
} ;
Application . DoEvents ( ) ;
}
catch ( Exception ex )
{
Console . WriteLine ( $"ShortcutRepository/RunShortcut exception: Trying to {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-12-09 07:47:30 +00:00
logger . Error ( ex , $"ShortcutRepository/RunShortcut exception setting NotifyIcon" ) ;
2020-11-19 09:40:08 +00:00
// ignored
}
}
}
else
{
// If we reach here then we're running the shortcut
// from the ShortcutLibrary window, so we need to
// remember what the text was so we can return it to
// normal after we're done!
oldNotifyText = notifyIcon . Text ;
oldContextMenuStrip = notifyIcon . ContextMenuStrip ;
notifyIcon . ContextMenuStrip = null ;
Application . DoEvents ( ) ;
}
2020-12-26 03:59:45 +00:00
2020-07-23 06:31:00 +00:00
// Now start the main game, and wait if we have to
if ( shortcutToUse . Category . Equals ( ShortcutCategory . Application ) )
{
// Start the executable
Process process = null ;
if ( shortcutToUse . ExecutableArgumentsRequired )
process = System . Diagnostics . Process . Start ( shortcutToUse . ExecutableNameAndPath , shortcutToUse . ExecutableArguments ) ;
else
process = System . Diagnostics . Process . Start ( shortcutToUse . ExecutableNameAndPath ) ;
2020-12-11 05:07:17 +00:00
// Figure out what we want to look for
string processNameToLookFor ;
2020-07-23 06:31:00 +00:00
if ( shortcutToUse . ProcessNameToMonitorUsesExecutable )
{
2020-12-11 05:07:17 +00:00
// If we are monitoring the same executable we started, then lets do get that name ready
processNameToLookFor = System . IO . Path . GetFileNameWithoutExtension ( shortcutToUse . ExecutableNameAndPath ) ;
2020-07-23 06:31:00 +00:00
}
else
{
2020-12-11 05:07:17 +00:00
// If we are monitoring a different executable, then lets do get that name ready instead
processNameToLookFor = System . IO . Path . GetFileNameWithoutExtension ( shortcutToUse . DifferentExecutableToMonitor ) ;
}
2020-07-23 06:31:00 +00:00
2020-12-11 05:07:17 +00:00
// Now look for the thing we're supposed to monitor
// and wait until it starts up
List < Process > processesToMonitor = new List < Process > ( ) ;
for ( int secs = 0 ; secs > = ( shortcutToUse . StartTimeout * 1000 ) ; secs + = 500 )
{
// Look for the processes with the ProcessName we sorted out earlier
processesToMonitor = Process . GetProcessesByName ( processNameToLookFor ) . ToList ( ) ;
2020-07-23 06:31:00 +00:00
2020-12-11 05:07:17 +00:00
// If we have found one or more processes then we should be good to go
// so let's break
if ( processesToMonitor . Count > 0 )
2020-07-23 06:31:00 +00:00
{
2020-12-11 08:40:45 +00:00
logger . Debug ( $"Found {processesToMonitor.Count} '{processNameToLookFor}' processes have started" ) ;
2020-12-11 05:07:17 +00:00
break ;
2020-07-23 06:31:00 +00:00
}
2020-12-11 05:07:17 +00:00
// Let's wait a little while if we couldn't find
// any processes yet
Thread . Sleep ( 500 ) ;
}
// make sure we have things to monitor and alert if not
if ( processesToMonitor . Count = = 0 )
{
2020-12-11 08:40:45 +00:00
logger . Error ( $"No '{processNameToLookFor}' processes found before waiting timeout" ) ;
2020-07-23 06:31:00 +00:00
}
// Store the process to monitor for later
IPCService . GetInstance ( ) . HoldProcessId = processesToMonitor . FirstOrDefault ( ) ? . Id ? ? 0 ;
IPCService . GetInstance ( ) . Status = InstanceStatus . OnHold ;
2020-12-11 05:07:17 +00:00
// Add a status notification icon in the status area
string notificationText = $"DisplayMagician: Running {shortcutToUse.ExecutableNameAndPath}..." ;
if ( notificationText . Length > = 64 )
{
string thingToRun = shortcutToUse . ExecutableNameAndPath . Substring ( 0 , 35 ) ;
notifyIcon . Text = $"DisplayMagician: Running {thingToRun}..." ;
}
Application . DoEvents ( ) ;
2020-12-26 03:59:45 +00:00
// Now we want to tell the user we're running an application!
// Construct the Windows toast content
ToastContentBuilder tcBuilder = new ToastContentBuilder ( )
. AddToastActivationInfo ( "notify=runningApplication" , ToastActivationType . Foreground )
2020-12-28 08:34:59 +00:00
. AddText ( $"Running {processNameToLookFor}" , hintMaxLines : 1 )
2020-12-26 03:59:45 +00:00
. AddText ( $"Waiting for all {processNameToLookFor} windows to exit..." ) ;
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
ToastContent toastContent = tcBuilder . Content ;
// Make sure to use Windows.Data.Xml.Dom
var doc = new XmlDocument ( ) ;
doc . LoadXml ( toastContent . GetContent ( ) ) ;
// And create the toast notification
var toast = new ToastNotification ( doc ) ;
// Remove any other Notifications from us
DesktopNotifications . DesktopNotificationManagerCompat . History . Clear ( ) ;
// And then show this notification
DesktopNotifications . DesktopNotificationManagerCompat . CreateToastNotifier ( ) . Show ( toast ) ;
2020-12-11 05:07:17 +00:00
// Wait an extra few seconds to give the application time to settle down
Thread . Sleep ( 2000 ) ;
2020-07-23 06:31:00 +00:00
2020-12-11 05:07:17 +00:00
// if we have things to monitor, then we should start to wait for them
2020-12-26 03:59:45 +00:00
Console . WriteLine ( $"Waiting for all {processNameToLookFor} windows to exit." ) ;
2020-12-11 08:40:45 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut - waiting for application {processNameToLookFor} to exit." ) ;
2020-12-11 05:07:17 +00:00
if ( processesToMonitor . Count > 0 )
2020-07-23 06:31:00 +00:00
{
2020-12-11 08:40:45 +00:00
logger . Debug ( $"{processesToMonitor.Count} '{processNameToLookFor}' processes are still running" ) ;
2020-12-11 05:07:17 +00:00
while ( true )
2020-07-23 06:31:00 +00:00
{
2020-12-11 05:07:17 +00:00
processesToMonitor = Process . GetProcessesByName ( processNameToLookFor ) . ToList ( ) ;
// If we have no more processes left then we're done!
if ( processesToMonitor . Count = = 0 )
2020-11-21 20:26:17 +00:00
{
2020-12-11 08:40:45 +00:00
logger . Debug ( $"No more '{processNameToLookFor}' processes are still running" ) ;
2020-12-11 05:07:17 +00:00
break ;
2020-11-21 20:26:17 +00:00
}
2020-07-23 06:31:00 +00:00
}
}
2020-12-11 05:07:17 +00:00
Console . WriteLine ( $"{processNameToLookFor} has exited." ) ;
2020-12-11 08:40:45 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut - Application {processNameToLookFor} has exited." ) ;
2020-12-11 05:07:17 +00:00
2020-12-28 08:34:59 +00:00
// Tell the user that the application has closed
// Construct the toast content
tcBuilder = new ToastContentBuilder ( )
. AddToastActivationInfo ( "notify=stopDetected" , ToastActivationType . Foreground )
. AddText ( $"{processNameToLookFor} was closed" , hintMaxLines : 1 )
. AddText ( $"All {processNameToLookFor} processes were shutdown and changes were reverted." ) ;
toastContent = tcBuilder . Content ;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument ( ) ;
doc . LoadXml ( toastContent . GetContent ( ) ) ;
// And create the toast notification
toast = new ToastNotification ( doc ) ;
// Remove any other Notifications from us
DesktopNotifications . DesktopNotificationManagerCompat . History . Clear ( ) ;
// And then show it
DesktopNotifications . DesktopNotificationManagerCompat . CreateToastNotifier ( ) . Show ( toast ) ;
2020-07-23 06:31:00 +00:00
}
else if ( shortcutToUse . Category . Equals ( ShortcutCategory . Game ) )
{
// If the game is a Steam Game we check for that
if ( shortcutToUse . GameLibrary . Equals ( SupportedGameLibrary . Steam ) )
{
2020-11-15 07:28:55 +00:00
2020-07-23 06:31:00 +00:00
// We now need to get the SteamGame info
SteamGame steamGameToRun = SteamLibrary . GetSteamGame ( shortcutToUse . GameAppId ) ;
// If the GameAppID matches a Steam game, then lets run it
if ( steamGameToRun is SteamGame )
{
// Prepare to start the steam game using the URI interface
// as used by Steam for it's own desktop shortcuts.
2020-10-18 08:17:21 +00:00
var address = $"steam://rungameid/{steamGameToRun.Id}" ;
2020-07-23 06:31:00 +00:00
if ( shortcutToUse . GameArgumentsRequired )
{
address + = "/" + shortcutToUse . GameArguments ;
}
2020-12-09 07:47:30 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut Steam launch address is {address}" ) ;
2020-07-23 06:31:00 +00:00
// Start the URI Handler to run Steam
2020-10-22 08:46:36 +00:00
Console . WriteLine ( $"Starting Steam Game: {steamGameToRun.Name}" ) ;
2020-10-13 09:02:46 +00:00
var steamProcess = Process . Start ( address ) ;
2020-07-23 06:31:00 +00:00
// Wait for Steam game to update if needed
2020-12-11 05:07:17 +00:00
for ( int secs = 0 ; secs > = ( shortcutToUse . StartTimeout * 1000 ) ; secs + = 500 )
2020-07-23 06:31:00 +00:00
{
if ( ! steamGameToRun . IsUpdating )
{
2020-12-11 05:07:17 +00:00
if ( steamGameToRun . IsRunning )
{
logger . Info ( $"Found the '{steamGameToRun.Name}' process has started" ) ;
break ;
}
2020-07-23 06:31:00 +00:00
}
2020-12-11 05:07:17 +00:00
// Delay 500ms
Thread . Sleep ( 500 ) ;
2020-07-23 06:31:00 +00:00
}
// Store the Steam Process ID for later
IPCService . GetInstance ( ) . HoldProcessId = steamProcess ? . Id ? ? 0 ;
IPCService . GetInstance ( ) . Status = InstanceStatus . OnHold ;
2020-11-19 09:40:08 +00:00
// Add a status notification icon in the status area
2020-12-03 10:10:25 +00:00
if ( steamGameToRun . Name . Length < = 41 )
notifyIcon . Text = $"DisplayMagician: Running {steamGameToRun.Name}..." ;
else
notifyIcon . Text = $"DisplayMagician: Running {steamGameToRun.Name.Substring(0, 41)}..." ;
2020-11-19 09:40:08 +00:00
Application . DoEvents ( ) ;
2020-11-15 07:28:55 +00:00
2020-12-26 03:59:45 +00:00
// Now we want to tell the user we're running a game!
// Construct the Windows toast content
ToastContentBuilder tcBuilder = new ToastContentBuilder ( )
. AddToastActivationInfo ( "notify=runningSteamGame" , ToastActivationType . Foreground )
2020-12-28 08:34:59 +00:00
. AddText ( $"Running {shortcutToUse.GameName}" , hintMaxLines : 1 )
2020-12-26 03:59:45 +00:00
. AddText ( $"Waiting for the Steam Game {shortcutToUse.GameName} to exit..." ) ;
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
ToastContent toastContent = tcBuilder . Content ;
// Make sure to use Windows.Data.Xml.Dom
var doc = new XmlDocument ( ) ;
doc . LoadXml ( toastContent . GetContent ( ) ) ;
// And create the toast notification
var toast = new ToastNotification ( doc ) ;
// Remove any other Notifications from us
DesktopNotifications . DesktopNotificationManagerCompat . History . Clear ( ) ;
// And then show this notification
DesktopNotifications . DesktopNotificationManagerCompat . CreateToastNotifier ( ) . Show ( toast ) ;
2020-12-10 22:43:51 +00:00
// Wait 5 seconds for the game process to spawn
Thread . Sleep ( 5000 ) ;
2020-12-09 07:47:30 +00:00
// Wait for the game to exit
Console . WriteLine ( $"Waiting for {steamGameToRun.Name} to exit." ) ;
2020-12-11 08:40:45 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut - waiting for Steam Game {steamGameToRun.Name} to exit." ) ;
2020-12-09 07:47:30 +00:00
while ( true )
2020-07-23 06:31:00 +00:00
{
2020-12-09 07:47:30 +00:00
if ( ! steamGameToRun . IsRunning )
2020-07-23 06:31:00 +00:00
{
2020-12-11 08:40:45 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut - Steam Game {steamGameToRun.Name} is no longer running (IsRunning is false)." ) ;
2020-12-09 07:47:30 +00:00
break ;
2020-07-23 06:31:00 +00:00
}
2020-12-09 07:47:30 +00:00
Thread . Sleep ( 300 ) ;
2020-07-23 06:31:00 +00:00
}
2020-12-09 07:47:30 +00:00
Console . WriteLine ( $"{steamGameToRun.Name} has exited." ) ;
2020-12-11 08:40:45 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut - Steam Game {steamGameToRun.Name} has exited." ) ;
2020-07-23 06:31:00 +00:00
2020-12-28 08:34:59 +00:00
// Tell the user that the Steam Game has closed
// Construct the toast content
tcBuilder = new ToastContentBuilder ( )
. AddToastActivationInfo ( "notify=stopDetected" , ToastActivationType . Foreground )
. AddText ( $"{shortcutToUse.GameName} was closed" , hintMaxLines : 1 )
. AddText ( $"{shortcutToUse.GameName} game was shutdown and changes were reverted." ) ;
toastContent = tcBuilder . Content ;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument ( ) ;
doc . LoadXml ( toastContent . GetContent ( ) ) ;
// And create the toast notification
toast = new ToastNotification ( doc ) ;
// Remove any other Notifications from us
DesktopNotifications . DesktopNotificationManagerCompat . History . Clear ( ) ;
// And then show it
DesktopNotifications . DesktopNotificationManagerCompat . CreateToastNotifier ( ) . Show ( toast ) ;
2020-07-23 06:31:00 +00:00
}
}
// If the game is a Uplay Game we check for that
2020-11-15 07:28:55 +00:00
else if ( shortcutToUse . GameLibrary . Equals ( SupportedGameLibrary . Uplay ) )
2020-07-23 06:31:00 +00:00
{
2020-12-10 22:43:51 +00:00
// We now need to get the Uplay Game info
2020-11-15 07:28:55 +00:00
UplayGame uplayGameToRun = UplayLibrary . GetUplayGame ( shortcutToUse . GameAppId ) ;
2020-12-10 22:43:51 +00:00
// If the GameAppID matches a Uplay game, then lets run it
2020-11-15 07:28:55 +00:00
if ( uplayGameToRun is UplayGame )
2020-07-23 06:31:00 +00:00
{
2020-12-10 22:43:51 +00:00
// Prepare to start the Uplay game using the URI interface
// as used by Uplay for it's own desktop shortcuts.
2020-11-15 07:28:55 +00:00
var address = $"uplay://launch/{uplayGameToRun.Id}" ;
2020-12-09 07:47:30 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut Uplay launch address is {address}" ) ;
2020-11-15 07:28:55 +00:00
if ( shortcutToUse . GameArgumentsRequired )
{
address + = "/" + shortcutToUse . GameArguments ;
}
else
{
address + = "/0" ;
}
2020-12-28 08:34:59 +00:00
// Now we want to tell the user we're starting upc.exe
// Construct the Windows toast content
ToastContentBuilder tcBuilder = new ToastContentBuilder ( )
. AddToastActivationInfo ( "notify=startingUplay" , ToastActivationType . Foreground )
. AddText ( $"Starting Uplay" , hintMaxLines : 1 )
. AddText ( $"Waiting for Uplay to start (and update if needed)..." ) ;
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
ToastContent toastContent = tcBuilder . Content ;
// Make sure to use Windows.Data.Xml.Dom
var doc = new XmlDocument ( ) ;
doc . LoadXml ( toastContent . GetContent ( ) ) ;
// And create the toast notification
var toast = new ToastNotification ( doc ) ;
// Remove any other Notifications from us
DesktopNotifications . DesktopNotificationManagerCompat . History . Clear ( ) ;
// And then show this notification
DesktopNotifications . DesktopNotificationManagerCompat . CreateToastNotifier ( ) . Show ( toast ) ;
2020-11-15 07:28:55 +00:00
// Start the URI Handler to run Uplay
2020-11-15 08:06:38 +00:00
Console . WriteLine ( $"Starting Uplay Game: {uplayGameToRun.Name}" ) ;
2020-12-28 08:34:59 +00:00
Process uplayStartProcess = Process . Start ( address ) ;
2020-11-15 07:28:55 +00:00
2020-12-28 08:34:59 +00:00
// Wait for Uplay to start
List < Process > uplayProcesses = null ;
for ( int secs = 0 ; secs > = ( shortcutToUse . StartTimeout * 1000 ) ; secs + = 500 )
{
// Look for the processes with the ProcessName we sorted out earlier
uplayProcesses = Process . GetProcessesByName ( "upc" ) . ToList ( ) ;
// If we have found one or more processes then we should be good to go
// so let's break
if ( uplayProcesses . Count > 0 )
{
logger . Debug ( $"Found {uplayProcesses.Count} 'upc' processes have started" ) ;
break ;
}
// Let's wait a little while if we couldn't find
// any processes yet
Thread . Sleep ( 500 ) ;
}
// Delay 5secs
Thread . Sleep ( 5000 ) ;
// Now we know the Uplay app is running then
// we wait until the Uplay game is running (*allows for uplay update)
2020-12-11 05:07:17 +00:00
for ( int secs = 0 ; secs > = ( shortcutToUse . StartTimeout * 1000 ) ; secs + = 500 )
2020-11-15 07:28:55 +00:00
{
2020-12-11 05:07:17 +00:00
2020-11-15 07:28:55 +00:00
if ( uplayGameToRun . IsRunning )
{
2020-12-11 08:40:45 +00:00
logger . Debug ( $"Found the '{uplayGameToRun.Name}' process has started" ) ;
2020-11-15 07:28:55 +00:00
break ;
}
2020-12-11 05:07:17 +00:00
// Delay 500ms
Thread . Sleep ( 500 ) ;
2020-11-15 07:28:55 +00:00
}
2020-12-10 22:43:51 +00:00
// Store the Uplay Process ID for later
2020-12-28 08:34:59 +00:00
IPCService . GetInstance ( ) . HoldProcessId = uplayStartProcess ? . Id ? ? 0 ;
2020-11-15 07:28:55 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . OnHold ;
2020-11-19 09:40:08 +00:00
// Add a status notification icon in the status area
2020-12-09 07:47:30 +00:00
if ( uplayGameToRun . Name . Length < = 41 )
notifyIcon . Text = $"DisplayMagician: Running {uplayGameToRun.Name}..." ;
else
notifyIcon . Text = $"DisplayMagician: Running {uplayGameToRun.Name.Substring(0, 41)}..." ;
2020-11-19 09:40:08 +00:00
Application . DoEvents ( ) ;
2020-11-15 07:28:55 +00:00
2020-12-26 03:59:45 +00:00
// Now we want to tell the user we're running a game!
// Construct the Windows toast content
2020-12-28 08:34:59 +00:00
tcBuilder = new ToastContentBuilder ( )
2020-12-26 03:59:45 +00:00
. AddToastActivationInfo ( "notify=runningUplayGame" , ToastActivationType . Foreground )
2020-12-28 08:34:59 +00:00
. AddText ( $"Running {shortcutToUse.GameName}" , hintMaxLines : 1 )
2020-12-26 03:59:45 +00:00
. AddText ( $"Waiting for the Uplay Game {shortcutToUse.GameName} to exit..." ) ;
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
2020-12-28 08:34:59 +00:00
toastContent = tcBuilder . Content ;
2020-12-26 03:59:45 +00:00
// Make sure to use Windows.Data.Xml.Dom
2020-12-28 08:34:59 +00:00
doc = new XmlDocument ( ) ;
2020-12-26 03:59:45 +00:00
doc . LoadXml ( toastContent . GetContent ( ) ) ;
// And create the toast notification
2020-12-28 08:34:59 +00:00
toast = new ToastNotification ( doc ) ;
2020-12-26 03:59:45 +00:00
// Remove any other Notifications from us
DesktopNotifications . DesktopNotificationManagerCompat . History . Clear ( ) ;
// And then show this notification
DesktopNotifications . DesktopNotificationManagerCompat . CreateToastNotifier ( ) . Show ( toast ) ;
2020-12-10 22:43:51 +00:00
// Wait 5 seconds for the game process to spawn
Thread . Sleep ( 5000 ) ;
2020-12-11 05:07:17 +00:00
2020-12-09 07:47:30 +00:00
// Wait for the game to exit
Console . WriteLine ( $"Waiting for {uplayGameToRun.Name} to exit." ) ;
2020-12-11 08:40:45 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut - waiting for Uplay Game {uplayGameToRun.Name} to exit." ) ;
2020-12-09 07:47:30 +00:00
while ( true )
2020-11-15 07:28:55 +00:00
{
2020-12-09 07:47:30 +00:00
if ( ! uplayGameToRun . IsRunning )
2020-11-15 07:28:55 +00:00
{
2020-12-11 08:40:45 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut - Uplay Game {uplayGameToRun.Name} is no longer running (IsRunning is false)." ) ;
2020-12-09 07:47:30 +00:00
break ;
2020-11-15 07:28:55 +00:00
}
2020-12-09 07:47:30 +00:00
Thread . Sleep ( 300 ) ;
}
Console . WriteLine ( $"{uplayGameToRun.Name} has exited." ) ;
2020-12-11 08:40:45 +00:00
logger . Debug ( $"ShortcutRepository/RunShortcut - Uplay Game {uplayGameToRun.Name} has exited." ) ;
2020-12-28 08:34:59 +00:00
// Tell the user that the Uplay Game has closed
// Construct the toast content
tcBuilder = new ToastContentBuilder ( )
. AddToastActivationInfo ( "notify=stopDetected" , ToastActivationType . Foreground )
. AddText ( $"{shortcutToUse.GameName} was closed" , hintMaxLines : 1 )
. AddText ( $"{shortcutToUse.GameName} game was shutdown and changes were reverted." ) ;
toastContent = tcBuilder . Content ;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument ( ) ;
doc . LoadXml ( toastContent . GetContent ( ) ) ;
// And create the toast notification
toast = new ToastNotification ( doc ) ;
// Remove any other Notifications from us
DesktopNotifications . DesktopNotificationManagerCompat . History . Clear ( ) ;
// And then show it
DesktopNotifications . DesktopNotificationManagerCompat . CreateToastNotifier ( ) . Show ( toast ) ;
2020-11-15 07:28:55 +00:00
}
2020-07-23 06:31:00 +00:00
2020-11-15 07:28:55 +00:00
}
2020-07-23 06:31:00 +00:00
}
2020-11-19 09:40:08 +00:00
// Remove the status notification icon from the status area
// once we've exited the game, but only if its a game or app
if ( temporaryNotifyIcon )
{
if ( ! shortcutToUse . Category . Equals ( ShortcutCategory . NoGame ) )
{
if ( notifyIcon ! = null )
{
notifyIcon . Visible = false ;
notifyIcon . Dispose ( ) ;
Application . DoEvents ( ) ;
}
}
}
else
{
// If we're running the shortcut from the ShortcutLibrary
// then we want to reset the NotifyIcon back
notifyIcon . Text = oldNotifyText ;
notifyIcon . ContextMenuStrip = oldContextMenuStrip ;
Application . DoEvents ( ) ;
}
2020-12-26 03:59:45 +00:00
// Only replace the notification if we're minimised
if ( Program . AppProgramSettings . MinimiseOnStart )
2020-12-28 08:34:59 +00:00
{
2020-12-26 03:59:45 +00:00
// Remind the user that DisplayMagician is running the in background
// Construct the toast content
ToastContentBuilder tcBuilder = new ToastContentBuilder ( )
. AddToastActivationInfo ( "notify=minimiseStart&action=open" , ToastActivationType . Foreground )
. AddText ( "DisplayMagician is minimised" , hintMaxLines : 1 )
. AddButton ( "Open" , ToastActivationType . Background , "notify=minimiseStart&action=open" ) ;
ToastContent toastContent = tcBuilder . Content ;
// Make sure to use Windows.Data.Xml.Dom
var doc = new XmlDocument ( ) ;
doc . LoadXml ( toastContent . GetContent ( ) ) ;
// And create the toast notification
var toast = new ToastNotification ( doc ) ;
toast . SuppressPopup = true ;
// And then show it
DesktopNotifications . DesktopNotificationManagerCompat . CreateToastNotifier ( ) . Show ( toast ) ;
}
2020-10-11 08:12:52 +00:00
// Stop the pre-started startPrograms that we'd started earlier
if ( startProgramsToStop . Count > 0 )
{
// Stop the programs in the reverse order we started them
foreach ( Process processToStop in startProgramsToStop . Reverse < Process > ( ) )
{
2020-10-13 07:22:42 +00:00
Console . WriteLine ( $"Stopping process {processToStop.StartInfo.FileName}" ) ;
2020-10-13 09:02:46 +00:00
try
{
// Stop the program
processToStop . CloseMainWindow ( ) ;
processToStop . WaitForExit ( 5000 ) ;
if ( ! processToStop . HasExited )
{
Console . WriteLine ( $"- Process {processToStop.StartInfo.FileName} wouldn't stop cleanly. Forcing program close." ) ;
processToStop . Kill ( ) ;
processToStop . WaitForExit ( 5000 ) ;
}
processToStop . Close ( ) ;
}
2020-12-11 08:40:45 +00:00
catch ( Win32Exception ex ) {
logger . Error ( ex , $"RunShortcut - Couldn't access the wait status for a process we're trying to stop." ) ;
}
catch ( InvalidOperationException ex ) {
logger . Error ( ex , $"RunShortcut - Couldn't kill the process as there is no process associated with the Process object." ) ;
}
catch ( SystemException ex )
{
logger . Error ( ex , $"RunShortcut - Couldn't WaitForExit the process as there is no process associated with the Process object (or cannot get the ID from the process handle)." ) ;
}
catch ( AggregateException ae ) {
logger . Error ( ae , $"RunShortcut - Got an AggregateException." ) ;
}
2020-10-13 09:02:46 +00:00
2020-10-11 08:12:52 +00:00
}
}
2020-12-03 10:10:25 +00:00
// Change Audio Device back (if one specified)
2020-12-07 08:11:51 +00:00
if ( needToChangeAudio )
2020-12-03 10:10:25 +00:00
{
// use the Audio Device
rollbackAudioDevice . SetAsDefault ( ) ;
2020-12-05 04:41:15 +00:00
if ( shortcutToUse . SetAudioVolume )
{
Task myTask = new Task ( ( ) = >
{
rollbackAudioDevice . SetVolumeAsync ( Convert . ToDouble ( rollbackAudioVolume ) ) ;
} ) ;
myTask . Start ( ) ;
myTask . Wait ( 2000 ) ;
}
2020-12-03 10:10:25 +00:00
}
2020-12-12 08:29:38 +00:00
// Change Capture Device back (if one specified)
if ( needToChangeCaptureDevice )
{
// use the Audio Device
rollbackCaptureDevice . SetAsDefault ( ) ;
if ( shortcutToUse . SetCaptureVolume )
{
Task myTask = new Task ( ( ) = >
{
rollbackCaptureDevice . SetVolumeAsync ( Convert . ToDouble ( rollbackCaptureVolume ) ) ;
} ) ;
myTask . Start ( ) ;
myTask . Wait ( 2000 ) ;
}
}
2020-12-03 10:10:25 +00:00
2020-10-11 08:12:52 +00:00
// Change back to the original profile only if it is different
if ( needToChangeProfiles )
2020-07-23 06:31:00 +00:00
{
2020-10-04 10:01:03 +00:00
//if (!ProfileRepository.ApplyProfile(rollbackProfile))
if ( ! Program . ApplyProfile ( rollbackProfile ) )
2020-07-23 06:31:00 +00:00
{
2020-10-22 08:46:36 +00:00
Console . WriteLine ( $"ERROR - Cannot revert back to '{rollbackProfile.Name}' Display Profile" ) ;
2020-07-23 06:31:00 +00:00
}
}
}
2020-06-01 10:25:52 +00:00
#endregion
}
[global::System.Serializable]
public class ShortcutRepositoryException : Exception
{
public ShortcutRepositoryException ( ) { }
public ShortcutRepositoryException ( string message ) : base ( message ) { }
public ShortcutRepositoryException ( string message , Exception inner ) : base ( message , inner ) { }
protected ShortcutRepositoryException (
System . Runtime . Serialization . SerializationInfo info ,
System . Runtime . Serialization . StreamingContext context ) : base ( info , context ) { }
}
}