ref: 2f8ed99c11279ab932dbda6db0647f70c3280b7a
parent: a941e8c70a73570b6c9bae3c037e880262bb499d
author: Alex Mayfield <alexmax2742@gmail.com>
date: Fri Feb 10 13:40:34 EST 2017
Normalize header comments and file extensions
--- /dev/null
+++ b/midiproc/main.c
@@ -1,0 +1,377 @@
+//
+// Copyright(C) 2012 James Haley
+//
+// 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:
+//
+// Win32/SDL_mixer MIDI RPC Server
+//
+// Uses RPC to communicate with Doom. This allows this separate process to
+// have its own independent volume control even under Windows Vista and up's
+// broken, stupid, completely useless mixer model that can't assign separate
+// volumes to different devices for the same process.
+//
+// Seriously, how did they screw up something so fundamental?
+//
+
+#include <windows.h>
+#include <stdlib.h>
+#include "SDL.h"
+#include "SDL_mixer.h"
+#include "midiproc.h"
+
+// Currently playing music track
+static Mix_Music *music = NULL;
+static SDL_RWops *rw = NULL;
+
+static void UnregisterSong();
+
+//=============================================================================
+//
+// 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);
+}
+
+//=============================================================================
+//
+// SDL_mixer Interface
+//
+
+//
+// InitSDL
+//
+// Start up SDL and SDL_mixer.
+//
+static bool InitSDL()
+{
+ if(SDL_Init(SDL_INIT_AUDIO) == -1)
+ return false;
+
+ if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
+ return false;
+
+ return true;
+}
+
+//
+// RegisterSong
+//
+static void RegisterSong(void *data, size_t size)
+{
+ if(music)
+ UnregisterSong();
+
+ rw = SDL_RWFromMem(data, size);
+ music = Mix_LoadMUS_RW(rw);
+}
+
+//
+// StartSong
+//
+static void StartSong(bool loop)
+{
+ if(music)
+ Mix_PlayMusic(music, loop ? -1 : 0);
+}
+
+//
+// SetVolume
+//
+static void SetVolume(int volume)
+{
+ Mix_VolumeMusic((volume * 128) / 15);
+}
+
+static int paused_midi_volume;
+
+//
+// PauseSong
+//
+static void PauseSong()
+{
+ paused_midi_volume = Mix_VolumeMusic(-1);
+ Mix_VolumeMusic(0);
+}
+
+//
+// ResumeSong
+//
+static void ResumeSong()
+{
+ Mix_VolumeMusic(paused_midi_volume);
+}
+
+//
+// StopSong
+//
+static void StopSong()
+{
+ if(music)
+ Mix_HaltMusic();
+}
+
+//
+// UnregisterSong
+//
+static void UnregisterSong()
+{
+ if(!music)
+ return;
+
+ StopSong();
+ Mix_FreeMusic(music);
+ rw = NULL;
+ music = NULL;
+}
+
+//
+// ShutdownSDL
+//
+static void ShutdownSDL()
+{
+ UnregisterSong();
+ Mix_CloseAudio();
+ SDL_Quit();
+}
+
+//=============================================================================
+//
+// Song Buffer
+//
+// The MIDI program will be transmitted by the client across RPC in fixed-size
+// chunks until all data has been transmitted.
+//
+
+typedef unsigned char midibyte;
+
+class SongBuffer
+{
+protected:
+ midibyte *buffer; // accumulated input
+ size_t size; // size of input
+ size_t allocated; // amount of memory allocated (>= size)
+
+ static const int defaultSize = 128*1024; // 128 KB
+
+public:
+ // Constructor
+ // Start out with an empty 128 KB buffer.
+ SongBuffer()
+ {
+ buffer = static_cast<midibyte *>(calloc(1, defaultSize));
+ size = 0;
+ allocated = defaultSize;
+ }
+
+ // Destructor.
+ // Release the buffer.
+ ~SongBuffer()
+ {
+ if(buffer)
+ {
+ free(buffer);
+ buffer = NULL;
+ size = allocated = 0;
+ }
+ }
+
+ //
+ // addChunk
+ //
+ // Add a chunk of MIDI data to the buffer.
+ //
+ void addChunk(midibyte *data, size_t newsize)
+ {
+ if(size + newsize > allocated)
+ {
+ allocated += newsize * 2;
+ buffer = static_cast<midibyte *>(realloc(buffer, allocated));
+ }
+
+ memcpy(buffer + size, data, newsize);
+ size += newsize;
+ }
+
+ // Accessors
+
+ midibyte *getBuffer() const { return buffer; }
+ size_t getSize() const { return size; }
+};
+
+static SongBuffer *song;
+
+//=============================================================================
+//
+// RPC Server Interface
+//
+
+//
+// MidiRPC_PrepareNewSong
+//
+// Prepare the engine to receive new song data from the RPC client.
+//
+void MidiRPC_PrepareNewSong()
+{
+ // Stop anything currently playing and free it.
+ UnregisterSong();
+
+ // free any previous song buffer
+ delete song;
+
+ // prep new song buffer
+ song = new SongBuffer();
+}
+
+//
+// MidiRPC_AddChunk
+//
+// Add a chunk of data to the song.
+//
+void MidiRPC_AddChunk(unsigned int count, byte *pBuf)
+{
+ song->addChunk(pBuf, static_cast<size_t>(count));
+}
+
+//
+// MidiRPC_PlaySong
+//
+// Start playing the song.
+//
+void MidiRPC_PlaySong(boolean looping)
+{
+ RegisterSong(song->getBuffer(), song->getSize());
+ StartSong(!!looping);
+}
+
+//
+// MidiRPC_StopSong
+//
+// Stop the song.
+//
+void MidiRPC_StopSong()
+{
+ StopSong();
+}
+
+//
+// MidiRPC_ChangeVolume
+//
+// Set playback volume level.
+//
+void MidiRPC_ChangeVolume(int volume)
+{
+ SetVolume(volume);
+}
+
+//
+// MidiRPC_PauseSong
+//
+// Pause the song.
+//
+void MidiRPC_PauseSong()
+{
+ PauseSong();
+}
+
+//
+// MidiRPC_ResumeSong
+//
+// Resume after pausing.
+//
+void MidiRPC_ResumeSong()
+{
+ ResumeSong();
+}
+
+//
+// MidiRPC_StopServer
+//
+// Stops the RPC server so the program can shutdown.
+//
+void MidiRPC_StopServer()
+{
+ // Local shutdown tasks
+ ShutdownSDL();
+ delete song;
+ song = NULL;
+
+ // Stop RPC server
+ RpcMgmtStopServerListening(NULL);
+}
+
+//
+// RPC Server Init
+//
+static bool MidiRPC_InitServer()
+{
+ RPC_STATUS status;
+
+ // Initialize RPC protocol
+ status =
+ RpcServerUseProtseqEp
+ (
+ (RPC_CSTR)("ncalrpc"),
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+ (RPC_CSTR)("2d4dc2f9-ce90-4080-8a00-1cb819086970"),
+ NULL
+ );
+
+ if(status)
+ return false;
+
+ // Register server
+ status = RpcServerRegisterIf(MidiRPC_v1_0_s_ifspec, NULL, NULL);
+
+ if(status)
+ return false;
+
+ // Start listening
+ status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
+
+ return !status;
+}
+
+//=============================================================================
+//
+// Main Program
+//
+
+//
+// WinMain
+//
+// Application entry point.
+//
+int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine, int nCmdShow)
+{
+ // Initialize SDL
+ if(!InitSDL())
+ return -1;
+
+ // Initialize RPC Server
+ if(!MidiRPC_InitServer())
+ return -1;
+
+ return 0;
+}
+
+// EOF
+
--- a/midiproc/main.cpp
+++ /dev/null
@@ -1,386 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2012 James Haley
-//
-// 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.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-//
-// Win32/SDL_mixer MIDI RPC Server
-//
-// Uses RPC to communicate with Eternity. This allows this separate process to
-// have its own independent volume control even under Windows Vista and up's
-// broken, stupid, completely useless mixer model that can't assign separate
-// volumes to different devices for the same process.
-//
-// Seriously, how did they screw up something so fundamental?
-//
-//-----------------------------------------------------------------------------
-
-#include <windows.h>
-#include <stdlib.h>
-#include "SDL.h"
-#include "SDL_mixer.h"
-#include "midiproc.h"
-
-// Currently playing music track
-static Mix_Music *music = NULL;
-static SDL_RWops *rw = NULL;
-
-static void UnregisterSong();
-
-//=============================================================================
-//
-// 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);
-}
-
-//=============================================================================
-//
-// SDL_mixer Interface
-//
-
-//
-// InitSDL
-//
-// Start up SDL and SDL_mixer.
-//
-static bool InitSDL()
-{
- if(SDL_Init(SDL_INIT_AUDIO) == -1)
- return false;
-
- if(Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
- return false;
-
- return true;
-}
-
-//
-// RegisterSong
-//
-static void RegisterSong(void *data, size_t size)
-{
- if(music)
- UnregisterSong();
-
- rw = SDL_RWFromMem(data, size);
- music = Mix_LoadMUS_RW(rw);
-}
-
-//
-// StartSong
-//
-static void StartSong(bool loop)
-{
- if(music)
- Mix_PlayMusic(music, loop ? -1 : 0);
-}
-
-//
-// SetVolume
-//
-static void SetVolume(int volume)
-{
- Mix_VolumeMusic((volume * 128) / 15);
-}
-
-static int paused_midi_volume;
-
-//
-// PauseSong
-//
-static void PauseSong()
-{
- paused_midi_volume = Mix_VolumeMusic(-1);
- Mix_VolumeMusic(0);
-}
-
-//
-// ResumeSong
-//
-static void ResumeSong()
-{
- Mix_VolumeMusic(paused_midi_volume);
-}
-
-//
-// StopSong
-//
-static void StopSong()
-{
- if(music)
- Mix_HaltMusic();
-}
-
-//
-// UnregisterSong
-//
-static void UnregisterSong()
-{
- if(!music)
- return;
-
- StopSong();
- Mix_FreeMusic(music);
- rw = NULL;
- music = NULL;
-}
-
-//
-// ShutdownSDL
-//
-static void ShutdownSDL()
-{
- UnregisterSong();
- Mix_CloseAudio();
- SDL_Quit();
-}
-
-//=============================================================================
-//
-// Song Buffer
-//
-// The MIDI program will be transmitted by the client across RPC in fixed-size
-// chunks until all data has been transmitted.
-//
-
-typedef unsigned char midibyte;
-
-class SongBuffer
-{
-protected:
- midibyte *buffer; // accumulated input
- size_t size; // size of input
- size_t allocated; // amount of memory allocated (>= size)
-
- static const int defaultSize = 128*1024; // 128 KB
-
-public:
- // Constructor
- // Start out with an empty 128 KB buffer.
- SongBuffer()
- {
- buffer = static_cast<midibyte *>(calloc(1, defaultSize));
- size = 0;
- allocated = defaultSize;
- }
-
- // Destructor.
- // Release the buffer.
- ~SongBuffer()
- {
- if(buffer)
- {
- free(buffer);
- buffer = NULL;
- size = allocated = 0;
- }
- }
-
- //
- // addChunk
- //
- // Add a chunk of MIDI data to the buffer.
- //
- void addChunk(midibyte *data, size_t newsize)
- {
- if(size + newsize > allocated)
- {
- allocated += newsize * 2;
- buffer = static_cast<midibyte *>(realloc(buffer, allocated));
- }
-
- memcpy(buffer + size, data, newsize);
- size += newsize;
- }
-
- // Accessors
-
- midibyte *getBuffer() const { return buffer; }
- size_t getSize() const { return size; }
-};
-
-static SongBuffer *song;
-
-//=============================================================================
-//
-// RPC Server Interface
-//
-
-//
-// MidiRPC_PrepareNewSong
-//
-// Prepare the engine to receive new song data from the RPC client.
-//
-void MidiRPC_PrepareNewSong()
-{
- // Stop anything currently playing and free it.
- UnregisterSong();
-
- // free any previous song buffer
- delete song;
-
- // prep new song buffer
- song = new SongBuffer();
-}
-
-//
-// MidiRPC_AddChunk
-//
-// Add a chunk of data to the song.
-//
-void MidiRPC_AddChunk(unsigned int count, byte *pBuf)
-{
- song->addChunk(pBuf, static_cast<size_t>(count));
-}
-
-//
-// MidiRPC_PlaySong
-//
-// Start playing the song.
-//
-void MidiRPC_PlaySong(boolean looping)
-{
- RegisterSong(song->getBuffer(), song->getSize());
- StartSong(!!looping);
-}
-
-//
-// MidiRPC_StopSong
-//
-// Stop the song.
-//
-void MidiRPC_StopSong()
-{
- StopSong();
-}
-
-//
-// MidiRPC_ChangeVolume
-//
-// Set playback volume level.
-//
-void MidiRPC_ChangeVolume(int volume)
-{
- SetVolume(volume);
-}
-
-//
-// MidiRPC_PauseSong
-//
-// Pause the song.
-//
-void MidiRPC_PauseSong()
-{
- PauseSong();
-}
-
-//
-// MidiRPC_ResumeSong
-//
-// Resume after pausing.
-//
-void MidiRPC_ResumeSong()
-{
- ResumeSong();
-}
-
-//
-// MidiRPC_StopServer
-//
-// Stops the RPC server so the program can shutdown.
-//
-void MidiRPC_StopServer()
-{
- // Local shutdown tasks
- ShutdownSDL();
- delete song;
- song = NULL;
-
- // Stop RPC server
- RpcMgmtStopServerListening(NULL);
-}
-
-//
-// RPC Server Init
-//
-static bool MidiRPC_InitServer()
-{
- RPC_STATUS status;
-
- // Initialize RPC protocol
- status =
- RpcServerUseProtseqEp
- (
- (RPC_CSTR)("ncalrpc"),
- RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
- (RPC_CSTR)("2d4dc2f9-ce90-4080-8a00-1cb819086970"),
- NULL
- );
-
- if(status)
- return false;
-
- // Register server
- status = RpcServerRegisterIf(MidiRPC_v1_0_s_ifspec, NULL, NULL);
-
- if(status)
- return false;
-
- // Start listening
- status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, FALSE);
-
- return !status;
-}
-
-//=============================================================================
-//
-// Main Program
-//
-
-//
-// WinMain
-//
-// Application entry point.
-//
-int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, int nCmdShow)
-{
- // Initialize SDL
- if(!InitSDL())
- return -1;
-
- // Initialize RPC Server
- if(!MidiRPC_InitServer())
- return -1;
-
- return 0;
-}
-
-// EOF
-
--- /dev/null
+++ b/src/i_midirpc.c
@@ -1,0 +1,389 @@
+//
+// 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.cpp
+++ /dev/null
@@ -1,398 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// 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 3 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.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see http://www.gnu.org/licenses/
-//
-//----------------------------------------------------------------------------
-//
-// 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
+++ b/src/i_midirpc.h
@@ -1,12 +1,10 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
//
-// Copyright (C) 2013 James Haley et al.
+// 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 3 of the License, or
-// (at your option) any later version.
+// 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
@@ -13,19 +11,9 @@
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see http://www.gnu.org/licenses/
-//
-// Additional terms and conditions compatible with the GPLv3 apply. See the
-// file COPYING-EE for details.
-//
-//----------------------------------------------------------------------------
-//
// DESCRIPTION:
+// Client Interface to RPC Midi Server
//
-// Client Interface to RPC Midi Server
-//
-//-----------------------------------------------------------------------------
#ifndef I_MIDIRPC_H__
#define I_MIDIRPC_H__