SDL_mixer: remove the external music player (cmd) support.

From 1cd7c62c3abb5888a72615664823659b693c4a29 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Wed, 9 Oct 2024 01:22:14 +0300
Subject: [PATCH] remove the external music player (cmd) support.

Closes https://github.com/libsdl-org/SDL_mixer/issues/640
---
 CMakeLists.txt                                |  32 --
 VisualC/SDL_mixer.vcxproj                     |   2 -
 VisualC/SDL_mixer.vcxproj.filters             |   6 -
 .../pkg-support/cmake/sdl3_mixer-config.cmake |   2 -
 Xcode/SDL_mixer.xcodeproj/project.pbxproj     |   8 -
 .../resources/CMake/sdl3_mixer-config.cmake   |   2 -
 cmake/SDL3_mixerConfig.cmake.in               |   2 -
 examples/playmus.c                            |   6 -
 include/SDL3_mixer/SDL_mixer.h                |  25 --
 src/SDL_mixer.sym                             |   1 -
 src/codecs/music_cmd.c                        | 307 ------------------
 src/codecs/music_cmd.h                        |  28 --
 src/mixer.c                                   |   4 +-
 src/music.c                                   |  25 --
 src/music.h                                   |   2 -
 15 files changed, 1 insertion(+), 451 deletions(-)
 delete mode 100644 src/codecs/music_cmd.c
 delete mode 100644 src/codecs/music_cmd.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a5bcf2a30..e03568148 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -102,13 +102,6 @@ endif()
 option(SDLMIXER_SAMPLES "Build the SDL3_mixer sample program(s)" ${SDLMIXER_SAMPLES_DEFAULT})
 cmake_dependent_option(SDLMIXER_SAMPLES_INSTALL "Install the SDL3_mixer sample program(s)" OFF "SDLMIXER_SAMPLES;SDLMIXER_INSTALL" OFF)
 
-if(UNIX AND NOT APPLE)
-    set(sdl3mixer_cmd_default ON)
-else()
-    set(sdl3mixer_cmd_default OFF)
-endif()
-option(SDLMIXER_CMD "Support an external music player" ${sdl3mixer_cmd_default})
-
 option(SDLMIXER_SNDFILE "Support loading sounds via libsndfile" OFF)
 option(SDLMIXER_SNDFILE_SHARED "Dynamically load libsndfile" "${SDLMIXER_DEPS_SHARED}")
 
