shithub: choc

Download patch

ref: 97a13cc0c116e0fb9564adab4c854c98f55305a1
parent: 2f8ed99c11279ab932dbda6db0647f70c3280b7a
author: Alex Mayfield <[email protected]>
date: Fri Feb 10 18:16:11 EST 2017

First attempt at MidiSocket client

Instead of using RPC, I am going to try using SDL_net over a local
socket to transmit music instructions.

Right now only the client is implemented, and I'm pretty sure that even
if the server worked there would be countless bugs.  It at least
compiles and doesn't blow itself to smithereens when you run it.

--- a/src/i_midirpc.c
+++ /dev/null
@@ -1,389 +1,0 @@
-//
-// Copyright(C) 2013 James Haley et al.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// DESCRIPTION:
-//     Client Interface to RPC Midi Server
-//
-
-#ifdef EE_FEATURE_MIDIRPC
-
-#include <windows.h>
-#include "midiproc.h"
-
-#include "../hal/i_timer.h"
-#include "../m_qstr.h"
-
-#if defined(_DEBUG) && defined(EE_RPC_DEBUG)
-#define DEBUGOUT(s) puts(s)
-#else
-#define DEBUGOUT(s)
-#endif
-
-//=============================================================================
-//
-// Data
-//
-
-static unsigned char *szStringBinding; // RPC client binding string
-static bool serverInit = false;        // if true, server was started
-static bool clientInit = false;        // if true, client was bound
-
-// server process information
-static STARTUPINFO         si;
-static PROCESS_INFORMATION pi;
-
-//=============================================================================
-//
-// RPC Memory Management
-//
-
-void __RPC_FAR * __RPC_USER midl_user_allocate(size_t size)
-{
-   return malloc(size);
-}
-
-void __RPC_USER midl_user_free(void __RPC_FAR *p)
-{
-   free(p);
-}
-
-//=============================================================================
-//
-// RPC Wrappers
-//
-
-//
-// CHECK_RPC_STATUS
-//
-// If either server or client initialization failed, we don't try to make any
-// RPC calls.
-//
-#define CHECK_RPC_STATUS()        \
-   if(!serverInit || !clientInit) \
-      return false
-
-#define MIDIRPC_MAXTRIES 50 // This number * 10 is the amount of time you can try to wait for.
-
-static bool I_MidiRPCWaitForServer()
-{
-   int tries = 0;
-   while(RpcMgmtIsServerListening(hMidiRPCBinding) != RPC_S_OK)
-   {
-      i_haltimer.Sleep(10);
-      if(++tries >= MIDIRPC_MAXTRIES)
-         return false;
-   }
-   return true;
-}
-
-//
-// I_MidiRPCRegisterSong
-//
-// Prepare the RPC MIDI engine to receive new song data, and transmit the song
-// data to the server process.
-//
-bool I_MidiRPCRegisterSong(void *data, int size)
-{
-   unsigned int rpcSize = static_cast<unsigned int>(size);
-
-   CHECK_RPC_STATUS();
-
-   RpcTryExcept
-   {
-      MidiRPC_PrepareNewSong();
-
-      // TODO: Try passing it as one chunk; if this ends up not working, 
-      // I'll have to stream it in as smaller divisions.
-      MidiRPC_AddChunk(rpcSize, static_cast<byte *>(data));
-   }
-   RpcExcept(1)
-   {
-      DEBUGOUT("I_MidiRPCRegisterSong failed");
-      return false;
-   }
-   RpcEndExcept
-
-   DEBUGOUT("I_MidiRPCRegisterSong succeeded");
-   return true;
-}
-
-//
-// I_MidiRPCPlaySong
-//
-// Tell the RPC server to start playing a song.
-//
-bool I_MidiRPCPlaySong(bool looping)
-{
-   CHECK_RPC_STATUS();
-
-   RpcTryExcept
-   {
-      MidiRPC_PlaySong(looping ? TRUE : FALSE);
-   }
-   RpcExcept(1)
-   {
-      DEBUGOUT("I_MidiRPCPlaySong failed");
-      return false;
-   }
-   RpcEndExcept
-
-   DEBUGOUT("I_MidiRPCPlaySong succeeded");
-   return true;
-}
-
-// 
-// I_MidiRPCStopSong
-//
-// Tell the RPC server to stop any currently playing song.
-//
-bool I_MidiRPCStopSong()
-{
-   CHECK_RPC_STATUS();
-
-   RpcTryExcept
-   {
-      MidiRPC_StopSong();
-   }
-   RpcExcept(1)
-   {
-      DEBUGOUT("I_MidiRPCStopSong failed");
-      return false;
-   }
-   RpcEndExcept
-
-   DEBUGOUT("I_MidiRPCStopSong succeeded");
-   return true;
-}
-
-//
-// I_MidiRPCSetVolume
-//
-// Change the volume level of music played by the RPC midi server.
-//
-bool I_MidiRPCSetVolume(int volume)
-{
-   CHECK_RPC_STATUS();
-   
-   RpcTryExcept
-   {
-      MidiRPC_ChangeVolume(volume);
-   }
-   RpcExcept(1)
-   {
-      DEBUGOUT("I_MidiRPCSetVolume failed");
-      return false;
-   }
-   RpcEndExcept
-
-   DEBUGOUT("I_MidiRPCSetVolume succeeded");
-   return true;
-}
-
-//
-// I_MidiRPCPauseSong
-//
-// Pause the music being played by the server. In actuality, due to SDL_mixer
-// limitations, this just temporarily sets the volume to zero.
-//
-bool I_MidiRPCPauseSong()
-{
-   CHECK_RPC_STATUS();
-
-   RpcTryExcept
-   {
-      MidiRPC_PauseSong();
-   }
-   RpcExcept(1)
-   {
-      DEBUGOUT("I_MidiRPCPauseSong failed");
-      return false;
-   }
-   RpcEndExcept
-
-   DEBUGOUT("I_MidiRPCPauseSong succeeded");
-   return true;
-}
-
-//
-// I_MidiRPCResumeSong
-//
-// Resume a song after having paused it.
-//
-bool I_MidiRPCResumeSong()
-{
-   CHECK_RPC_STATUS();
-
-   RpcTryExcept
-   {
-      MidiRPC_ResumeSong();
-   }
-   RpcExcept(1)
-   {
-      DEBUGOUT("I_MidiRPCResumeSong failed");
-      return false;
-   }
-   RpcEndExcept
-
-   DEBUGOUT("I_MidiRPCResumeSong succeeded");
-   return true;
-}
-
-//=============================================================================
-//
-// Public Interface
-//
-
-//
-// I_MidiRPCInitServer
-//
-// Start up the RPC MIDI server.
-//
-bool I_MidiRPCInitServer()
-{
-   struct stat sbuf;
-   char filename[MAX_PATH+1];
-
-   memset(filename, 0, sizeof(filename));
-   GetModuleFileName(NULL, filename, MAX_PATH);
-
-   qstring module;
-
-   module = filename;
-   module.removeFileSpec();
-   module.pathConcatenate("midiproc.exe");
-   DEBUGOUT(module.constPtr());
-
-   // Look for executable file
-   if(stat(module.constPtr(), &sbuf))
-   {
-      DEBUGOUT("Could not find midiproc");
-      return false;
-   }
-
-   si.cb = sizeof(si);
-
-   BOOL result = CreateProcess(module.constPtr(), NULL, NULL, NULL, FALSE,
-                               0, NULL, NULL, &si, &pi);
-
-   if(result)
-   {
-      DEBUGOUT("RPC server started");
-      serverInit = true;
-   }
-   else
-      DEBUGOUT("CreateProcess failed to start midiproc");
-
-   return !!result;
-}
-
-//
-// I_MidiRPCInitClient
-//
-// Initialize client RPC bindings and bind to the server.
-//
-bool I_MidiRPCInitClient()
-{
-   RPC_STATUS status;
-
-   // If server didn't start, client cannot be bound.
-   if(!serverInit)
-      return false;
-
-   // Compose binding string
-   status =
-      RpcStringBindingCompose
-      (
-         NULL,
-         (RPC_CSTR)("ncalrpc"),
-         NULL,
-         (RPC_CSTR)("2d4dc2f9-ce90-4080-8a00-1cb819086970"),
-         NULL,
-         &szStringBinding
-      );
-
-   if(status)
-   {
-      DEBUGOUT("RPC binding composition failed");
-      return false;
-   }
-
-   // Create binding handle
-   status = RpcBindingFromStringBinding(szStringBinding, &hMidiRPCBinding);
-
-   if(status)
-   {
-      DEBUGOUT("RPC client binding failed");
-      return false;
-   }
-
-   DEBUGOUT("RPC client initialized");
-   clientInit = true;
-
-   return I_MidiRPCWaitForServer();
-}
-
-//
-// I_MidiRPCClientShutDown
-//
-// Shutdown the RPC Client
-//
-void I_MidiRPCClientShutDown()
-{
-   // stop the server
-   if(serverInit)
-   {
-      RpcTryExcept
-      {
-         MidiRPC_StopServer();
-      }
-      RpcExcept(1)
-      {
-         DEBUGOUT("Exception thrown when stopping RPC server");
-      }
-      RpcEndExcept
-
-      serverInit = false;
-   }
-
-   if(szStringBinding)
-   {
-      RpcStringFree(&szStringBinding);
-      szStringBinding = NULL;
-   }
-
-   if(hMidiRPCBinding)
-   {
-      RpcBindingFree(&hMidiRPCBinding);
-      hMidiRPCBinding = NULL;
-   }
-
-   clientInit = false;
-}
-
-//
-// I_MidiRPCReady
-//
-// Returns true if both server and client initialized successfully.
-//
-bool I_MidiRPCReady()
-{
-   CHECK_RPC_STATUS();
-
-   return true;
-}
-
-#endif
-
-// EOF
-
-
--- a/src/i_midirpc.h
+++ /dev/null
@@ -1,40 +1,0 @@
-//
-// Copyright(C) 2013 James Haley et al.
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// DESCRIPTION:
-//     Client Interface to RPC Midi Server
-//
-
-#ifndef I_MIDIRPC_H__
-#define I_MIDIRPC_H__
-
-#ifdef EE_FEATURE_MIDIRPC
-
-bool I_MidiRPCInitServer();
-bool I_MidiRPCInitClient();
-void I_MidiRPCClientShutDown();
-bool I_MidiRPCReady();
-
-bool I_MidiRPCRegisterSong(void *data, int size);
-bool I_MidiRPCPlaySong(bool looping);
-bool I_MidiRPCStopSong();
-bool I_MidiRPCSetVolume(int volume);
-bool I_MidiRPCPauseSong();
-bool I_MidiRPCResumeSong();
-
-#endif
-
-#endif
-
-// EOF
-
--- /dev/null
+++ b/src/i_midisocket.c
@@ -1,0 +1,390 @@
+//
+// Copyright(C) 2013 James Haley et al.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// DESCRIPTION:
+//     Client Interface to RPC Midi Server
+//
+
+#if _WIN32
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <SDL_net.h>
+
+#include "i_midisocket.h"
+
+#include "m_misc.h"
+#include "net_packet.h"
+
+#if defined(_DEBUG)
+#define DEBUGOUT(s) puts(s)
+#else
+#define DEBUGOUT(s)
+#endif
+
+typedef enum {
+	NET_MIDISOCKET_PACKET_TYPE_PREPARE_NEW_SONG,
+    NET_MIDISOCKET_PACKET_TYPE_REGISTER_SONG,
+	NET_MIDISOCKET_PACKET_TYPE_PLAY_SONG,
+	NET_MIDISOCKET_PACKET_TYPE_STOP_SONG,
+	NET_MIDISOCKET_PACKET_TYPE_CHANGE_VOLUME,
+	NET_MIDISOCKET_PACKET_TYPE_PAUSE_SONG,
+	NET_MIDISOCKET_PACKET_TYPE_RESUME_SONG,
+	NET_MIDISOCKET_PACKET_TYPE_STOP_SERVER
+} net_midisocket_packet_type_t;
+
+//=============================================================================
+//
+// Data
+//
+
+static TCPsocket midi_socket;       // Client socket
+static boolean server_init = false; // if true, server was started
+static boolean client_init = false; // if true, client was bound
+
+// server process information
+static STARTUPINFO         si;
+static PROCESS_INFORMATION pi;
+
+//=============================================================================
+//
+// RPC Wrappers
+//
+
+//
+// CHECK_RPC_STATUS
+//
+// If either server or client initialization failed, we don't try to make any
+// RPC calls.
+//
+#define CHECK_RPC_STATUS() \
+    if(!server_init || !client_init) \
+        return false
+
+#define MIDIRPC_MAXTRIES 50 // This number * 10 is the amount of time you can try to wait for.
+
+static boolean I_MidiSocketWaitForServer()
+{
+    int tries = 0;
+    while(false) // TODO: Is there some way to tell if the server is listening?
+    {
+        I_Sleep(10);
+        if (++tries >= MIDIRPC_MAXTRIES)
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+//
+// I_MidiSocketRegisterSong
+//
+// Prepare the RPC MIDI engine to receive new song data, and transmit the song
+// filename to the server process.
+//
+boolean I_MidiSocketRegisterSong(const char *filename)
+{
+    CHECK_RPC_STATUS();
+
+    net_packet_t *packet;
+    packet = NET_NewPacket(2);
+    NET_WriteInt16(packet, NET_MIDISOCKET_PACKET_TYPE_PREPARE_NEW_SONG);
+    int len = SDLNet_TCP_Send(midi_socket, packet->data, packet->len);
+    if (len < packet->len)
+    {
+        goto fail;
+    }
+    NET_FreePacket(packet);
+
+    packet = NET_NewPacket(64);
+    NET_WriteInt16(packet, NET_MIDISOCKET_PACKET_TYPE_REGISTER_SONG);
+    NET_WriteString(packet, filename);
+    len = SDLNet_TCP_Send(midi_socket, packet->data, packet->len);
+    if (len < packet->len)
+    {
+        goto fail;
+    }
+    NET_FreePacket(packet);
+
+    DEBUGOUT("I_MidiSocketRegisterSong succeeded");
+    return true;
+
+fail:
+    NET_FreePacket(packet);
+
+    DEBUGOUT("I_MidiSocketRegisterSong failed");
+    return false;
+}
+
+//
+// I_MidiSocketPlaySong
+//
+// Tell the RPC server to start playing a song.
+//
+boolean I_MidiSocketPlaySong(boolean looping)
+{
+    CHECK_RPC_STATUS();
+
+    net_packet_t *packet;
+    packet = NET_NewPacket(3);
+    NET_WriteInt16(packet, NET_MIDISOCKET_PACKET_TYPE_PLAY_SONG);
+    NET_WriteInt8(packet, looping);
+    int len = SDLNet_TCP_Send(midi_socket, packet->data, packet->len);
+    NET_FreePacket(packet);
+    if (len < packet->len)
+    {
+        DEBUGOUT("I_MidiSocketPlaySong failed");
+        return false;
+    }
+
+    DEBUGOUT("I_MidiSocketPlaySong succeeded");
+    return true;
+}
+
+// 
+// I_MidiSocketStopSong
+//
+// Tell the RPC server to stop any currently playing song.
+//
+boolean I_MidiSocketStopSong()
+{
+    CHECK_RPC_STATUS();
+
+    net_packet_t *packet;
+    packet = NET_NewPacket(2);
+    NET_WriteInt16(packet, NET_MIDISOCKET_PACKET_TYPE_STOP_SONG);
+    int len = SDLNet_TCP_Send(midi_socket, packet->data, packet->len);
+    NET_FreePacket(packet);
+    if (len < packet->len)
+    {
+        DEBUGOUT("I_MidiSocketStopSong failed");
+        return false;
+    }
+
+    DEBUGOUT("I_MidiSocketStopSong succeeded");
+    return true;
+}
+
+//
+// I_MidiSocketSetVolume
+//
+// Change the volume level of music played by the RPC midi server.
+//
+boolean I_MidiSocketSetVolume(int volume)
+{
+    CHECK_RPC_STATUS();
+
+    net_packet_t *packet;
+    packet = NET_NewPacket(6);
+    NET_WriteInt16(packet, NET_MIDISOCKET_PACKET_TYPE_CHANGE_VOLUME);
+    NET_WriteInt32(packet, volume);
+    int len = SDLNet_TCP_Send(midi_socket, packet->data, packet->len);
+    NET_FreePacket(packet);
+    if (len < packet->len)
+    {
+        DEBUGOUT("I_MidiSocketSetVolume failed");
+        return false;
+    }
+
+    DEBUGOUT("I_MidiSocketSetVolume succeeded");
+    return true;
+}
+
+//
+// I_MidiSocketPauseSong
+//
+// Pause the music being played by the server. In actuality, due to SDL_mixer
+// limitations, this just temporarily sets the volume to zero.
+//
+boolean I_MidiSocketPauseSong()
+{
+    CHECK_RPC_STATUS();
+
+    net_packet_t *packet;
+    packet = NET_NewPacket(2);
+    NET_WriteInt16(packet, NET_MIDISOCKET_PACKET_TYPE_PAUSE_SONG);
+    int len = SDLNet_TCP_Send(midi_socket, packet->data, packet->len);
+    NET_FreePacket(packet);
+    if (len < packet->len)
+    {
+        DEBUGOUT("I_MidiSocketPauseSong failed");
+        return false;
+    }
+
+    DEBUGOUT("I_MidiSocketPauseSong succeeded");
+    return true;
+}
+
+//
+// I_MidiSocketResumeSong
+//
+// Resume a song after having paused it.
+//
+boolean I_MidiSocketResumeSong()
+{
+    CHECK_RPC_STATUS();
+
+    net_packet_t *packet;
+    packet = NET_NewPacket(2);
+    NET_WriteInt16(packet, NET_MIDISOCKET_PACKET_TYPE_RESUME_SONG);
+    int len = SDLNet_TCP_Send(midi_socket, packet->data, packet->len);
+    NET_FreePacket(packet);
+    if (len < packet->len)
+    {
+        DEBUGOUT("I_MidiSocketResumeSong failed");
+        return false;
+    }
+
+    DEBUGOUT("I_MidiSocketResumeSong succeeded");
+   return true;
+}
+
+//=============================================================================
+//
+// Public Interface
+//
+
+//
+// I_MidiSocketInitServer
+//
+// Start up the RPC MIDI server.
+//
+boolean I_MidiSocketInitServer()
+{
+    struct stat sbuf;
+    char filename[MAX_PATH+1];
+
+    memset(filename, 0, sizeof(filename));
+    size_t filename_len = GetModuleFileName(NULL, filename, MAX_PATH);
+
+    // Remove filespec
+    // TODO: Move this to m_misc
+    char *fp = &filename[filename_len];
+    while (filename <= fp && *fp != DIR_SEPARATOR)
+    {
+        fp--;
+    }
+    *(fp + 1) = '\0';
+    char* module = M_StringJoin(filename, "midiproc.exe", NULL);
+    DEBUGOUT(module);
+
+    // Look for executable file
+    if(stat(module, &sbuf))
+    {
+        DEBUGOUT("Could not find midiproc");
+        return false;
+    }
+
+    si.cb = sizeof(si);
+
+    boolean result = CreateProcess(module, NULL, NULL, NULL, FALSE,
+                                   0, NULL, NULL, &si, &pi);
+
+    if (result)
+    {
+        DEBUGOUT("RPC server started");
+        server_init = true;
+    }
+    else
+    {
+        DEBUGOUT("CreateProcess failed to start midiproc");
+    }
+
+    return result;
+}
+
+//
+// I_MidiSocketInitClient
+//
+// Initialize client RPC bindings and bind to the server.
+//
+boolean I_MidiSocketInitClient()
+{
+    IPaddress ipaddress;
+
+    // If server didn't start, client cannot be bound.
+    if (!server_init)
+    {
+        goto fail;
+    }
+
+    // Resolve localhost to an IP address.
+    if (SDLNet_ResolveHost(&ipaddress, "localhost", 2993) == -1)
+    {
+        goto fail;
+    }
+
+    // Connect to the server.
+    midi_socket = SDLNet_TCP_Open(&ipaddress);
+    if (midi_socket == NULL)
+    {
+        goto fail;
+    }
+
+    DEBUGOUT("RPC client initialized");
+    client_init = true;
+
+    return I_MidiSocketWaitForServer();
+
+fail:
+    DEBUGOUT("RPC client binding failed");
+    return false;
+}
+
+//
+// I_MidiSocketClientShutDown
+//
+// Shutdown the RPC Client
+//
+void I_MidiSocketClientShutDown()
+{
+    // stop the server
+    if(server_init)
+    {
+        net_packet_t *packet;
+        packet = NET_NewPacket(2);
+        NET_WriteInt16(packet, NET_MIDISOCKET_PACKET_TYPE_STOP_SERVER);
+        int len = SDLNet_TCP_Send(midi_socket, packet->data, packet->len);
+        NET_FreePacket(packet);
+        if (len < packet->len)
+        {
+            DEBUGOUT("Problem encountered when stopping RPC server");
+        }
+
+        server_init = false;
+    }
+
+    if (midi_socket)
+    {
+        SDLNet_TCP_Close(midi_socket);
+        midi_socket = NULL;
+    }
+
+    client_init = false;
+}
+
+//
+// I_MidiSocketReady
+//
+// Returns true if both server and client initialized successfully.
+//
+boolean I_MidiSocketReady()
+{
+    CHECK_RPC_STATUS();
+
+    return true;
+}
+
+#endif
+
--- /dev/null
+++ b/src/i_midisocket.h
@@ -1,0 +1,40 @@
+//
+// Copyright(C) 2013 James Haley et al.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// DESCRIPTION:
+//     Client Interface to RPC Midi Server
+//
+
+#ifndef __I_MIDISOCKET__
+#define __I_MIDISOCKET__
+
+#if _WIN32
+
+#include "doomtype.h"
+
+boolean I_MidiSocketInitServer();
+boolean I_MidiSocketInitClient();
+void I_MidiSocketClientShutDown();
+boolean I_MidiSocketReady();
+
+boolean I_MidiSocketRegisterSong(const char *filename);
+boolean I_MidiSocketPlaySong(boolean looping);
+boolean I_MidiSocketStopSong();
+boolean I_MidiSocketSetVolume(int volume);
+boolean I_MidiSocketPauseSong();
+boolean I_MidiSocketResumeSong();
+
+#endif
+
+#endif
+
--- a/src/i_sdlmusic.c
+++ b/src/i_sdlmusic.c
@@ -25,6 +25,8 @@
 #include "SDL.h"
 #include "SDL_mixer.h"
 
+#include "i_midisocket.h"
+
 #include "config.h"
 #include "doomtype.h"
 #include "memio.h"
@@ -972,6 +974,10 @@
         LoadSubstituteConfigs();
     }
 
+#if WIN32
+    I_MidiSocketInitServer();
+#endif
+
     return music_initialized;
 }
 
@@ -993,7 +999,11 @@
         vol = (current_music_volume * MIX_MAX_VOLUME) / 127;
     }
 
+#if WIN32
+    I_MidiSocketSetVolume(vol);
+#else
     Mix_VolumeMusic(vol);
+#endif
 }
 
 // Set music volume (0 - 127)
@@ -1044,7 +1054,11 @@
         SDL_UnlockAudio();
     }
 
+#if _WIN32
+    I_MidiSocketPlaySong(loops);
+#else
     Mix_PlayMusic(current_track_music, loops);
+#endif
 }
 
 static void I_SDL_PauseSong(void)
@@ -1078,7 +1092,12 @@
         return;
     }
 
+#if _WIN32
+    I_MidiSocketStopSong();
+#else
     Mix_HaltMusic();
+#endif
+
     playing_substitute = false;
     current_track_music = NULL;
 }
@@ -1189,7 +1208,11 @@
     // by now, but Mix_SetMusicCMD() only works with Mix_LoadMUS(), so
     // we have to generate a temporary file.
 
+#ifdef _WIN32
+    music = (Mix_Music*)I_MidiSocketRegisterSong(filename);
+#else
     music = Mix_LoadMUS(filename);
+#endif
 
     if (music == NULL)
     {