Skip to content

Commit

Permalink
Interact with SoundPad using the remote control pipe (which appears t…
Browse files Browse the repository at this point in the history
…o be largely undocumented for whatever reason but we got there eventually)
  • Loading branch information
L-uu committed Feb 29, 2024
1 parent f4afb1e commit 940baba
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 1 deletion.
2 changes: 2 additions & 0 deletions MusicToSoundpad.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
<ItemGroup>
<ClCompile Include="src\main.c" />
<ClCompile Include="src\md5.c" />
<ClCompile Include="src\pipes.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\md5.h" />
<ClInclude Include="src\pipes.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
Expand Down
6 changes: 6 additions & 0 deletions MusicToSoundpad.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@
<ClCompile Include="src\md5.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\pipes.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\md5.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\pipes.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
46 changes: 45 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <wchar.h>
#include <Urlmon.h>
#include "md5.h"
#include "pipes.h"

#pragma comment(lib, "urlmon.lib")

Expand Down Expand Up @@ -97,8 +98,51 @@ BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi;
wchar_t commandLine[MAX_PATH];
swprintf_s(commandLine, MAX_PATH, L"\"utils\\yt-dlp.exe\" -f ba -x ytsearch:\"%s\"", windowTitle);
swprintf_s(commandLine, MAX_PATH, L"\"utils\\yt-dlp.exe\" -f ba -x --audio-format mp3 -o \"%%USERPROFILE%%\\Music\\%s.%%(ext)s\" ytsearch:\"%s\"", windowTitle, windowTitle);
if (CreateProcessW(NULL, commandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
// Wait for the process to finish before continuing
WaitForSingleObject(pi.hProcess, INFINITE);

// FIXME: We need to convert windowTitle from a wide to narrow

// Determine the size of the required buffer
size_t bufferSize = 0;
if (wcstombs_s(&bufferSize, NULL, 0, windowTitle, 0) != 0) {
perror("wcstombs_s");
return 1;
}

// Allocate memory for the narrow character buffer
char* narrowWindowTitle = (char*)malloc(bufferSize + 8); // +1 for null terminator
if (narrowWindowTitle == NULL) {
perror("malloc");
return 1;
}

// Perform the conversion
if (wcstombs_s(NULL, narrowWindowTitle, bufferSize + 1, windowTitle, bufferSize) != 0) {
perror("wcstombs");
free(narrowWindowTitle);
return 1;
}

// We now have to construct a path to the .mp3 file for SoundPad
char userProfile[512];
char path[512];

// Get the value of the USERPROFILE environment variable
char* userProfileEnv = getenv("USERPROFILE");
if (userProfileEnv == NULL) {
fprintf(stderr, "USERPROFILE environment variable not found\n");
return 1;
}

// Construct the path using USERPROFILE
snprintf(path, sizeof(path), "%s\\Music\\%s.mp3", userProfileEnv, narrowWindowTitle);

// Add to SoundPad library and start playing
checkForEntry(getSoundList(), path);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
Expand Down
138 changes: 138 additions & 0 deletions src/pipes.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include "pipes.h"

#define PIPE_NAME "\\\\.\\pipe\\sp_remote_control"
#define BUFFER_SIZE 4096
#define RESPONSE_SIZE 4096

HANDLE pipeHandle = NULL;

void init() {
if (pipeHandle == NULL || pipeHandle == INVALID_HANDLE_VALUE) {
pipeHandle = CreateFileA(
PIPE_NAME,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);

if (pipeHandle == INVALID_HANDLE_VALUE) {
printf("Error opening pipe\n");
exit(EXIT_FAILURE);
}
}
}

void uninit() {
if (pipeHandle != NULL && pipeHandle != INVALID_HANDLE_VALUE) {
CloseHandle(pipeHandle);
pipeHandle = NULL;
}
}

char* sendRequest(const char* request) {
init();

DWORD bytesWritten;
if (!WriteFile(pipeHandle, request, strlen(request), &bytesWritten, NULL)) {
printf("Error writing to pipe\n");
exit(EXIT_FAILURE);
}

char response[RESPONSE_SIZE];
DWORD bytesRead;
if (!ReadFile(pipeHandle, response, RESPONSE_SIZE - 1, &bytesRead, NULL)) {
printf("Error reading from pipe\n");
exit(EXIT_FAILURE);
}
response[bytesRead] = '\0'; // Null-terminate the string

return _strdup(response);
}

int isSuccessPrintResponse(const char* response) {
if (strcmp(response, "R-200") != 0) {
printf("Error: %s\n", response);
return 0;
}
return 1;
}

char* getSoundList() {
char request[BUFFER_SIZE];
snprintf(request, BUFFER_SIZE, "GetSoundlist()");

// Call sendRequest function and store response
char* response = sendRequest(request);
if (response == NULL) {
fprintf(stderr, "Failed to get sound list\n");
return NULL; // Return NULL if sendRequest fails
}

return response;
}

int addSound(const char* url) {
char request[BUFFER_SIZE];
snprintf(request, BUFFER_SIZE, "DoAddSound(\"%s\")", url);
char* response = sendRequest(request);
int success = isSuccessPrintResponse(response);
free(response);
return success;
}

int playSound(const int index) {
char request[BUFFER_SIZE];
snprintf(request, BUFFER_SIZE, "DoPlaySound(%d)", index);
char* response = sendRequest(request);
int success = isSuccessPrintResponse(response);
free(response);
return success;
}

int getIndex(const char* inputCopy, const char* searchTerm) {
int songIndex = 0;
char* context = NULL;
char* line = strtok_s(inputCopy, "\n", &context);
while (line != NULL) {
if (strstr(line, searchTerm) != NULL) {
printf("%s\n", line);
if (sscanf_s(line, "%*[^0-9]%d", &songIndex) == 1) {
printf("Extracted index value: %d\n", songIndex);
}
else {
printf("Failed to extract index value.\n");
return 0;
}
break; // Exit loop after finding the line
}
line = strtok_s(NULL, "\n", &context);
}
return songIndex;
}

int checkForEntry(const char* input, const char* searchTerm) {
int songIndex = getIndex(input, searchTerm);

if (!songIndex) { // Item is not present in the Soundpad library. We need to add it.
if (!addSound(searchTerm)) {
printf("Failed to add sound: %s", searchTerm);
return 1;
}
printf("Sound added to SoundPad library.\n");
Sleep(1000);
songIndex = getIndex(getSoundList(), searchTerm);
}
if (!playSound(songIndex)) {
printf("Failed to play sound\n");
}
uninit(); // Clean up resources
return 0;
}
11 changes: 11 additions & 0 deletions src/pipes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

void init();
void uninit();
char* sendRequest(const char* request);
int isSuccessPrintResponse(const char* response);
char* getSoundList();
int addSound(const char* url);
int playSound(const int index);
int getIndex(const char* inputCopy, const char* searchTerm);
int checkForEntry(const char* input, const char* searchTerm);

0 comments on commit 940baba

Please sign in to comment.