From efaeb275f78e18d594d9ee8ff04eccd2dc59512c Mon Sep 17 00:00:00 2001 From: truelight Date: Mon, 9 Aug 2004 17:04:08 +0000 Subject: (svn r1) Import of revision 975 of old (crashed) SVN --- w32dm2.cpp | 305 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 w32dm2.cpp (limited to 'w32dm2.cpp') diff --git a/w32dm2.cpp b/w32dm2.cpp new file mode 100644 index 000000000..eac3fe41c --- /dev/null +++ b/w32dm2.cpp @@ -0,0 +1,305 @@ +/********************************************************************* + * OpenTTD: An Open Source Transport Tycoon Deluxe clone * + * Copyright (c) 2002-2004 OpenTTD Developers. All Rights Reserved. * + * * + * Web site: http://openttd.sourceforge.net/ * + *********************************************************************/ + +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* DirectMusic driver for Win32 */ +/* Based on dxmci from TTDPatch */ + +#include "stdafx.h" + +#ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT + +// for gcc, the GUIDs are available in a library instead +#ifndef __GNUC__ +#define INITGUID +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ttd.h" +#include "sound.h" +#include "hal.h" + +#ifdef __cplusplus + } +#endif + +#include +#include + +#include +#include +#include +#include + +#define VARIANT int + +#define MSGBOX(output) DEBUG(misc, 0) ("DirectMusic driver: %s\n", output); //MessageBox(NULL, output, "dxmci",MB_OK); +#define MULTI_TO_WIDE( x,y ) MultiByteToWideChar( CP_ACP,MB_PRECOMPOSED, y,-1,x,_MAX_PATH); + +// the performance object controls manipulation of the segments +IDirectMusicPerformance *performance = NULL; + +// the segment object is where the MIDI data is stored for playback +IDirectMusicSegment *segment = NULL; + +// the loader bject can load many types of DMusic related files +IDirectMusicLoader *loader = NULL; + +// whether we've initialized COM or not (when deciding whether to shut down) +int COMInitialized = 0; + + +extern "C" bool LoadLibraryList(void **proc, const char *dll); + +// Use lazy linking +struct ProcPtrs { + unsigned long (WINAPI *CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID * ppv); + HRESULT (WINAPI *CoInitialize)( LPVOID pvReserved ); + void (WINAPI *CoUninitialize)( ); +}; + +#define M(x) x "\0" +static const char ole_files[] = + M("ole32.dll") + M("CoCreateInstance") + M("CoInitialize") + M("CoUninitialize") + M("") +; +#undef M + + +static ProcPtrs _proc; + +static bool LoadOleDLL() +{ + if (_proc.CoCreateInstance != NULL) + return true; + if (!LoadLibraryList((void**)&_proc, ole_files)) + return false; + return true; +} + + +#ifdef __cplusplus +extern "C" { +#endif + +// Initialize COM and DirectMusic +bool InitDirectMusic (void) +{ + if (NULL != performance) + return true; + + // Initialize COM + if (!COMInitialized) { + if (!LoadOleDLL()) { + MSGBOX("ole32.dll load failed"); + return false; + } + + _proc.CoInitialize(NULL); + COMInitialized = 1; + } + + // Create the performance object via CoCreateInstance + if (FAILED(_proc.CoCreateInstance( + (REFCLSID)CLSID_DirectMusicPerformance, + NULL, + CLSCTX_INPROC, + (REFIID)IID_IDirectMusicPerformance, + (LPVOID *)&performance))) { + MSGBOX ("Failed to create the performance object"); + return false; + } + + // Initialize it + if (FAILED(performance->Init(NULL, NULL, NULL))) { + MSGBOX("Failed to initialize performance object"); + return false; + } + + // Choose default Windows synth + if (FAILED(performance->AddPort (NULL))) { + MSGBOX("AddPort failed"); + return false; + } + + // now we'll create the loader object. This will be used to load the + // midi file for our demo. Again, we need to use CoCreateInstance + // and pass the appropriate ID parameters + if (FAILED(_proc.CoCreateInstance((REFCLSID)CLSID_DirectMusicLoader, + NULL, CLSCTX_INPROC, + (REFIID)IID_IDirectMusicLoader, + (LPVOID *)&loader))) { + MSGBOX("Failed to create loader object"); + return false; + } + + // that's it for initialization. If we made it this far we + // were successful. + return true; +} + +// Releases memory used by all of the initialized +// DirectMusic objects in the program +void ReleaseSegment (void) +{ + if (NULL != segment) { + segment->Release (); + segment = NULL; + } +} +void ShutdownDirectMusic (void) +{ + // release everything but the segment, which the performance + // will release automatically (and it'll crash if it's been + // released already) + + if (NULL != loader) { + loader->Release (); + loader = NULL; + } + + if (NULL != performance) + { + performance->CloseDown (); + performance->Release (); + performance = NULL; + } + + if (COMInitialized) { + _proc.CoUninitialize(); + COMInitialized = 0; + } +} + +// Load MIDI file for playing +bool LoadMIDI (char *directory, char *filename) +{ + DMUS_OBJECTDESC obj_desc; + WCHAR w_directory[_MAX_PATH]; // utf-16 version of the directory name. + WCHAR w_filename[_MAX_PATH]; // utf-16 version of the file name + + if (NULL == performance) + return false; + + MULTI_TO_WIDE(w_directory,directory); + + if (FAILED(loader->SetSearchDirectory((REFGUID) GUID_DirectMusicAllTypes, + w_directory, FALSE))) { + MSGBOX("LoadMIDI: SetSearchDirectory failed"); + return false; + } + + // set up the loader object info + ZeroMemory (&obj_desc, sizeof (obj_desc)); + obj_desc.dwSize = sizeof (obj_desc); + + MULTI_TO_WIDE(w_filename,filename); + obj_desc.guidClass = CLSID_DirectMusicSegment; + + wcscpy (obj_desc.wszFileName,w_filename); + obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME; + + // release the existing segment if we have any + if (NULL != segment) + ReleaseSegment(); + + // and make a new segment + if (FAILED(loader->GetObject(&obj_desc, + (REFIID)IID_IDirectMusicSegment, + (LPVOID *) &segment))) { + MSGBOX("LoadMIDI: Get object failed"); + return FALSE; + } + + // next we need to tell the segment what kind of data it contains. We do this + // with the IDirectMusicSegment::SetParam function. + if (FAILED(segment->SetParam((REFGUID)GUID_StandardMIDIFile, + -1, 0, 0, (LPVOID)performance))) { + MSGBOX("LoadMIDI: SetParam (MIDI file) failed"); + return false; + } + + // finally, we need to tell the segment to 'download' the instruments + if (FAILED(segment->SetParam((REFGUID)GUID_Download, + -1, 0, 0, (LPVOID)performance))) { + MSGBOX("LoadMIDI: Failed to download instruments"); + return false; + } + + // at this point, the MIDI file is loaded and ready to play! + return true; +} + +// Start playing the MIDI file +void PlaySegment (void) +{ + if (NULL == performance) + return; + + if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) { + MSGBOX("PlaySegment failed"); + } +} + +// Stop playing +void StopSegment (void) +{ + if (NULL == performance || NULL == segment) + return; + + if (FAILED(performance->Stop(segment, NULL, 0, 0))) { + MSGBOX("StopSegment failed"); + } +} + +// Find out whether playing has started or stopped +bool IsSegmentPlaying (void) +{ + if (NULL == performance || NULL == segment) + return FALSE; + + // IsPlaying return S_OK if the segment is currently playing + return performance->IsPlaying(segment, NULL) == S_OK ? TRUE : FALSE; +} + +void SetVolume(long vol) +{ + long db; + + if (performance == NULL && !InitDirectMusic()) + return; + + db = ((vol >> 21) & 0x7ff) - 1000; + performance->SetGlobalParam(GUID_PerfMasterVolume, &db, sizeof(db)); +} + +#if defined(__cplusplus) +} +#endif + +#endif // WIN32_ENABLE_DIRECTMUSIC_SUPPORT -- cgit v1.2.3-54-g00ecf