@@ -236,7 +229,6 @@ add_library(${sdl3_mixer_target_name}
     src/codecs/load_voc.c
     src/codecs/load_sndfile.c
     src/codecs/mp3utils.c
-    src/codecs/music_cmd.c
     src/codecs/music_drflac.c
     src/codecs/music_flac.c
     src/codecs/music_fluidsynth.c
@@ -343,30 +335,6 @@ set(PC_LIBS)
 set(PC_REQUIRES)
 set(SDLMIXER_BACKENDS)
 
-list(APPEND SDLMIXER_BACKENDS CMD)
-set(SDLMIXER_CMD_ENABLED FALSE)
-if(SDLMIXER_CMD)
-    target_compile_definitions(${sdl3_mixer_target_name} PRIVATE MUSIC_CMD)
-    set(fork_found OFF)
-    if(NOT fork_found)
-        check_symbol_exists(fork unistd.h HAVE_FORK)
-        if(HAVE_FORK)
-            set(SDLMIXER_CMD_ENABLED TRUE)
-            target_compile_definitions(${sdl3_mixer_target_name} PRIVATE HAVE_FORK)
-        endif()
-    endif()
-    if(NOT fork_found)
-        check_symbol_exists(vfork unistd.h HAVE_VFORK)
-        if(HAVE_VFORK)
-            set(SDLMIXER_CMD_ENABLED TRUE)
-            target_compile_definitions(${sdl3_mixer_target_name} PRIVATE HAVE_VFORK)
-        endif()
-    endif()
-    if(NOT SDLMIXER_CMD_ENABLED)
-        message(${fatal_error} "Neither fork() nor vfork() or available on this platform. Reconfigure with -DSDLMIXER_CMD=OFF.")
-    endif()
-endif()
-
 list(APPEND SDLMIXER_BACKENDS SNDFILE)
 set(SDLMIXER_SNDFILE_ENABLED FALSE)
 if(SDLMIXER_SNDFILE)
diff --git a/VisualC/SDL_mixer.vcxproj b/VisualC/SDL_mixer.vcxproj
index bc43fd8cb..85278322d 100644
--- a/VisualC/SDL_mixer.vcxproj
+++ b/VisualC/SDL_mixer.vcxproj
@@ -222,7 +222,6 @@
     <ClInclude Include="..\src\codecs\load_sndfile.h" />
     <ClInclude Include="..\src\codecs\load_voc.h" />
     <ClInclude Include="..\src\codecs\mp3utils.h" />
-    <ClInclude Include="..\src\codecs\music_cmd.h" />
     <ClInclude Include="..\src\codecs\music_drflac.h" />
     <ClInclude Include="..\src\codecs\music_flac.h" />
     <ClInclude Include="..\src\codecs\music_fluidsynth.h" />
@@ -447,7 +446,6 @@
     <ClCompile Include="..\src\codecs\load_sndfile.c" />
     <ClCompile Include="..\src\codecs\load_voc.c" />
     <ClCompile Include="..\src\codecs\mp3utils.c" />
-    <ClCompile Include="..\src\codecs\music_cmd.c" />
     <ClCompile Include="..\src\codecs\music_drflac.c" />
     <ClCompile Include="..\src\codecs\music_flac.c" />
     <ClCompile Include="..\src\codecs\music_fluidsynth.c" />
diff --git a/VisualC/SDL_mixer.vcxproj.filters b/VisualC/SDL_mixer.vcxproj.filters
index 4624941a2..dfd7adb20 100644
--- a/VisualC/SDL_mixer.vcxproj.filters
+++ b/VisualC/SDL_mixer.vcxproj.filters
@@ -28,9 +28,6 @@
     <ClInclude Include="..\src\codecs\mp3utils.h">
       <Filter>Sources</Filter>
     </ClInclude>
-    <ClInclude Include="..\src\codecs\music_cmd.h">
-      <Filter>Sources</Filter>
-    </ClInclude>
     <ClInclude Include="..\src\codecs\music_drflac.h">
       <Filter>Sources</Filter>
     </ClInclude>
@@ -167,9 +164,6 @@
     <ClCompile Include="..\src\codecs\mp3utils.c">
       <Filter>Sources</Filter>
     </ClCompile>
-    <ClCompile Include="..\src\codecs\music_cmd.c">
-      <Filter>Sources</Filter>
-    </ClCompile>
     <ClCompile Include="..\src\codecs\music_drflac.c">
       <Filter>Sources</Filter>
     </ClCompile>
diff --git a/VisualC/pkg-support/cmake/sdl3_mixer-config.cmake b/VisualC/pkg-support/cmake/sdl3_mixer-config.cmake
index 6b5a674a5..891c40eed 100644
--- a/VisualC/pkg-support/cmake/sdl3_mixer-config.cmake
+++ b/VisualC/pkg-support/cmake/sdl3_mixer-config.cmake
@@ -13,8 +13,6 @@ set(SDL3_mixer_FOUND                TRUE)
 
 set(SDLMIXER_VENDORED              TRUE)
 
-set(SDLMIXER_CMD                   FALSE)
-
 set(SDLMIXER_FLAC_LIBFLAC          FALSE)
 set(SDLMIXER_FLAC_DRFLAC           TRUE)
 
diff --git a/Xcode/SDL_mixer.xcodeproj/project.pbxproj b/Xcode/SDL_mixer.xcodeproj/project.pbxproj
index a3185caf3..14410f617 100644
--- a/Xcode/SDL_mixer.xcodeproj/project.pbxproj
+++ b/Xcode/SDL_mixer.xcodeproj/project.pbxproj
@@ -68,8 +68,6 @@
 		AAE405FB1F9607C300EDAF53 /* music_timidity.c in Sources */ = {isa = PBXBuildFile; fileRef = AAE405D71F9607C200EDAF53 /* music_timidity.c */; };
 		AAE405FD1F9607C300EDAF53 /* music_ogg.c in Sources */ = {isa = PBXBuildFile; fileRef = AAE405D91F9607C200EDAF53 /* music_ogg.c */; };
 		AAE405FE1F9607C300EDAF53 /* music_nativemidi.h in Headers */ = {isa = PBXBuildFile; fileRef = AAE405DA1F9607C200EDAF53 /* music_nativemidi.h */; };
-		AAE405FF1F9607C300EDAF53 /* music_cmd.h in Headers */ = {isa = PBXBuildFile; fileRef = AAE405DB1F9607C200EDAF53 /* music_cmd.h */; };
-		AAE406021F9607C300EDAF53 /* music_cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = AAE405DE1F9607C300EDAF53 /* music_cmd.c */; };
 		AAE406031F9607C300EDAF53 /* music_mpg123.c in Sources */ = {isa = PBXBuildFile; fileRef = AAE405DF1F9607C300EDAF53 /* music_mpg123.c */; };
 		AAE406041F9607C300EDAF53 /* effect_stereoreverse.c in Sources */ = {isa = PBXBuildFile; fileRef = AAE405E01F9607C300EDAF53 /* effect_stereoreverse.c */; };
 		AAE406051F9607C300EDAF53 /* effects_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = AAE405E11F9607C300EDAF53 /* effects_internal.h */; };
