Created
December 26, 2016 18:44
-
-
Save VelocityRa/79e91d1521e88fefad128a6c5498be00 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SpotifyAdMuter.cpp : Defines the entry point for the console application. | |
// | |
#include <iostream> | |
#include <string> | |
#include <windows.h> | |
#include <stdio.h> | |
#include <tlhelp32.h> | |
#include <stdlib.h> | |
#include <cassert> | |
#ifdef _DEBUG | |
static bool debug = true; | |
#else | |
static bool debug = false; | |
#endif | |
namespace std { | |
#if defined _UNICODE || defined UNICODE | |
typedef wstring tstring; | |
#else | |
typedef string tstring; | |
#endif | |
} | |
using namespace std; | |
const string APP_VERSION = "0.8"; | |
struct handle_data { | |
unsigned long process_id; | |
HWND best_handle; | |
}; | |
BOOL CALLBACK enumWindowsProc(HWND handle, LPARAM lParam) | |
{ | |
handle_data& data = *reinterpret_cast<handle_data*>(lParam); | |
unsigned long process_id = 0; | |
GetWindowThreadProcessId(handle, &process_id); | |
if (data.process_id != process_id) { | |
return TRUE; | |
} | |
data.best_handle = handle; // Found a matching PID, save the handle | |
return FALSE; // and stop searching | |
} | |
HWND GetSpofifyWindowHandle(DWORD process_id) | |
{ | |
cout << "Finding Spotify window handle...\n"; | |
handle_data data; | |
data.process_id = process_id; | |
data.best_handle = nullptr; | |
if (!EnumWindows(enumWindowsProc, LPARAM(&data))) | |
cout << "Found Spotify window handle.\n\n"; | |
else | |
{ | |
cerr << "Couldn't find Spotify window handle\n"; | |
getchar(); | |
exit(EXIT_FAILURE); | |
} | |
return data.best_handle; | |
} | |
// Returns how many processes it found. Should be 3 for Spotify | |
int FindProcessID(const char* p_ProcessName, DWORD processes[]) | |
{ | |
PROCESSENTRY32 s_ProcessEntry; | |
s_ProcessEntry.dwSize = sizeof(PROCESSENTRY32); | |
HANDLE s_Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); | |
auto processCount = 0; | |
if (Process32First(s_Snapshot, &s_ProcessEntry)) | |
{ | |
while (Process32Next(s_Snapshot, &s_ProcessEntry) && processCount < 3) // Spotify always has 3 processes running | |
{ | |
if (_stricmp(s_ProcessEntry.szExeFile, p_ProcessName) == 0) | |
{ | |
processes[processCount] = s_ProcessEntry.th32ProcessID; | |
processCount++; | |
} | |
} | |
} | |
CloseHandle(s_Snapshot); | |
return processCount; | |
} | |
int LocateSpotifyProcesses(DWORD processes[]) | |
{ | |
auto processesFound = -1; | |
auto waitingForSpotify = false; | |
cout << "Locating Spotify processes... \n"; | |
while (processesFound != 3) | |
{ | |
processesFound = FindProcessID("Spotify.exe", processes); | |
if (processesFound == 3) | |
{ | |
cout << "Found 3 Spotify processes succesfully.\n\n"; | |
if (debug) | |
{ | |
cout << "PIDs:\n"; | |
for (auto i = 0; i < processesFound; i++) | |
cout << " - " << processes[i] << endl; | |
cout << endl; | |
} | |
} | |
else | |
{ | |
if (!waitingForSpotify) | |
{ | |
waitingForSpotify = true; | |
cout << "Couldn't find 3 processes, found " << processesFound << " instead.\n\n"; | |
cout << "Make sure Spotify is running.\n"; | |
} | |
Sleep(1000); | |
} | |
} | |
return 0; | |
} | |
string GetWindowTitle(HWND handle) | |
{ | |
auto length = ::GetWindowTextLength(handle); | |
TCHAR* buffer; | |
buffer = new TCHAR[length + 1]; | |
memset(buffer, 0, (length + 1) * sizeof(TCHAR)); | |
if (!GetWindowText(handle, buffer, length + 1)) | |
{ | |
cerr << "Title bar is empty, or window handle is invalid.\n"; | |
getchar(); | |
exit(EXIT_FAILURE); | |
} | |
auto windowTitle = tstring(buffer); | |
if(debug) | |
//cout << handle << TEXT(": ") << windowTitle << endl; | |
delete[] buffer; | |
return windowTitle; | |
} | |
void initApplication() | |
{ | |
SetConsoleTitleA("Spotify Ad Muter - v1.0"); | |
cout << string(35, '='); | |
cout << "\n|| Spotify Ad Muter v" + APP_VERSION + " ||\n"; | |
cout << string(35, '=') << "\n\n"; | |
} | |
// Returns true if currently playing, false if paused | |
bool ReadPlayingStatus(DWORD processID) | |
{ | |
// Get a handle to the process. | |
HANDLE hProcess = OpenProcess( | |
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, | |
FALSE, | |
processID | |
); | |
if (!hProcess) | |
{ | |
cerr << "Couldn't open Spotify process."; | |
getchar(); | |
} | |
DWORD playingStatusAdress = 0xF5DC58; // This is the address that we want to read from | |
unsigned char value = 0; // This will store our value. In my case, its an integer, which is the timer | |
ReadProcessMemory(hProcess, reinterpret_cast<void*>(playingStatusAdress), &value, sizeof(value), nullptr); | |
// Byte is either 3 for playing or 5 for paused | |
assert(value == 3 || value == 5, "Adress needs updating."); | |
return value == 3; | |
} | |
int main() | |
{ | |
DWORD processes[3]; | |
bool playing; | |
const auto filler = string(100, ' '); | |
initApplication(); | |
LocateSpotifyProcesses(processes); | |
// Use the first found PID to find the window handle (any one of the 3 works) | |
auto spotifyHandle = GetSpofifyWindowHandle(processes[2]); | |
if(debug) | |
cout << "Spotify window handle: " << spotifyHandle << endl; | |
while(1) | |
{ | |
playing = ReadPlayingStatus(processes[0]); | |
cout << "\rStatus: "; | |
if (playing) | |
cout << "Playing " + GetWindowTitle(spotifyHandle); | |
else | |
cout << "Paused" << filler; | |
Sleep(500); | |
} | |
getchar(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment