1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD 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, version 2.
4  * OpenTTD 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.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
8 /** @file dmusic.cpp Playing music via DirectMusic. */
9 
10 #define INITGUID
11 #include "../stdafx.h"
12 #ifdef WIN32_LEAN_AND_MEAN
13 #	undef WIN32_LEAN_AND_MEAN // Don't exclude rarely-used stuff from Windows headers
14 #endif
15 #include "../debug.h"
16 #include "../os/windows/win32.h"
17 #include "../core/mem_func.hpp"
18 #include "../thread.h"
19 #include "../fileio_func.h"
20 #include "../base_media_base.h"
21 #include "dmusic.h"
22 #include "midifile.hpp"
23 #include "midi.h"
24 
25 #include <windows.h>
26 #include <dmksctrl.h>
27 #include <dmusicc.h>
28 #include <mutex>
29 
30 #include "../safeguards.h"
31 
32 #if defined(_MSC_VER)
33 #	pragma comment(lib, "ole32.lib")
34 #endif /* defined(_MSC_VER) */
35 
36 static const int MS_TO_REFTIME = 1000 * 10; ///< DirectMusic time base is 100 ns.
37 static const int MIDITIME_TO_REFTIME = 10;  ///< Time base of the midi file reader is 1 us.
38 
39 
40 #define FOURCC_INFO  mmioFOURCC('I','N','F','O')
41 #define FOURCC_fmt   mmioFOURCC('f','m','t',' ')
42 #define FOURCC_data  mmioFOURCC('d','a','t','a')
43 
44 /** A DLS file. */
45 struct DLSFile {
46 	/** An instrument region maps a note range to wave data. */
47 	struct DLSRegion {
48 		RGNHEADER hdr;
49 		WAVELINK wave;
50 		WSMPL wave_sample;
51 
52 		std::vector<WLOOP> wave_loops;
53 		std::vector<CONNECTION> articulators;
54 	};
55 
56 	/** Instrument definition read from a DLS file. */
57 	struct DLSInstrument {
58 		INSTHEADER hdr;
59 
60 		std::vector<CONNECTION> articulators;
61 		std::vector<DLSRegion> regions;
62 	};
63 
64 	/** Wave data definition from a DLS file. */
65 	struct DLSWave {
66 		long file_offset;
67 
68 		PCMWAVEFORMAT fmt;
69 		std::vector<BYTE> data;
70 
71 		WSMPL wave_sample;
72 		std::vector<WLOOP> wave_loops;
73 
operator ==DLSFile::DLSWave74 		bool operator ==(long offset) const {
75 			return this->file_offset == offset;
76 		}
77 	};
78 
79 	std::vector<DLSInstrument> instruments;
80 	std::vector<POOLCUE> pool_cues;
81 	std::vector<DLSWave> waves;
82 
83 	/** Try loading a DLS file into memory. */
84 	bool LoadFile(const wchar_t *file);
85 
86 private:
87 	/** Load an articulation structure from a DLS file. */
88 	bool ReadDLSArticulation(FILE *f, DWORD list_length, std::vector<CONNECTION> &out);
89 	/** Load a list of regions from a DLS file. */
90 	bool ReadDLSRegionList(FILE *f, DWORD list_length, DLSInstrument &instrument);
91 	/** Load a single region from a DLS file. */
92 	bool ReadDLSRegion(FILE *f, DWORD list_length, std::vector<DLSRegion> &out);
93 	/** Load a list of instruments from a DLS file. */
94 	bool ReadDLSInstrumentList(FILE *f, DWORD list_length);
95 	/** Load a single instrument from a DLS file. */
96 	bool ReadDLSInstrument(FILE *f, DWORD list_length);
97 	/** Load a list of waves from a DLS file. */
98 	bool ReadDLSWaveList(FILE *f, DWORD list_length);
99 	/** Load a single wave from a DLS file. */
100 	bool ReadDLSWave(FILE *f, DWORD list_length, long offset);
101 };
102 
103 /** A RIFF chunk header. */
104 PACK_N(struct ChunkHeader {
105 	FOURCC type;  ///< Chunk type.
106 	DWORD length; ///< Length of the chunk, not including the chunk header itself.
107 }, 2);
108 
109 /** Buffer format for a DLS wave download. */
110 PACK_N(struct WAVE_DOWNLOAD {
111 	DMUS_DOWNLOADINFO   dlInfo;
112 	ULONG               ulOffsetTable[2];
113 	DMUS_WAVE           dmWave;
114 	DMUS_WAVEDATA       dmWaveData;
115 }, 2);
116 
117 struct PlaybackSegment {
118 	uint32 start, end;
119 	size_t start_block;
120 	bool loop;
121 };
122 
123 static struct {
124 	bool shutdown;    ///< flag to indicate playback thread shutdown
125 	bool playing;     ///< flag indicating that playback is active
126 	bool do_start;    ///< flag for starting playback of next_file at next opportunity
127 	bool do_stop;     ///< flag for stopping playback at next opportunity
128 
129 	int preload_time; ///< preload time for music blocks.
130 	byte new_volume;  ///< volume setting to change to
131 
132 	MidiFile next_file;           ///< upcoming file to play
133 	PlaybackSegment next_segment; ///< segment info for upcoming file
134 } _playback;
135 
136 /** Handle to our worker thread. */
137 static std::thread _dmusic_thread;
138 /** Event to signal the thread that it should look at a state change. */
139 static HANDLE _thread_event = nullptr;
140 /** Lock access to playback data that is not thread-safe. */
141 static std::mutex _thread_mutex;
142 
143 /** The direct music object manages buffers and ports. */
144 static IDirectMusic *_music = nullptr;
145 /** The port object lets us send MIDI data to the synthesizer. */
146 static IDirectMusicPort *_port = nullptr;
147 /** The buffer object collects the data to sent. */
148 static IDirectMusicBuffer *_buffer = nullptr;
149 /** List of downloaded DLS instruments. */
150 static std::vector<IDirectMusicDownload *> _dls_downloads;
151 
152 
153 static FMusicDriver_DMusic iFMusicDriver_DMusic;
154 
155 
ReadDLSArticulation(FILE * f,DWORD list_length,std::vector<CONNECTION> & out)156 bool DLSFile::ReadDLSArticulation(FILE *f, DWORD list_length, std::vector<CONNECTION> &out)
157 {
158 	while (list_length > 0) {
159 		ChunkHeader chunk;
160 		if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false;
161 		list_length -= chunk.length + sizeof(chunk);
162 
163 		if (chunk.type == FOURCC_ART1) {
164 			CONNECTIONLIST conns;
165 			if (fread(&conns, sizeof(conns), 1, f) != 1) return false;
166 			fseek(f, conns.cbSize - sizeof(conns), SEEK_CUR);
167 
168 			/* Read all defined articulations. */
169 			for (ULONG i = 0; i < conns.cConnections; i++) {
170 				CONNECTION con;
171 				if (fread(&con, sizeof(con), 1, f) != 1) return false;
172 				out.push_back(con);
173 			}
174 		} else {
175 			fseek(f, chunk.length, SEEK_CUR);
176 		}
177 	}
178 
179 	return true;
180 }
181 
ReadDLSRegion(FILE * f,DWORD list_length,std::vector<DLSRegion> & out)182 bool DLSFile::ReadDLSRegion(FILE *f, DWORD list_length, std::vector<DLSRegion> &out)
183 {
184 	out.push_back(DLSRegion());
185 	DLSRegion &region = out.back();
186 
187 	/* Set default values. */
188 	region.wave_sample.cbSize = 0;
189 
190 	while (list_length > 0) {
191 		ChunkHeader chunk;
192 		if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false;
193 		list_length -= chunk.length + sizeof(chunk);
194 
195 		if (chunk.type == FOURCC_LIST) {
196 			/* Unwrap list header. */
197 			if (fread(&chunk.type, sizeof(chunk.type), 1, f) != 1) return false;
198 			chunk.length -= sizeof(chunk.type);
199 		}
200 
201 		switch (chunk.type) {
202 			case FOURCC_RGNH:
203 				if (fread(&region.hdr, sizeof(region.hdr), 1, f) != 1) return false;
204 				break;
205 
206 			case FOURCC_WSMP:
207 				if (fread(&region.wave_sample, sizeof(region.wave_sample), 1, f) != 1) return false;
208 				fseek(f, region.wave_sample.cbSize - sizeof(region.wave_sample), SEEK_CUR);
209 
210 				/* Read all defined sample loops. */
211 				for (ULONG i = 0; i < region.wave_sample.cSampleLoops; i++) {
212 					WLOOP loop;
213 					if (fread(&loop, sizeof(loop), 1, f) != 1) return false;
214 					region.wave_loops.push_back(loop);
215 				}
216 				break;
217 
218 			case FOURCC_WLNK:
219 				if (fread(&region.wave, sizeof(region.wave), 1, f) != 1) return false;
220 				break;
221 
222 			case FOURCC_LART: // List chunk
223 				if (!this->ReadDLSArticulation(f, chunk.length, region.articulators)) return false;
224 				break;
225 
226 			case FOURCC_INFO:
227 				/* We don't care about info stuff. */
228 				fseek(f, chunk.length, SEEK_CUR);
229 				break;
230 
231 			default:
232 				Debug(driver, 7, "DLS: Ignoring unknown chunk {}{}{}{}", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF));
233 				fseek(f, chunk.length, SEEK_CUR);
234 				break;
235 		}
236 	}
237 
238 	return true;
239 }
240 
ReadDLSRegionList(FILE * f,DWORD list_length,DLSInstrument & instrument)241 bool DLSFile::ReadDLSRegionList(FILE *f, DWORD list_length, DLSInstrument &instrument)
242 {
243 	while (list_length > 0) {
244 		ChunkHeader chunk;
245 		if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false;
246 		list_length -= chunk.length + sizeof(chunk);
247 
248 		if (chunk.type == FOURCC_LIST) {
249 			FOURCC list_type;
250 			if (fread(&list_type, sizeof(list_type), 1, f) != 1) return false;
251 
252 			if (list_type == FOURCC_RGN) {
253 				this->ReadDLSRegion(f, chunk.length - sizeof(list_type), instrument.regions);
254 			} else {
255 				Debug(driver, 7, "DLS: Ignoring unknown list chunk of type {}{}{}{}", (char)(list_type & 0xFF), (char)((list_type >> 8) & 0xFF), (char)((list_type >> 16) & 0xFF), (char)((list_type >> 24) & 0xFF));
256 				fseek(f, chunk.length - sizeof(list_type), SEEK_CUR);
257 			}
258 		} else {
259 			Debug(driver, 7, "DLS: Ignoring chunk {}{}{}{}", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF));
260 			fseek(f, chunk.length, SEEK_CUR);
261 		}
262 	}
263 
264 	return true;
265 }
266 
ReadDLSInstrument(FILE * f,DWORD list_length)267 bool DLSFile::ReadDLSInstrument(FILE *f, DWORD list_length)
268 {
269 	this->instruments.push_back(DLSInstrument());
270 	DLSInstrument &instrument = this->instruments.back();
271 
272 	while (list_length > 0) {
273 		ChunkHeader chunk;
274 		if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false;
275 		list_length -= chunk.length + sizeof(chunk);
276 
277 		if (chunk.type == FOURCC_LIST) {
278 			/* Unwrap list header. */
279 			if (fread(&chunk.type, sizeof(chunk.type), 1, f) != 1) return false;
280 			chunk.length -= sizeof(chunk.type);
281 		}
282 
283 		switch (chunk.type) {
284 			case FOURCC_INSH:
285 				if (fread(&instrument.hdr, sizeof(instrument.hdr), 1, f) != 1) return false;
286 				break;
287 
288 			case FOURCC_LART: // List chunk
289 				if (!this->ReadDLSArticulation(f, chunk.length, instrument.articulators)) return false;
290 				break;
291 
292 			case FOURCC_LRGN: // List chunk
293 				if (!this->ReadDLSRegionList(f, chunk.length, instrument)) return false;
294 				break;
295 
296 			case FOURCC_INFO:
297 				/* We don't care about info stuff. */
298 				fseek(f, chunk.length, SEEK_CUR);
299 				break;
300 
301 			default:
302 				Debug(driver, 7, "DLS: Ignoring unknown chunk {}{}{}{}", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF));
303 				fseek(f, chunk.length, SEEK_CUR);
304 				break;
305 		}
306 	}
307 
308 	return true;
309 }
310 
ReadDLSInstrumentList(FILE * f,DWORD list_length)311 bool DLSFile::ReadDLSInstrumentList(FILE *f, DWORD list_length)
312 {
313 	while (list_length > 0) {
314 		ChunkHeader chunk;
315 		if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false;
316 		list_length -= chunk.length + sizeof(chunk);
317 
318 		if (chunk.type == FOURCC_LIST) {
319 			FOURCC list_type;
320 			if (fread(&list_type, sizeof(list_type), 1, f) != 1) return false;
321 
322 			if (list_type == FOURCC_INS) {
323 				Debug(driver, 6, "DLS: Reading instrument {}", (int)instruments.size());
324 
325 				if (!this->ReadDLSInstrument(f, chunk.length - sizeof(list_type))) return false;
326 			} else {
327 				Debug(driver, 7, "DLS: Ignoring unknown list chunk of type {}{}{}{}", (char)(list_type & 0xFF), (char)((list_type >> 8) & 0xFF), (char)((list_type >> 16) & 0xFF), (char)((list_type >> 24) & 0xFF));
328 				fseek(f, chunk.length - sizeof(list_type), SEEK_CUR);
329 			}
330 		} else {
331 			Debug(driver, 7, "DLS: Ignoring chunk {}{}{}{}", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF));
332 			fseek(f, chunk.length, SEEK_CUR);
333 		}
334 	}
335 
336 	return true;
337 }
338 
ReadDLSWave(FILE * f,DWORD list_length,long offset)339 bool DLSFile::ReadDLSWave(FILE *f, DWORD list_length, long offset)
340 {
341 	this->waves.push_back(DLSWave());
342 	DLSWave &wave = this->waves.back();
343 
344 	/* Set default values. */
345 	MemSetT(&wave.wave_sample, 0);
346 	wave.wave_sample.cbSize = sizeof(WSMPL);
347 	wave.wave_sample.usUnityNote = 60;
348 	wave.file_offset = offset; // Store file offset so we can resolve the wave pool table later on.
349 
350 	while (list_length > 0) {
351 		ChunkHeader chunk;
352 		if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false;
353 		list_length -= chunk.length + sizeof(chunk);
354 
355 		if (chunk.type == FOURCC_LIST) {
356 			/* Unwrap list header. */
357 			if (fread(&chunk.type, sizeof(chunk.type), 1, f) != 1) return false;
358 			chunk.length -= sizeof(chunk.type);
359 		}
360 
361 		switch (chunk.type) {
362 			case FOURCC_fmt:
363 				if (fread(&wave.fmt, sizeof(wave.fmt), 1, f) != 1) return false;
364 				if (chunk.length > sizeof(wave.fmt)) fseek(f, chunk.length - sizeof(wave.fmt), SEEK_CUR);
365 				break;
366 
367 			case FOURCC_WSMP:
368 				if (fread(&wave.wave_sample, sizeof(wave.wave_sample), 1, f) != 1) return false;
369 				fseek(f, wave.wave_sample.cbSize - sizeof(wave.wave_sample), SEEK_CUR);
370 
371 				/* Read all defined sample loops. */
372 				for (ULONG i = 0; i < wave.wave_sample.cSampleLoops; i++) {
373 					WLOOP loop;
374 					if (fread(&loop, sizeof(loop), 1, f) != 1) return false;
375 					wave.wave_loops.push_back(loop);
376 				}
377 				break;
378 
379 			case FOURCC_data:
380 				wave.data.resize(chunk.length);
381 				if (fread(&wave.data[0], sizeof(BYTE), wave.data.size(), f) != wave.data.size()) return false;
382 				break;
383 
384 			case FOURCC_INFO:
385 				/* We don't care about info stuff. */
386 				fseek(f, chunk.length, SEEK_CUR);
387 				break;
388 
389 			default:
390 				Debug(driver, 7, "DLS: Ignoring unknown chunk {}{}{}{}", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF));
391 				fseek(f, chunk.length, SEEK_CUR);
392 				break;
393 		}
394 	}
395 
396 	return true;
397 }
398 
ReadDLSWaveList(FILE * f,DWORD list_length)399 bool DLSFile::ReadDLSWaveList(FILE *f, DWORD list_length)
400 {
401 	long base_offset = ftell(f);
402 
403 	while (list_length > 0) {
404 		long chunk_offset = ftell(f);
405 
406 		ChunkHeader chunk;
407 		if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false;
408 		list_length -= chunk.length + sizeof(chunk);
409 
410 		if (chunk.type == FOURCC_LIST) {
411 			FOURCC list_type;
412 			if (fread(&list_type, sizeof(list_type), 1, f) != 1) return false;
413 
414 			if (list_type == FOURCC_wave) {
415 				Debug(driver, 6, "DLS: Reading wave {}", waves.size());
416 
417 				if (!this->ReadDLSWave(f, chunk.length - sizeof(list_type), chunk_offset - base_offset)) return false;
418 			} else {
419 				Debug(driver, 7, "DLS: Ignoring unknown list chunk of type {}{}{}{}", (char)(list_type & 0xFF), (char)((list_type >> 8) & 0xFF), (char)((list_type >> 16) & 0xFF), (char)((list_type >> 24) & 0xFF));
420 				fseek(f, chunk.length - sizeof(list_type), SEEK_CUR);
421 			}
422 		} else {
423 			Debug(driver, 7, "DLS: Ignoring chunk {}{}{}{}", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF));
424 			fseek(f, chunk.length, SEEK_CUR);
425 		}
426 	}
427 
428 	return true;
429 }
430 
LoadFile(const wchar_t * file)431 bool DLSFile::LoadFile(const wchar_t *file)
432 {
433 	Debug(driver, 2, "DMusic: Try to load DLS file {}", FS2OTTD(file));
434 
435 	FILE *f = _wfopen(file, L"rb");
436 	if (f == nullptr) return false;
437 
438 	FileCloser f_scope(f);
439 
440 	/* Check DLS file header. */
441 	ChunkHeader hdr;
442 	FOURCC dls_type;
443 	if (fread(&hdr, sizeof(hdr), 1, f) != 1) return false;
444 	if (fread(&dls_type, sizeof(dls_type), 1, f) != 1) return false;
445 	if (hdr.type != FOURCC_RIFF || dls_type != FOURCC_DLS) return false;
446 
447 	hdr.length -= sizeof(FOURCC);
448 
449 	Debug(driver, 2, "DMusic: Parsing DLS file");
450 
451 	DLSHEADER header;
452 	MemSetT(&header, 0);
453 
454 	/* Iterate over all chunks in the file. */
455 	while (hdr.length > 0) {
456 		ChunkHeader chunk;
457 		if (fread(&chunk, sizeof(chunk), 1, f) != 1) return false;
458 		hdr.length -= chunk.length + sizeof(chunk);
459 
460 		if (chunk.type == FOURCC_LIST) {
461 			/* Unwrap list header. */
462 			if (fread(&chunk.type, sizeof(chunk.type), 1, f) != 1) return false;
463 			chunk.length -= sizeof(chunk.type);
464 		}
465 
466 		switch (chunk.type) {
467 			case FOURCC_COLH:
468 				if (fread(&header, sizeof(header), 1, f) != 1) return false;
469 				break;
470 
471 			case FOURCC_LINS: // List chunk
472 				if (!this->ReadDLSInstrumentList(f, chunk.length)) return false;
473 				break;
474 
475 			case FOURCC_WVPL: // List chunk
476 				if (!this->ReadDLSWaveList(f, chunk.length)) return false;
477 				break;
478 
479 			case FOURCC_PTBL:
480 				POOLTABLE ptbl;
481 				if (fread(&ptbl, sizeof(ptbl), 1, f) != 1) return false;
482 				fseek(f, ptbl.cbSize - sizeof(ptbl), SEEK_CUR);
483 
484 				/* Read all defined cues. */
485 				for (ULONG i = 0; i < ptbl.cCues; i++) {
486 					POOLCUE cue;
487 					if (fread(&cue, sizeof(cue), 1, f) != 1) return false;
488 					this->pool_cues.push_back(cue);
489 				}
490 				break;
491 
492 			case FOURCC_INFO:
493 				/* We don't care about info stuff. */
494 				fseek(f, chunk.length, SEEK_CUR);
495 				break;
496 
497 			default:
498 				Debug(driver, 7, "DLS: Ignoring unknown chunk {}{}{}{}", (char)(chunk.type & 0xFF), (char)((chunk.type >> 8) & 0xFF), (char)((chunk.type >> 16) & 0xFF), (char)((chunk.type >> 24) & 0xFF));
499 				fseek(f, chunk.length, SEEK_CUR);
500 				break;
501 		}
502 	}
503 
504 	/* Have we read as many instruments as indicated? */
505 	if (header.cInstruments != this->instruments.size()) return false;
506 
507 	/* Resolve wave pool table. */
508 	for (std::vector<POOLCUE>::iterator cue = this->pool_cues.begin(); cue != this->pool_cues.end(); cue++) {
509 		std::vector<DLSWave>::iterator w = std::find(this->waves.begin(), this->waves.end(), cue->ulOffset);
510 		if (w != this->waves.end()) {
511 			cue->ulOffset = (ULONG)(w - this->waves.begin());
512 		} else {
513 			cue->ulOffset = 0;
514 		}
515 	}
516 
517 	return true;
518 }
519 
520 
ScaleVolume(byte original,byte scale)521 static byte ScaleVolume(byte original, byte scale)
522 {
523 	return original * scale / 127;
524 }
525 
TransmitChannelMsg(IDirectMusicBuffer * buffer,REFERENCE_TIME rt,byte status,byte p1,byte p2=0)526 static void TransmitChannelMsg(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, byte status, byte p1, byte p2 = 0)
527 {
528 	if (buffer->PackStructured(rt, 0, status | (p1 << 8) | (p2 << 16)) == E_OUTOFMEMORY) {
529 		/* Buffer is full, clear it and try again. */
530 		_port->PlayBuffer(buffer);
531 		buffer->Flush();
532 
533 		buffer->PackStructured(rt, 0, status | (p1 << 8) | (p2 << 16));
534 	}
535 }
536 
TransmitSysex(IDirectMusicBuffer * buffer,REFERENCE_TIME rt,const byte * & msg_start,size_t & remaining)537 static void TransmitSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, const byte *&msg_start, size_t &remaining)
538 {
539 	/* Find end of message. */
540 	const byte *msg_end = msg_start;
541 	while (*msg_end != MIDIST_ENDSYSEX) msg_end++;
542 	msg_end++; // Also include SysEx end byte.
543 
544 	if (buffer->PackUnstructured(rt, 0, msg_end - msg_start, const_cast<LPBYTE>(msg_start)) == E_OUTOFMEMORY) {
545 		/* Buffer is full, clear it and try again. */
546 		_port->PlayBuffer(buffer);
547 		buffer->Flush();
548 
549 		buffer->PackUnstructured(rt, 0, msg_end - msg_start, const_cast<LPBYTE>(msg_start));
550 	}
551 
552 	/* Update position in buffer. */
553 	remaining -= msg_end - msg_start;
554 	msg_start = msg_end;
555 }
556 
TransmitStandardSysex(IDirectMusicBuffer * buffer,REFERENCE_TIME rt,MidiSysexMessage msg)557 static void TransmitStandardSysex(IDirectMusicBuffer *buffer, REFERENCE_TIME rt, MidiSysexMessage msg)
558 {
559 	size_t length = 0;
560 	const byte *data = MidiGetStandardSysexMessage(msg, length);
561 	TransmitSysex(buffer, rt, data, length);
562 }
563 
564 /** Transmit 'Note off' messages to all MIDI channels. */
TransmitNotesOff(IDirectMusicBuffer * buffer,REFERENCE_TIME block_time,REFERENCE_TIME cur_time)565 static void TransmitNotesOff(IDirectMusicBuffer *buffer, REFERENCE_TIME block_time, REFERENCE_TIME cur_time)
566 {
567 	for (int ch = 0; ch < 16; ch++) {
568 		TransmitChannelMsg(_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_MODE_ALLNOTESOFF, 0);
569 		TransmitChannelMsg(_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_SUSTAINSW, 0);
570 		TransmitChannelMsg(_buffer, block_time + 10, MIDIST_CONTROLLER | ch, MIDICT_MODE_RESETALLCTRL, 0);
571 	}
572 
573 	/* Performing a GM reset stops all sound and resets all parameters. */
574 	TransmitStandardSysex(_buffer, block_time + 20, MidiSysexMessage::ResetGM);
575 	TransmitStandardSysex(_buffer, block_time + 30, MidiSysexMessage::RolandSetReverb);
576 
577 	/* Explicitly flush buffer to make sure the messages are processed,
578 	 * as we want sound to stop immediately. */
579 	_port->PlayBuffer(_buffer);
580 	_buffer->Flush();
581 
582 	/* Wait until message time has passed. */
583 	Sleep(Clamp((block_time - cur_time) / MS_TO_REFTIME, 5, 1000));
584 }
585 
MidiThreadProc()586 static void MidiThreadProc()
587 {
588 	Debug(driver, 2, "DMusic: Entering playback thread");
589 
590 	REFERENCE_TIME last_volume_time = 0; // timestamp of the last volume change
591 	REFERENCE_TIME block_time = 0;       // timestamp of the last block sent to the port
592 	REFERENCE_TIME playback_start_time;  // timestamp current file began playback
593 	MidiFile current_file;               // file currently being played from
594 	PlaybackSegment current_segment;     // segment info for current playback
595 	size_t current_block = 0;            // next block index to send
596 	byte current_volume = 0;             // current effective volume setting
597 	byte channel_volumes[16];            // last seen volume controller values in raw data
598 
599 	/* Get pointer to the reference clock of our output port. */
600 	IReferenceClock *clock;
601 	_port->GetLatencyClock(&clock);
602 
603 	REFERENCE_TIME cur_time;
604 	clock->GetTime(&cur_time);
605 
606 	_port->PlayBuffer(_buffer);
607 	_buffer->Flush();
608 
609 	DWORD next_timeout = 1000;
610 	while (true) {
611 		/* Wait for a signal from the GUI thread or until the time for the next event has come. */
612 		DWORD wfso = WaitForSingleObject(_thread_event, next_timeout);
613 
614 		if (_playback.shutdown) {
615 			_playback.playing = false;
616 			break;
617 		}
618 
619 		if (_playback.do_stop) {
620 			Debug(driver, 2, "DMusic thread: Stopping playback");
621 
622 			/* Turn all notes off and wait a bit to allow the messages to be handled. */
623 			clock->GetTime(&cur_time);
624 			TransmitNotesOff(_buffer, block_time, cur_time);
625 
626 			_playback.playing = false;
627 			_playback.do_stop = false;
628 			block_time = 0;
629 			next_timeout = 1000;
630 			continue;
631 		}
632 
633 		if (wfso == WAIT_OBJECT_0) {
634 			if (_playback.do_start) {
635 				Debug(driver, 2, "DMusic thread: Starting playback");
636 				{
637 					/* New scope to limit the time the mutex is locked. */
638 					std::lock_guard<std::mutex> lock(_thread_mutex);
639 
640 					current_file.MoveFrom(_playback.next_file);
641 					std::swap(_playback.next_segment, current_segment);
642 					current_segment.start_block = 0;
643 					current_block = 0;
644 					_playback.playing = true;
645 					_playback.do_start = false;
646 				}
647 
648 				/* Reset playback device between songs. */
649 				clock->GetTime(&cur_time);
650 				TransmitNotesOff(_buffer, block_time, cur_time);
651 
652 				MemSetT<byte>(channel_volumes, 127, lengthof(channel_volumes));
653 
654 				/* Take the current time plus the preload time as the music start time. */
655 				clock->GetTime(&playback_start_time);
656 				playback_start_time += _playback.preload_time * MS_TO_REFTIME;
657 			}
658 		}
659 
660 		if (_playback.playing) {
661 			/* skip beginning of file? */
662 			if (current_segment.start > 0 && current_block == 0 && current_segment.start_block == 0) {
663 				/* find first block after start time and pretend playback started earlier
664 				 * this is to allow all blocks prior to the actual start to still affect playback,
665 				 * as they may contain important controller and program changes */
666 				size_t preload_bytes = 0;
667 				for (size_t bl = 0; bl < current_file.blocks.size(); bl++) {
668 					MidiFile::DataBlock &block = current_file.blocks[bl];
669 					preload_bytes += block.data.size();
670 					if (block.ticktime >= current_segment.start) {
671 						if (current_segment.loop) {
672 							Debug(driver, 2, "DMusic: timer: loop from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, ((int)block.realtime) / 1000.0, preload_bytes);
673 							current_segment.start_block = bl;
674 							break;
675 						} else {
676 							/* Skip the transmission delay compensation performed in the Win32 MIDI driver.
677 							 * The DMusic driver will most likely be used with the MS softsynth, which is not subject to transmission delays.
678 							 */
679 							Debug(driver, 2, "DMusic: timer: start from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, ((int)block.realtime) / 1000.0, preload_bytes);
680 							playback_start_time -= block.realtime * MIDITIME_TO_REFTIME;
681 							break;
682 						}
683 					}
684 				}
685 			}
686 
687 			/* Get current playback timestamp. */
688 			REFERENCE_TIME current_time;
689 			clock->GetTime(&current_time);
690 
691 			/* Check for volume change. */
692 			if (current_volume != _playback.new_volume) {
693 				if (current_time - last_volume_time > 10 * MS_TO_REFTIME) {
694 					Debug(driver, 2, "DMusic thread: volume change");
695 					current_volume = _playback.new_volume;
696 					last_volume_time = current_time;
697 					for (int ch = 0; ch < 16; ch++) {
698 						int vol = ScaleVolume(channel_volumes[ch], current_volume);
699 						TransmitChannelMsg(_buffer, block_time + 1, MIDIST_CONTROLLER | ch, MIDICT_CHANVOLUME, vol);
700 					}
701 					_port->PlayBuffer(_buffer);
702 					_buffer->Flush();
703 				}
704 			}
705 
706 			while (current_block < current_file.blocks.size()) {
707 				MidiFile::DataBlock &block = current_file.blocks[current_block];
708 
709 				/* check that block isn't at end-of-song override */
710 				if (current_segment.end > 0 && block.ticktime >= current_segment.end) {
711 					if (current_segment.loop) {
712 						Debug(driver, 2, "DMusic thread: Looping song");
713 						current_block = current_segment.start_block;
714 						playback_start_time = current_time - current_file.blocks[current_block].realtime * MIDITIME_TO_REFTIME;
715 					} else {
716 						_playback.do_stop = true;
717 					}
718 					next_timeout = 0;
719 					break;
720 				}
721 				/* check that block is not in the future */
722 				REFERENCE_TIME playback_time = current_time - playback_start_time;
723 				if (block.realtime * MIDITIME_TO_REFTIME > playback_time +  3 *_playback.preload_time * MS_TO_REFTIME) {
724 					/* Stop the thread loop until we are at the preload time of the next block. */
725 					next_timeout = Clamp(((int64)block.realtime * MIDITIME_TO_REFTIME - playback_time) / MS_TO_REFTIME - _playback.preload_time, 0, 1000);
726 					Debug(driver, 9, "DMusic thread: Next event in {} ms (music {}, ref {})", next_timeout, block.realtime * MIDITIME_TO_REFTIME, playback_time);
727 					break;
728 				}
729 
730 				/* Timestamp of the current block. */
731 				block_time = playback_start_time + block.realtime * MIDITIME_TO_REFTIME;
732 				Debug(driver, 9, "DMusic thread: Streaming block {} (cur={}, block={})", current_block, (long long)(current_time / MS_TO_REFTIME), (long long)(block_time / MS_TO_REFTIME));
733 
734 				const byte *data = block.data.data();
735 				size_t remaining = block.data.size();
736 				byte last_status = 0;
737 				while (remaining > 0) {
738 					/* MidiFile ought to have converted everything out of running status,
739 					 * but handle it anyway just to be safe */
740 					byte status = data[0];
741 					if (status & 0x80) {
742 						last_status = status;
743 						data++;
744 						remaining--;
745 					} else {
746 						status = last_status;
747 					}
748 					switch (status & 0xF0) {
749 						case MIDIST_PROGCHG:
750 						case MIDIST_CHANPRESS:
751 							/* 2 byte channel messages */
752 							TransmitChannelMsg(_buffer, block_time, status, data[0]);
753 							data++;
754 							remaining--;
755 							break;
756 						case MIDIST_NOTEOFF:
757 						case MIDIST_NOTEON:
758 						case MIDIST_POLYPRESS:
759 						case MIDIST_PITCHBEND:
760 							/* 3 byte channel messages */
761 							TransmitChannelMsg(_buffer, block_time, status, data[0], data[1]);
762 							data += 2;
763 							remaining -= 2;
764 							break;
765 						case MIDIST_CONTROLLER:
766 							/* controller change */
767 							if (data[0] == MIDICT_CHANVOLUME) {
768 								/* volume controller, adjust for user volume */
769 								channel_volumes[status & 0x0F] = data[1];
770 								int vol = ScaleVolume(data[1], current_volume);
771 								TransmitChannelMsg(_buffer, block_time, status, data[0], vol);
772 							} else {
773 								/* handle other controllers normally */
774 								TransmitChannelMsg(_buffer, block_time, status, data[0], data[1]);
775 							}
776 							data += 2;
777 							remaining -= 2;
778 							break;
779 						case 0xF0:
780 							/* system messages */
781 							switch (status) {
782 								case MIDIST_SYSEX: /* system exclusive */
783 									TransmitSysex(_buffer, block_time, data, remaining);
784 									break;
785 								case MIDIST_TC_QFRAME: /* time code quarter frame */
786 								case MIDIST_SONGSEL: /* song select */
787 									data++;
788 									remaining--;
789 									break;
790 								case MIDIST_SONGPOSPTR: /* song position pointer */
791 									data += 2;
792 									remaining -= 2;
793 									break;
794 								default: /* remaining have no data bytes */
795 									break;
796 							}
797 							break;
798 					}
799 				}
800 
801 				current_block++;
802 			}
803 
804 			/* Anything in the playback buffer? Send it down the port. */
805 			DWORD used_buffer = 0;
806 			_buffer->GetUsedBytes(&used_buffer);
807 			if (used_buffer > 0) {
808 				_port->PlayBuffer(_buffer);
809 				_buffer->Flush();
810 			}
811 
812 			/* end? */
813 			if (current_block == current_file.blocks.size()) {
814 				if (current_segment.loop) {
815 					current_block = current_segment.start_block;
816 					playback_start_time = block_time - current_file.blocks[current_block].realtime * MIDITIME_TO_REFTIME;
817 				} else {
818 					_playback.do_stop = true;
819 				}
820 				next_timeout = 0;
821 			}
822 		}
823 	}
824 
825 	Debug(driver, 2, "DMusic: Exiting playback thread");
826 
827 	/* Turn all notes off and wait a bit to allow the messages to be handled by real hardware. */
828 	clock->GetTime(&cur_time);
829 	TransmitNotesOff(_buffer, block_time, cur_time);
830 	Sleep(_playback.preload_time * 4);
831 
832 	clock->Release();
833 }
834 
DownloadArticulationData(int base_offset,void * data,const std::vector<CONNECTION> & artic)835 static void * DownloadArticulationData(int base_offset, void *data, const std::vector<CONNECTION> &artic)
836 {
837 	DMUS_ARTICULATION2 *art = (DMUS_ARTICULATION2 *)data;
838 	art->ulArtIdx = base_offset + 1;
839 	art->ulFirstExtCkIdx = 0;
840 	art->ulNextArtIdx = 0;
841 
842 	CONNECTIONLIST *con_list = (CONNECTIONLIST *)(art + 1);
843 	con_list->cbSize = sizeof(CONNECTIONLIST);
844 	con_list->cConnections = (ULONG)artic.size();
845 	MemCpyT((CONNECTION *)(con_list + 1), &artic.front(), artic.size());
846 
847 	return (CONNECTION *)(con_list + 1) + artic.size();
848 }
849 
LoadDefaultDLSFile(const char * user_dls)850 static const char *LoadDefaultDLSFile(const char *user_dls)
851 {
852 	DMUS_PORTCAPS caps;
853 	MemSetT(&caps, 0);
854 	caps.dwSize = sizeof(DMUS_PORTCAPS);
855 	_port->GetCaps(&caps);
856 
857 	/* Nothing to unless it is a synth with instrument download that doesn't come with GM voices by default. */
858 	if ((caps.dwFlags & (DMUS_PC_DLS | DMUS_PC_DLS2)) != 0 && (caps.dwFlags & DMUS_PC_GMINHARDWARE) == 0) {
859 		DLSFile dls_file;
860 
861 		if (user_dls == nullptr) {
862 			/* Try loading the default GM DLS file stored in the registry. */
863 			HKEY hkDM;
864 			if (SUCCEEDED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\DirectMusic", 0, KEY_READ, &hkDM))) {
865 				wchar_t dls_path[MAX_PATH];
866 				DWORD buf_size = sizeof(dls_path); // Buffer size as to be given in bytes!
867 				if (SUCCEEDED(RegQueryValueEx(hkDM, L"GMFilePath", nullptr, nullptr, (LPBYTE)dls_path, &buf_size))) {
868 					wchar_t expand_path[MAX_PATH * 2];
869 					ExpandEnvironmentStrings(dls_path, expand_path, lengthof(expand_path));
870 					if (!dls_file.LoadFile(expand_path)) Debug(driver, 1, "Failed to load default GM DLS file from registry");
871 				}
872 				RegCloseKey(hkDM);
873 			}
874 
875 			/* If we couldn't load the file from the registry, try again at the default install path of the GM DLS file. */
876 			if (dls_file.instruments.size() == 0) {
877 				static const wchar_t *DLS_GM_FILE = L"%windir%\\System32\\drivers\\gm.dls";
878 				wchar_t path[MAX_PATH];
879 				ExpandEnvironmentStrings(DLS_GM_FILE, path, lengthof(path));
880 
881 				if (!dls_file.LoadFile(path)) return "Can't load GM DLS collection";
882 			}
883 		} else {
884 			if (!dls_file.LoadFile(OTTD2FS(user_dls).c_str())) return "Can't load GM DLS collection";
885 		}
886 
887 		/* Get download port and allocate download IDs. */
888 		IDirectMusicPortDownload *download_port = nullptr;
889 		if (FAILED(_port->QueryInterface(IID_IDirectMusicPortDownload, (LPVOID *)&download_port))) return "Can't get download port";
890 
891 		DWORD dlid_wave = 0, dlid_inst = 0;
892 		if (FAILED(download_port->GetDLId(&dlid_wave, (DWORD)dls_file.waves.size())) || FAILED(download_port->GetDLId(&dlid_inst, (DWORD)dls_file.instruments.size()))) {
893 			download_port->Release();
894 			return "Can't get enough DLS ids";
895 		}
896 
897 		DWORD dwAppend = 0;
898 		download_port->GetAppend(&dwAppend);
899 
900 		/* Download wave data. */
901 		for (DWORD i = 0; i < dls_file.waves.size(); i++) {
902 			IDirectMusicDownload *dl_wave = nullptr;
903 			if (FAILED(download_port->AllocateBuffer((DWORD)(sizeof(WAVE_DOWNLOAD) + dwAppend * dls_file.waves[i].fmt.wf.nBlockAlign + dls_file.waves[i].data.size()), &dl_wave))) {
904 				download_port->Release();
905 				return "Can't allocate wave download buffer";
906 			}
907 
908 			WAVE_DOWNLOAD *wave;
909 			DWORD wave_size = 0;
910 			if (FAILED(dl_wave->GetBuffer((LPVOID *)&wave, &wave_size))) {
911 				dl_wave->Release();
912 				download_port->Release();
913 				return "Can't get wave download buffer";
914 			}
915 
916 			/* Fill download data. */
917 			MemSetT(wave, 0);
918 			wave->dlInfo.dwDLType = DMUS_DOWNLOADINFO_WAVE;
919 			wave->dlInfo.cbSize = wave_size;
920 			wave->dlInfo.dwDLId = dlid_wave + i;
921 			wave->dlInfo.dwNumOffsetTableEntries = 2;
922 			wave->ulOffsetTable[0] = offsetof(WAVE_DOWNLOAD, dmWave);
923 			wave->ulOffsetTable[1] = offsetof(WAVE_DOWNLOAD, dmWaveData);
924 			wave->dmWave.ulWaveDataIdx = 1;
925 			MemCpyT((PCMWAVEFORMAT *)&wave->dmWave.WaveformatEx, &dls_file.waves[i].fmt, 1);
926 			wave->dmWaveData.cbSize = (DWORD)dls_file.waves[i].data.size();
927 			MemCpyT(wave->dmWaveData.byData, &dls_file.waves[i].data[0], dls_file.waves[i].data.size());
928 
929 			_dls_downloads.push_back(dl_wave);
930 			if (FAILED(download_port->Download(dl_wave))) {
931 				download_port->Release();
932 				return "Downloading DLS wave failed";
933 			}
934 		}
935 
936 		/* Download instrument data. */
937 		for (DWORD i = 0; i < dls_file.instruments.size(); i++) {
938 			DWORD offsets = 1 + (DWORD)dls_file.instruments[i].regions.size();
939 
940 			/* Calculate download size for the instrument. */
941 			size_t i_size = sizeof(DMUS_DOWNLOADINFO) + sizeof(DMUS_INSTRUMENT);
942 			if (dls_file.instruments[i].articulators.size() > 0) {
943 				/* Articulations are stored as two chunks, one containing meta data and one with the actual articulation data. */
944 				offsets += 2;
945 				i_size += sizeof(DMUS_ARTICULATION2) + sizeof(CONNECTIONLIST) + sizeof(CONNECTION) * dls_file.instruments[i].articulators.size();
946 			}
947 
948 			for (std::vector<DLSFile::DLSRegion>::iterator rgn = dls_file.instruments[i].regions.begin(); rgn != dls_file.instruments[i].regions.end(); rgn++) {
949 				if (rgn->articulators.size() > 0) {
950 					offsets += 2;
951 					i_size += sizeof(DMUS_ARTICULATION2) + sizeof(CONNECTIONLIST) + sizeof(CONNECTION) * rgn->articulators.size();
952 				}
953 
954 				/* Region size depends on the number of wave loops. The size of the
955 				 * declared structure already accounts for one loop. */
956 				if (rgn->wave_sample.cbSize != 0) {
957 					i_size += sizeof(DMUS_REGION) - sizeof(DMUS_REGION::WLOOP) + sizeof(WLOOP) * rgn->wave_loops.size();
958 				} else {
959 					i_size += sizeof(DMUS_REGION) - sizeof(DMUS_REGION::WLOOP) + sizeof(WLOOP) * dls_file.waves[dls_file.pool_cues[rgn->wave.ulTableIndex].ulOffset].wave_loops.size();
960 				}
961 			}
962 
963 			i_size += offsets * sizeof(ULONG);
964 
965 			/* Allocate download buffer. */
966 			IDirectMusicDownload *dl_inst = nullptr;
967 			if (FAILED(download_port->AllocateBuffer((DWORD)i_size, &dl_inst))) {
968 				download_port->Release();
969 				return "Can't allocate instrument download buffer";
970 			}
971 
972 			void *instrument;
973 			DWORD inst_size = 0;
974 			if (FAILED(dl_inst->GetBuffer((LPVOID *)&instrument, &inst_size))) {
975 				dl_inst->Release();
976 				download_port->Release();
977 				return "Can't get instrument download buffer";
978 			}
979 			char *inst_base = (char *)instrument;
980 
981 			/* Fill download header. */
982 			DMUS_DOWNLOADINFO *d_info = (DMUS_DOWNLOADINFO *)instrument;
983 			d_info->dwDLType = DMUS_DOWNLOADINFO_INSTRUMENT2;
984 			d_info->cbSize = inst_size;
985 			d_info->dwDLId = dlid_inst + i;
986 			d_info->dwNumOffsetTableEntries = offsets;
987 			instrument = d_info + 1;
988 
989 			/* Download offset table; contains the offsets of all chunks relative to the buffer start. */
990 			ULONG *offset_table = (ULONG *)instrument;
991 			instrument = offset_table + offsets;
992 			int last_offset = 0;
993 
994 			/* Instrument header. */
995 			DMUS_INSTRUMENT *inst_data = (DMUS_INSTRUMENT *)instrument;
996 			MemSetT(inst_data, 0);
997 			offset_table[last_offset++] = (char *)inst_data - inst_base;
998 			inst_data->ulPatch = (dls_file.instruments[i].hdr.Locale.ulBank & F_INSTRUMENT_DRUMS) | ((dls_file.instruments[i].hdr.Locale.ulBank & 0x7F7F) << 8) | (dls_file.instruments[i].hdr.Locale.ulInstrument & 0x7F);
999 			instrument = inst_data + 1;
1000 
1001 			/* Write global articulations. */
1002 			if (dls_file.instruments[i].articulators.size() > 0) {
1003 				inst_data->ulGlobalArtIdx = last_offset;
1004 				offset_table[last_offset++] = (char *)instrument - inst_base;
1005 				offset_table[last_offset++] = (char *)instrument + sizeof(DMUS_ARTICULATION2) - inst_base;
1006 
1007 				instrument = DownloadArticulationData(inst_data->ulGlobalArtIdx, instrument, dls_file.instruments[i].articulators);
1008 				assert((char *)instrument - inst_base <= (ptrdiff_t)inst_size);
1009 			}
1010 
1011 			/* Write out regions. */
1012 			inst_data->ulFirstRegionIdx = last_offset;
1013 			for (uint j = 0; j < dls_file.instruments[i].regions.size(); j++) {
1014 				DLSFile::DLSRegion &rgn = dls_file.instruments[i].regions[j];
1015 
1016 				DMUS_REGION *inst_region = (DMUS_REGION *)instrument;
1017 				offset_table[last_offset++] = (char *)inst_region - inst_base;
1018 				inst_region->RangeKey = rgn.hdr.RangeKey;
1019 				inst_region->RangeVelocity = rgn.hdr.RangeVelocity;
1020 				inst_region->fusOptions = rgn.hdr.fusOptions;
1021 				inst_region->usKeyGroup = rgn.hdr.usKeyGroup;
1022 				inst_region->ulFirstExtCkIdx = 0;
1023 
1024 				ULONG wave_id = dls_file.pool_cues[rgn.wave.ulTableIndex].ulOffset;
1025 				inst_region->WaveLink = rgn.wave;
1026 				inst_region->WaveLink.ulTableIndex = wave_id + dlid_wave;
1027 
1028 				/* The wave sample data will be taken from the region, if defined, otherwise from the wave itself. */
1029 				if (rgn.wave_sample.cbSize != 0) {
1030 					inst_region->WSMP = rgn.wave_sample;
1031 					if (rgn.wave_loops.size() > 0) MemCpyT(inst_region->WLOOP, &rgn.wave_loops.front(), rgn.wave_loops.size());
1032 
1033 					instrument = (char *)(inst_region + 1) - sizeof(DMUS_REGION::WLOOP) + sizeof(WLOOP) * rgn.wave_loops.size();
1034 				} else {
1035 					inst_region->WSMP = rgn.wave_sample;
1036 					if (dls_file.waves[wave_id].wave_loops.size() > 0) MemCpyT(inst_region->WLOOP, &dls_file.waves[wave_id].wave_loops.front(), dls_file.waves[wave_id].wave_loops.size());
1037 
1038 					instrument = (char *)(inst_region + 1) - sizeof(DMUS_REGION::WLOOP) + sizeof(WLOOP) * dls_file.waves[wave_id].wave_loops.size();
1039 				}
1040 
1041 				/* Write local articulator data. */
1042 				if (rgn.articulators.size() > 0) {
1043 					inst_region->ulRegionArtIdx = last_offset;
1044 					offset_table[last_offset++] = (char *)instrument - inst_base;
1045 					offset_table[last_offset++] = (char *)instrument + sizeof(DMUS_ARTICULATION2) - inst_base;
1046 
1047 					instrument = DownloadArticulationData(inst_region->ulRegionArtIdx, instrument, rgn.articulators);
1048 				} else {
1049 					inst_region->ulRegionArtIdx = 0;
1050 				}
1051 				assert((char *)instrument - inst_base <= (ptrdiff_t)inst_size);
1052 
1053 				/* Link to the next region unless this was the last one.*/
1054 				inst_region->ulNextRegionIdx = j < dls_file.instruments[i].regions.size() - 1 ? last_offset : 0;
1055 			}
1056 
1057 			_dls_downloads.push_back(dl_inst);
1058 			if (FAILED(download_port->Download(dl_inst))) {
1059 				download_port->Release();
1060 				return "Downloading DLS instrument failed";
1061 			}
1062 		}
1063 
1064 		download_port->Release();
1065 	}
1066 
1067 	return nullptr;
1068 }
1069 
1070 
Start(const StringList & parm)1071 const char *MusicDriver_DMusic::Start(const StringList &parm)
1072 {
1073 	/* Initialize COM */
1074 	if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED))) return "COM initialization failed";
1075 
1076 	/* Create the DirectMusic object */
1077 	if (FAILED(CoCreateInstance(
1078 				CLSID_DirectMusic,
1079 				nullptr,
1080 				CLSCTX_INPROC,
1081 				IID_IDirectMusic,
1082 				(LPVOID*)&_music
1083 			))) {
1084 		return "Failed to create the music object";
1085 	}
1086 
1087 	/* Assign sound output device. */
1088 	if (FAILED(_music->SetDirectSound(nullptr, nullptr))) return "Can't set DirectSound interface";
1089 
1090 	/* MIDI events need to be send to the synth in time before their playback time
1091 	 * has come. By default, we try send any events at least 50 ms before playback. */
1092 	_playback.preload_time = GetDriverParamInt(parm, "preload", 50);
1093 
1094 	int pIdx = GetDriverParamInt(parm, "port", -1);
1095 	if (_debug_driver_level > 0) {
1096 		/* Print all valid output ports. */
1097 		char desc[DMUS_MAX_DESCRIPTION];
1098 
1099 		DMUS_PORTCAPS caps;
1100 		MemSetT(&caps, 0);
1101 		caps.dwSize = sizeof(DMUS_PORTCAPS);
1102 
1103 		Debug(driver, 1, "Detected DirectMusic ports:");
1104 		for (int i = 0; _music->EnumPort(i, &caps) == S_OK; i++) {
1105 			if (caps.dwClass == DMUS_PC_OUTPUTCLASS) {
1106 				Debug(driver, 1, " {}: {}{}", i, convert_from_fs(caps.wszDescription, desc, lengthof(desc)), i == pIdx ? " (selected)" : "");
1107 			}
1108 		}
1109 	}
1110 
1111 	GUID guidPort;
1112 	if (pIdx >= 0) {
1113 		/* Check if the passed port is a valid port. */
1114 		DMUS_PORTCAPS caps;
1115 		MemSetT(&caps, 0);
1116 		caps.dwSize = sizeof(DMUS_PORTCAPS);
1117 		if (FAILED(_music->EnumPort(pIdx, &caps))) return "Supplied port parameter is not a valid port";
1118 		if (caps.dwClass != DMUS_PC_OUTPUTCLASS) return "Supplied port parameter is not an output port";
1119 		guidPort = caps.guidPort;
1120 	} else {
1121 		if (FAILED(_music->GetDefaultPort(&guidPort))) return "Can't query default music port";
1122 	}
1123 
1124 	/* Create new port. */
1125 	DMUS_PORTPARAMS params;
1126 	MemSetT(&params, 0);
1127 	params.dwSize = sizeof(DMUS_PORTPARAMS);
1128 	params.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS;
1129 	params.dwChannelGroups = 1;
1130 	if (FAILED(_music->CreatePort(guidPort, &params, &_port, nullptr))) return "Failed to create port";
1131 	/* Activate port. */
1132 	if (FAILED(_port->Activate(TRUE))) return "Failed to activate port";
1133 
1134 	/* Create playback buffer. */
1135 	DMUS_BUFFERDESC desc;
1136 	MemSetT(&desc, 0);
1137 	desc.dwSize = sizeof(DMUS_BUFFERDESC);
1138 	desc.guidBufferFormat = KSDATAFORMAT_SUBTYPE_DIRECTMUSIC;
1139 	desc.cbBuffer = 1024;
1140 	if (FAILED(_music->CreateMusicBuffer(&desc, &_buffer, nullptr))) return "Failed to create music buffer";
1141 
1142 	/* On soft-synths (e.g. the default DirectMusic one), we might need to load a wavetable set to get music. */
1143 	const char *dls = LoadDefaultDLSFile(GetDriverParam(parm, "dls"));
1144 	if (dls != nullptr) return dls;
1145 
1146 	/* Create playback thread and synchronization primitives. */
1147 	_thread_event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
1148 	if (_thread_event == nullptr) return "Can't create thread shutdown event";
1149 
1150 	if (!StartNewThread(&_dmusic_thread, "ottd:dmusic", &MidiThreadProc)) return "Can't create MIDI output thread";
1151 
1152 	return nullptr;
1153 }
1154 
1155 
~MusicDriver_DMusic()1156 MusicDriver_DMusic::~MusicDriver_DMusic()
1157 {
1158 	this->Stop();
1159 }
1160 
1161 
Stop()1162 void MusicDriver_DMusic::Stop()
1163 {
1164 	if (_dmusic_thread.joinable()) {
1165 		_playback.shutdown = true;
1166 		SetEvent(_thread_event);
1167 		_dmusic_thread.join();
1168 	}
1169 
1170 	/* Unloaded any instruments we loaded. */
1171 	if (_dls_downloads.size() > 0) {
1172 		IDirectMusicPortDownload *download_port = nullptr;
1173 		_port->QueryInterface(IID_IDirectMusicPortDownload, (LPVOID *)&download_port);
1174 
1175 		/* Instruments refer to waves. As the waves are at the beginning of the download list,
1176 		 * do the unload from the back so that references are cleared properly. */
1177 		for (std::vector<IDirectMusicDownload *>::reverse_iterator i = _dls_downloads.rbegin(); download_port != nullptr && i != _dls_downloads.rend(); i++) {
1178 			download_port->Unload(*i);
1179 			(*i)->Release();
1180 		}
1181 		_dls_downloads.clear();
1182 
1183 		if (download_port != nullptr) download_port->Release();
1184 	}
1185 
1186 	if (_buffer != nullptr) {
1187 		_buffer->Release();
1188 		_buffer = nullptr;
1189 	}
1190 
1191 	if (_port != nullptr) {
1192 		_port->Activate(FALSE);
1193 		_port->Release();
1194 		_port = nullptr;
1195 	}
1196 
1197 	if (_music != nullptr) {
1198 		_music->Release();
1199 		_music = nullptr;
1200 	}
1201 
1202 	CloseHandle(_thread_event);
1203 
1204 	CoUninitialize();
1205 }
1206 
1207 
PlaySong(const MusicSongInfo & song)1208 void MusicDriver_DMusic::PlaySong(const MusicSongInfo &song)
1209 {
1210 	std::lock_guard<std::mutex> lock(_thread_mutex);
1211 
1212 	if (!_playback.next_file.LoadSong(song)) return;
1213 
1214 	_playback.next_segment.start = song.override_start;
1215 	_playback.next_segment.end = song.override_end;
1216 	_playback.next_segment.loop = song.loop;
1217 
1218 	_playback.do_start = true;
1219 	SetEvent(_thread_event);
1220 }
1221 
1222 
StopSong()1223 void MusicDriver_DMusic::StopSong()
1224 {
1225 	_playback.do_stop = true;
1226 	SetEvent(_thread_event);
1227 }
1228 
1229 
IsSongPlaying()1230 bool MusicDriver_DMusic::IsSongPlaying()
1231 {
1232 	return _playback.playing || _playback.do_start;
1233 }
1234 
1235 
SetVolume(byte vol)1236 void MusicDriver_DMusic::SetVolume(byte vol)
1237 {
1238 	_playback.new_volume = vol;
1239 }
1240