@@ -202,8 +200,6 @@
 		AAE405D71F9607C200EDAF53 /* music_timidity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = music_timidity.c; sourceTree = "<group>"; };
 		AAE405D91F9607C200EDAF53 /* music_ogg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = music_ogg.c; sourceTree = "<group>"; };
 		AAE405DA1F9607C200EDAF53 /* music_nativemidi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = music_nativemidi.h; sourceTree = "<group>"; };
-		AAE405DB1F9607C200EDAF53 /* music_cmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = music_cmd.h; sourceTree = "<group>"; };
-		AAE405DE1F9607C300EDAF53 /* music_cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = music_cmd.c; sourceTree = "<group>"; };
 		AAE405DF1F9607C300EDAF53 /* music_mpg123.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = music_mpg123.c; sourceTree = "<group>"; };
 		AAE405E01F9607C300EDAF53 /* effect_stereoreverse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = effect_stereoreverse.c; sourceTree = "<group>"; };
 		AAE405E11F9607C300EDAF53 /* effects_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = effects_internal.h; sourceTree = "<group>"; };
@@ -321,8 +317,6 @@
 				AAE405C31F9607C000EDAF53 /* load_voc.h */,
 				639197EF239FE66700F1D8F8 /* mp3utils.c */,
 				639197F0239FE66700F1D8F8 /* mp3utils.h */,
-				AAE405DE1F9607C300EDAF53 /* music_cmd.c */,
-				AAE405DB1F9607C200EDAF53 /* music_cmd.h */,
 				F37A8D492838A23400C38E95 /* music_drflac.c */,
 				F37A8D412838A23400C38E95 /* music_drflac.h */,
 				AAE405D41F9607C100EDAF53 /* music_flac.c */,
@@ -481,7 +475,6 @@
 				F30240632881DF95002F32D6 /* music_xmp.h in Headers */,
 				AAE405E41F9607C300EDAF53 /* mixer.h in Headers */,
 				F3F8795829B30FDA0007FDA1 /* load_sndfile.h in Headers */,
-				AAE405FF1F9607C300EDAF53 /* music_cmd.h in Headers */,
 				F3F8795229B30FDA0007FDA1 /* music_gme.h in Headers */,
 				AAE405EB1F9607C300EDAF53 /* music_flac.h in Headers */,
 				AAE406051F9607C300EDAF53 /* effects_internal.h in Headers */,
@@ -701,7 +694,6 @@
 				AAE405F41F9607C300EDAF53 /* effect_position.c in Sources */,
 				AAE405F81F9607C300EDAF53 /* music_flac.c in Sources */,
 				AAE405F21F9607C300EDAF53 /* effects_internal.c in Sources */,
-				AAE406021F9607C300EDAF53 /* music_cmd.c in Sources */,
 				F3F8795029B30FDA0007FDA1 /* load_sndfile.c in Sources */,
 				AAE405FB1F9607C300EDAF53 /* music_timidity.c in Sources */,
 				F37A8DB52838AD1300C38E95 /* music_ogg_stb.c in Sources */,
