w32dm2.cpp
changeset 2168 01b4b1c5720a
parent 2166 d57d078cf659
equal deleted inserted replaced
2167:99d31f4eeb37 2168:01b4b1c5720a
    52 #include <dmksctrl.h>
    52 #include <dmksctrl.h>
    53 #include <dmusici.h>
    53 #include <dmusici.h>
    54 #include <dmusicc.h>
    54 #include <dmusicc.h>
    55 #include <dmusicf.h>
    55 #include <dmusicf.h>
    56 
    56 
    57 #define VARIANT int
       
    58 
       
    59 #define MSGBOX(output)	DEBUG(misc, 0) ("DirectMusic driver: %s\n", output); //MessageBox(NULL, output, "dxmci",MB_OK);
    57 #define MSGBOX(output)	DEBUG(misc, 0) ("DirectMusic driver: %s\n", output); //MessageBox(NULL, output, "dxmci",MB_OK);
    60 #define MULTI_TO_WIDE( x,y )  MultiByteToWideChar( CP_ACP,MB_PRECOMPOSED, y,-1,x,_MAX_PATH);
    58 
       
    59 static void MultiToWide(WCHAR* to, const char* from)
       
    60 {
       
    61 	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, from, -1, to, _MAX_PATH);
       
    62 }
    61 
    63 
    62 // the performance object controls manipulation of  the segments
    64 // the performance object controls manipulation of  the segments
    63 IDirectMusicPerformance *performance = NULL;
    65 static IDirectMusicPerformance *performance = NULL;
    64 
    66 
    65 // the segment object is where the MIDI data is stored for playback
    67 // the segment object is where the MIDI data is stored for playback
    66 IDirectMusicSegment *segment = NULL;
    68 static IDirectMusicSegment *segment = NULL;
    67 
    69 
    68 // the loader bject can load many types of DMusic related files
    70 // the loader bject can load many types of DMusic related files
    69 IDirectMusicLoader *loader = NULL;
    71 static IDirectMusicLoader *loader = NULL;
    70 
    72 
    71 // whether we've initialized COM or not (when deciding whether to shut down)
    73 // whether we've initialized COM or not (when deciding whether to shut down)
    72 int COMInitialized = 0;
    74 static int COMInitialized = 0;
    73 
    75 
    74 
    76 
    75 extern "C" bool LoadLibraryList(void **proc, const char *dll);
    77 extern "C" bool LoadLibraryList(void **proc, const char *dll);
    76 
    78 
    77 // Use lazy linking
    79 // Use lazy linking
   107 #ifdef __cplusplus
   109 #ifdef __cplusplus
   108 extern "C" {
   110 extern "C" {
   109 #endif
   111 #endif
   110 
   112 
   111 // Initialize COM and DirectMusic
   113 // Initialize COM and DirectMusic
   112 bool InitDirectMusic (void)
   114 bool InitDirectMusic(void)
   113 {
   115 {
   114 	if (NULL != performance)
   116 	if (NULL != performance)
   115 		return true;
   117 		return true;
   116 
   118 
   117 	// Initialize COM
   119 	// Initialize COM
   125 		COMInitialized = 1;
   127 		COMInitialized = 1;
   126 	}
   128 	}
   127 
   129 
   128 	// Create the performance object via CoCreateInstance
   130 	// Create the performance object via CoCreateInstance
   129 	if (FAILED(_proc.CoCreateInstance(
   131 	if (FAILED(_proc.CoCreateInstance(
   130 			(REFCLSID)CLSID_DirectMusicPerformance,
   132 				CLSID_DirectMusicPerformance,
   131 			NULL,
   133 				NULL,
   132 			CLSCTX_INPROC,
   134 				CLSCTX_INPROC,
   133 			(REFIID)IID_IDirectMusicPerformance,
   135 				IID_IDirectMusicPerformance,
   134 			(LPVOID *)&performance))) {
   136 				(LPVOID*)&performance
   135 		MSGBOX ("Failed to create the performance object");
   137 			))) {
       
   138 		MSGBOX("Failed to create the performance object");
   136 		return false;
   139 		return false;
   137 	}
   140 	}
   138 
   141 
   139 	// Initialize it
   142 	// Initialize it
   140 	if (FAILED(performance->Init(NULL, NULL, NULL))) {
   143 	if (FAILED(performance->Init(NULL, NULL, NULL))) {
   141 		MSGBOX("Failed to initialize performance object");
   144 		MSGBOX("Failed to initialize performance object");
   142 		return false;
   145 		return false;
   143 	}
   146 	}
   144 
   147 
   145 	// Choose default Windows synth
   148 	// Choose default Windows synth
   146 	if (FAILED(performance->AddPort (NULL))) {
   149 	if (FAILED(performance->AddPort(NULL))) {
   147 		MSGBOX("AddPort failed");
   150 		MSGBOX("AddPort failed");
   148 		return false;
   151 		return false;
   149 	}
   152 	}
   150 
   153 
   151 	// now we'll create the loader object. This will be used to load the
   154 	// now we'll create the loader object. This will be used to load the
   152 	// midi file for our demo. Again, we need to use CoCreateInstance
   155 	// midi file for our demo. Again, we need to use CoCreateInstance
   153 	// and pass the appropriate ID parameters
   156 	// and pass the appropriate ID parameters
   154 	if (FAILED(_proc.CoCreateInstance((REFCLSID)CLSID_DirectMusicLoader,
   157 	if (FAILED(_proc.CoCreateInstance(
   155 			NULL, CLSCTX_INPROC,
   158 				CLSID_DirectMusicLoader,
   156 			(REFIID)IID_IDirectMusicLoader,
   159 				NULL,
   157 			(LPVOID *)&loader))) {
   160 				CLSCTX_INPROC,
       
   161 				IID_IDirectMusicLoader,
       
   162 				(LPVOID*)&loader
       
   163 			))) {
   158 		MSGBOX("Failed to create loader object");
   164 		MSGBOX("Failed to create loader object");
   159 		return false;
   165 		return false;
   160 	}
   166 	}
   161 
   167 
   162 	// that's it for initialization. If we made it this far we
   168 	// that's it for initialization. If we made it this far we
   164 	return true;
   170 	return true;
   165 }
   171 }
   166 
   172 
   167 // Releases memory used by all of the initialized
   173 // Releases memory used by all of the initialized
   168 // DirectMusic objects in the program
   174 // DirectMusic objects in the program
   169 void ReleaseSegment (void)
   175 void ReleaseSegment(void)
   170 {
   176 {
   171 	if (NULL != segment) {
   177 	if (NULL != segment) {
   172 		segment->Release ();
   178 		segment->Release();
   173 		segment = NULL;
   179 		segment = NULL;
   174 	}
   180 	}
   175 }
   181 }
   176 void ShutdownDirectMusic (void)
   182 
       
   183 void ShutdownDirectMusic(void)
   177 {
   184 {
   178 	// release everything but the segment, which the performance
   185 	// release everything but the segment, which the performance
   179 	// will release automatically (and it'll crash if it's been
   186 	// will release automatically (and it'll crash if it's been
   180 	// released already)
   187 	// released already)
   181 
   188 
   182 	if (NULL != loader) {
   189 	if (NULL != loader) {
   183 		loader->Release ();
   190 		loader->Release();
   184 		loader = NULL;
   191 		loader = NULL;
   185 	}
   192 	}
   186 
   193 
   187 	if (NULL != performance)
   194 	if (NULL != performance) {
   188 	{
   195 		performance->CloseDown();
   189  		performance->CloseDown ();
   196 		performance->Release();
   190 		performance->Release ();
       
   191 		performance = NULL;
   197 		performance = NULL;
   192 	}
   198 	}
   193 
   199 
   194 	if (COMInitialized) {
   200 	if (COMInitialized) {
   195 		_proc.CoUninitialize();
   201 		_proc.CoUninitialize();
   196 		COMInitialized = 0;
   202 		COMInitialized = 0;
   197 	}
   203 	}
   198 }
   204 }
   199 
   205 
   200 // Load MIDI file for playing
   206 // Load MIDI file for playing
   201 bool LoadMIDI (char *directory, char *filename)
   207 bool LoadMIDI(const char *directory, const char *filename)
   202 {
   208 {
   203 	DMUS_OBJECTDESC obj_desc;
   209 	DMUS_OBJECTDESC obj_desc;
   204 	WCHAR w_directory[_MAX_PATH];	// utf-16 version of the directory name.
   210 	WCHAR w_directory[_MAX_PATH];	// utf-16 version of the directory name.
   205 	WCHAR w_filename[_MAX_PATH];	// utf-16 version of the file name
   211 	WCHAR w_filename[_MAX_PATH];	// utf-16 version of the file name
   206 
   212 
   207 	if (NULL == performance)
   213 	if (NULL == performance)
   208 		return false;
   214 		return false;
   209 
   215 
   210 	MULTI_TO_WIDE(w_directory,directory);
   216 	MultiToWide(w_directory, directory);
   211 
   217 
   212 	if (FAILED(loader->SetSearchDirectory((REFGUID) GUID_DirectMusicAllTypes,
   218 	if (FAILED(loader->SetSearchDirectory(
   213 				w_directory, FALSE))) {
   219 				GUID_DirectMusicAllTypes, w_directory, FALSE
       
   220 			))) {
   214 		MSGBOX("LoadMIDI: SetSearchDirectory failed");
   221 		MSGBOX("LoadMIDI: SetSearchDirectory failed");
   215 		return false;
   222 		return false;
   216 	}
   223 	}
   217 
   224 
   218 	// set up the loader object info
   225 	// set up the loader object info
   219 	ZeroMemory (&obj_desc, sizeof (obj_desc));
   226 	ZeroMemory(&obj_desc, sizeof(obj_desc));
   220 	obj_desc.dwSize = sizeof (obj_desc);
   227 	obj_desc.dwSize = sizeof(obj_desc);
   221 
   228 
   222 	MULTI_TO_WIDE(w_filename,filename);
   229 	MultiToWide(w_filename, filename);
   223 	obj_desc.guidClass = CLSID_DirectMusicSegment;
   230 	obj_desc.guidClass = CLSID_DirectMusicSegment;
   224 
   231 
   225 	wcscpy (obj_desc.wszFileName,w_filename);
   232 	wcscpy(obj_desc.wszFileName, w_filename);
   226 	obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
   233 	obj_desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
   227 
   234 
   228 	// release the existing segment if we have any
   235 	// release the existing segment if we have any
   229 	if (NULL != segment)
   236 	if (NULL != segment)
   230 		ReleaseSegment();
   237 		ReleaseSegment();
   231 
   238 
   232 	// and make a new segment
   239 	// and make a new segment
   233 	if (FAILED(loader->GetObject(&obj_desc,
   240 	if (FAILED(loader->GetObject(
   234 			(REFIID)IID_IDirectMusicSegment,
   241 				&obj_desc, IID_IDirectMusicSegment, (LPVOID*)&segment
   235 			(LPVOID *) &segment))) {
   242 			))) {
   236 		MSGBOX("LoadMIDI: Get object failed");
   243 		MSGBOX("LoadMIDI: Get object failed");
   237 		return FALSE;
   244 		return false;
   238 	}
   245 	}
   239 
   246 
   240 	// next we need to tell the segment what kind of data it contains. We do this
   247 	// next we need to tell the segment what kind of data it contains. We do this
   241 	// with the IDirectMusicSegment::SetParam function.
   248 	// with the IDirectMusicSegment::SetParam function.
   242 	if (FAILED(segment->SetParam((REFGUID)GUID_StandardMIDIFile,
   249 	if (FAILED(segment->SetParam(
   243 			0xFFFFFFFF, 0, 0, (LPVOID)performance))) {
   250 				GUID_StandardMIDIFile, 0xFFFFFFFF, 0, 0, performance
       
   251 			))) {
   244 		MSGBOX("LoadMIDI: SetParam (MIDI file) failed");
   252 		MSGBOX("LoadMIDI: SetParam (MIDI file) failed");
   245 		return false;
   253 		return false;
   246 	}
   254 	}
   247 
   255 
   248 	// finally, we need to tell the segment to 'download' the instruments
   256 	// finally, we need to tell the segment to 'download' the instruments
   249 	if (FAILED(segment->SetParam((REFGUID)GUID_Download,
   257 	if (FAILED(segment->SetParam(GUID_Download, 0xFFFFFFFF, 0, 0, performance))) {
   250 			0xFFFFFFFF, 0, 0, (LPVOID)performance))) {
       
   251 		MSGBOX("LoadMIDI: Failed to download instruments");
   258 		MSGBOX("LoadMIDI: Failed to download instruments");
   252 		return false;
   259 		return false;
   253 	}
   260 	}
   254 
   261 
   255 	// at this point, the MIDI file is loaded and ready to play!
   262 	// at this point, the MIDI file is loaded and ready to play!
   256 	return true;
   263 	return true;
   257 }
   264 }
   258 
   265 
   259 // Start playing the MIDI file
   266 // Start playing the MIDI file
   260 void PlaySegment (void)
   267 void PlaySegment(void)
   261 {
   268 {
   262 	if (NULL == performance)
   269 	if (NULL == performance)
   263 		return;
   270 		return;
   264 
   271 
   265 	if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) {
   272 	if (FAILED(performance->PlaySegment(segment, 0, 0, NULL))) {
   266 		MSGBOX("PlaySegment failed");
   273 		MSGBOX("PlaySegment failed");
   267 	}
   274 	}
   268 }
   275 }
   269 
   276 
   270 // Stop playing
   277 // Stop playing
   271 void StopSegment (void)
   278 void StopSegment(void)
   272 {
   279 {
   273 	if (NULL == performance || NULL == segment)
   280 	if (NULL == performance || NULL == segment)
   274 		return;
   281 		return;
   275 
   282 
   276 	if (FAILED(performance->Stop(segment, NULL, 0, 0))) {
   283 	if (FAILED(performance->Stop(segment, NULL, 0, 0))) {
   277 		MSGBOX("StopSegment failed");
   284 		MSGBOX("StopSegment failed");
   278 	}
   285 	}
   279 }
   286 }
   280 
   287 
   281 // Find out whether playing has started or stopped
   288 // Find out whether playing has started or stopped
   282 bool IsSegmentPlaying (void)
   289 bool IsSegmentPlaying(void)
   283 {
   290 {
   284 	if (NULL == performance || NULL == segment)
   291 	if (NULL == performance || NULL == segment)
   285 		return FALSE;
   292 		return false;
   286 
   293 
   287 	// IsPlaying return S_OK if the segment is currently playing
   294 	// IsPlaying return S_OK if the segment is currently playing
   288 	return performance->IsPlaying(segment, NULL) == S_OK ? TRUE : FALSE;
   295 	return performance->IsPlaying(segment, NULL) == S_OK;
   289 }
   296 }
   290 
   297 
   291 void SetVolume(long vol)
   298 void SetVolume(long vol)
   292 {
   299 {
   293 	long db;
   300 	long db;