From 6bee5636708c6f56b5aabd50070168b7a08c588b Mon Sep 17 00:00:00 2001 From: Rafael Rivera Date: Mon, 13 Jul 2015 14:27:20 -0700 Subject: [PATCH 01/23] NoResize for tablet mode compat (fixes #11) --- EarTrumpet/MainWindow.xaml | 1 + 1 file changed, 1 insertion(+) diff --git a/EarTrumpet/MainWindow.xaml b/EarTrumpet/MainWindow.xaml index 3e7919fd6..f150721cb 100644 --- a/EarTrumpet/MainWindow.xaml +++ b/EarTrumpet/MainWindow.xaml @@ -13,6 +13,7 @@ PreviewKeyDown="Window_PreviewKeyDown" Foreground="{DynamicResource WindowForeground}" Background="{DynamicResource WindowBackground}" + ResizeMode="NoResize" x:Name="VolumeWindow"> Date: Fri, 17 Jul 2015 15:48:09 +1000 Subject: [PATCH 02/23] Fixes #6 --- EarTrumpet/MainWindow.xaml | 5 +---- EarTrumpet/ViewModels/AppItemViewModel.cs | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/EarTrumpet/MainWindow.xaml b/EarTrumpet/MainWindow.xaml index f150721cb..191e472ce 100644 --- a/EarTrumpet/MainWindow.xaml +++ b/EarTrumpet/MainWindow.xaml @@ -190,14 +190,11 @@ - - - - Date: Thu, 16 Jul 2015 23:44:07 -0700 Subject: [PATCH 03/23] Fix C6214, rein in OP tokens --- EarTrumpet.Interop/AudioSessionService.cpp | 18 +++++++++++++----- EarTrumpet.Interop/AudioSessionService.h | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/EarTrumpet.Interop/AudioSessionService.cpp b/EarTrumpet.Interop/AudioSessionService.cpp index 8f638387e..5a8da5d48 100644 --- a/EarTrumpet.Interop/AudioSessionService.cpp +++ b/EarTrumpet.Interop/AudioSessionService.cpp @@ -90,7 +90,8 @@ HRESULT AudioSessionService::CreateEtAudioSessionFromAudioSession(CComPtrQueryInterface(IID_PPV_ARGS(&simpleAudioVolume))); FAST_FAIL(simpleAudioVolume->GetMasterVolume(&etAudioSession->Volume)); - if (IsImmersiveProcess(pid)) + HRESULT hr = IsImmersiveProcess(pid); + if (hr == S_OK) { PWSTR appUserModelId; FAST_FAIL(GetAppUserModelIdFromPid(pid, &appUserModelId)); @@ -99,7 +100,7 @@ HRESULT AudioSessionService::CreateEtAudioSessionFromAudioSession(CComPtrIsDesktopApp = false; } - else + else if (hr == S_FALSE) { bool isSystemSoundsSession = (S_OK == audioSessionControl2->IsSystemSoundsSession()); @@ -163,12 +164,19 @@ HRESULT AudioSessionService::GetAudioSessions(void** audioSessions) return S_OK; } -BOOL AudioSessionService::IsImmersiveProcess(DWORD pid) +HRESULT AudioSessionService::IsImmersiveProcess(DWORD pid) { - shared_ptr processHandle(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), CloseHandle); + shared_ptr processHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid), CloseHandle); FAST_FAIL_HANDLE(processHandle.get()); - return ::IsImmersiveProcess(processHandle.get()); + if (::IsImmersiveProcess(processHandle.get())) + { + return S_OK; + } + else + { + return S_FALSE; + } } HRESULT AudioSessionService::GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr) diff --git a/EarTrumpet.Interop/AudioSessionService.h b/EarTrumpet.Interop/AudioSessionService.h index 94ca549c9..489a79736 100644 --- a/EarTrumpet.Interop/AudioSessionService.h +++ b/EarTrumpet.Interop/AudioSessionService.h @@ -25,7 +25,7 @@ namespace EarTrumpet HRESULT CreateEtAudioSessionFromAudioSession(CComPtr sessionEnumerator, int sessionCount, EarTrumpetAudioSession* etAudioSession); HRESULT GetAppProperties(PCWSTR pszAppId, PWSTR* ppszName, PWSTR* ppszIcon, ULONG *background); HRESULT GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr); - BOOL IsImmersiveProcess(DWORD pid); + HRESULT IsImmersiveProcess(DWORD pid); std::vector _sessions; std::map> _sessionMap; From 86a7ef73175292d4426f7a1a9d89759335ec6509 Mon Sep 17 00:00:00 2001 From: Rafael Rivera Date: Thu, 16 Jul 2015 23:51:08 -0700 Subject: [PATCH 04/23] Untabify --- EarTrumpet.Interop/AudioSessionService.cpp | 288 +++++++++--------- EarTrumpet.Interop/AudioSessionService.h | 74 ++--- EarTrumpet.Interop/exports.cpp | 8 +- .../Models/EarTrumpetAudioSessionModel.cs | 18 +- EarTrumpet/Services/AccentColorService.cs | 48 +-- .../Services/EarTrumpetAudioSessionService.cs | 70 ++--- .../Services/UserSystemPreferencesService.cs | 44 +-- 7 files changed, 275 insertions(+), 275 deletions(-) diff --git a/EarTrumpet.Interop/AudioSessionService.cpp b/EarTrumpet.Interop/AudioSessionService.cpp index 5a8da5d48..819dbe27f 100644 --- a/EarTrumpet.Interop/AudioSessionService.cpp +++ b/EarTrumpet.Interop/AudioSessionService.cpp @@ -16,103 +16,103 @@ AudioSessionService* AudioSessionService::__instance = nullptr; void AudioSessionService::CleanUpAudioSessions() { - for (auto session = _sessions.begin(); session != _sessions.end(); session++) - { - CoTaskMemFree(session->DisplayName); - CoTaskMemFree(session->IconPath); - } - - _sessions.clear(); - _sessionMap.clear(); + for (auto session = _sessions.begin(); session != _sessions.end(); session++) + { + CoTaskMemFree(session->DisplayName); + CoTaskMemFree(session->IconPath); + } + + _sessions.clear(); + _sessionMap.clear(); } int AudioSessionService::GetAudioSessionCount() { - return _sessions.size(); + return _sessions.size(); } HRESULT AudioSessionService::RefreshAudioSessions() { - CleanUpAudioSessions(); + CleanUpAudioSessions(); - CComPtr deviceEnumerator; - FAST_FAIL(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&deviceEnumerator))); + CComPtr deviceEnumerator; + FAST_FAIL(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&deviceEnumerator))); - // TIP: Role parameter is not actually used https://msdn.microsoft.com/en-us/library/windows/desktop/dd371401.aspx - CComPtr device; - FAST_FAIL(deviceEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eMultimedia, &device)); + // TIP: Role parameter is not actually used https://msdn.microsoft.com/en-us/library/windows/desktop/dd371401.aspx + CComPtr device; + FAST_FAIL(deviceEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eMultimedia, &device)); - CComPtr audioSessionManager; - FAST_FAIL(device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_INPROC, nullptr, (void**)&audioSessionManager)); + CComPtr audioSessionManager; + FAST_FAIL(device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_INPROC, nullptr, (void**)&audioSessionManager)); - CComPtr audioSessionEnumerator; - FAST_FAIL(audioSessionManager->GetSessionEnumerator(&audioSessionEnumerator)); + CComPtr audioSessionEnumerator; + FAST_FAIL(audioSessionManager->GetSessionEnumerator(&audioSessionEnumerator)); - int sessionCount; - FAST_FAIL(audioSessionEnumerator->GetCount(&sessionCount)); + int sessionCount; + FAST_FAIL(audioSessionEnumerator->GetCount(&sessionCount)); - for (int i = 0; i < sessionCount; i++) - { - EarTrumpetAudioSession audioSession; - if (SUCCEEDED(CreateEtAudioSessionFromAudioSession(audioSessionEnumerator, i, &audioSession))) - { - _sessions.push_back(audioSession); - } - } + for (int i = 0; i < sessionCount; i++) + { + EarTrumpetAudioSession audioSession; + if (SUCCEEDED(CreateEtAudioSessionFromAudioSession(audioSessionEnumerator, i, &audioSession))) + { + _sessions.push_back(audioSession); + } + } - return S_OK; + return S_OK; } HRESULT AudioSessionService::CreateEtAudioSessionFromAudioSession(CComPtr audioSessionEnumerator, int sessionCount, EarTrumpetAudioSession* etAudioSession) { - CComPtr audioSessionControl; - FAST_FAIL(audioSessionEnumerator->GetSession(sessionCount, &audioSessionControl)); + CComPtr audioSessionControl; + FAST_FAIL(audioSessionEnumerator->GetSession(sessionCount, &audioSessionControl)); - CComPtr audioSessionControl2; - FAST_FAIL(audioSessionControl->QueryInterface(IID_PPV_ARGS(&audioSessionControl2))); + CComPtr audioSessionControl2; + FAST_FAIL(audioSessionControl->QueryInterface(IID_PPV_ARGS(&audioSessionControl2))); - DWORD pid; - FAST_FAIL(audioSessionControl2->GetProcessId(&pid)); + DWORD pid; + FAST_FAIL(audioSessionControl2->GetProcessId(&pid)); etAudioSession->ProcessId = pid; FAST_FAIL(audioSessionControl2->GetGroupingParam(&etAudioSession->GroupingId)); - CComHeapPtr sessionIdString; - FAST_FAIL(audioSessionControl2->GetSessionIdentifier(&sessionIdString)); + CComHeapPtr sessionIdString; + FAST_FAIL(audioSessionControl2->GetSessionIdentifier(&sessionIdString)); - hash stringHash; - etAudioSession->SessionId = stringHash(static_cast(sessionIdString)); + hash stringHash; + etAudioSession->SessionId = stringHash(static_cast(sessionIdString)); - _sessionMap[etAudioSession->SessionId] = audioSessionControl2; + _sessionMap[etAudioSession->SessionId] = audioSessionControl2; - CComPtr simpleAudioVolume; - FAST_FAIL(audioSessionControl->QueryInterface(IID_PPV_ARGS(&simpleAudioVolume))); - FAST_FAIL(simpleAudioVolume->GetMasterVolume(&etAudioSession->Volume)); + CComPtr simpleAudioVolume; + FAST_FAIL(audioSessionControl->QueryInterface(IID_PPV_ARGS(&simpleAudioVolume))); + FAST_FAIL(simpleAudioVolume->GetMasterVolume(&etAudioSession->Volume)); - HRESULT hr = IsImmersiveProcess(pid); - if (hr == S_OK) - { - PWSTR appUserModelId; - FAST_FAIL(GetAppUserModelIdFromPid(pid, &appUserModelId)); + HRESULT hr = IsImmersiveProcess(pid); + if (hr == S_OK) + { + PWSTR appUserModelId; + FAST_FAIL(GetAppUserModelIdFromPid(pid, &appUserModelId)); - FAST_FAIL(GetAppProperties(appUserModelId, &etAudioSession->DisplayName, &etAudioSession->IconPath, &etAudioSession->BackgroundColor)); + FAST_FAIL(GetAppProperties(appUserModelId, &etAudioSession->DisplayName, &etAudioSession->IconPath, &etAudioSession->BackgroundColor)); - etAudioSession->IsDesktopApp = false; - } - else if (hr == S_FALSE) - { + etAudioSession->IsDesktopApp = false; + } + else if (hr == S_FALSE) + { bool isSystemSoundsSession = (S_OK == audioSessionControl2->IsSystemSoundsSession()); - AudioSessionState state; - FAST_FAIL(audioSessionControl2->GetState(&state)); - if (!isSystemSoundsSession && (state == AudioSessionState::AudioSessionStateExpired)) - { - return E_NOT_VALID_STATE; - } - - if (isSystemSoundsSession) - { + AudioSessionState state; + FAST_FAIL(audioSessionControl2->GetState(&state)); + if (!isSystemSoundsSession && (state == AudioSessionState::AudioSessionStateExpired)) + { + return E_NOT_VALID_STATE; + } + + if (isSystemSoundsSession) + { PCWSTR pszDllPath; BOOL isWow64Process; if (!IsWow64Process(GetCurrentProcess(), &isWow64Process) || isWow64Process) @@ -132,122 +132,122 @@ HRESULT AudioSessionService::CreateEtAudioSessionFromAudioSession(CComPtrIconPath)); FAST_FAIL(SHStrDup(L"System Sounds", &etAudioSession->DisplayName)); - } - else - { - shared_ptr processHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid), CloseHandle); - FAST_FAIL_HANDLE(processHandle.get()); - - wchar_t imagePath[MAX_PATH] = {}; - DWORD dwCch = ARRAYSIZE(imagePath); + } + else + { + shared_ptr processHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid), CloseHandle); + FAST_FAIL_HANDLE(processHandle.get()); + + wchar_t imagePath[MAX_PATH] = {}; + DWORD dwCch = ARRAYSIZE(imagePath); FAST_FAIL(QueryFullProcessImageName(processHandle.get(), 0, imagePath, &dwCch) == 0 ? E_FAIL : S_OK); FAST_FAIL(SHStrDup(imagePath, &etAudioSession->IconPath)); FAST_FAIL(SHStrDup(PathFindFileName(imagePath), &etAudioSession->DisplayName)); - } + } - etAudioSession->IsDesktopApp = true; - etAudioSession->BackgroundColor = 0x00000000; - } + etAudioSession->IsDesktopApp = true; + etAudioSession->BackgroundColor = 0x00000000; + } - return S_OK; + return S_OK; } HRESULT AudioSessionService::GetAudioSessions(void** audioSessions) { - if (_sessions.size() == 0) - { - return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); - } + if (_sessions.size() == 0) + { + return HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS); + } - *audioSessions = &_sessions[0]; - return S_OK; + *audioSessions = &_sessions[0]; + return S_OK; } HRESULT AudioSessionService::IsImmersiveProcess(DWORD pid) { - shared_ptr processHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid), CloseHandle); - FAST_FAIL_HANDLE(processHandle.get()); - - if (::IsImmersiveProcess(processHandle.get())) - { - return S_OK; - } - else - { - return S_FALSE; - } + shared_ptr processHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid), CloseHandle); + FAST_FAIL_HANDLE(processHandle.get()); + + if (::IsImmersiveProcess(processHandle.get())) + { + return S_OK; + } + else + { + return S_FALSE; + } } HRESULT AudioSessionService::GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr) { - shared_ptr processHandle(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), CloseHandle); - FAST_FAIL_HANDLE(processHandle.get()); - - unsigned int appUserModelIdLength = 0; - long returnCode = GetApplicationUserModelId(processHandle.get(), &appUserModelIdLength, NULL); - if (returnCode != ERROR_INSUFFICIENT_BUFFER) - { - return HRESULT_FROM_WIN32(returnCode); - } - - unique_ptr appUserModelId(new wchar_t[appUserModelIdLength]); - returnCode = GetApplicationUserModelId(processHandle.get(), &appUserModelIdLength, appUserModelId.get()); - if (returnCode != ERROR_SUCCESS) - { - return HRESULT_FROM_WIN32(returnCode); - } - - FAST_FAIL(SHStrDup(appUserModelId.get(), applicationUserModelIdPtr)); - - return S_OK; + shared_ptr processHandle(OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid), CloseHandle); + FAST_FAIL_HANDLE(processHandle.get()); + + unsigned int appUserModelIdLength = 0; + long returnCode = GetApplicationUserModelId(processHandle.get(), &appUserModelIdLength, NULL); + if (returnCode != ERROR_INSUFFICIENT_BUFFER) + { + return HRESULT_FROM_WIN32(returnCode); + } + + unique_ptr appUserModelId(new wchar_t[appUserModelIdLength]); + returnCode = GetApplicationUserModelId(processHandle.get(), &appUserModelIdLength, appUserModelId.get()); + if (returnCode != ERROR_SUCCESS) + { + return HRESULT_FROM_WIN32(returnCode); + } + + FAST_FAIL(SHStrDup(appUserModelId.get(), applicationUserModelIdPtr)); + + return S_OK; } HRESULT AudioSessionService::SetAudioSessionVolume(unsigned long sessionId, float volume) { - if (!_sessionMap[sessionId]) - { - return E_INVALIDARG; - } + if (!_sessionMap[sessionId]) + { + return E_INVALIDARG; + } - CComPtr simpleAudioVolume; - FAST_FAIL(_sessionMap[sessionId]->QueryInterface(IID_PPV_ARGS(&simpleAudioVolume))); + CComPtr simpleAudioVolume; + FAST_FAIL(_sessionMap[sessionId]->QueryInterface(IID_PPV_ARGS(&simpleAudioVolume))); - FAST_FAIL(simpleAudioVolume->SetMasterVolume(volume, nullptr)); - - return S_OK; + FAST_FAIL(simpleAudioVolume->SetMasterVolume(volume, nullptr)); + + return S_OK; } HRESULT AudioSessionService::GetAppProperties(PCWSTR pszAppId, PWSTR* ppszName, PWSTR* ppszIcon, ULONG *background) { - *ppszIcon = nullptr; - *ppszName = nullptr; - *background = 0; + *ppszIcon = nullptr; + *ppszName = nullptr; + *background = 0; - CComPtr item; - FAST_FAIL(SHCreateItemInKnownFolder(FOLDERID_AppsFolder, KF_FLAG_DONT_VERIFY, pszAppId, IID_PPV_ARGS(&item))); + CComPtr item; + FAST_FAIL(SHCreateItemInKnownFolder(FOLDERID_AppsFolder, KF_FLAG_DONT_VERIFY, pszAppId, IID_PPV_ARGS(&item))); - CComHeapPtr itemName; - FAST_FAIL(item->GetString(PKEY_ItemNameDisplay, &itemName)); - FAST_FAIL(item->GetUInt32(PKEY_AppUserModel_Background, background)); + CComHeapPtr itemName; + FAST_FAIL(item->GetString(PKEY_ItemNameDisplay, &itemName)); + FAST_FAIL(item->GetUInt32(PKEY_AppUserModel_Background, background)); - CComHeapPtr installPath; - FAST_FAIL(item->GetString(PKEY_AppUserModel_PackageInstallPath, &installPath)); + CComHeapPtr installPath; + FAST_FAIL(item->GetString(PKEY_AppUserModel_PackageInstallPath, &installPath)); - CComHeapPtr iconPath; - FAST_FAIL(item->GetString(PKEY_AppUserModel_Icon, &iconPath)); + CComHeapPtr iconPath; + FAST_FAIL(item->GetString(PKEY_AppUserModel_Icon, &iconPath)); - wchar_t fullPath[MAX_PATH] = {}; - FAST_FAIL(PathCchCombine(fullPath, ARRAYSIZE(fullPath), installPath, iconPath)); + wchar_t fullPath[MAX_PATH] = {}; + FAST_FAIL(PathCchCombine(fullPath, ARRAYSIZE(fullPath), installPath, iconPath)); - CStringW path(fullPath); + CStringW path(fullPath); - if (!PathFileExists(path)) - { - path.Replace(L".png", L".scale-100.png"); - } + if (!PathFileExists(path)) + { + path.Replace(L".png", L".scale-100.png"); + } - FAST_FAIL(SHStrDup(path, ppszIcon)); - *ppszName = itemName.Detach(); - return S_OK; + FAST_FAIL(SHStrDup(path, ppszIcon)); + *ppszName = itemName.Detach(); + return S_OK; } \ No newline at end of file diff --git a/EarTrumpet.Interop/AudioSessionService.h b/EarTrumpet.Interop/AudioSessionService.h index 489a79736..2ebdde958 100644 --- a/EarTrumpet.Interop/AudioSessionService.h +++ b/EarTrumpet.Interop/AudioSessionService.h @@ -2,48 +2,48 @@ namespace EarTrumpet { - namespace Interop - { - struct EarTrumpetAudioSession - { - wchar_t* DisplayName; - wchar_t* IconPath; + namespace Interop + { + struct EarTrumpetAudioSession + { + wchar_t* DisplayName; + wchar_t* IconPath; GUID GroupingId; - unsigned long SessionId; - unsigned long ProcessId; - unsigned long BackgroundColor; - float Volume; + unsigned long SessionId; + unsigned long ProcessId; + unsigned long BackgroundColor; + float Volume; bool IsDesktopApp; - }; + }; - class AudioSessionService - { + class AudioSessionService + { private: - static AudioSessionService* __instance; - - void CleanUpAudioSessions(); - HRESULT CreateEtAudioSessionFromAudioSession(CComPtr sessionEnumerator, int sessionCount, EarTrumpetAudioSession* etAudioSession); - HRESULT GetAppProperties(PCWSTR pszAppId, PWSTR* ppszName, PWSTR* ppszIcon, ULONG *background); - HRESULT GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr); - HRESULT IsImmersiveProcess(DWORD pid); + static AudioSessionService* __instance; + + void CleanUpAudioSessions(); + HRESULT CreateEtAudioSessionFromAudioSession(CComPtr sessionEnumerator, int sessionCount, EarTrumpetAudioSession* etAudioSession); + HRESULT GetAppProperties(PCWSTR pszAppId, PWSTR* ppszName, PWSTR* ppszIcon, ULONG *background); + HRESULT GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr); + BOOL IsImmersiveProcess(DWORD pid); - std::vector _sessions; - std::map> _sessionMap; - + std::vector _sessions; + std::map> _sessionMap; + public: - static AudioSessionService* instance() - { - if (!__instance) - { - __instance = new AudioSessionService; - } - return __instance; - } + static AudioSessionService* instance() + { + if (!__instance) + { + __instance = new AudioSessionService; + } + return __instance; + } - int GetAudioSessionCount(); - HRESULT GetAudioSessions(void** audioSessions); - HRESULT RefreshAudioSessions(); - HRESULT SetAudioSessionVolume(unsigned long sessionId, float volume); - }; - } + int GetAudioSessionCount(); + HRESULT GetAudioSessions(void** audioSessions); + HRESULT RefreshAudioSessions(); + HRESULT SetAudioSessionVolume(unsigned long sessionId, float volume); + }; + } } \ No newline at end of file diff --git a/EarTrumpet.Interop/exports.cpp b/EarTrumpet.Interop/exports.cpp index fb4c42a98..2142a02d3 100644 --- a/EarTrumpet.Interop/exports.cpp +++ b/EarTrumpet.Interop/exports.cpp @@ -6,20 +6,20 @@ using namespace EarTrumpet::Interop; extern "C" __declspec(dllexport) HRESULT RefreshAudioSessions() { - return AudioSessionService::instance()->RefreshAudioSessions(); + return AudioSessionService::instance()->RefreshAudioSessions(); } extern "C" __declspec(dllexport) int GetAudioSessionCount() { - return AudioSessionService::instance()->GetAudioSessionCount(); + return AudioSessionService::instance()->GetAudioSessionCount(); } extern "C" __declspec(dllexport) HRESULT GetAudioSessions(void** audioSessions) { - return AudioSessionService::instance()->GetAudioSessions(audioSessions); + return AudioSessionService::instance()->GetAudioSessions(audioSessions); } extern "C" __declspec(dllexport) HRESULT SetAudioSessionVolume(unsigned long sessionId, float volume) { - return AudioSessionService::instance()->SetAudioSessionVolume(sessionId, volume); + return AudioSessionService::instance()->SetAudioSessionVolume(sessionId, volume); } \ No newline at end of file diff --git a/EarTrumpet/Models/EarTrumpetAudioSessionModel.cs b/EarTrumpet/Models/EarTrumpetAudioSessionModel.cs index 756429cc6..0d18d1590 100644 --- a/EarTrumpet/Models/EarTrumpetAudioSessionModel.cs +++ b/EarTrumpet/Models/EarTrumpetAudioSessionModel.cs @@ -3,18 +3,18 @@ namespace EarTrumpet.Models { - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] - public struct EarTrumpetAudioSessionModel - { - public string DisplayName; + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + public struct EarTrumpetAudioSessionModel + { + public string DisplayName; public string IconPath; public Guid GroupingId; public uint SessionId; public uint ProcessId; - public uint BackgroundColor; - public float Volume; - - [MarshalAs(UnmanagedType.I1)] + public uint BackgroundColor; + public float Volume; + + [MarshalAs(UnmanagedType.I1)] public bool IsDesktop; - } + } } diff --git a/EarTrumpet/Services/AccentColorService.cs b/EarTrumpet/Services/AccentColorService.cs index a6ecadf8b..7b689f28e 100644 --- a/EarTrumpet/Services/AccentColorService.cs +++ b/EarTrumpet/Services/AccentColorService.cs @@ -5,37 +5,37 @@ namespace EarTrumpet.Services { - public static class AccentColorService - { - static class Interop - { - // Thanks, Quppa! -RR + public static class AccentColorService + { + static class Interop + { + // Thanks, Quppa! -RR - [DllImport("uxtheme.dll", EntryPoint = "#94", CharSet = CharSet.Unicode)] - internal static extern int GetImmersiveColorSetCount(); + [DllImport("uxtheme.dll", EntryPoint = "#94", CharSet = CharSet.Unicode)] + internal static extern int GetImmersiveColorSetCount(); - [DllImport("uxtheme.dll", EntryPoint = "#95", CharSet = CharSet.Unicode)] - internal static extern uint GetImmersiveColorFromColorSetEx(uint dwImmersiveColorSet, uint dwImmersiveColorType, bool bIgnoreHighContrast, uint dwHighContrastCacheMode); + [DllImport("uxtheme.dll", EntryPoint = "#95", CharSet = CharSet.Unicode)] + internal static extern uint GetImmersiveColorFromColorSetEx(uint dwImmersiveColorSet, uint dwImmersiveColorType, bool bIgnoreHighContrast, uint dwHighContrastCacheMode); - [DllImport("uxtheme.dll", EntryPoint = "#96", CharSet = CharSet.Unicode)] - internal static extern uint GetImmersiveColorTypeFromName(string name); + [DllImport("uxtheme.dll", EntryPoint = "#96", CharSet = CharSet.Unicode)] + internal static extern uint GetImmersiveColorTypeFromName(string name); - [DllImport("uxtheme.dll", EntryPoint = "#98", CharSet = CharSet.Unicode)] - internal static extern uint GetImmersiveUserColorSetPreference(bool bForceCheckRegistry, bool bSkipCheckOnFail); + [DllImport("uxtheme.dll", EntryPoint = "#98", CharSet = CharSet.Unicode)] + internal static extern uint GetImmersiveUserColorSetPreference(bool bForceCheckRegistry, bool bSkipCheckOnFail); - [DllImport("uxtheme.dll", EntryPoint = "#100", CharSet = CharSet.Unicode)] - internal static extern IntPtr GetImmersiveColorNamedTypeByIndex(uint dwIndex); - } + [DllImport("uxtheme.dll", EntryPoint = "#100", CharSet = CharSet.Unicode)] + internal static extern IntPtr GetImmersiveColorNamedTypeByIndex(uint dwIndex); + } - public static Color GetColorByTypeName(string name) - { - var colorSet = Interop.GetImmersiveUserColorSetPreference(false, false); - var colorType = Interop.GetImmersiveColorTypeFromName(name); - - uint rawColor = Interop.GetImmersiveColorFromColorSetEx(colorSet, colorType, false, 0); + public static Color GetColorByTypeName(string name) + { + var colorSet = Interop.GetImmersiveUserColorSetPreference(false, false); + var colorType = Interop.GetImmersiveColorTypeFromName(name); + + uint rawColor = Interop.GetImmersiveColorFromColorSetEx(colorSet, colorType, false, 0); return FromABGR(rawColor); - } + } public static Color FromABGR(uint abgrValue) { @@ -47,5 +47,5 @@ public static Color FromABGR(uint abgrValue) return Color.FromArgb(colorBytes[0], colorBytes[3], colorBytes[2], colorBytes[1]); } - } + } } diff --git a/EarTrumpet/Services/EarTrumpetAudioSessionService.cs b/EarTrumpet/Services/EarTrumpetAudioSessionService.cs index a5fbb77c8..e4b09526a 100644 --- a/EarTrumpet/Services/EarTrumpetAudioSessionService.cs +++ b/EarTrumpet/Services/EarTrumpetAudioSessionService.cs @@ -6,43 +6,43 @@ namespace EarTrumpet.Services { - public class EarTrumpetAudioSessionService - { - static class Interop - { - [DllImport("EarTrumpet.Interop.dll")] - public static extern int RefreshAudioSessions(); + public class EarTrumpetAudioSessionService + { + static class Interop + { + [DllImport("EarTrumpet.Interop.dll")] + public static extern int RefreshAudioSessions(); - [DllImport("EarTrumpet.Interop.dll")] - public static extern int GetAudioSessionCount(); + [DllImport("EarTrumpet.Interop.dll")] + public static extern int GetAudioSessionCount(); - [DllImport("EarTrumpet.Interop.dll")] - public static extern int GetAudioSessions(ref IntPtr sessions); + [DllImport("EarTrumpet.Interop.dll")] + public static extern int GetAudioSessions(ref IntPtr sessions); - [DllImport("EarTrumpet.Interop.dll")] + [DllImport("EarTrumpet.Interop.dll")] public static extern int SetAudioSessionVolume(uint sessionId, float volume); - } - - public IEnumerable GetAudioSessions() - { - Interop.RefreshAudioSessions(); - - var sessionCount = Interop.GetAudioSessionCount(); - var sessions = new List(); - - IntPtr rawSessionsPtr = IntPtr.Zero; - Interop.GetAudioSessions(ref rawSessionsPtr); - - var sizeOfAudioSessionStruct = Marshal.SizeOf(typeof(EarTrumpetAudioSessionModel)); - for(int i = 0; i < sessionCount; i++) - { - var window = new IntPtr(rawSessionsPtr.ToInt64() + (sizeOfAudioSessionStruct * i)); - - var session = (EarTrumpetAudioSessionModel)Marshal.PtrToStructure(window, typeof(EarTrumpetAudioSessionModel)); - sessions.Add(session); - } - return sessions; - } + } + + public IEnumerable GetAudioSessions() + { + Interop.RefreshAudioSessions(); + + var sessionCount = Interop.GetAudioSessionCount(); + var sessions = new List(); + + IntPtr rawSessionsPtr = IntPtr.Zero; + Interop.GetAudioSessions(ref rawSessionsPtr); + + var sizeOfAudioSessionStruct = Marshal.SizeOf(typeof(EarTrumpetAudioSessionModel)); + for(int i = 0; i < sessionCount; i++) + { + var window = new IntPtr(rawSessionsPtr.ToInt64() + (sizeOfAudioSessionStruct * i)); + + var session = (EarTrumpetAudioSessionModel)Marshal.PtrToStructure(window, typeof(EarTrumpetAudioSessionModel)); + sessions.Add(session); + } + return sessions; + } public IEnumerable GetAudioSessionGroups() { @@ -53,7 +53,7 @@ public IEnumerable GetAudioSessionGroups() public void SetAudioSessionVolume(uint sessionId, float volume) { - Interop.SetAudioSessionVolume(sessionId, volume); + Interop.SetAudioSessionVolume(sessionId, volume); } - } + } } diff --git a/EarTrumpet/Services/UserSystemPreferencesService.cs b/EarTrumpet/Services/UserSystemPreferencesService.cs index bf969f2f4..7a3117620 100644 --- a/EarTrumpet/Services/UserSystemPreferencesService.cs +++ b/EarTrumpet/Services/UserSystemPreferencesService.cs @@ -2,28 +2,28 @@ namespace EarTrumpet.Services { - public static class UserSystemPreferencesService - { - public static bool IsTransparencyEnabled - { - get - { - using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)) - { - return (int)baseKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize").GetValue("EnableTransparency", 0) > 0; - } - } - } + public static class UserSystemPreferencesService + { + public static bool IsTransparencyEnabled + { + get + { + using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)) + { + return (int)baseKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize").GetValue("EnableTransparency", 0) > 0; + } + } + } - public static bool UseAccentColor - { - get - { - using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)) - { - return (int)baseKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize").GetValue("ColorPrevalence", 0) > 0; - } - } - } + public static bool UseAccentColor + { + get + { + using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)) + { + return (int)baseKey.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize").GetValue("ColorPrevalence", 0) > 0; + } + } + } } } From ee704f3b53d52e0bb5ccc0411a25b2187aa1ca1e Mon Sep 17 00:00:00 2001 From: David Golden Date: Fri, 17 Jul 2015 17:43:35 +1000 Subject: [PATCH 05/23] Fixes #8 --- EarTrumpet/EarTrumpet.csproj | 1 + EarTrumpet/Extensions/WindowExtensions.cs | 78 +++++++++++++++++------ EarTrumpet/MainWindow.xaml.cs | 5 +- EarTrumpet/Services/TaskbarService.cs | 72 +++++++++++++++++++++ 4 files changed, 136 insertions(+), 20 deletions(-) create mode 100644 EarTrumpet/Services/TaskbarService.cs diff --git a/EarTrumpet/EarTrumpet.csproj b/EarTrumpet/EarTrumpet.csproj index d0d598a7f..7d0a12b79 100644 --- a/EarTrumpet/EarTrumpet.csproj +++ b/EarTrumpet/EarTrumpet.csproj @@ -63,6 +63,7 @@ + diff --git a/EarTrumpet/Extensions/WindowExtensions.cs b/EarTrumpet/Extensions/WindowExtensions.cs index 7dfc191f0..72226a462 100644 --- a/EarTrumpet/Extensions/WindowExtensions.cs +++ b/EarTrumpet/Extensions/WindowExtensions.cs @@ -10,19 +10,41 @@ internal static class WindowExtensions public static void HideWithAnimation(this Window window) { TimeSpan slidetime = TimeSpan.FromSeconds(0.2); - DoubleAnimation topAnimation = new DoubleAnimation(); - topAnimation.Duration = new Duration(slidetime); - topAnimation.From = window.Top; - topAnimation.To = window.Top + 10; - topAnimation.FillBehavior = FillBehavior.Stop; + DoubleAnimation hideAnimation = new DoubleAnimation(); + hideAnimation.Duration = new Duration(slidetime); + var taskbarPosition = TaskbarService.TaskbarPosition; + switch (taskbarPosition) + { + case TaskbarPosition.Top: hideAnimation.From = window.Top; break; + case TaskbarPosition.Bottom: hideAnimation.From = window.Top; break; + case TaskbarPosition.Left: hideAnimation.From = window.Left; break; + case TaskbarPosition.Right: hideAnimation.From = window.Left; break; + default: hideAnimation.From = window.Top; break; + } + hideAnimation.To = (taskbarPosition == TaskbarPosition.Top || taskbarPosition == TaskbarPosition.Left) ? hideAnimation.From - 10 : hideAnimation.From + 10; + hideAnimation.FillBehavior = FillBehavior.Stop; var easing = new QuinticEase(); easing.EasingMode = EasingMode.EaseIn; - topAnimation.EasingFunction = easing; - topAnimation.Completed += (s, e) => + hideAnimation.EasingFunction = easing; + hideAnimation.Completed += (s, e) => { window.Visibility = Visibility.Hidden; }; - window.BeginAnimation(Window.TopProperty, topAnimation); + + switch (taskbarPosition) + { + case TaskbarPosition.Top: + case TaskbarPosition.Bottom: + window.BeginAnimation(Window.TopProperty, hideAnimation); + break; + case TaskbarPosition.Left: + case TaskbarPosition.Right: + window.BeginAnimation(Window.LeftProperty, hideAnimation); + break; + default: + window.BeginAnimation(Window.TopProperty, hideAnimation); + break; + } } public static void ShowwithAnimation(this Window window) @@ -30,25 +52,45 @@ public static void ShowwithAnimation(this Window window) window.Visibility = Visibility.Visible; window.Topmost = false; TimeSpan slidetime = TimeSpan.FromSeconds(0.3); - DoubleAnimation bottomAnimation = new DoubleAnimation(); - bottomAnimation.Duration = new Duration(slidetime); - double top = window.Top; - bottomAnimation.From = window.Top + 25; - bottomAnimation.To = window.Top; - bottomAnimation.FillBehavior = FillBehavior.Stop; - bottomAnimation.Completed += (s, e) => + DoubleAnimation showAnimation = new DoubleAnimation(); + showAnimation.Duration = new Duration(slidetime); + var taskbarPosition = TaskbarService.TaskbarPosition; + switch (taskbarPosition) + { + case TaskbarPosition.Top: showAnimation.To = window.Top; break; + case TaskbarPosition.Bottom: showAnimation.To = window.Top; break; + case TaskbarPosition.Left: showAnimation.To = window.Left; break; // + window.Width + case TaskbarPosition.Right: showAnimation.To = window.Left; break; + default: showAnimation.To = window.Top; break; + } + showAnimation.From = (taskbarPosition == TaskbarPosition.Top || taskbarPosition == TaskbarPosition.Left) ? showAnimation.To - 25 : showAnimation.To + 25; + showAnimation.FillBehavior = FillBehavior.Stop; + showAnimation.Completed += (s, e) => { window.Topmost = true; // Set the final position again. This covers a case where frames are dropped. // and the window ends up over the taskbar instead. - window.Top = top; + //window.Top = (double)showAnimation.To; window.Activate(); window.Focus(); }; var easing = new QuinticEase(); easing.EasingMode = EasingMode.EaseOut; - bottomAnimation.EasingFunction = easing; - window.BeginAnimation(Window.TopProperty, bottomAnimation); + showAnimation.EasingFunction = easing; + switch (taskbarPosition) + { + case TaskbarPosition.Top: + case TaskbarPosition.Bottom: + window.BeginAnimation(Window.TopProperty, showAnimation); + break; + case TaskbarPosition.Left: + case TaskbarPosition.Right: + window.BeginAnimation(Window.LeftProperty, showAnimation); + break; + default: + window.BeginAnimation(Window.TopProperty, showAnimation); + break; + } } } } diff --git a/EarTrumpet/MainWindow.xaml.cs b/EarTrumpet/MainWindow.xaml.cs index 0be6dafe5..d11dc534c 100644 --- a/EarTrumpet/MainWindow.xaml.cs +++ b/EarTrumpet/MainWindow.xaml.cs @@ -148,8 +148,9 @@ private void UpdateWindowPosition() this.Height = this.LayoutRoot.DesiredSize.Height; var desktopWorkingArea = SystemParameters.WorkArea; - this.Left = desktopWorkingArea.Right - this.Width; - this.Top = desktopWorkingArea.Bottom - this.Height; + var taskbarPosition = TaskbarService.TaskbarPostionRect; + this.Left = taskbarPosition.Right == System.Windows.SystemParameters.PrimaryScreenWidth ? desktopWorkingArea.Right - this.Width : desktopWorkingArea.Left; + this.Top = taskbarPosition.Bottom == System.Windows.SystemParameters.PrimaryScreenHeight ? desktopWorkingArea.Bottom - this.Height : desktopWorkingArea.Top; } } } diff --git a/EarTrumpet/Services/TaskbarService.cs b/EarTrumpet/Services/TaskbarService.cs new file mode 100644 index 000000000..25606de3b --- /dev/null +++ b/EarTrumpet/Services/TaskbarService.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace EarTrumpet.Services +{ + public sealed class TaskbarService + { + private const string ClassName = "Shell_TrayWnd"; + + public static Rectangle TaskbarPostionRect + { + get + { + IntPtr taskbarHandle = User32.FindWindow(TaskbarService.ClassName, null); + + RECT r = new RECT(); + User32.GetWindowRect(taskbarHandle, ref r); + + return Rectangle.FromLTRB(r.left, r.top, r.right, r.bottom); + } + } + + public static TaskbarPosition TaskbarPosition + { + get + { + var rect = TaskbarPostionRect; + if (rect.Bottom == System.Windows.SystemParameters.PrimaryScreenHeight && rect.Top == 0) + { + return (rect.Left == 0) ? TaskbarPosition.Left : TaskbarPosition.Right; + } + if (rect.Right == System.Windows.SystemParameters.PrimaryScreenWidth && rect.Left == 0) + { + return (rect.Top == 0) ? TaskbarPosition.Top : TaskbarPosition.Bottom; + } + return TaskbarPosition.Bottom; + } + } + } + + public static class User32 + { + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); + } + + [StructLayout(LayoutKind.Sequential)] + public struct RECT + { + public int left; + public int top; + public int right; + public int bottom; + } + + public enum TaskbarPosition + { + Top, + Left, + Right, + Bottom + } +} From 6ac8a37dcda5c8b0972a581a5cf5b70c17062026 Mon Sep 17 00:00:00 2001 From: Rafael Rivera Date: Fri, 17 Jul 2015 00:54:47 -0700 Subject: [PATCH 06/23] Ternary cleanup, fix header glitch --- EarTrumpet.Interop/AudioSessionService.cpp | 10 +--------- EarTrumpet.Interop/AudioSessionService.h | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/EarTrumpet.Interop/AudioSessionService.cpp b/EarTrumpet.Interop/AudioSessionService.cpp index 819dbe27f..dbad07d44 100644 --- a/EarTrumpet.Interop/AudioSessionService.cpp +++ b/EarTrumpet.Interop/AudioSessionService.cpp @@ -168,15 +168,7 @@ HRESULT AudioSessionService::IsImmersiveProcess(DWORD pid) { shared_ptr processHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid), CloseHandle); FAST_FAIL_HANDLE(processHandle.get()); - - if (::IsImmersiveProcess(processHandle.get())) - { - return S_OK; - } - else - { - return S_FALSE; - } + return (::IsImmersiveProcess(processHandle.get()) ? S_OK : S_FALSE); } HRESULT AudioSessionService::GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr) diff --git a/EarTrumpet.Interop/AudioSessionService.h b/EarTrumpet.Interop/AudioSessionService.h index 2ebdde958..440765043 100644 --- a/EarTrumpet.Interop/AudioSessionService.h +++ b/EarTrumpet.Interop/AudioSessionService.h @@ -25,7 +25,7 @@ namespace EarTrumpet HRESULT CreateEtAudioSessionFromAudioSession(CComPtr sessionEnumerator, int sessionCount, EarTrumpetAudioSession* etAudioSession); HRESULT GetAppProperties(PCWSTR pszAppId, PWSTR* ppszName, PWSTR* ppszIcon, ULONG *background); HRESULT GetAppUserModelIdFromPid(DWORD pid, LPWSTR* applicationUserModelIdPtr); - BOOL IsImmersiveProcess(DWORD pid); + HRESULT IsImmersiveProcess(DWORD pid); std::vector _sessions; std::map> _sessionMap; From 78d3747a547aca0ac46c882a56f095631360c684 Mon Sep 17 00:00:00 2001 From: David Golden Date: Fri, 17 Jul 2015 20:01:36 +1000 Subject: [PATCH 07/23] Remove window activate from animation completion for smoother animations and to fix the animations breaking the window on first show when the tray icon is clicked too quickly. --- EarTrumpet/Extensions/WindowExtensions.cs | 35 +++++++++++------------ 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/EarTrumpet/Extensions/WindowExtensions.cs b/EarTrumpet/Extensions/WindowExtensions.cs index 72226a462..350af8bff 100644 --- a/EarTrumpet/Extensions/WindowExtensions.cs +++ b/EarTrumpet/Extensions/WindowExtensions.cs @@ -34,23 +34,24 @@ public static void HideWithAnimation(this Window window) switch (taskbarPosition) { case TaskbarPosition.Top: - case TaskbarPosition.Bottom: - window.BeginAnimation(Window.TopProperty, hideAnimation); + case TaskbarPosition.Bottom: + window.ApplyAnimationClock(Window.TopProperty, hideAnimation.CreateClock()); break; case TaskbarPosition.Left: - case TaskbarPosition.Right: - window.BeginAnimation(Window.LeftProperty, hideAnimation); + case TaskbarPosition.Right: + window.ApplyAnimationClock(Window.LeftProperty, hideAnimation.CreateClock()); break; - default: - window.BeginAnimation(Window.TopProperty, hideAnimation); + default: + window.ApplyAnimationClock(Window.TopProperty, hideAnimation.CreateClock()); break; } } public static void ShowwithAnimation(this Window window) - { + { window.Visibility = Visibility.Visible; - window.Topmost = false; + window.Topmost = false; + window.Activate(); TimeSpan slidetime = TimeSpan.FromSeconds(0.3); DoubleAnimation showAnimation = new DoubleAnimation(); showAnimation.Duration = new Duration(slidetime); @@ -68,11 +69,7 @@ public static void ShowwithAnimation(this Window window) showAnimation.Completed += (s, e) => { window.Topmost = true; - // Set the final position again. This covers a case where frames are dropped. - // and the window ends up over the taskbar instead. - //window.Top = (double)showAnimation.To; - window.Activate(); - window.Focus(); + window.Focus(); }; var easing = new QuinticEase(); easing.EasingMode = EasingMode.EaseOut; @@ -80,15 +77,15 @@ public static void ShowwithAnimation(this Window window) switch (taskbarPosition) { case TaskbarPosition.Top: - case TaskbarPosition.Bottom: - window.BeginAnimation(Window.TopProperty, showAnimation); + case TaskbarPosition.Bottom: + window.ApplyAnimationClock(Window.TopProperty, showAnimation.CreateClock()); break; case TaskbarPosition.Left: - case TaskbarPosition.Right: - window.BeginAnimation(Window.LeftProperty, showAnimation); + case TaskbarPosition.Right: + window.ApplyAnimationClock(Window.LeftProperty, showAnimation.CreateClock()); break; - default: - window.BeginAnimation(Window.TopProperty, showAnimation); + default: + window.ApplyAnimationClock(Window.TopProperty, showAnimation.CreateClock()); break; } } From a0e5059491a5589a31a1b758a5d07ccaa1ed11e6 Mon Sep 17 00:00:00 2001 From: David Golden Date: Fri, 17 Jul 2015 23:48:51 +1000 Subject: [PATCH 08/23] Added min version to setup file. Updated Readme. (Fixes #12, Fixes #7) --- EarTrumpet/EarTrumpet.iss | 2 ++ README.md | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/EarTrumpet/EarTrumpet.iss b/EarTrumpet/EarTrumpet.iss index d769ac21b..da46d487d 100644 --- a/EarTrumpet/EarTrumpet.iss +++ b/EarTrumpet/EarTrumpet.iss @@ -20,6 +20,8 @@ AllowUNCPath=no DisableReadyPage=yes DisableStartupPrompt=yes DisableWelcomePage=yes +MinVersion=10.0 +SetupMutex=EarTrumpetSetup [Files] Source: "EarTrumpet.exe"; DestDir: "{app}"; Flags: replacesameversion diff --git a/README.md b/README.md index ae5654b47..43d53484d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ # EarTrumpet -Icon created by Artjom Kormanfrom the Noun Project +![Ear Trumpet Screenshot](https://pbs.twimg.com/media/CJoDCsjUMAAeWq7.png:large) + +Ear Trumpet is a volume control app for Windows. Frustrated with the lack of volume controls for Modern apps in Windows 8, 8.1 and 10, we created Ear Trumpet. The app was quickly expanded to also allow the control of Windows Desktop apps. + +To show Windows Desktop apps, right-click the Ear Trumpet icon in the tray and click Show Desktop Apps. + +## Supported Versions ## +- Windows 10 + +## Credits ## + +Originally created by David Golden (@GoldenTao) and Rafael Rivera (@RiveraR) + +Icon created by Artjom Kormanfrom from the Noun Project From 30e1607c1132edc388a75d7198a1ccaf4bad7e19 Mon Sep 17 00:00:00 2001 From: David Golden Date: Sun, 19 Jul 2015 21:03:57 +1000 Subject: [PATCH 09/23] Better animation curves. --- EarTrumpet/Extensions/WindowExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EarTrumpet/Extensions/WindowExtensions.cs b/EarTrumpet/Extensions/WindowExtensions.cs index 350af8bff..b48072fac 100644 --- a/EarTrumpet/Extensions/WindowExtensions.cs +++ b/EarTrumpet/Extensions/WindowExtensions.cs @@ -23,7 +23,7 @@ public static void HideWithAnimation(this Window window) } hideAnimation.To = (taskbarPosition == TaskbarPosition.Top || taskbarPosition == TaskbarPosition.Left) ? hideAnimation.From - 10 : hideAnimation.From + 10; hideAnimation.FillBehavior = FillBehavior.Stop; - var easing = new QuinticEase(); + var easing = new ExponentialEase(); easing.EasingMode = EasingMode.EaseIn; hideAnimation.EasingFunction = easing; hideAnimation.Completed += (s, e) => @@ -71,7 +71,7 @@ public static void ShowwithAnimation(this Window window) window.Topmost = true; window.Focus(); }; - var easing = new QuinticEase(); + var easing = new ExponentialEase(); easing.EasingMode = EasingMode.EaseOut; showAnimation.EasingFunction = easing; switch (taskbarPosition) From c6c3d038bde2894f11e4ce6186105550d3a62874 Mon Sep 17 00:00:00 2001 From: David Golden Date: Sun, 19 Jul 2015 21:05:25 +1000 Subject: [PATCH 10/23] Fix issue with positioning window for different taskbar positions. --- EarTrumpet/MainWindow.xaml.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EarTrumpet/MainWindow.xaml.cs b/EarTrumpet/MainWindow.xaml.cs index d11dc534c..663277ef5 100644 --- a/EarTrumpet/MainWindow.xaml.cs +++ b/EarTrumpet/MainWindow.xaml.cs @@ -148,9 +148,9 @@ private void UpdateWindowPosition() this.Height = this.LayoutRoot.DesiredSize.Height; var desktopWorkingArea = SystemParameters.WorkArea; - var taskbarPosition = TaskbarService.TaskbarPostionRect; - this.Left = taskbarPosition.Right == System.Windows.SystemParameters.PrimaryScreenWidth ? desktopWorkingArea.Right - this.Width : desktopWorkingArea.Left; - this.Top = taskbarPosition.Bottom == System.Windows.SystemParameters.PrimaryScreenHeight ? desktopWorkingArea.Bottom - this.Height : desktopWorkingArea.Top; + var taskbarPosition = TaskbarService.TaskbarPosition; + Left = (taskbarPosition == TaskbarPosition.Left) ? desktopWorkingArea.Left : desktopWorkingArea.Right - Width; + Top = (taskbarPosition == TaskbarPosition.Top) ? desktopWorkingArea.Top : desktopWorkingArea.Bottom - Height; } } } From e401311546fbb19ac17e17d9f3cd976ef5101420 Mon Sep 17 00:00:00 2001 From: David Golden Date: Sun, 19 Jul 2015 21:12:16 +1000 Subject: [PATCH 11/23] Handle hiding and showing the window while it is part way through animating. --- EarTrumpet/Extensions/WindowExtensions.cs | 9 +++++++++ EarTrumpet/MainWindow.xaml.cs | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/EarTrumpet/Extensions/WindowExtensions.cs b/EarTrumpet/Extensions/WindowExtensions.cs index b48072fac..e44795b93 100644 --- a/EarTrumpet/Extensions/WindowExtensions.cs +++ b/EarTrumpet/Extensions/WindowExtensions.cs @@ -7,6 +7,13 @@ namespace EarTrumpet.Extensions { internal static class WindowExtensions { + private static bool _windowVisible; + + public static bool IsWindowVisible(this Window window) + { + return _windowVisible; + } + public static void HideWithAnimation(this Window window) { TimeSpan slidetime = TimeSpan.FromSeconds(0.2); @@ -45,6 +52,7 @@ public static void HideWithAnimation(this Window window) window.ApplyAnimationClock(Window.TopProperty, hideAnimation.CreateClock()); break; } + _windowVisible = false; } public static void ShowwithAnimation(this Window window) @@ -88,6 +96,7 @@ public static void ShowwithAnimation(this Window window) window.ApplyAnimationClock(Window.TopProperty, showAnimation.CreateClock()); break; } + _windowVisible = true; } } } diff --git a/EarTrumpet/MainWindow.xaml.cs b/EarTrumpet/MainWindow.xaml.cs index 663277ef5..bbb5dad53 100644 --- a/EarTrumpet/MainWindow.xaml.cs +++ b/EarTrumpet/MainWindow.xaml.cs @@ -33,7 +33,7 @@ public MainWindow() void TrayIcon_Invoked() { - if (this.Visibility == Visibility.Visible) + if (this.IsWindowVisible()) { this.HideWithAnimation(); } From 5830321c165b603e3143276470e9914fb1ef1d68 Mon Sep 17 00:00:00 2001 From: David Golden Date: Sun, 19 Jul 2015 22:07:07 +1000 Subject: [PATCH 12/23] Code cleanup. --- EarTrumpet/App.xaml.cs | 2 +- EarTrumpet/Extensions/CollectionExtensions.cs | 4 +- EarTrumpet/Extensions/IconExtensions.cs | 4 +- EarTrumpet/Extensions/WindowExtensions.cs | 60 +++++++++---------- EarTrumpet/MainWindow.xaml | 4 +- EarTrumpet/MainWindow.xaml.cs | 18 +++--- .../EarTrumpetAudioSessionModelGroup.cs | 3 +- EarTrumpet/Services/AccentColorService.cs | 9 ++- .../Services/EarTrumpetAudioSessionService.cs | 4 +- EarTrumpet/Services/TaskbarService.cs | 19 +++--- EarTrumpet/Services/ThemeService.cs | 22 +++---- EarTrumpet/Services/UserPreferencesService.cs | 8 +-- EarTrumpet/ViewModels/AppItemViewModel.cs | 37 ++++-------- .../ViewModels/AppItemViewModelComparer.cs | 5 +- EarTrumpet/ViewModels/AudioMixerViewModel.cs | 11 +--- .../IAudioMixerViewModelCallback.cs | 3 +- 16 files changed, 89 insertions(+), 124 deletions(-) diff --git a/EarTrumpet/App.xaml.cs b/EarTrumpet/App.xaml.cs index 87b96246f..2cd3e1a80 100644 --- a/EarTrumpet/App.xaml.cs +++ b/EarTrumpet/App.xaml.cs @@ -2,7 +2,7 @@ namespace EarTrumpet { - public partial class App : Application + public partial class App { private void Application_Startup(object sender, StartupEventArgs e) { diff --git a/EarTrumpet/Extensions/CollectionExtensions.cs b/EarTrumpet/Extensions/CollectionExtensions.cs index bca88b6cb..13e679e20 100644 --- a/EarTrumpet/Extensions/CollectionExtensions.cs +++ b/EarTrumpet/Extensions/CollectionExtensions.cs @@ -7,7 +7,7 @@ public static class CollectionExtensions { public static void AddRange(this ICollection destination, IEnumerable source) { - foreach (T item in source) + foreach (var item in source) { destination.Add(item); } @@ -15,7 +15,7 @@ public static void AddRange(this ICollection destination, IEnumerable s public static void AddSorted(this ObservableCollection collection, T item, IComparer comparer) { - int i = 0; + var i = 0; while ((i < collection.Count) && (comparer.Compare(collection[i], item) < 0)) { i++; diff --git a/EarTrumpet/Extensions/IconExtensions.cs b/EarTrumpet/Extensions/IconExtensions.cs index f38520770..cb17f310a 100644 --- a/EarTrumpet/Extensions/IconExtensions.cs +++ b/EarTrumpet/Extensions/IconExtensions.cs @@ -22,8 +22,8 @@ public static class IconExtensions public static ImageSource ToImageSource(this Icon icon) { - Bitmap bitmap = icon.ToBitmap(); - IntPtr hBitmap = bitmap.GetHbitmap(); + var bitmap = icon.ToBitmap(); + var hBitmap = bitmap.GetHbitmap(); ImageSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap( hBitmap, diff --git a/EarTrumpet/Extensions/WindowExtensions.cs b/EarTrumpet/Extensions/WindowExtensions.cs index e44795b93..e84df4bea 100644 --- a/EarTrumpet/Extensions/WindowExtensions.cs +++ b/EarTrumpet/Extensions/WindowExtensions.cs @@ -16,23 +16,24 @@ public static bool IsWindowVisible(this Window window) public static void HideWithAnimation(this Window window) { - TimeSpan slidetime = TimeSpan.FromSeconds(0.2); - DoubleAnimation hideAnimation = new DoubleAnimation(); - hideAnimation.Duration = new Duration(slidetime); + var hideAnimation = new DoubleAnimation + { + Duration = new Duration(TimeSpan.FromSeconds(0.2)), + FillBehavior = FillBehavior.Stop, + EasingFunction = new ExponentialEase {EasingMode = EasingMode.EaseIn} + }; var taskbarPosition = TaskbarService.TaskbarPosition; switch (taskbarPosition) { - case TaskbarPosition.Top: hideAnimation.From = window.Top; break; - case TaskbarPosition.Bottom: hideAnimation.From = window.Top; break; - case TaskbarPosition.Left: hideAnimation.From = window.Left; break; - case TaskbarPosition.Right: hideAnimation.From = window.Left; break; - default: hideAnimation.From = window.Top; break; + case TaskbarPosition.Left: + case TaskbarPosition.Right: + hideAnimation.From = window.Left; + break; + default: + hideAnimation.From = window.Top; + break; } hideAnimation.To = (taskbarPosition == TaskbarPosition.Top || taskbarPosition == TaskbarPosition.Left) ? hideAnimation.From - 10 : hideAnimation.From + 10; - hideAnimation.FillBehavior = FillBehavior.Stop; - var easing = new ExponentialEase(); - easing.EasingMode = EasingMode.EaseIn; - hideAnimation.EasingFunction = easing; hideAnimation.Completed += (s, e) => { window.Visibility = Visibility.Hidden; @@ -40,10 +41,6 @@ public static void HideWithAnimation(this Window window) switch (taskbarPosition) { - case TaskbarPosition.Top: - case TaskbarPosition.Bottom: - window.ApplyAnimationClock(Window.TopProperty, hideAnimation.CreateClock()); - break; case TaskbarPosition.Left: case TaskbarPosition.Right: window.ApplyAnimationClock(Window.LeftProperty, hideAnimation.CreateClock()); @@ -60,34 +57,31 @@ public static void ShowwithAnimation(this Window window) window.Visibility = Visibility.Visible; window.Topmost = false; window.Activate(); - TimeSpan slidetime = TimeSpan.FromSeconds(0.3); - DoubleAnimation showAnimation = new DoubleAnimation(); - showAnimation.Duration = new Duration(slidetime); + var showAnimation = new DoubleAnimation + { + Duration = new Duration(TimeSpan.FromSeconds(0.3)), + FillBehavior = FillBehavior.Stop, + EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut } + }; var taskbarPosition = TaskbarService.TaskbarPosition; switch (taskbarPosition) { - case TaskbarPosition.Top: showAnimation.To = window.Top; break; - case TaskbarPosition.Bottom: showAnimation.To = window.Top; break; - case TaskbarPosition.Left: showAnimation.To = window.Left; break; // + window.Width - case TaskbarPosition.Right: showAnimation.To = window.Left; break; - default: showAnimation.To = window.Top; break; - } + case TaskbarPosition.Left: + case TaskbarPosition.Right: + showAnimation.To = window.Left; + break; + default: + showAnimation.To = window.Top; + break; + } showAnimation.From = (taskbarPosition == TaskbarPosition.Top || taskbarPosition == TaskbarPosition.Left) ? showAnimation.To - 25 : showAnimation.To + 25; - showAnimation.FillBehavior = FillBehavior.Stop; showAnimation.Completed += (s, e) => { window.Topmost = true; window.Focus(); }; - var easing = new ExponentialEase(); - easing.EasingMode = EasingMode.EaseOut; - showAnimation.EasingFunction = easing; switch (taskbarPosition) { - case TaskbarPosition.Top: - case TaskbarPosition.Bottom: - window.ApplyAnimationClock(Window.TopProperty, showAnimation.CreateClock()); - break; case TaskbarPosition.Left: case TaskbarPosition.Right: window.ApplyAnimationClock(Window.LeftProperty, showAnimation.CreateClock()); diff --git a/EarTrumpet/MainWindow.xaml b/EarTrumpet/MainWindow.xaml index 191e472ce..435987630 100644 --- a/EarTrumpet/MainWindow.xaml +++ b/EarTrumpet/MainWindow.xaml @@ -1,6 +1,7 @@  @@ -180,7 +180,7 @@ HorizontalContentAlignment="Stretch" Focusable="False"> - + diff --git a/EarTrumpet/MainWindow.xaml.cs b/EarTrumpet/MainWindow.xaml.cs index bbb5dad53..7454fea69 100644 --- a/EarTrumpet/MainWindow.xaml.cs +++ b/EarTrumpet/MainWindow.xaml.cs @@ -8,7 +8,7 @@ namespace EarTrumpet { - public partial class MainWindow : Window + public partial class MainWindow { private readonly AudioMixerViewModel _viewModel; @@ -51,9 +51,9 @@ private void Window_Deactivated(object sender, EventArgs e) this.HideWithAnimation(); } - private void Window_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) + private void Window_PreviewKeyDown(object sender, KeyEventArgs e) { - if (e.Key == System.Windows.Input.Key.Escape) + if (e.Key == Key.Escape) { this.HideWithAnimation(); } @@ -69,7 +69,7 @@ private void Slider_TouchDown(object sender, TouchEventArgs e) e.Handled = true; } - private void Slider_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) + private void Slider_MouseDown(object sender, MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { @@ -91,7 +91,7 @@ private void Slider_TouchUp(object sender, TouchEventArgs e) e.Handled = true; } - private void Slider_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) + private void Slider_MouseUp(object sender, MouseButtonEventArgs e) { var slider = (Slider)sender; if (slider.IsMouseCaptured) @@ -118,7 +118,7 @@ private void Slider_TouchMove(object sender, TouchEventArgs e) } } - private void Slider_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) + private void Slider_MouseMove(object sender, MouseEventArgs e) { var slider = (Slider)sender; if (slider.IsMouseCaptured) @@ -143,9 +143,9 @@ private void UpdateTheme() private void UpdateWindowPosition() { - this.LayoutRoot.UpdateLayout(); - this.LayoutRoot.Measure(new Size(Double.PositiveInfinity, this.MaxHeight)); - this.Height = this.LayoutRoot.DesiredSize.Height; + LayoutRoot.UpdateLayout(); + LayoutRoot.Measure(new Size(double.PositiveInfinity, MaxHeight)); + Height = LayoutRoot.DesiredSize.Height; var desktopWorkingArea = SystemParameters.WorkArea; var taskbarPosition = TaskbarService.TaskbarPosition; diff --git a/EarTrumpet/Models/EarTrumpetAudioSessionModelGroup.cs b/EarTrumpet/Models/EarTrumpetAudioSessionModelGroup.cs index ec14e35a1..9b8aac92f 100644 --- a/EarTrumpet/Models/EarTrumpetAudioSessionModelGroup.cs +++ b/EarTrumpet/Models/EarTrumpetAudioSessionModelGroup.cs @@ -1,5 +1,4 @@ -using EarTrumpet.Models; -using System.Collections.Generic; +using System.Collections.Generic; namespace EarTrumpet.Models { diff --git a/EarTrumpet/Services/AccentColorService.cs b/EarTrumpet/Services/AccentColorService.cs index 7b689f28e..0b7a38ad1 100644 --- a/EarTrumpet/Services/AccentColorService.cs +++ b/EarTrumpet/Services/AccentColorService.cs @@ -1,5 +1,4 @@ -using EarTrumpet.Extensions; -using System; +using System; using System.Runtime.InteropServices; using System.Windows.Media; @@ -32,17 +31,17 @@ public static Color GetColorByTypeName(string name) var colorSet = Interop.GetImmersiveUserColorSetPreference(false, false); var colorType = Interop.GetImmersiveColorTypeFromName(name); - uint rawColor = Interop.GetImmersiveColorFromColorSetEx(colorSet, colorType, false, 0); + var rawColor = Interop.GetImmersiveColorFromColorSetEx(colorSet, colorType, false, 0); return FromABGR(rawColor); } public static Color FromABGR(uint abgrValue) { - byte[] colorBytes = new byte[4]; + var colorBytes = new byte[4]; colorBytes[0] = (byte)((0xFF000000 & abgrValue) >> 24); // A colorBytes[1] = (byte)((0x00FF0000 & abgrValue) >> 16); // B - colorBytes[2] = (byte)((0x0000FF00 & abgrValue) >> 8); // G + colorBytes[2] = (byte)((0x0000FF00 & abgrValue) >> 8); // G colorBytes[3] = (byte)(0x000000FF & abgrValue); // R return Color.FromArgb(colorBytes[0], colorBytes[3], colorBytes[2], colorBytes[1]); diff --git a/EarTrumpet/Services/EarTrumpetAudioSessionService.cs b/EarTrumpet/Services/EarTrumpetAudioSessionService.cs index e4b09526a..c1d73a85d 100644 --- a/EarTrumpet/Services/EarTrumpetAudioSessionService.cs +++ b/EarTrumpet/Services/EarTrumpetAudioSessionService.cs @@ -30,11 +30,11 @@ public IEnumerable GetAudioSessions() var sessionCount = Interop.GetAudioSessionCount(); var sessions = new List(); - IntPtr rawSessionsPtr = IntPtr.Zero; + var rawSessionsPtr = IntPtr.Zero; Interop.GetAudioSessions(ref rawSessionsPtr); var sizeOfAudioSessionStruct = Marshal.SizeOf(typeof(EarTrumpetAudioSessionModel)); - for(int i = 0; i < sessionCount; i++) + for(var i = 0; i < sessionCount; i++) { var window = new IntPtr(rawSessionsPtr.ToInt64() + (sizeOfAudioSessionStruct * i)); diff --git a/EarTrumpet/Services/TaskbarService.cs b/EarTrumpet/Services/TaskbarService.cs index 25606de3b..b9eb4ba40 100644 --- a/EarTrumpet/Services/TaskbarService.cs +++ b/EarTrumpet/Services/TaskbarService.cs @@ -1,10 +1,7 @@ using System; -using System.Collections.Generic; using System.Drawing; -using System.Linq; using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; +using System.Windows; namespace EarTrumpet.Services { @@ -16,9 +13,9 @@ public static Rectangle TaskbarPostionRect { get { - IntPtr taskbarHandle = User32.FindWindow(TaskbarService.ClassName, null); + var taskbarHandle = User32.FindWindow(ClassName, null); - RECT r = new RECT(); + var r = new RECT(); User32.GetWindowRect(taskbarHandle, ref r); return Rectangle.FromLTRB(r.left, r.top, r.right, r.bottom); @@ -30,14 +27,14 @@ public static TaskbarPosition TaskbarPosition get { var rect = TaskbarPostionRect; - if (rect.Bottom == System.Windows.SystemParameters.PrimaryScreenHeight && rect.Top == 0) + if (rect.Bottom == SystemParameters.PrimaryScreenHeight && rect.Top == 0) { return (rect.Left == 0) ? TaskbarPosition.Left : TaskbarPosition.Right; } - if (rect.Right == System.Windows.SystemParameters.PrimaryScreenWidth && rect.Left == 0) + if (rect.Right == SystemParameters.PrimaryScreenWidth && rect.Left == 0) { return (rect.Top == 0) ? TaskbarPosition.Top : TaskbarPosition.Bottom; - } + } return TaskbarPosition.Bottom; } } @@ -61,7 +58,7 @@ public struct RECT public int right; public int bottom; } - + public enum TaskbarPosition { Top, @@ -69,4 +66,4 @@ public enum TaskbarPosition Right, Bottom } -} +} \ No newline at end of file diff --git a/EarTrumpet/Services/ThemeService.cs b/EarTrumpet/Services/ThemeService.cs index 65fad1b30..0c8f4396e 100644 --- a/EarTrumpet/Services/ThemeService.cs +++ b/EarTrumpet/Services/ThemeService.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows; +using System.Windows; using System.Windows.Media; namespace EarTrumpet.Services @@ -8,10 +7,7 @@ public class ThemeService { public static bool IsWindowTransparencyEnabled { - get - { - return !SystemParameters.HighContrast && UserSystemPreferencesService.IsTransparencyEnabled; - } + get { return !SystemParameters.HighContrast && UserSystemPreferencesService.IsTransparencyEnabled; } } public static void UpdateThemeResources(ResourceDictionary dictionary) @@ -37,23 +33,23 @@ private static Color GetWindowBackgroundColor() } else if (UserSystemPreferencesService.UseAccentColor) { - resource = ThemeService.IsWindowTransparencyEnabled ? "ImmersiveSystemAccentDark2" : "ImmersiveSystemAccentDark1"; + resource = IsWindowTransparencyEnabled ? "ImmersiveSystemAccentDark2" : "ImmersiveSystemAccentDark1"; } else { resource = "ImmersiveDarkChromeMedium"; } - Color color = AccentColorService.GetColorByTypeName(resource); - color.A = (byte)(ThemeService.IsWindowTransparencyEnabled ? 190 : 255); + var color = AccentColorService.GetColorByTypeName(resource); + color.A = (byte) (IsWindowTransparencyEnabled ? 190 : 255); return color; } private static void SetBrushWithOpacity(ResourceDictionary dictionary, string name, string immersiveAccentName, double opacity) { - Color color = AccentColorService.GetColorByTypeName(immersiveAccentName); - color.A = (byte)(opacity * 255); - ((SolidColorBrush)dictionary[name]).Color = color; + var color = AccentColorService.GetColorByTypeName(immersiveAccentName); + color.A = (byte) (opacity*255); + ((SolidColorBrush) dictionary[name]).Color = color; } private static void SetBrush(ResourceDictionary dictionary, string name, string immersiveAccentName) @@ -66,4 +62,4 @@ private static void ReplaceBrush(ResourceDictionary dictionary, string name, str dictionary[name] = new SolidColorBrush(AccentColorService.GetColorByTypeName(immersiveAccentName)); } } -} +} \ No newline at end of file diff --git a/EarTrumpet/Services/UserPreferencesService.cs b/EarTrumpet/Services/UserPreferencesService.cs index 9f6445171..0c1baed90 100644 --- a/EarTrumpet/Services/UserPreferencesService.cs +++ b/EarTrumpet/Services/UserPreferencesService.cs @@ -1,6 +1,6 @@ -using Microsoft.Win32; -using System; +using System; using System.Diagnostics; +using Microsoft.Win32; namespace EarTrumpet.Services { @@ -12,7 +12,7 @@ public static bool ShowDesktopApps { try { - return 1 == (int)Registry.CurrentUser.CreateSubKey(@"Software\EarTrumpet").GetValue("ShowDesktopApps"); + return 1 == (int) Registry.CurrentUser.CreateSubKey(@"Software\EarTrumpet").GetValue("ShowDesktopApps"); } catch (Exception e) { @@ -27,4 +27,4 @@ public static bool ShowDesktopApps } } } -} +} \ No newline at end of file diff --git a/EarTrumpet/ViewModels/AppItemViewModel.cs b/EarTrumpet/ViewModels/AppItemViewModel.cs index a34c1c1da..60f20aa56 100644 --- a/EarTrumpet/ViewModels/AppItemViewModel.cs +++ b/EarTrumpet/ViewModels/AppItemViewModel.cs @@ -21,7 +21,7 @@ public class AppItemViewModel : BindableBase public double IconHeight { get; set; } public double IconWidth { get; set; } - private int _volume = 0; + private int _volume; public int Volume { get @@ -36,7 +36,7 @@ public int Volume foreach (var session in _sessions.Sessions) { - _callback.SetVolume(session, (float)_volume / 100.0f); + _callback.SetVolume(session, _volume / 100.0f); } RaisePropertyChanged("Volume"); } @@ -64,16 +64,12 @@ public AppItemViewModel(IAudioMixerViewModelCallback callback, EarTrumpetAudioSe { try { - if (Path.GetExtension(session.IconPath) == ".dll") - { - Icon = IconExtensions.ExtractIconFromDll(session.IconPath); - } - else - { - Icon = System.Drawing.Icon.ExtractAssociatedIcon(session.IconPath).ToImageSource(); - } + Icon = Path.GetExtension(session.IconPath) == ".dll" ? IconExtensions.ExtractIconFromDll(session.IconPath) : System.Drawing.Icon.ExtractAssociatedIcon(session.IconPath).ToImageSource(); + } + catch + { + // ignored } - catch { } Background = new SolidColorBrush(Colors.Transparent); @@ -96,24 +92,15 @@ public AppItemViewModel(IAudioMixerViewModelCallback callback, EarTrumpetAudioSe public void UpdateFromOther(AppItemViewModel other) { - if (_volume != other.Volume) - { - _sessions = other._sessions; - _volume = other.Volume; - RaisePropertyChanged("Volume"); - } + if (_volume == other.Volume) return; + _sessions = other._sessions; + _volume = other.Volume; + RaisePropertyChanged("Volume"); } public bool IsSame(AppItemViewModel other) { - foreach (var session in other._sessions.Sessions) - { - if (_sessions.Sessions.Where(x => x.SessionId == session.SessionId).Any()) - { - return true; - } - } - return false; + return other._sessions.Sessions.Any(session => _sessions.Sessions.Any(x => x.SessionId == session.SessionId)); } } } diff --git a/EarTrumpet/ViewModels/AppItemViewModelComparer.cs b/EarTrumpet/ViewModels/AppItemViewModelComparer.cs index 2a910024a..61150e42d 100644 --- a/EarTrumpet/ViewModels/AppItemViewModelComparer.cs +++ b/EarTrumpet/ViewModels/AppItemViewModelComparer.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace EarTrumpet.ViewModels { @@ -8,7 +9,7 @@ public class AppItemViewModelComparer : IComparer public int Compare(AppItemViewModel one, AppItemViewModel two) { - return one.DisplayName.CompareTo(two.DisplayName); + return string.Compare(one.DisplayName, two.DisplayName, StringComparison.Ordinal); } } } diff --git a/EarTrumpet/ViewModels/AudioMixerViewModel.cs b/EarTrumpet/ViewModels/AudioMixerViewModel.cs index 07d1dfd71..7283675a4 100644 --- a/EarTrumpet/ViewModels/AudioMixerViewModel.cs +++ b/EarTrumpet/ViewModels/AudioMixerViewModel.cs @@ -48,22 +48,15 @@ public void Refresh() var sessions = _audioService.GetAudioSessionGroups().Select(x => new AppItemViewModel(_proxy, x)); - List staleSessionsToRemove = new List(); + List staleSessionsToRemove = Apps.Where(app => !sessions.Any(x => (x.IsSame(app) && (!app.IsDesktop || UserPreferencesService.ShowDesktopApps)))).ToList(); // remove stale apps - foreach (var app in Apps) - { - if (!sessions.Where(x => (x.IsSame(app) && (!app.IsDesktop || UserPreferencesService.ShowDesktopApps))).Any()) - { - staleSessionsToRemove.Add(app); - } - } foreach (var app in staleSessionsToRemove) { Apps.Remove(app); } // add new apps foreach (var session in sessions) { - var findApp = Apps.Where(x => x.IsSame(session)).FirstOrDefault(); + var findApp = Apps.FirstOrDefault(x => x.IsSame(session)); if (findApp == null) { if (!session.IsDesktop || UserPreferencesService.ShowDesktopApps) diff --git a/EarTrumpet/ViewModels/IAudioMixerViewModelCallback.cs b/EarTrumpet/ViewModels/IAudioMixerViewModelCallback.cs index 203982cc1..43eaac167 100644 --- a/EarTrumpet/ViewModels/IAudioMixerViewModelCallback.cs +++ b/EarTrumpet/ViewModels/IAudioMixerViewModelCallback.cs @@ -1,5 +1,4 @@ - -using EarTrumpet.Models; +using EarTrumpet.Models; namespace EarTrumpet.ViewModels { From 6aa08ca54edbfeb32ede188d1846947606307e4b Mon Sep 17 00:00:00 2001 From: Rafael Rivera Date: Sun, 19 Jul 2015 18:13:06 -0700 Subject: [PATCH 13/23] Add drop shadow and window border adornments (closes #2) --- EarTrumpet/Extensions/BlurWindowExtensions.cs | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/EarTrumpet/Extensions/BlurWindowExtensions.cs b/EarTrumpet/Extensions/BlurWindowExtensions.cs index 8abf8d996..f498a587f 100644 --- a/EarTrumpet/Extensions/BlurWindowExtensions.cs +++ b/EarTrumpet/Extensions/BlurWindowExtensions.cs @@ -1,7 +1,8 @@ -using System; -using System.Runtime.InteropServices; -using System.Windows; -using System.Windows.Interop; +using System; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; +using EarTrumpet.Services; namespace EarTrumpet.Extensions { @@ -23,11 +24,23 @@ internal struct WindowCompositionAttribData [StructLayout(LayoutKind.Sequential)] internal struct AccentPolicy { - public AccentState AccentState; - public int AccentFlags; + public AccentState AccentState; + public AccentFlags AccentFlags; public int GradientColor; public int AnimationId; - } + } + + [Flags] + internal enum AccentFlags + { + // ... + DrawLeftBorder = 0x20, + DrawTopBorder = 0x40, + DrawRightBorder = 0x80, + DrawBottomBorder = 0x100, + DrawAllBorders = (DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder) + // ... + } internal enum WindowCompositionAttribute { @@ -66,7 +79,8 @@ private static void SetAccentPolicy(Window window, Interop.AccentState accentSta var windowHelper = new WindowInteropHelper(window); var accent = new Interop.AccentPolicy(); - accent.AccentState = accentState; + accent.AccentState = accentState; + accent.AccentFlags = GetAccentFlagsForTaskbarPosition(); var accentStructSize = Marshal.SizeOf(accent); @@ -82,5 +96,31 @@ private static void SetAccentPolicy(Window window, Interop.AccentState accentSta Marshal.FreeHGlobal(accentPtr); } + + private static Interop.AccentFlags GetAccentFlagsForTaskbarPosition() + { + var flags = Interop.AccentFlags.DrawAllBorders; + + switch(TaskbarService.TaskbarPosition) + { + case TaskbarPosition.Top: + flags &= ~Interop.AccentFlags.DrawTopBorder; + break; + + case TaskbarPosition.Bottom: + flags &= ~Interop.AccentFlags.DrawBottomBorder; + break; + + case TaskbarPosition.Left: + flags &= ~Interop.AccentFlags.DrawLeftBorder; + break; + + case TaskbarPosition.Right: + flags &= ~Interop.AccentFlags.DrawRightBorder; + break; + } + + return flags; + } } } From 65fae2c73108e0ed9fc1dd1f8021d6365348260e Mon Sep 17 00:00:00 2001 From: Rafael Rivera Date: Sun, 19 Jul 2015 18:14:27 -0700 Subject: [PATCH 14/23] Untabify --- EarTrumpet/Extensions/BlurWindowExtensions.cs | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/EarTrumpet/Extensions/BlurWindowExtensions.cs b/EarTrumpet/Extensions/BlurWindowExtensions.cs index f498a587f..130d960a4 100644 --- a/EarTrumpet/Extensions/BlurWindowExtensions.cs +++ b/EarTrumpet/Extensions/BlurWindowExtensions.cs @@ -25,22 +25,22 @@ internal struct WindowCompositionAttribData internal struct AccentPolicy { public AccentState AccentState; - public AccentFlags AccentFlags; + public AccentFlags AccentFlags; public int GradientColor; public int AnimationId; } - [Flags] - internal enum AccentFlags - { - // ... - DrawLeftBorder = 0x20, - DrawTopBorder = 0x40, - DrawRightBorder = 0x80, - DrawBottomBorder = 0x100, - DrawAllBorders = (DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder) - // ... - } + [Flags] + internal enum AccentFlags + { + // ... + DrawLeftBorder = 0x20, + DrawTopBorder = 0x40, + DrawRightBorder = 0x80, + DrawBottomBorder = 0x100, + DrawAllBorders = (DrawLeftBorder | DrawTopBorder | DrawRightBorder | DrawBottomBorder) + // ... + } internal enum WindowCompositionAttribute { @@ -80,7 +80,7 @@ private static void SetAccentPolicy(Window window, Interop.AccentState accentSta var accent = new Interop.AccentPolicy(); accent.AccentState = accentState; - accent.AccentFlags = GetAccentFlagsForTaskbarPosition(); + accent.AccentFlags = GetAccentFlagsForTaskbarPosition(); var accentStructSize = Marshal.SizeOf(accent); @@ -97,30 +97,30 @@ private static void SetAccentPolicy(Window window, Interop.AccentState accentSta Marshal.FreeHGlobal(accentPtr); } - private static Interop.AccentFlags GetAccentFlagsForTaskbarPosition() - { - var flags = Interop.AccentFlags.DrawAllBorders; + private static Interop.AccentFlags GetAccentFlagsForTaskbarPosition() + { + var flags = Interop.AccentFlags.DrawAllBorders; - switch(TaskbarService.TaskbarPosition) - { - case TaskbarPosition.Top: - flags &= ~Interop.AccentFlags.DrawTopBorder; - break; + switch(TaskbarService.TaskbarPosition) + { + case TaskbarPosition.Top: + flags &= ~Interop.AccentFlags.DrawTopBorder; + break; - case TaskbarPosition.Bottom: - flags &= ~Interop.AccentFlags.DrawBottomBorder; - break; + case TaskbarPosition.Bottom: + flags &= ~Interop.AccentFlags.DrawBottomBorder; + break; - case TaskbarPosition.Left: - flags &= ~Interop.AccentFlags.DrawLeftBorder; - break; + case TaskbarPosition.Left: + flags &= ~Interop.AccentFlags.DrawLeftBorder; + break; - case TaskbarPosition.Right: - flags &= ~Interop.AccentFlags.DrawRightBorder; - break; - } + case TaskbarPosition.Right: + flags &= ~Interop.AccentFlags.DrawRightBorder; + break; + } - return flags; - } + return flags; + } } } From b3ec1bd274b53ceb8655771ea1006dd59637246b Mon Sep 17 00:00:00 2001 From: GoldenTao Date: Mon, 20 Jul 2015 19:11:10 +1000 Subject: [PATCH 15/23] Allow for main taskbar to not be on primary screen. --- EarTrumpet/MainWindow.xaml.cs | 6 +++--- EarTrumpet/Services/TaskbarService.cs | 22 ++++++++++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/EarTrumpet/MainWindow.xaml.cs b/EarTrumpet/MainWindow.xaml.cs index 7454fea69..a32e8b6a6 100644 --- a/EarTrumpet/MainWindow.xaml.cs +++ b/EarTrumpet/MainWindow.xaml.cs @@ -147,10 +147,10 @@ private void UpdateWindowPosition() LayoutRoot.Measure(new Size(double.PositiveInfinity, MaxHeight)); Height = LayoutRoot.DesiredSize.Height; - var desktopWorkingArea = SystemParameters.WorkArea; + var taskbarScreenWorkArea = TaskbarService.TaskbarScreen.WorkingArea; var taskbarPosition = TaskbarService.TaskbarPosition; - Left = (taskbarPosition == TaskbarPosition.Left) ? desktopWorkingArea.Left : desktopWorkingArea.Right - Width; - Top = (taskbarPosition == TaskbarPosition.Top) ? desktopWorkingArea.Top : desktopWorkingArea.Bottom - Height; + Left = (taskbarPosition == TaskbarPosition.Left) ? taskbarScreenWorkArea.Left : taskbarScreenWorkArea.Right - Width; + Top = (taskbarPosition == TaskbarPosition.Top) ? taskbarScreenWorkArea.Top : taskbarScreenWorkArea.Bottom - Height; } } } diff --git a/EarTrumpet/Services/TaskbarService.cs b/EarTrumpet/Services/TaskbarService.cs index b9eb4ba40..3324e6720 100644 --- a/EarTrumpet/Services/TaskbarService.cs +++ b/EarTrumpet/Services/TaskbarService.cs @@ -1,7 +1,9 @@ using System; using System.Drawing; +using System.Linq; using System.Runtime.InteropServices; using System.Windows; +using System.Windows.Forms; namespace EarTrumpet.Services { @@ -27,17 +29,29 @@ public static TaskbarPosition TaskbarPosition get { var rect = TaskbarPostionRect; - if (rect.Bottom == SystemParameters.PrimaryScreenHeight && rect.Top == 0) + var screen = TaskbarScreen; + if (screen == null) return TaskbarPosition.Bottom; + + if (rect.Bottom == screen.Bounds.Bottom && rect.Top == screen.Bounds.Top) { - return (rect.Left == 0) ? TaskbarPosition.Left : TaskbarPosition.Right; + return (rect.Left == screen.Bounds.Left) ? TaskbarPosition.Left : TaskbarPosition.Right; } - if (rect.Right == SystemParameters.PrimaryScreenWidth && rect.Left == 0) + if (rect.Right == screen.Bounds.Right && rect.Left == screen.Bounds.Left) { - return (rect.Top == 0) ? TaskbarPosition.Top : TaskbarPosition.Bottom; + return (rect.Top == screen.Bounds.Top) ? TaskbarPosition.Top : TaskbarPosition.Bottom; } return TaskbarPosition.Bottom; } } + + public static Screen TaskbarScreen + { + get + { + var rect = TaskbarPostionRect; + return Screen.AllScreens.FirstOrDefault(x => x.Bounds.Contains(rect)); + } + } } public static class User32 From 3b055a9f623290d95604a154f36cf4cef767bab0 Mon Sep 17 00:00:00 2001 From: GoldenTao Date: Mon, 20 Jul 2015 19:12:51 +1000 Subject: [PATCH 16/23] Linq statement was too complex, reversed. --- EarTrumpet/ViewModels/AudioMixerViewModel.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/EarTrumpet/ViewModels/AudioMixerViewModel.cs b/EarTrumpet/ViewModels/AudioMixerViewModel.cs index 7283675a4..85bd368ce 100644 --- a/EarTrumpet/ViewModels/AudioMixerViewModel.cs +++ b/EarTrumpet/ViewModels/AudioMixerViewModel.cs @@ -48,9 +48,16 @@ public void Refresh() var sessions = _audioService.GetAudioSessionGroups().Select(x => new AppItemViewModel(_proxy, x)); - List staleSessionsToRemove = Apps.Where(app => !sessions.Any(x => (x.IsSame(app) && (!app.IsDesktop || UserPreferencesService.ShowDesktopApps)))).ToList(); + List staleSessionsToRemove = new List(); // remove stale apps + foreach (var app in Apps) + { + if (!sessions.Where(x => (x.IsSame(app) && (!app.IsDesktop || UserPreferencesService.ShowDesktopApps))).Any()) + { + staleSessionsToRemove.Add(app); + } + } foreach (var app in staleSessionsToRemove) { Apps.Remove(app); } // add new apps From 03a5ac4f84889edd01409f940321ec8b63c9a7f8 Mon Sep 17 00:00:00 2001 From: GoldenTao Date: Mon, 20 Jul 2015 19:35:58 +1000 Subject: [PATCH 17/23] Add single instance. Fixes #13 --- EarTrumpet/App.xaml | 2 +- EarTrumpet/App.xaml.cs | 28 +++++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/EarTrumpet/App.xaml b/EarTrumpet/App.xaml index 176b2f05b..b3f4c64ae 100644 --- a/EarTrumpet/App.xaml +++ b/EarTrumpet/App.xaml @@ -1,5 +1,5 @@  + Startup="Application_Startup" Exit="App_OnExit"> diff --git a/EarTrumpet/App.xaml.cs b/EarTrumpet/App.xaml.cs index 2cd3e1a80..9c2ccfe9c 100644 --- a/EarTrumpet/App.xaml.cs +++ b/EarTrumpet/App.xaml.cs @@ -1,12 +1,38 @@ -using System.Windows; +using System.Globalization; +using System.Reflection; +using System.Threading; +using System.Windows; namespace EarTrumpet { public partial class App { + private Mutex _mMutex; + private void Application_Startup(object sender, StartupEventArgs e) { + var assembly = Assembly.GetExecutingAssembly(); + bool mutexCreated; + var mutexName = string.Format(CultureInfo.InvariantCulture, "Local\\{{{0}}}{{{1}}}", assembly.GetType().GUID, assembly.GetName().Name); + + _mMutex = new Mutex(true, mutexName, out mutexCreated); + + if (!mutexCreated) + { + _mMutex = null; + Current.Shutdown(); + return; + } + new MainWindow(); } + + private void App_OnExit(object sender, ExitEventArgs e) + { + if (_mMutex == null) return; + _mMutex.ReleaseMutex(); + _mMutex.Close(); + _mMutex = null; + } } } From 34e8c7585b1de50c46391f06a99700c10baaeca5 Mon Sep 17 00:00:00 2001 From: Abraham Hinteregger Date: Mon, 20 Jul 2015 13:07:46 +0200 Subject: [PATCH 18/23] slider mousewheel event also simplified the bounding in the SetPositionByControlPoint function --- EarTrumpet/EarTrumpet.csproj | 1 + EarTrumpet/Extensions/DoubleExtensions.cs | 16 ++++++++++++++++ EarTrumpet/Extensions/SliderExtensions.cs | 7 ++++++- EarTrumpet/MainWindow.xaml | 1 + EarTrumpet/MainWindow.xaml.cs | 7 +++++++ 5 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 EarTrumpet/Extensions/DoubleExtensions.cs diff --git a/EarTrumpet/EarTrumpet.csproj b/EarTrumpet/EarTrumpet.csproj index 7d0a12b79..f3ea7e4cc 100644 --- a/EarTrumpet/EarTrumpet.csproj +++ b/EarTrumpet/EarTrumpet.csproj @@ -58,6 +58,7 @@ MSBuild:Compile Designer + diff --git a/EarTrumpet/Extensions/DoubleExtensions.cs b/EarTrumpet/Extensions/DoubleExtensions.cs new file mode 100644 index 000000000..4d679d3f4 --- /dev/null +++ b/EarTrumpet/Extensions/DoubleExtensions.cs @@ -0,0 +1,16 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; +using EarTrumpet.Services; + +namespace EarTrumpet.Extensions +{ + static class DoubleExtensions + { + public static double Bound(this double val, double min, double max) + { + return Math.Max(min, Math.Min(max, val)); + } + } +} diff --git a/EarTrumpet/Extensions/SliderExtensions.cs b/EarTrumpet/Extensions/SliderExtensions.cs index d9bfa31db..4b95ef117 100644 --- a/EarTrumpet/Extensions/SliderExtensions.cs +++ b/EarTrumpet/Extensions/SliderExtensions.cs @@ -9,7 +9,12 @@ public static void SetPositionByControlPoint(this Slider slider, Point point) { var percent = point.X / slider.ActualWidth; var newValue = (slider.Maximum - slider.Minimum) * percent; - slider.Value = (newValue > slider.Maximum ? slider.Maximum : (newValue < slider.Minimum ? slider.Minimum : newValue)); + slider.Value = newValue.Bound(slider.Minimum,slider.Maximum); + } + + public static void ChangePositionByAmount(this Slider slider, double amount) + { + slider.Value = (slider.Value + amount).Bound(slider.Minimum, slider.Maximum); } } } diff --git a/EarTrumpet/MainWindow.xaml b/EarTrumpet/MainWindow.xaml index 435987630..26e1bd858 100644 --- a/EarTrumpet/MainWindow.xaml +++ b/EarTrumpet/MainWindow.xaml @@ -220,6 +220,7 @@ TouchMove="Slider_TouchMove" PreviewMouseDown="Slider_MouseDown" PreviewMouseUp="Slider_MouseUp" + MouseWheel="MouseWheel_Manipulation" MouseMove="Slider_MouseMove" /> Date: Tue, 21 Jul 2015 09:59:27 +0200 Subject: [PATCH 19/23] fixed naming/formatting added spaces and renamed mousewheel function --- EarTrumpet/MainWindow.xaml | 2 +- EarTrumpet/MainWindow.xaml.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/EarTrumpet/MainWindow.xaml b/EarTrumpet/MainWindow.xaml index 26e1bd858..4eb360657 100644 --- a/EarTrumpet/MainWindow.xaml +++ b/EarTrumpet/MainWindow.xaml @@ -220,7 +220,7 @@ TouchMove="Slider_TouchMove" PreviewMouseDown="Slider_MouseDown" PreviewMouseUp="Slider_MouseUp" - MouseWheel="MouseWheel_Manipulation" + MouseWheel="Slider_MouseWheel" MouseMove="Slider_MouseMove" /> Date: Sat, 1 Aug 2015 17:26:57 +1000 Subject: [PATCH 20/23] Initial hack for missing image. #17 --- EarTrumpet/ViewModels/AppItemViewModel.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/EarTrumpet/ViewModels/AppItemViewModel.cs b/EarTrumpet/ViewModels/AppItemViewModel.cs index 60f20aa56..eaf251485 100644 --- a/EarTrumpet/ViewModels/AppItemViewModel.cs +++ b/EarTrumpet/ViewModels/AppItemViewModel.cs @@ -85,7 +85,10 @@ public AppItemViewModel(IAudioMixerViewModelCallback callback, EarTrumpetAudioSe } else { - Icon = new BitmapImage(new Uri(session.IconPath)); + if (File.Exists(session.IconPath)) //hack until we invoke the resource manager correctly. + { + Icon = new BitmapImage(new Uri(session.IconPath)); + } Background = new SolidColorBrush(AccentColorService.FromABGR(session.BackgroundColor)); } } From 3ce137be50f90bcad2748412233160c1a301ab99 Mon Sep 17 00:00:00 2001 From: Rafael Rivera Date: Sat, 1 Aug 2015 00:37:58 -0700 Subject: [PATCH 21/23] Hollowed out readme for now --- README.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 43d53484d..6eb3c5380 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,11 @@ ![Ear Trumpet Screenshot](https://pbs.twimg.com/media/CJoDCsjUMAAeWq7.png:large) -Ear Trumpet is a volume control app for Windows. Frustrated with the lack of volume controls for Modern apps in Windows 8, 8.1 and 10, we created Ear Trumpet. The app was quickly expanded to also allow the control of Windows Desktop apps. - -To show Windows Desktop apps, right-click the Ear Trumpet icon in the tray and click Show Desktop Apps. - -## Supported Versions ## +## Supported operating systems ## - Windows 10 ## Credits ## +- David Golden (@GoldenTao) +- Rafael Rivera (@RiveraR) -Originally created by David Golden (@GoldenTao) and Rafael Rivera (@RiveraR) - -Icon created by Artjom Kormanfrom from the Noun Project +*Ear Trumpet* icon created by Artjom Kormanfrom from the Noun Project From 1ed893246b5771c5b780818ead94d9a320f81b22 Mon Sep 17 00:00:00 2001 From: Rafael Rivera Date: Sat, 1 Aug 2015 00:43:09 -0700 Subject: [PATCH 22/23] Rev up --- EarTrumpet/Properties/AssemblyInfo.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EarTrumpet/Properties/AssemblyInfo.cs b/EarTrumpet/Properties/AssemblyInfo.cs index d7bf04dc8..dd824b700 100644 --- a/EarTrumpet/Properties/AssemblyInfo.cs +++ b/EarTrumpet/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.InteropServices; using System.Windows; @@ -10,7 +10,7 @@ [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] [assembly: ComVisible(false)] -[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] \ No newline at end of file +[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] From 0c9974380ccb01b1e1c8485dfb71ff8f9dbb352f Mon Sep 17 00:00:00 2001 From: GoldenTao Date: Sat, 1 Aug 2015 17:44:22 +1000 Subject: [PATCH 23/23] Add AppId to install for future version updates. --- EarTrumpet/EarTrumpet.iss | 1 + 1 file changed, 1 insertion(+) diff --git a/EarTrumpet/EarTrumpet.iss b/EarTrumpet/EarTrumpet.iss index da46d487d..3e63bf729 100644 --- a/EarTrumpet/EarTrumpet.iss +++ b/EarTrumpet/EarTrumpet.iss @@ -3,6 +3,7 @@ [Setup] AppName=Ear Trumpet AppVersion={#AppVer} +AppId=BA8684A3-9834-4D78-A666-04E88FF0EC82 VersionInfoVersion={#AppVer} DefaultDirName={pf}\Ear Trumpet DefaultGroupName=Ear Trumpet