diff --git a/Xcode/pkg-support/resources/CMake/sdl3_mixer-config.cmake b/Xcode/pkg-support/resources/CMake/sdl3_mixer-config.cmake
index 59e1f12b2..5ccf2d14b 100644
--- a/Xcode/pkg-support/resources/CMake/sdl3_mixer-config.cmake
+++ b/Xcode/pkg-support/resources/CMake/sdl3_mixer-config.cmake
@@ -14,8 +14,6 @@ set(SDL3_mixer_FOUND                TRUE)
 
 set(SDLMIXER_VENDORED              TRUE)
 
-set(SDLMIXER_CMD                   FALSE)
-
 set(SDLMIXER_FLAC_LIBFLAC          FALSE)
 set(SDLMIXER_FLAC_DRFLAC           TRUE)
 
diff --git a/cmake/SDL3_mixerConfig.cmake.in b/cmake/SDL3_mixerConfig.cmake.in
index 36330ff3e..ee4e2514e 100644
--- a/cmake/SDL3_mixerConfig.cmake.in
+++ b/cmake/SDL3_mixerConfig.cmake.in
@@ -12,8 +12,6 @@ set(SDL3_mixer_FOUND                ON)
 
 set(SDLMIXER_VENDORED              @SDLMIXER_VENDORED@)
 
-set(SDLMIXER_CMD                   @SDLMIXER_CMD_ENABLED@)
-
 set(SDLMIXER_SNDFILE               @SDLMIXER_SNDFILE_ENABLED@)
 
 set(SDLMIXER_FLAC                  @SDLMIXER_FLAC_ENABLED@)
diff --git a/examples/playmus.c b/examples/playmus.c
index 6254a0990..5a5fa1e72 100644
--- a/examples/playmus.c
+++ b/examples/playmus.c
@@ -204,9 +204,6 @@ int main(int argc, char *argv[])
     /* Set the music volume */
     Mix_VolumeMusic(audio_volume);
 
