-
Notifications
You must be signed in to change notification settings - Fork 166
Add Mod: Taskbar Music Lounge #2746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
A sleek, pill-shaped music ticker for your Windows 11 taskbar. It sits unobtrusively in the corner, scrolling your current track and providing quick media controls.
|
Thank you for the submission. It doesn't look so well on a light theme:
Also, this mod has no good reason to run as part of explorer.exe, except that it's convenient. We discussed it here: #1916 (comment)
Currently, Windhawk doesn't have a built-in functionality for something like that, but for now, I implemented some code that can be added to a mod to make it run as part of a separate windhawk.exe process: Details
////////////////////////////////////////////////////////////////////////////////
// Windhawk tool mod implementation for mods which don't need to inject to other
// processes or hook other functions. Context:
// https://github.com/ramensoftware/windhawk-mods/pull/1916
//
// The mod will load and run in a dedicated windhawk.exe process.
//
// Paste the code below as part of the mod code, and use these callbacks:
// * WhTool_ModInit
// * WhTool_ModSettingsChanged
// * WhTool_ModUninit
//
// Currently, other callbacks are not supported.
bool g_isToolModProcessLauncher;
HANDLE g_toolModProcessMutex;
void WINAPI EntryPoint_Hook() {
Wh_Log(L">");
ExitThread(0);
}
BOOL Wh_ModInit() {
bool isService = false;
bool isToolModProcess = false;
bool isCurrentToolModProcess = false;
int argc;
LPWSTR* argv = CommandLineToArgvW(GetCommandLine(), &argc);
if (!argv) {
Wh_Log(L"CommandLineToArgvW failed");
return FALSE;
}
for (int i = 1; i < argc; i++) {
if (wcscmp(argv[i], L"-service") == 0) {
isService = true;
break;
}
}
for (int i = 1; i < argc - 1; i++) {
if (wcscmp(argv[i], L"-tool-mod") == 0) {
isToolModProcess = true;
if (wcscmp(argv[i + 1], WH_MOD_ID) == 0) {
isCurrentToolModProcess = true;
}
break;
}
}
LocalFree(argv);
if (isService) {
return FALSE;
}
if (isCurrentToolModProcess) {
g_toolModProcessMutex =
CreateMutex(nullptr, TRUE, L"windhawk-tool-mod_" WH_MOD_ID);
if (!g_toolModProcessMutex) {
Wh_Log(L"CreateMutex failed");
ExitProcess(1);
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
Wh_Log(L"Tool mod already running (%s)", WH_MOD_ID);
ExitProcess(1);
}
if (!WhTool_ModInit()) {
ExitProcess(1);
}
IMAGE_DOS_HEADER* dosHeader =
(IMAGE_DOS_HEADER*)GetModuleHandle(nullptr);
IMAGE_NT_HEADERS* ntHeaders =
(IMAGE_NT_HEADERS*)((BYTE*)dosHeader + dosHeader->e_lfanew);
DWORD entryPointRVA = ntHeaders->OptionalHeader.AddressOfEntryPoint;
void* entryPoint = (BYTE*)dosHeader + entryPointRVA;
Wh_SetFunctionHook(entryPoint, (void*)EntryPoint_Hook, nullptr);
return TRUE;
}
if (isToolModProcess) {
return FALSE;
}
g_isToolModProcessLauncher = true;
return TRUE;
}
void Wh_ModAfterInit() {
if (!g_isToolModProcessLauncher) {
return;
}
WCHAR currentProcessPath[MAX_PATH];
switch (GetModuleFileName(nullptr, currentProcessPath,
ARRAYSIZE(currentProcessPath))) {
case 0:
case ARRAYSIZE(currentProcessPath):
Wh_Log(L"GetModuleFileName failed");
return;
}
WCHAR
commandLine[MAX_PATH + 2 +
(sizeof(L" -tool-mod \"" WH_MOD_ID "\"") / sizeof(WCHAR)) - 1];
swprintf_s(commandLine, L"\"%s\" -tool-mod \"%s\"", currentProcessPath,
WH_MOD_ID);
HMODULE kernelModule = GetModuleHandle(L"kernelbase.dll");
if (!kernelModule) {
kernelModule = GetModuleHandle(L"kernel32.dll");
if (!kernelModule) {
Wh_Log(L"No kernelbase.dll/kernel32.dll");
return;
}
}
using CreateProcessInternalW_t = BOOL(WINAPI*)(
HANDLE hUserToken, LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, WINBOOL bInheritHandles,
DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation,
PHANDLE hRestrictedUserToken);
CreateProcessInternalW_t pCreateProcessInternalW =
(CreateProcessInternalW_t)GetProcAddress(kernelModule,
"CreateProcessInternalW");
if (!pCreateProcessInternalW) {
Wh_Log(L"No CreateProcessInternalW");
return;
}
STARTUPINFO si{
.cb = sizeof(STARTUPINFO),
.dwFlags = STARTF_FORCEOFFFEEDBACK,
};
PROCESS_INFORMATION pi;
if (!pCreateProcessInternalW(nullptr, currentProcessPath, commandLine,
nullptr, nullptr, FALSE, NORMAL_PRIORITY_CLASS,
nullptr, nullptr, &si, &pi, nullptr)) {
Wh_Log(L"CreateProcess failed");
return;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
void Wh_ModSettingsChanged() {
if (g_isToolModProcessLauncher) {
return;
}
WhTool_ModSettingsChanged();
}
void Wh_ModUninit() {
if (g_isToolModProcessLauncher) {
return;
}
WhTool_ModUninit();
ExitProcess(0);
}Please do the following:
Please try it and let me know if it behaves as expected in all cases. If it is, let's adapt it. In the future, such functionality might become part of Windhawk. |
Code Refactor: - Relies on windhawk process instead of direct injection - Added theme support
|
Hello! Thanks for your reply. I have implemented your suggested changes. Please check |
|
Thanks. Why did you make changes in the code, such as replacing |
|
Sorry, my bad, I did that for my personal code understanding. I fixed it now. |
mods/taskbar-music-lounge.wh.cpp
Outdated
| *pResult = title; | ||
| return FALSE; | ||
| } | ||
| if (title.find(L"Spotify") != wstring::npos && title.find(L" - ") != wstring::npos) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, the mod only supports YouTube Music and Spotify, it makes sense to mention it in the readme.
By the way, you might prefer using GlobalSystemMediaTransportControlsSessionManager for a universal solution. You can take a look at this pull request for a reference:
m417z/my-windhawk-mods#34
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, the mod only supports YouTube Music and Spotify, it makes sense to mention it in the readme.
Noted, I will make the changes accordingly.
you might prefer using GlobalSystemMediaTransportControlsSessionManager for a universal solution.
I needed some advice regarding that, Implementing GSMTC in C++ requires using WinRT interfaces, wont this add significant complexity, new libraries, and potential stability issues??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wont this add significant complexity
Depends on the implementation, generally it shouldn't.
new libraries
Sure, but that shouldn't be an issue.
and potential stability issues
That, too, depends on the implementation, but the WinRT APIs themselves aren't unstable or something, they are used by Windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Also, I have another question, I want to use DWM native rounding which available only on Win11, should I use that or stay windows version neutral?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's up to you. Windows 11 has rounded design and Windows 10 doesn't so I think it'd be a good fit, but if you want to leave it up to the user to you can add an option for that.
| g_Settings.offsetY = Wh_GetIntSetting(L"OffsetY"); | ||
| g_Settings.autoTheme = Wh_GetIntSetting(L"AutoTheme") != 0; | ||
|
|
||
| PCWSTR textHex = Wh_GetStringSetting(L"TextColor"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A call to Wh_FreeStringSetting to free the string is missing, here and below.
|
Sorry, but I really wonder, if the mod affects only the taskbar and would be useless without Explorer running, is not it natural to run it inside Explorer.exe?... |
|
The mod doesn't affect the taskbar in the technical sense. It acts like a separate app which creates a window and positions it on the screen. It so happens that it chooses to position it on top of the taskbar. It also means that there are quirks such as when too many taskbar items are opened, they appear beneath the music lounge window. Also, due to that technical design, it can run without Explorer and without the taskbar, it will just keep appearing at the corner of the screen. |
|
Thanks, this clears it up. |
|
Is this mod intended to be something similar to AudioBand and modern like FluentFlyout? |
Added DWM and GSMTC Implementation for Win11
|
@m417z Hello! sorry for this delay and silence, I got busy with some work. I have made some changes as discussed; hope you like them!
I havent really implemented this part yet, I will think about it and maybe develop that too but maybe not right now.
@AlwaysBorderRadius I initially didnt plan for this, but now you got me interested🤔 |
|
I'll take a look later. Looks promising at a first glance over the code. Just one thing I noticed for now: please restore the "Windhawk tool mod launcher code" area to the original code I posted. There are several mods using this code, and unless there's a good reason to change it, keeping it unified making it easier to manage. |
|
@Hashah2311 Damn, you got me hyped now haha. I would love to see that become a reality!!! |
* Replaced the topmost timer with notification Z-Band usage. Made the mod target explorer.exe and not windhawk.exe for it to work. * Fixed the process failing to exit by clearing g_SessionManager in the right thread. * Reverted to the original Windhawk tool mod code (mostly formatting and logs).
|
I played with the new version and it's really nice, well done! I made some small improvements:
I also made it so that the window can no longer be closed with Alt+F4. I meant to post the changes as suggestions, but it ended up as a commit: @Hashah2311 please take a look, let me know if the changes look good to you, and if there's anything else you'd like to change. If it looks good, I'll go ahead and merge it. |
|
This looks perfect! lets merge it. |
|
@SpacEagle17 probably the easiest way is to set an AppID to the mod's process, and then use it in "Taskbar auto-hide when maximized". To set an AppID as "taskbar-music-lounge", add these two lines: #include <windows.h>
+#include <shobjidl.h>
#include <shellapi.h>
#include <dwmapi.h>
#include <gdiplus.h> // --- CALLBACKS ---
BOOL WhTool_ModInit() {
+ SetCurrentProcessExplicitAppUserModelID(L"taskbar-music-lounge");
LoadSettings();
g_Running = true;
g_pMediaThread = new std::thread(MediaThread);@Hashah2311 you might want to add it to the mod in the next update. |
It was discussed here, you might want to try the proposed solution: 2eddf69#commitcomment-173045991 |
And once again, all changes mentioned there made this perfect! Yep those changes linked above and the AppUserModelID should for sure be in the next update of this mod! Works all as expected and perfectly! Also, with the taskbar styler mod and a modified taskbar to make it narrower, for example the glass theme one does not even have to disable widgets (visible in my video shared earlier in this thread). Just wanted to mention that, as it was stated in the readme to be incompatible. Just another report: |
|
That's a quite nice tool! A few observations:
|
|
Prerequisite: This is a continuation of my "Issue" here: #2828 Hey @Hashah2311, 1: I want to say if you haven't read the "issue" I created before, I am incredibly grateful for this mod man, I have been looking for something exactly like this as a Rainmeter skin and just wanted to say thank you and sorry if any of this sounds assertive or anything like im taking over your amazing work you likely spent a LOT more time into than me just doing this. Anyway, I've spent some time extensively reworking the mod, This version fixes a fair amount of issues others have experienced (like auto-hide lag and it remaining visible in fullscreen apps) and improves general stability. Could you please review the code below and consider pushing it as an official update? ========================================================
Summary of changes: To fix the Auto-Hide, Fullscreen, and High-DPI issues, the logic was overhauled from a "guessing" system to a "listening" system. Here is the breakdown:
Personal TODOs:
|
|
Hey @Cinabutts and everyone, |
|
If no media is playing it should also hide itself imho. I've implemented this change locally. |
Major update: Comprehensive fixes for v4 This version addresses and incorporates multiple suggestions. A detailed diff table has been added to the README. Addressed Issues & Fixes: * [#3666395914](ramensoftware#2746 (comment)) * [#3666527577](ramensoftware#2746 (comment)) * [2eddf69](ramensoftware@2eddf69#commitcomment-173045991) * [#3671818092](ramensoftware#2746 (comment)) * [ramensoftware#2828](ramensoftware#2828) * [#3689038965](ramensoftware#2746 (comment)) * [#3690241518](ramensoftware#2746 (comment)) Credits: Special thanks to @Cinabutts and @Deykii for code references and the community for testing. Testing Note: AIMP and MPC-BE integration is implemented but currently untested. Please report any issues with these players.
|
Check out the newest version v4. |
|
@Hashah2311 please create a new pull request. |
|
Hey @Hashah2311 thanks for pushing some of my code, here's my latest version if you're interested. It's main changes is regarding the background, in this version you are being able to set a custom background color when auto hide is off, or if you leave it default 0,0,0 it sticks with the original light/dark theme and i've added the option to invert the mods perceived mode. My next plan is to add a toggle-able slim progress bar at the top so when the mod auto hides it still shows this progress bar, thus in my mind helps negate the fact that when the taskbar is hidden via auto hide and the widget gets docked, when I hover over the widget it doesn't allow the taskbar to reappear.(maybe that'll be fixed in the later versions?) mod.wh.cpp.zip
|
|
I personally don't think a progress bar for auto hiding is necessary at all. You can keep such changes for your local edit |
probably right, in my mind it just makes since because when it's docked and the taskbar is hidden the widget as said is docked so it still shows a few pixels where it once was, hovering over this whilst auto-hide is on doesn't allow the taskbar to reappear, soo might as well make it useful i feel. but i get it. kinda visually distracting, thus why i said it'd be toggle-able. |








A sleek, pill-shaped music ticker for your Windows 11 taskbar. It sits unobtrusively in the corner, scrolling your current track and providing quick media controls.