dmusic.cpp

Go to the documentation of this file.
00001 /* $Id: dmusic.cpp 11826 2008-01-13 00:14:29Z glx $ */
00002 
00005 #ifdef WIN32_ENABLE_DIRECTMUSIC_SUPPORT
00006 
00007 #include "../stdafx.h"
00008 #include "../debug.h"
00009 #include "../win32.h"
00010 #include "dmusic.h"
00011 
00012 #include <windows.h>
00013 #include <dmksctrl.h>
00014 #include <dmusici.h>
00015 #include <dmusicc.h>
00016 #include <dmusicf.h>
00017 
00018 static FMusicDriver_DMusic iFMusicDriver_DMusic;
00019 
00021 static IDirectMusicPerformance* performance = NULL;
00022 
00024 static IDirectMusicLoader* loader = NULL;
00025 
00027 static IDirectMusicSegment* segment = NULL;
00028 
00029 static bool seeking = false;
00030 
00031 
00032 #define M(x) x "\0"
00033 static const char ole_files[] =
00034   M("ole32.dll")
00035   M("CoCreateInstance")
00036   M("CoInitialize")
00037   M("CoUninitialize")
00038   M("")
00039 ;
00040 #undef M
00041 
00042 struct ProcPtrs {
00043   unsigned long (WINAPI * CoCreateInstance)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID* ppv);
00044   HRESULT (WINAPI * CoInitialize)(LPVOID pvReserved);
00045   void (WINAPI * CoUninitialize)();
00046 };
00047 
00048 static ProcPtrs proc;
00049 
00050 
00051 const char *MusicDriver_DMusic::Start(const char * const *parm)
00052 {
00053   if (performance != NULL) return NULL;
00054 
00055   if (proc.CoCreateInstance == NULL) {
00056     if (!LoadLibraryList((Function*)&proc, ole_files))
00057       return "ole32.dll load failed";
00058   }
00059 
00060   /* Initialize COM */
00061   if (FAILED(proc.CoInitialize(NULL))) {
00062     return "COM initialization failed";
00063   }
00064 
00065   /* create the performance object */
00066   if (FAILED(proc.CoCreateInstance(
00067         CLSID_DirectMusicPerformance,
00068         NULL,
00069         CLSCTX_INPROC,
00070         IID_IDirectMusicPerformance,
00071         (LPVOID*)&performance
00072       ))) {
00073     proc.CoUninitialize();
00074     return "Failed to create the performance object";
00075   }
00076 
00077   /* initialize it */
00078   if (FAILED(performance->Init(NULL, NULL, NULL))) {
00079     performance->Release();
00080     performance = NULL;
00081     proc.CoUninitialize();
00082     return "Failed to initialize performance object";
00083   }
00084 
00085   /* choose default Windows synth */
00086   if (FAILED(performance->AddPort(NULL))) {
00087     performance->CloseDown();
00088     performance->Release();
00089     performance = NULL;
00090     proc.CoUninitialize();
00091     return "AddPort failed";
00092   }
00093 
00094   /* create the loader object; this will be used to load the MIDI file */
00095   if (FAILED(proc.CoCreateInstance(
00096         CLSID_DirectMusicLoader,
00097         NULL,
00098         CLSCTX_INPROC,
00099         IID_IDirectMusicLoader,
00100         (LPVOID*)&loader
00101       ))) {
00102     performance->CloseDown();
00103     performance->Release();
00104     performance = NULL;
00105     proc.CoUninitialize();
00106     return "Failed to create loader object";
00107   }
00108 
00109   return NULL;
00110 }
00111 
00112 
00113 void MusicDriver_DMusic::Stop()
00114 {
00115   seeking = false;
00116 
00117   if (performance != NULL) performance->Stop(NULL, NULL, 0, 0);
00118 
00119   if (segment != NULL) {
00120     segment->SetParam(GUID_Unload, 0xFFFFFFFF, 0, 0, performance);
00121     segment->Release();
00122     segment = NULL;
00123   }
00124 
00125   if (performance != NULL) {
00126     performance->CloseDown();
00127     performance->Release();
00128     performance = NULL;
00129   }
00130 
00131   if (loader != NULL) {
00132     loader->Release();
00133     loader = NULL;
00134   }
00135 
00136   proc.CoUninitialize();
00137 }
00138 
00139 
00140 void MusicDriver_DMusic::PlaySong(const char* filename)
00141 {
00142   /* set up the loader object info */
00143   DMUS_OBJECTDESC obj_desc;
00144   ZeroMemory(&obj_desc, sizeof(obj_desc));
00145   obj_desc.dwSize = sizeof(obj_desc);
00146   obj_desc.guidClass = CLSID_DirectMusicSegment;
00147   obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;
00148   MultiByteToWideChar(
00149     CP_ACP, MB_PRECOMPOSED,
00150     filename, -1,
00151     obj_desc.wszFileName, lengthof(obj_desc.wszFileName)
00152   );
00153 
00154   /* release the existing segment if we have any */
00155   if (segment != NULL) {
00156     segment->Release();
00157     segment = NULL;
00158   }
00159 
00160   /* make a new segment */
00161   if (FAILED(loader->GetObject(
00162         &obj_desc, IID_IDirectMusicSegment, (LPVOID*)&segment
00163       ))) {
00164     DEBUG(driver, 0, "DirectMusic: GetObject failed");
00165     return;
00166   }
00167 
00168   /* tell the segment what kind of data it contains */
00169   if (FAILED(segment->SetParam(
00170         GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, performance
00171       ))) {
00172     DEBUG(driver, 0, "DirectMusic: SetParam (MIDI file) failed");
00173     return;
00174   }
00175 
00176   /* tell the segment to 'download' the instruments */
00177   if (FAILED(segment->SetParam(GUID_Download, 0xFFFFFFFF, 0, 0, performance))) {
00178     DEBUG(driver, 0, "DirectMusic: failed to download instruments");
00179     return;
00180   }
00181 
00182   /* start playing the MIDI file */
00183   if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) {
00184     DEBUG(driver, 0, "DirectMusic: PlaySegment failed");
00185     return;
00186   }
00187 
00188   seeking = true;
00189 }
00190 
00191 
00192 void MusicDriver_DMusic::StopSong()
00193 {
00194   if (FAILED(performance->Stop(segment, NULL, 0, 0))) {
00195     DEBUG(driver, 0, "DirectMusic: StopSegment failed");
00196   }
00197   seeking = false;
00198 }
00199 
00200 
00201 bool MusicDriver_DMusic::IsSongPlaying()
00202 {
00203   /* Not the nicest code, but there is a short delay before playing actually
00204    * starts. OpenTTD makes no provision for this. */
00205   if (performance->IsPlaying(segment, NULL) == S_OK) {
00206     seeking = false;
00207     return true;
00208   } else {
00209     return seeking;
00210   }
00211 }
00212 
00213 
00214 void MusicDriver_DMusic::SetVolume(byte vol)
00215 {
00216   long db = vol * 2000 / 127 - 2000; 
00217   performance->SetGlobalParam(GUID_PerfMasterVolume, &db, sizeof(db));
00218 }
00219 
00220 
00221 #endif /* WIN32_ENABLE_DIRECTMUSIC_SUPPORT */

Generated on Mon Sep 22 20:34:16 2008 for openttd by  doxygen 1.5.6