Refactor: extract platform abstraction for subprocess spawning
Move all Unix-specific syscalls (fork, execvp, waitpid, strerror, /tmp) into a platform layer so the same spectrogram.c can target Windows (CreateProcess) and WebAssembly (stubs). Key changes: - src/platform.h: public API with spawn handle, error codes, path helpers - src/platform_linux.c: fork/execvp implementation, /tmp, strerror - src/platform_win32.c: CreateProcess implementation, temp dir lookup - src/platform_web.c: stub implementations (no subprocess support on web) - src/spectrogram.c: consume only platform.h; replace pid_t/fork/execvp with Platform_SpawnChild/WaitForChild; use Platform_GetTempDir() for /tmp path; replace strdup with malloc/memcpy for portability - Build: add platform_*.c to gmake, Premake, and build_web.sh
This commit is contained in:
+45
-26
@@ -1,11 +1,9 @@
|
||||
// spectrogram.c - Spectrogram viewer with region selection and playback
|
||||
// Based on Unity Audio-Experiments project
|
||||
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include "raylib.h"
|
||||
#include "resource_dir.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -418,21 +416,34 @@ static void FreeSTFT(StftResult* result)
|
||||
// Convert audio file to WAV using ffmpeg (if available)
|
||||
static bool ConvertToFFmpegWAV(const char* inputPath, char* outputPath, size_t outputSize)
|
||||
{
|
||||
// Create temp WAV path
|
||||
snprintf(outputPath, outputSize, "/tmp/rspektrum_temp_converted.wav");
|
||||
|
||||
// Build ffmpeg command
|
||||
char cmd[1024];
|
||||
snprintf(cmd, sizeof(cmd), "ffmpeg -y -loglevel quiet -i \"%s\" -ar 48000 -ac 1 -f wav \"%s\" 2>&1", inputPath, outputPath);
|
||||
|
||||
int result = system(cmd);
|
||||
|
||||
if (result == 0 && FileExists(outputPath)) {
|
||||
snprintf(outputPath, outputSize, "%s/rspektrum_temp_converted.wav",
|
||||
Platform_GetTempDir());
|
||||
|
||||
/* Build argv array — no shell = no injection risk */
|
||||
const char* argv[] = {
|
||||
"ffmpeg", "-y", "-loglevel", "quiet",
|
||||
"-i", inputPath,
|
||||
"-ar", "48000", "-ac", "1", "-f", "wav",
|
||||
outputPath, NULL
|
||||
};
|
||||
|
||||
PlatformSpawnHandle handle = { 0 };
|
||||
PlatformError rc = Platform_SpawnChild("ffmpeg", argv, &handle);
|
||||
if (rc != PLATFORM_OK) {
|
||||
TraceLog(LOG_WARNING, "Failed to spawn ffmpeg: %s", Platform_GetLastErrorMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
Platform_WaitForChild(&handle);
|
||||
|
||||
int exit_code = 0;
|
||||
SpawnStatus status = Platform_GetExitStatus(&handle, &exit_code);
|
||||
if (status == SPAWN_EXITED && exit_code == 0 && FileExists(outputPath)) {
|
||||
TraceLog(LOG_INFO, "FFmpeg conversion successful: %s", outputPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
TraceLog(LOG_WARNING, "FFmpeg conversion failed or not available");
|
||||
|
||||
TraceLog(LOG_WARNING, "FFmpeg conversion failed (exit code %d)", exit_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -457,10 +468,10 @@ static bool LoadWavFile(const char* filepath, AudioSignal* signal)
|
||||
}
|
||||
|
||||
Wave wave = LoadWave(filepath);
|
||||
if (wave.data == NULL) {
|
||||
TraceLog(LOG_ERROR, "Failed to open WAV file: %s", filepath);
|
||||
if (isConverted) remove(convertedPath);
|
||||
return false;
|
||||
if (wave.data == NULL) {
|
||||
TraceLog(LOG_ERROR, "Failed to open WAV file: %s", filepath);
|
||||
if (isConverted) FileRemove(convertedPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
signal->sampleRate = wave.sampleRate;
|
||||
@@ -493,7 +504,7 @@ static bool LoadWavFile(const char* filepath, AudioSignal* signal)
|
||||
|
||||
// Clean up temp file if converted
|
||||
if (isConverted) {
|
||||
remove(convertedPath);
|
||||
FileRemove(convertedPath);
|
||||
TraceLog(LOG_INFO, "Cleaned up temp file: %s", convertedPath);
|
||||
}
|
||||
|
||||
@@ -768,9 +779,13 @@ static void ScanDirectory(const char* path)
|
||||
const char* name = GetFileName(files.paths[i]);
|
||||
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
|
||||
if (DirectoryExists(files.paths[i])) {
|
||||
app.browserFiles[app.browserFileCount] = strdup(name);
|
||||
app.browserIsDir[app.browserFileCount] = true;
|
||||
app.browserFileCount++;
|
||||
size_t len = strlen(name) + 1;
|
||||
app.browserFiles[app.browserFileCount] = (char*)malloc(len);
|
||||
if (app.browserFiles[app.browserFileCount]) {
|
||||
memcpy(app.browserFiles[app.browserFileCount], name, len);
|
||||
app.browserIsDir[app.browserFileCount] = true;
|
||||
app.browserFileCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < files.count; i++) {
|
||||
@@ -780,9 +795,13 @@ static void ScanDirectory(const char* path)
|
||||
const char* ext = GetFileExtension(files.paths[i]);
|
||||
if (ext && (strcmp(ext, ".wav") == 0 || strcmp(ext, ".WAV") == 0 ||
|
||||
strcmp(ext, ".Wave") == 0 || strcmp(ext, ".Wav") == 0)) {
|
||||
app.browserFiles[app.browserFileCount] = strdup(name);
|
||||
app.browserIsDir[app.browserFileCount] = false;
|
||||
app.browserFileCount++;
|
||||
size_t len = strlen(name) + 1;
|
||||
app.browserFiles[app.browserFileCount] = (char*)malloc(len);
|
||||
if (app.browserFiles[app.browserFileCount]) {
|
||||
memcpy(app.browserFiles[app.browserFileCount], name, len);
|
||||
app.browserIsDir[app.browserFileCount] = false;
|
||||
app.browserFileCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user