Changeset - r2197:2448467991a5
[Not reviewed]
master
2 2 1
tron - 19 years ago 2005-07-26 06:59:48
tron@openttd.org
(svn r2712) Overhaul DirectMusic MIDI backend:
- Merge the .c and .cpp part into one file
- Properly deinitialize at the end
- Remove "experimental" status
- Miscellaneous smaller changes
-Fix: Volume control works now
5 files changed with 229 insertions and 437 deletions:
0 comments (0 inline, 0 general)
Makefile
Show inline comments
 
@@ -66,6 +66,7 @@
 
# MIDI: if set, it will use it as custom path to midi player.
 
#       If unset, it will use the hardcoded path in the c code
 
#       This can still be overriden by the music.extmidi openttd.cfg option.
 
# WITH_DIRECTMUSIC: enable DirectMusic MIDI support
 
# WITH_NETWORK: enable networking
 
# DEDICATED: allows compilation on UNIX without SDL. Useful for dedicated servers
 
#
 
@@ -118,9 +119,6 @@
 
# CC_HOST: the gcc of your localhost if you are making a target that produces incompatible executables
 
# CFLAGS_HOST: cflags used for CC_HOST. Make it something if you are getting errors when you try to compi
 
#		windows executables on linux. (just: CFLAGS_HOST:='-I' or something)
 
#
 
# Experimental (does not work properly):
 
# WITH_DIRECTMUSIC: enable DirectMusic MIDI support
 

	
 

	
 
##############################################################################
 
@@ -751,8 +749,7 @@ OBJS += winres.o
 
endif
 

	
 
ifdef WITH_DIRECTMUSIC
 
C_SOURCES += music/dmusic.c
 
CXX_SOURCES += music/dmusic2.cpp
 
CXX_SOURCES += music/dmusic.cpp
 
endif
 

	
 
DEPS = $(OBJS:%.o=.deps/%.d)
makefiledir/Makefile.config_writer
Show inline comments
 
@@ -27,6 +27,7 @@ CONFIG_LINE=@$(SHELL) -c 'echo $(1)' >> 
 
	$(call CONFIG_LINE,MIDI:=$(MIDI))
 
	$(call CONFIG_LINE,MIDI_ARG:=$(MIDI_ARG))
 
	$(call CONFIG_LINE,SUPRESS_LANG_ERRORS:=$(SUPRESS_LANG_ERRORS))
 
	$(call CONFIG_LINE,WITH_DIRECTMUSIC:=$(WITH_DIRECTMUSIC))
 
	$(call CONFIG_LINE,WITH_NETWORK:=$(WITH_NETWORK))
 
	$(call CONFIG_LINE,DEDICATED:=$(DEDICATED))
 
	$(call CONFIG_LINE,GPMI:=$(GPMI))
 