-    /* Set the external music player, if any */
-    Mix_SetMusicCMD(SDL_getenv("MUSIC_CMD"));
-
     while (argv[i]) {
         next_track = 0;
 
@@ -222,9 +219,6 @@ int main(int argc, char *argv[])
         }
 
         switch (Mix_GetMusicType(music)) {
-        case MUS_CMD:
-            typ = "CMD";
-            break;
         case MUS_WAV:
             typ = "WAV";
             break;
diff --git a/include/SDL3_mixer/SDL_mixer.h b/include/SDL3_mixer/SDL_mixer.h
index d38dabc1f..e145d962a 100644
--- a/include/SDL3_mixer/SDL_mixer.h
+++ b/include/SDL3_mixer/SDL_mixer.h
@@ -212,7 +212,6 @@ typedef enum Mix_Fading {
  */
 typedef enum Mix_MusicType {
     MUS_NONE,
-    MUS_CMD,
     MUS_WAV,
     MUS_MOD,
     MUS_MID,
@@ -2440,30 +2439,6 @@ extern SDL_DECLSPEC int SDLCALL Mix_Playing(int channel);
  */
 extern SDL_DECLSPEC bool SDLCALL Mix_PlayingMusic(void);
 
-/**
- * Run an external command as the music stream.
- *
- * This halts any currently-playing music, and next time the music stream is
- * played, SDL_mixer will spawn a process using the command line specified in
- * `command`. This command is not subject to shell expansion, and beyond some
- * basic splitting up of arguments, is passed to execvp() on most platforms,
- * not system().
- *
- * The command is responsible for generating sound; it is NOT mixed by
- * SDL_mixer! SDL_mixer will kill the child process if asked to halt the
- * music, but otherwise does not have any control over what the process does.
- *
- * You are strongly encouraged not to use this function without an extremely
- * good reason.
- *
- * \param command command.
- * \returns true on success or false on failure; call SDL_GetError() for more
- *          information.
- *
- * \since This function is available since SDL_mixer 3.0.0.
- */
-extern SDL_DECLSPEC bool SDLCALL Mix_SetMusicCMD(const char *command);
-
 /**
  * Set SoundFonts paths to use by supported MIDI backends.
  *
diff --git a/src/SDL_mixer.sym b/src/SDL_mixer.sym
index 60b434b66..02556f95b 100644
--- a/src/SDL_mixer.sym
+++ b/src/SDL_mixer.sym
@@ -81,7 +81,6 @@ SDL3_mixer_0.0.0 {
     Mix_ResumeMusic;
     Mix_RewindMusic;
     Mix_SetDistance;
-    Mix_SetMusicCMD;
     Mix_SetMusicPosition;
     Mix_SetPanning;
     Mix_SetPosition;
diff --git a/src/codecs/music_cmd.c b/src/codecs/music_cmd.c
deleted file mode 100644
index 974ff47fd..000000000
--- a/src/codecs/music_cmd.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-  SDL_mixer:  An audio mixer library based on the SDL library
-  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-#include <SDL3/SDL_platform.h>
-
-/* This file supports an external command for playing music */
-
-#ifdef MUSIC_CMD
-
-#ifdef __APPLE__
-#define _DARWIN_C_SOURCE
-#endif
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <signal.h>
-#include <ctype.h>
-#include <limits.h>
-#if defined(__linux__) && defined(__arm__)
-# include <linux/limits.h>
-#endif
-
-#include "music_cmd.h"
-
-
-typedef struct {
-    char *file;
-    char *cmd;
-    pid_t pid;
-    int play_count;
-} MusicCMD;
-
-
-/* Load a music stream from the given file */
-static void *MusicCMD_CreateFromFile(const char *file)
-{
-    MusicCMD *music;
-
-    if (!music_cmd) {
-        SDL_SetError("You must call Mix_SetMusicCMD() first");
-        return NULL;
-    }
-
-    /* Allocate and fill the music structure */
-    music = (MusicCMD *)SDL_calloc(1, sizeof *music);
-    if (music == NULL) {
-        return NULL;
-    }
-    music->file = SDL_strdup(file);
-    music->cmd = SDL_strdup(music_cmd);
-    music->pid = 0;
-
-    /* We're done */
-    return music;
-}
-
-/* Parse a command line buffer into arguments */
-static int ParseCommandLine(char *cmdline, char **argv)
-{
-    char *bufp;
-    int argc;
-
-    argc = 0;
-    for (bufp = cmdline; *bufp;) {
-        /* Skip leading whitespace */
-        while (SDL_isspace(*bufp)) {
-            ++bufp;
-        }
-        /* Skip over argument */
-        if (*bufp == '"') {
-            ++bufp;
-            if (*bufp) {
-                if (argv) {
-                    argv[argc] = bufp;
-                }
-                ++argc;
-            }
-            /* Skip over word */
-            while (*bufp && (*bufp != '"')) {
-                ++bufp;
-            }
-        } else {
-            if (*bufp) {
-                if (argv) {
-                    argv[argc] = bufp;
-                }
-                ++argc;
-            }
-            /* Skip over word */
-            while (*bufp && ! SDL_isspace(*bufp)) {
-                ++bufp;
-            }
-        }
-        if (*bufp) {
-            if (argv) {
-                *bufp = '\0';
-            }
-            ++bufp;
-        }
-    }
-    if (argv) {
-        argv[argc] = NULL;
-    }
-    return argc;
-}
-
-static char **parse_args(char *command, char *last_arg)
-{
-    int argc;
-    char **argv;
-
-    /* Parse the command line */
-    argc = ParseCommandLine(command, NULL);
-    if (last_arg) {
-        ++argc;
-    }
-    argv = (char **)SDL_malloc((argc+1)*(sizeof *argv));
-    if (argv == NULL) {
-        return NULL;
-    }
-    argc = ParseCommandLine(command, argv);
-
-    /* Add last command line argument */
-    if (last_arg) {
-        argv[argc++] = last_arg;
-    }
-    argv[argc] = NULL;
-
-    /* We're ready! */
-    return argv;
-}
-
-/* Start playback of a given music stream */
-static int MusicCMD_Play(void *context, int play_count)
-{
-    MusicCMD *music = (MusicCMD *)context;
-
-    music->play_count = play_count;
-#ifdef HAVE_FORK
-    music->pid = fork();
-#elif defined(HAVE_VFORK)
-    music->pid = vfork();
-#else
-    music->pid = -1;
-#endif
-    switch(music->pid) {
-    /* Failed fork() system call */
-    case -1:
-        SDL_SetError("fork() failed");
-        return -1;
-
-    /* Child process - executes here */
-    case 0: {
-        char **argv;
-
-        /* Unblock signals in case we're called from a thread */
-        {
-            sigset_t mask;
-            sigemptyset(&mask);
-            sigprocmask(SIG_SETMASK, &mask, NULL);
-        }
-
-        /* Execute the command */
-        argv = parse_args(music->cmd, music->file);
-        if (argv != NULL) {
-            execvp(argv[0], argv);
-
-            /* exec() failed */
-            perror(argv[0]);
-        }
-        _exit(-1);
-    }
-    break;
-
-    /* Parent process - executes here */
-    default:
-        break;
-    }
-    return 0;
-}
-
-/* Return non-zero if a stream is currently playing */
-static bool MusicCMD_IsPlaying(void *context)
-{
-    MusicCMD *music = (MusicCMD *)context;
-    int status;
-
-    if (music->pid > 0) {
-        waitpid(music->pid, &status, WNOHANG);
-        if (kill(music->pid, 0) == 0) {
-            return true;
-        }
-
-        /* We might want to loop */
-        if (music->play_count != 1) {
-            int play_count = -1;
-            if (music->play_count > 0) {
-                play_count = (music->play_count - 1);
-            }
-            MusicCMD_Play(music, play_count);
-            return true;
-        }
-    }
-    return false;
-}
-
-/* Pause playback of a given music stream */
-static void MusicCMD_Pause(void *context)
-{
-    MusicCMD *music = (MusicCMD *)context;
-    if (music->pid > 0) {
-        kill(music->pid, SIGSTOP);
-    }
-}
-
-/* Resume playback of a given music stream */
-static void MusicCMD_Resume(void *context)
-{
-    MusicCMD *music = (MusicCMD *)context;
-    if (music->pid > 0) {
-        kill(music->pid, SIGCONT);
-    }
-}
-
-/* Stop playback of a stream previously started with MusicCMD_Start() */
-static void MusicCMD_Stop(void *context)
-{
-    MusicCMD *music = (MusicCMD *)context;
-    int status;
-
-    if (music->pid > 0) {
-        while (kill(music->pid, 0) == 0) {
-            kill(music->pid, SIGTERM);
-            sleep(1);
-            waitpid(music->pid, &status, WNOHANG);
-        }
-        music->pid = 0;
-    }
-}
-
-/* Close the given music stream */
-void MusicCMD_Delete(void *context)
-{
-    MusicCMD *music = (MusicCMD *)context;
-    SDL_free(music->file);
-    SDL_free(music);
-}
-
-Mix_MusicInterface Mix_MusicInterface_CMD =
-{
-    "CMD",
-    MIX_MUSIC_CMD,
-    MUS_CMD,
-    false,
-    false,
-
-    NULL,   /* Load */
-    NULL,   /* Open */
-    NULL,   /* CreateFromIO */
-    MusicCMD_CreateFromFile,
-    NULL,   /* SetVolume */
-    NULL,   /* GetVolume */
-    MusicCMD_Play,
-    MusicCMD_IsPlaying,
-    NULL,   /* GetAudio */
-    NULL,   /* Jump */
-    NULL,   /* Seek */
-    NULL,   /* Tell */
-    NULL,   /* Duration */
-    NULL,   /* LoopStart */
-    NULL,   /* LoopEnd */
-    NULL,   /* LoopLength */
-    NULL,   /* GetMetaTag */
-    NULL,   /* GetNumTracks */
-    NULL,   /* StartTrack */
-    MusicCMD_Pause,
-    MusicCMD_Resume,
-    MusicCMD_Stop,
-    MusicCMD_Delete,
-    NULL,   /* Close */
-    NULL    /* Unload */
-};
-
-#endif /* MUSIC_CMD */
-
-/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/codecs/music_cmd.h b/src/codecs/music_cmd.h
deleted file mode 100644
index 6da37c024..000000000
--- a/src/codecs/music_cmd.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-  SDL_mixer:  An audio mixer library based on the SDL library
-  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-/* This file supports an external command for playing music */
-
-#include "music.h"
-
-extern Mix_MusicInterface Mix_MusicInterface_CMD;
-
-/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/mixer.c b/src/mixer.c
index 80a3ce4ad..334007e6f 100644
--- a/src/mixer.c
+++ b/src/mixer.c
@@ -687,8 +687,7 @@ static SDL_AudioSpec *Mix_LoadMusic_IO(SDL_IOStream *src, bool closeio, SDL_Audi
         }
 
         /* These music interfaces are not safe to use while music is playing */
-        if (interface->api == MIX_MUSIC_CMD ||
-             interface->api == MIX_MUSIC_NATIVEMIDI) {
+        if (interface->api == MIX_MUSIC_NATIVEMIDI) {
             continue;
         }
 
@@ -1381,7 +1380,6 @@ void Mix_CloseAudio(void)
             }
             Mix_UnregisterAllEffects(MIX_CHANNEL_POST);
             close_music();
-            Mix_SetMusicCMD(NULL);
             Mix_HaltChannel(-1);
             _Mix_DeinitEffects();
             SDL_DestroyAudioStream(audio_stream);
diff --git a/src/music.c b/src/music.c
index 94f11560f..668019e3c 100644
--- a/src/music.c
+++ b/src/music.c
@@ -26,7 +26,6 @@
 #include "mixer.h"
 #include "music.h"
 
-#include "music_cmd.h"
 #include "music_wav.h"
 #include "music_modplug.h"
 #include "music_xmp.h"
@@ -54,7 +53,6 @@
 #define SDL_MIXER_HINT_DEBUG_MUSIC_INTERFACES \
     "SDL_MIXER_DEBUG_MUSIC_INTERFACES"
 
-char *music_cmd = NULL;
 static bool music_active = true;
 static int music_volume = MIX_MAX_VOLUME;
 static Mix_Music *music_playing = NULL;
@@ -160,9 +158,6 @@ static SDL_INLINE const char *get_last_dirsep (const char *p) {
 /* Interfaces for the various music interfaces, ordered by priority */
 static Mix_MusicInterface *s_music_interfaces[] =
 {
-#ifdef MUSIC_CMD
-    &Mix_MusicInterface_CMD,
-#endif
 #ifdef MUSIC_WAV
     &Mix_MusicInterface_WAV,
 #endif
@@ -520,7 +515,6 @@ void open_music(const SDL_AudioSpec *spec)
 #endif
 
     /* Load the music interfaces that don't have explicit initialization */
-    load_music_type(MUS_CMD);
     load_music_type(MUS_WAV);
 
     /* Open all the interfaces that are loaded */
@@ -1387,25 +1381,6 @@ bool Mix_PlayingMusic(void)
     return playing;
 }
 
-/* Set the external music playback command */
-bool Mix_SetMusicCMD(const char *command)
-{
-    Mix_HaltMusic();
-    if (music_cmd) {
-        SDL_free(music_cmd);
-        music_cmd = NULL;
-    }
-    if (command) {
-        size_t length = SDL_strlen(command) + 1;
-        music_cmd = (char *)SDL_malloc(length);
-        if (music_cmd == NULL) {
-            return false;
-        }
-        SDL_memcpy(music_cmd, command, length);
-    }
-    return true;
-}
-
 /* Uninitialize the music interfaces */
 void close_music(void)
 {
diff --git a/src/music.h b/src/music.h
index 183600641..8d356d1b9 100644
--- a/src/music.h
+++ b/src/music.h
@@ -27,7 +27,6 @@
 
 typedef enum
 {
-    MIX_MUSIC_CMD,
     MIX_MUSIC_WAVE,
     MIX_MUSIC_MODPLUG,
     MIX_MUSIC_FLUIDSYNTH,
@@ -174,7 +173,6 @@ extern void pause_async_music(int pause_on);
 extern void close_music(void);
 extern void unload_music(void);
 
-extern char *music_cmd;
 extern SDL_AudioSpec music_spec;
 
 #endif /* MUSIC_H_ */