@@ -48,11 +49,6 @@ CONFIG_LINE=@$(SHELL) -c 'echo $(1)' >> 
 
	$(call CONFIG_LINE,CUSTOM_LANG_PATH:=$(CUSTOM_LANG_PATH))
 
	$(call CONFIG_LINE,)
 

	
 
	$(call CONFIG_LINE,\# Experimental)
 
	$(call CONFIG_LINE,WITH_DIRECTMUSIC:=$(WITH_DIRECTMUSIC))
 
	$(call CONFIG_LINE,)
 
	$(call CONFIG_LINE,)
 

	
 
	$(call CONFIG_LINE,\# Flag to skip test for OS when building static)
 
	$(call CONFIG_LINE,\# OpenTTD have only been succesfully tested with static builds on MorphOS and MacOSX)
 
	$(call CONFIG_LINE,\# If you want to try anyway on other OSes, set this flag)
music/dmusic.c
Show inline comments
 
deleted file
music/dmusic.cpp
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
#include "../stdafx.h"
 

	
 
#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT
 

	
 
extern "C" {
 
	#include "../openttd.h"
 
	#include "../debug.h"
 
	#include "../win32.h"
 
	#include "dmusic.h"
 
}
 

	
 
#include <windows.h>
 
#include <dmksctrl.h>
 
#include <dmusici.h>
 
#include <dmusicc.h>
 
#include <dmusicf.h>
 

	
 

	
 
// the performance object controls manipulation of the segments
 
static IDirectMusicPerformance* performance = NULL;
 

	
 
// the loader object can load many types of DMusic related files
 
static IDirectMusicLoader* loader = NULL;
 

	
 
// the segment object is where the MIDI data is stored for playback
 
static IDirectMusicSegment* segment = NULL;
 

	
 
static bool seeking = false;
 

	
 

	
 
#define M(x) x "\0"
 
static const char ole_files[] =
 
	M("ole32.dll")
 
	M("CoCreateInstance")
 
	M("CoInitialize")
 
	M("CoUninitialize")
 
	M("")
 
;
 
#undef M
 

	
 
struct ProcPtrs {
 
	unsigned long (WINAPI * CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID* ppv);
 
	HRESULT (WINAPI * CoInitialize)(LPVOID pvReserved);
 
	void (WINAPI * CoUninitialize)();
 
};
 

	
 
static ProcPtrs proc;
 

	
 

	
 
static const char* DMusicMidiStart(const char* const* parm)
 
{
 
	if (performance != NULL) return NULL;
 

	
 
	if (proc.CoCreateInstance == NULL) {
 
		if (!LoadLibraryList((Function*)&proc, ole_files))
 
			return "ole32.dll load failed";
 
	}
 

	
 
	// Initialize COM
 
	if (FAILED(proc.CoInitialize(NULL))) {
 
		return "COM initialization failed";
 
	}
 

	
 
	// create the performance object
 
	if (FAILED(proc.CoCreateInstance(
 
				CLSID_DirectMusicPerformance,
 
				NULL,
 
				CLSCTX_INPROC,
 
				IID_IDirectMusicPerformance,
 
				(LPVOID*)&performance
 
			))) {
 
		proc.CoUninitialize();
 
		return "Failed to create the performance object";
 
	}
 

	
 
	// initialize it
 
	if (FAILED(performance->Init(NULL, NULL, NULL))) {
 
		performance->Release();
 
		performance = NULL;
 
		proc.CoUninitialize();
 
		return "Failed to initialize performance object";
 
	}
 

	
 
	// choose default Windows synth
 
	if (FAILED(performance->AddPort(NULL))) {
 
		performance->CloseDown();
 
		performance->Release();
 
		performance = NULL;
 
		proc.CoUninitialize();
 
		return "AddPort failed";
 
	}
 

	
 
	// create the loader object; this will be used to load the MIDI file
 
	if (FAILED(proc.CoCreateInstance(
 
				CLSID_DirectMusicLoader,
 
				NULL,
 
				CLSCTX_INPROC,
 
				IID_IDirectMusicLoader,
 
				(LPVOID*)&loader
 
			))) {
 
		performance->CloseDown();
 
		performance->Release();
 
		performance = NULL;
 
		proc.CoUninitialize();
 
		return "Failed to create loader object";
 
	}
 

	
 
	return NULL;
 
}
 

	
 

	
 
static void DMusicMidiStop(void)
 
{
 
	/* release everything but the segment, which the performance
 
	 * will release automatically (and it'll crash if it's been
 
	 * released already) */
 

	
 
	seeking = false;
 

	
 
	loader->Release();
 
	loader = NULL;
 

	
 
	performance->CloseDown();
 
	performance->Release();
 
	performance = NULL;
 

	
 
	segment = NULL;
 

	
 
	proc.CoUninitialize();
 
}
 

	
 

	
 
static void DMusicMidiPlaySong(const char* filename)
 
{
 
	// set up the loader object info
 
	DMUS_OBJECTDESC obj_desc;
 
	ZeroMemory(&obj_desc, sizeof(obj_desc));
 
	obj_desc.dwSize = sizeof(obj_desc);
 
	obj_desc.guidClass = CLSID_DirectMusicSegment;
 
	obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;
 
	MultiByteToWideChar(
 
		CP_ACP, MB_PRECOMPOSED,
 
		filename, -1,
 
		obj_desc.wszFileName, lengthof(obj_desc.wszFileName)
 
	);
 

	
 
	// release the existing segment if we have any
 
	if (segment != NULL) {
 
		segment->Release();
 
		segment = NULL;
 
	}
 

	
 
	// make a new segment
 
	if (FAILED(loader->GetObject(
 
				&obj_desc, IID_IDirectMusicSegment, (LPVOID*)&segment
 
			))) {
 
		DEBUG(misc, 0) ("DirectMusic: Get object failed");
 
		return;
 
	}
 

	
 
	// tell the segment what kind of data it contains
 
	if (FAILED(segment->SetParam(
 
				GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, performance
 
			))) {
 
		DEBUG(misc, 0) ("DirectMusic: SetParam (MIDI file) failed");
 
		return;
 
	}
 

	
 
	// tell the segment to 'download' the instruments
 
	if (FAILED(segment->SetParam(GUID_Download, 0xFFFFFFFF, 0, 0, performance))) {
 
		DEBUG(misc, 0) ("DirectMusic: Failed to download instruments");
 
		return;
 
	}
 

	
 
	// start playing the MIDI file
 
	if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) {
 
		DEBUG(misc, 0) ("DirectMusic: PlaySegment failed");
 
		return;
 
	}
 

	
 
	seeking = true;
 
}
 

	
 

	
 
static void DMusicMidiStopSong(void)
 
{
 
	if (FAILED(performance->Stop(segment, NULL, 0, 0))) {
 
		DEBUG(misc, 0) ("DirecMusic: StopSegment failed");
 
	}
 
	seeking = false;
 
}
 

	
 

	
 
static bool DMusicMidiIsSongPlaying(void)
 
{
 
	/* Not the nicest code, but there is a short delay before playing actually
 
	 * starts. OpenTTD makes no provision for this. */
 
	if (performance->IsPlaying(segment, NULL) == S_OK) {
 
		seeking = false;
 
		return true;
 
	} else {
 
		return seeking;
 
	}
 
}
 

	
 

	
 
static void DMusicMidiSetVolume(byte vol)
 
{
 
	// 0 - 127 -> -2000 - 0
 
	long db = vol * 2000 / 127 - 2000;
 
	performance->SetGlobalParam(GUID_PerfMasterVolume, &db, sizeof(db));
 
}
 

	
 

	
 
extern "C" const HalMusicDriver _dmusic_midi_driver = {
 
	DMusicMidiStart,
 
	DMusicMidiStop,
 
	DMusicMidiPlaySong,
 
	DMusicMidiStopSong,
 
	DMusicMidiIsSongPlaying,
 
	DMusicMidiSetVolume,
 
};
 

	
 
#endif
music/dmusic2.cpp
Show inline comments
 
deleted file
0 comments (0 inline, 0 general)