[Scummvm-git-logs] scummvm master -> ca88c5206401943fc542707ff35fcb571f6c0669

bluegr noreply at scummvm.org
Mon Nov 4 21:01:02 UTC 2024


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
6a03f4ada3 AUDIO: Add checkDevice support for FluidSynth
4436ed5d08 BACKENDS: Add device enumeration and synth device support to OSS MIDI driver
becf6c529a BACKENDS: Fix excessive calls to getDeviceString on Windows MIDI
ca88c52064 AUDIO: Split MIDI check flags out, fail checkDevice by default for "auto"


Commit: 6a03f4ada32d02b65526fea86f5afa3527ccecfa
    https://github.com/scummvm/scummvm/commit/6a03f4ada32d02b65526fea86f5afa3527ccecfa
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-11-04T23:00:57+02:00

Commit Message:
AUDIO: Add checkDevice support for FluidSynth

Changed paths:
    audio/mididrv.cpp
    audio/mididrv.h
    audio/musicplugin.h
    audio/softsynth/fluidsynth.cpp
    audio/softsynth/mt32.cpp
    engines/dragons/midimusicplayer.cpp


diff --git a/audio/mididrv.cpp b/audio/mididrv.cpp
index 50b95777106..5d2ad58ba22 100644
--- a/audio/mididrv.cpp
+++ b/audio/mididrv.cpp
@@ -216,6 +216,9 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 		break;
 	}
 
+	int checkFlags = (flags & (MDT_SUPPLIED_SOUND_FONT));
+	flags ^= checkFlags;
+
 	Common::String failedDevStr;
 	if (getMusicType(hdl) == MT_INVALID) {
 		// If the expressly selected driver or device cannot be found (no longer compiled in, turned off, etc.)
@@ -230,7 +233,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 
 	MusicType tp = getMusicType(reslt);
 	if (tp != MT_INVALID && tp != MT_AUTO) {
-		if (checkDevice(reslt)) {
+		if (checkDevice(reslt, checkFlags, false)) {
 			return reslt;
 		} else {
 			// If the expressly selected device cannot be used we display a warning and continue.
@@ -249,6 +252,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 	// If only MDT_MIDI but not MDT_PREFER_MT32 or MDT_PREFER_GM is set we prefer the other devices (which will always be
 	// detected since they are hard coded and cannot be disabled).
 	bool skipMidi = !(flags & (MDT_PREFER_GM | MDT_PREFER_MT32));
+
 	while (flags != MDT_NONE) {
 		if ((flags & MDT_MIDI) && !skipMidi) {
 			// If a preferred MT32 or GM device has been selected that device gets returned if available.
@@ -279,7 +283,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 						dialog.runModal();
 					}
 				} else if (type != MT_AUTO) {
-					if (checkDevice(hdl)) {
+					if (checkDevice(hdl, checkFlags, false)) {
 						if (flags & MDT_PREFER_MT32)
 							// If we have a preferred MT32 device we disable the gm/mt32 mapping (more about this in mididrv.h).
 							_forceTypeMT32 = true;
@@ -307,7 +311,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 						for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
 							if (d->getMusicType() == MT_MT32) {
 								hdl = d->getHandle();
-								if (checkDevice(hdl))
+								if (checkDevice(hdl, checkFlags, true))
 									return hdl;
 							}
 						}
@@ -322,7 +326,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 						for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
 							if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS) {
 								hdl = d->getHandle();
-								if (checkDevice(hdl))
+								if (checkDevice(hdl, checkFlags, true))
 									return hdl;
 							}
 						}
@@ -381,7 +385,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 			for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
 				if (d->getMusicType() == tp) {
 					hdl = d->getHandle();
-					if (checkDevice(hdl))
+					if (checkDevice(hdl, checkFlags, true))
 						return hdl;
 				}
 			}
@@ -403,12 +407,12 @@ MidiDriver *MidiDriver::createMidi(MidiDriver::DeviceHandle handle) {
 	return driver;
 }
 
-bool MidiDriver::checkDevice(MidiDriver::DeviceHandle handle) {
+bool MidiDriver::checkDevice(MidiDriver::DeviceHandle handle, int flags, bool quiet) {
 	const PluginList p = MusicMan.getPlugins();
 	for (PluginList::const_iterator m = p.begin(); m != p.end(); m++) {
 		const MusicPluginObject &musicPlugin = (*m)->get<MusicPluginObject>();
 		if (getDeviceString(handle, MidiDriver::kDriverId).equals(musicPlugin.getId()))
-			return musicPlugin.checkDevice(handle);
+			return musicPlugin.checkDevice(handle, flags, quiet);
 	}
 
 	return false;
diff --git a/audio/mididrv.h b/audio/mididrv.h
index 4f5f12a9f27..290031c9c29 100644
--- a/audio/mididrv.h
+++ b/audio/mididrv.h
@@ -79,22 +79,24 @@ enum MusicType {
  * @todo Rename MidiDriverFlags to MusicDriverFlags
  */
 enum MidiDriverFlags {
-	MDT_NONE        = 0,
-	MDT_PCSPK       = 1 << 0,		// PC Speaker: Maps to MT_PCSPK and MT_PCJR
-	MDT_CMS         = 1 << 1,		// Creative Music System / Gameblaster: Maps to MT_CMS
-	MDT_PCJR        = 1 << 2,		// Tandy/PC Junior driver
-	MDT_ADLIB       = 1 << 3,		// AdLib: Maps to MT_ADLIB
-	MDT_C64         = 1 << 4,
-	MDT_AMIGA       = 1 << 5,
-	MDT_APPLEIIGS   = 1 << 6,
-	MDT_TOWNS       = 1 << 7,		// FM-TOWNS: Maps to MT_TOWNS
-	MDT_PC98        = 1 << 8,		// PC-98: Maps to MT_PC98
-	MDT_SEGACD		= 1 << 9,
-	MDT_MIDI        = 1 << 10,		// Real MIDI
-	MDT_PREFER_MT32 = 1 << 11,		// MT-32 output is preferred
-	MDT_PREFER_GM   = 1 << 12,		// GM output is preferred
-	MDT_PREFER_FLUID= 1 << 13,		// FluidSynth driver is preferred
-	MDT_MACINTOSH	= 1 << 14
+	MDT_NONE				= 0,
+	MDT_PCSPK				= 1 << 0,		// PC Speaker: Maps to MT_PCSPK and MT_PCJR
+	MDT_CMS					= 1 << 1,		// Creative Music System / Gameblaster: Maps to MT_CMS
+	MDT_PCJR				= 1 << 2,		// Tandy/PC Junior driver
+	MDT_ADLIB				= 1 << 3,		// AdLib: Maps to MT_ADLIB
+	MDT_C64					= 1 << 4,
+	MDT_AMIGA				= 1 << 5,
+	MDT_APPLEIIGS			= 1 << 6,
+	MDT_TOWNS				= 1 << 7,		// FM-TOWNS: Maps to MT_TOWNS
+	MDT_PC98				= 1 << 8,		// PC-98: Maps to MT_PC98
+	MDT_SEGACD				= 1 << 9,
+	MDT_MIDI				= 1 << 10,		// Real MIDI
+	MDT_PREFER_MT32			= 1 << 11,		// MT-32 output is preferred
+	MDT_PREFER_GM			= 1 << 12,		// GM output is preferred
+	MDT_PREFER_FLUID		= 1 << 13,		// FluidSynth driver is preferred
+	MDT_MACINTOSH			= 1 << 14,
+
+	MDT_SUPPLIED_SOUND_FONT = 1 << 15,		// Engine will supply sound font (allows checkDevice to pass if it would fail due to missing sound font)
 };
 
 /**
@@ -326,8 +328,16 @@ public:
 	/** Find the music driver matching the given driver name/description. */
 	static DeviceHandle getDeviceHandle(const Common::String &identifier);
 
-	/** Check whether the device with the given handle is available. */
-	static bool checkDevice(DeviceHandle handle);
+	/** Check whether the device with the given handle is available.
+	 *
+	 * @param handle A device handle to check.
+	 * @param flags A mask of flags from MidiDriverFlags to check with.
+	 * @param quiet If true, then failure produces no warnings.
+	 *              If false, then failure throws a warning.
+	 *
+	 * @return True if the device is expected to be available, false if not.
+	 */
+	static bool checkDevice(DeviceHandle handle, int flags, bool quiet);
 
 	/** Get the music type matching the given device handle, or MT_AUTO if there is no match. */
 	static MusicType getMusicType(DeviceHandle handle);
diff --git a/audio/musicplugin.h b/audio/musicplugin.h
index 8e2ac29d24e..80e2f9fe159 100644
--- a/audio/musicplugin.h
+++ b/audio/musicplugin.h
@@ -102,7 +102,7 @@ public:
 	 * implemented for the MT-32 emulator to check whether the required rom
 	 * files are present.
 	 */
-	virtual bool checkDevice(MidiDriver::DeviceHandle) const { return true; }
+	virtual bool checkDevice(MidiDriver::DeviceHandle hdl, int flags, bool quiet) const { return true; }
 
 	/**
 	 * Tries to instantiate a MIDI Driver instance based on the device
diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp
index 276ec7acb05..a1d93e0eac6 100644
--- a/audio/softsynth/fluidsynth.cpp
+++ b/audio/softsynth/fluidsynth.cpp
@@ -110,11 +110,11 @@ protected:
 
 	void generateSamples(int16 *buf, int len) override;
 
-	Common::Path getSoundFontPath() const;
-
 public:
 	MidiDriver_FluidSynth(Audio::Mixer *mixer);
 
+	static Common::Path getSoundFontPath();
+
 	int open() override;
 	void close() override;
 	void send(uint32 b) override;
@@ -280,7 +280,7 @@ static long SoundFontMemLoader_tell(void *handle) {
 
 #endif // USE_FLUIDLITE
 
-Common::Path MidiDriver_FluidSynth::getSoundFontPath() const {
+Common::Path MidiDriver_FluidSynth::getSoundFontPath() {
 	Common::Path path = ConfMan.getPath("soundfont");
 	if (path.empty())
 		return path;
@@ -592,6 +592,7 @@ public:
 	}
 
 	MusicDevices getDevices() const override;
+	bool checkDevice(MidiDriver::DeviceHandle, int flags, bool quiet) const override;
 	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const override;
 };
 
@@ -601,6 +602,19 @@ MusicDevices FluidSynthMusicPlugin::getDevices() const {
 	return devices;
 }
 
+bool FluidSynthMusicPlugin::checkDevice(MidiDriver::DeviceHandle, int flags, bool quiet) const {
+#ifdef FS_HAS_STREAM_SUPPORT
+	if (flags & MDT_SUPPLIED_SOUND_FONT)
+		return true;
+#endif
+
+	Common::Path sfPath = MidiDriver_FluidSynth::getSoundFontPath();
+	if (sfPath.empty())
+		return false;
+
+	return Common::FSNode(sfPath).exists();
+}
+
 Common::Error FluidSynthMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
 	*mididriver = new MidiDriver_FluidSynth(g_system->getMixer());
 
diff --git a/audio/softsynth/mt32.cpp b/audio/softsynth/mt32.cpp
index 093d9be5188..f6c4ef81e1b 100644
--- a/audio/softsynth/mt32.cpp
+++ b/audio/softsynth/mt32.cpp
@@ -446,7 +446,7 @@ public:
 	}
 
 	MusicDevices getDevices() const override;
-	bool checkDevice(MidiDriver::DeviceHandle) const override;
+	bool checkDevice(MidiDriver::DeviceHandle, int flags, bool quiet) const override;
 	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const override;
 };
 
@@ -456,10 +456,11 @@ MusicDevices MT32EmuMusicPlugin::getDevices() const {
 	return devices;
 }
 
-bool MT32EmuMusicPlugin::checkDevice(MidiDriver::DeviceHandle) const {
+bool MT32EmuMusicPlugin::checkDevice(MidiDriver::DeviceHandle, int flags, bool quiet) const {
 	if (!((Common::File::exists("MT32_CONTROL.ROM") && Common::File::exists("MT32_PCM.ROM")) ||
 		(Common::File::exists("CM32L_CONTROL.ROM") && Common::File::exists("CM32L_PCM.ROM")))) {
-			warning("The MT-32 emulator requires one of the two following file sets (not bundled with ScummVM):\n Either 'MT32_CONTROL.ROM' and 'MT32_PCM.ROM' or 'CM32L_CONTROL.ROM' and 'CM32L_PCM.ROM'");
+			if (!quiet)
+				warning("The MT-32 emulator requires one of the two following file sets (not bundled with ScummVM):\n Either 'MT32_CONTROL.ROM' and 'MT32_PCM.ROM' or 'CM32L_CONTROL.ROM' and 'CM32L_PCM.ROM'");
 			return false;
 	}
 
diff --git a/engines/dragons/midimusicplayer.cpp b/engines/dragons/midimusicplayer.cpp
index 6f4d4990845..2edeaf9e1ed 100644
--- a/engines/dragons/midimusicplayer.cpp
+++ b/engines/dragons/midimusicplayer.cpp
@@ -32,7 +32,7 @@ namespace Dragons {
 
 MidiMusicPlayer::MidiMusicPlayer(BigfileArchive *bigFileArchive): _midiDataSize(0) {
 	_midiData = nullptr;
-	MidiPlayer::createDriver(MDT_PREFER_FLUID | MDT_MIDI);
+	MidiPlayer::createDriver(MDT_PREFER_FLUID | MDT_SUPPLIED_SOUND_FONT | MDT_MIDI);
 
 	if (_driver->acceptsSoundFontData()) {
 		_driver->setEngineSoundFont(loadSoundFont(bigFileArchive));


Commit: 4436ed5d08b48023e22cd9a1a3864412517e3daa
    https://github.com/scummvm/scummvm/commit/4436ed5d08b48023e22cd9a1a3864412517e3daa
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-11-04T23:00:57+02:00

Commit Message:
BACKENDS: Add device enumeration and synth device support to OSS MIDI driver

Changed paths:
    backends/midi/seq.cpp


diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp
index 7a6fc96b652..9181d8bbdc7 100644
--- a/backends/midi/seq.cpp
+++ b/backends/midi/seq.cpp
@@ -41,6 +41,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
 
 ////////////////////////////////////////
 //
@@ -52,58 +54,53 @@
 
 class MidiDriver_SEQ : public MidiDriver_MPU401 {
 public:
-	MidiDriver_SEQ();
+	MidiDriver_SEQ(int port, bool isSynth);
 	int open() override;
 	bool isOpen() const override { return _isOpen; }
 	void close() override;
 	void send(uint32 b) override;
 	void sysEx(const byte *msg, uint16 length) override;
 
+	static const char *getDeviceName();
+
 private:
+	bool _isSynth;
 	bool _isOpen;
-	int device, _device_num;
+	int _device;
+	int _port;
 };
 
-MidiDriver_SEQ::MidiDriver_SEQ() {
+MidiDriver_SEQ::MidiDriver_SEQ(int port, bool isSynth) {
 	_isOpen = false;
-	device = 0;
-	_device_num = 0;
+	_isSynth = isSynth;
+	_device = -1;
+	_port = port;
 }
 
 int MidiDriver_SEQ::open() {
-	char *device_name;
-	char dev_seq[] = "/dev/sequencer";
-
 	if (_isOpen)
 		return MERR_ALREADY_OPEN;
-	_isOpen = true;
-	device = 0;
 
-	device_name = getenv("SCUMMVM_MIDI");
-
-	if (device_name == NULL) {
-		warning("SCUMMVM_MIDI environment variable not set, using /dev/sequencer");
-		device_name = dev_seq;
-	}
+	const char *deviceName = getDeviceName();
 
-	device = ::open((device_name), O_RDWR, 0);
+	_isOpen = true;
+	_device = ::open(deviceName, O_RDWR, 0);
 
-	if (device < 0) {
-		warning("Cannot open rawmidi device %s - using /dev/null (no music will be heard)",
-					device_name);
-		device = (::open(("/dev/null"), O_RDWR, 0));
-		if (device < 0)
+	if (_device < 0) {
+		warning("Cannot open rawmidi device %s - using /dev/null (no music will be heard)", deviceName);
+		_device = (::open(("/dev/null"), O_RDWR, 0));
+		if (_device < 0)
 			error("Cannot open /dev/null to dump midi output");
 	}
 
-	if (getenv("SCUMMVM_MIDIPORT"))
-		_device_num = atoi(getenv("SCUMMVM_MIDIPORT"));
 	return 0;
 }
 
 void MidiDriver_SEQ::close() {
 	MidiDriver_MPU401::close();
-	::close(device);
+
+	if (_isOpen)
+		::close(_device);
 	_isOpen = false;
 }
 
@@ -113,41 +110,98 @@ void MidiDriver_SEQ::send(uint32 b) {
 	unsigned char buf[256];
 	int position = 0;
 
-	switch (b & 0xF0) {
-	case 0x80:
-	case 0x90:
-	case 0xA0:
-	case 0xB0:
-	case 0xE0:
-		buf[position++] = SEQ_MIDIPUTC;
-		buf[position++] = (unsigned char)b;
-		buf[position++] = _device_num;
-		buf[position++] = 0;
-		buf[position++] = SEQ_MIDIPUTC;
-		buf[position++] = (unsigned char)((b >> 8) & 0x7F);
-		buf[position++] = _device_num;
-		buf[position++] = 0;
-		buf[position++] = SEQ_MIDIPUTC;
-		buf[position++] = (unsigned char)((b >> 16) & 0x7F);
-		buf[position++] = _device_num;
-		buf[position++] = 0;
-		break;
-	case 0xC0:
-	case 0xD0:
-		buf[position++] = SEQ_MIDIPUTC;
-		buf[position++] = (unsigned char)b;
-		buf[position++] = _device_num;
-		buf[position++] = 0;
-		buf[position++] = SEQ_MIDIPUTC;
-		buf[position++] = (unsigned char)((b >> 8) & 0x7F);
-		buf[position++] = _device_num;
-		buf[position++] = 0;
-		break;
-	default:
-		warning("MidiDriver_SEQ::send: unknown: %08x", (int)b);
-		break;
+	if (_isSynth) {
+		switch (b & 0xf0) {
+		case 0x80:
+		case 0x90:
+		case 0xa0:
+			buf[position++] = EV_CHN_VOICE;
+			buf[position++] = _port;
+			buf[position++] = (unsigned char)(b & 0xf0);
+			buf[position++] = (unsigned char)(b & 0x0f);
+			buf[position++] = (unsigned char)((b >> 8) & 0xff);
+			buf[position++] = (unsigned char)((b >> 16) & 0xff);
+			buf[position++] = 0;
+			buf[position++] = 0;
+			break;
+		case 0xc0:	// Program change
+		case 0xd0:	// Channel pressure
+			buf[position++] = EV_CHN_COMMON;
+			buf[position++] = _port;
+			buf[position++] = (unsigned char)(b & 0xf0);
+			buf[position++] = (unsigned char)(b & 0x0f);
+			buf[position++] = (unsigned char)((b >> 8) & 0xff);
+			buf[position++] = 0;
+			buf[position++] = 0;
+			buf[position++] = 0;
+			break;
+		case 0xb0:	// Control change
+			buf[position++] = EV_CHN_COMMON;
+			buf[position++] = _port;
+			buf[position++] = (unsigned char)(b & 0xf0);
+			buf[position++] = (unsigned char)(b & 0x0f);
+			buf[position++] = (unsigned char)((b >> 8) & 0xff);
+			buf[position++] = 0;
+
+			// TODO/FIXME?: Main volume control in the soundcard.h macros is value*16383/100, expression is value*128, and pan is (value+128)/2
+			// Not sure how those translate to the scales we're using here.
+			*reinterpret_cast<uint16 *>(buf + position) = static_cast<uint16>((b >> 16) & 0xffff);
+			position += 2;
+			break;
+		case 0xe0: // Pitch bend
+			buf[position++] = EV_CHN_COMMON;
+			buf[position++] = _port;
+			buf[position++] = (unsigned char)(b & 0xf0);
+			buf[position++] = (unsigned char)(b & 0x0f);
+			buf[position++] = 0;
+			buf[position++] = 0;
+
+			*reinterpret_cast<uint16 *>(buf + position) = static_cast<uint16>((b >> 8) & 0xffff);
+			position += 2;
+			break;
+		default:
+			warning("MidiDriver_SEQ::send: unknown: %08x", (int)b);
+			break;
+
+		}
+	} else {
+		switch (b & 0xF0) {
+		case 0x80:
+		case 0x90:
+		case 0xA0:
+		case 0xB0:
+		case 0xE0:
+			buf[position++] = SEQ_MIDIPUTC;
+			buf[position++] = (unsigned char)b;
+			buf[position++] = _port;
+			buf[position++] = 0;
+			buf[position++] = SEQ_MIDIPUTC;
+			buf[position++] = (unsigned char)((b >> 8) & 0x7F);
+			buf[position++] = _port;
+			buf[position++] = 0;
+			buf[position++] = SEQ_MIDIPUTC;
+			buf[position++] = (unsigned char)((b >> 16) & 0x7F);
+			buf[position++] = _port;
+			buf[position++] = 0;
+			break;
+		case 0xC0:
+		case 0xD0:
+			buf[position++] = SEQ_MIDIPUTC;
+			buf[position++] = (unsigned char)b;
+			buf[position++] = _port;
+			buf[position++] = 0;
+			buf[position++] = SEQ_MIDIPUTC;
+			buf[position++] = (unsigned char)((b >> 8) & 0x7F);
+			buf[position++] = _port;
+			buf[position++] = 0;
+			break;
+		default:
+			warning("MidiDriver_SEQ::send: unknown: %08x", (int)b);
+			break;
+		}
 	}
-	if (write(device, buf, position) == -1)
+
+	if (write(_device, buf, position) == -1)
 		warning("MidiDriver_SEQ::send: write failed (%s)", strerror(errno));
 }
 
@@ -160,26 +214,60 @@ void MidiDriver_SEQ::sysEx(const byte *msg, uint16 length) {
 
 	midiDriverCommonSysEx(msg, length);
 
-	buf[position++] = SEQ_MIDIPUTC;
-	buf[position++] = 0xF0;
-	buf[position++] = _device_num;
-	buf[position++] = 0;
-	for (; length; --length, ++chr) {
+	if (_isSynth) {
+		int chunksRequired = (length + 7) / 6;
+
+		assert(chunksRequired * 8 <= static_cast<int>(sizeof(buf)));
+
+		for (int i = 0; i < chunksRequired; i++) {
+			int chunkStart = i * 6;
+
+			buf[position++] = EV_SYSEX;
+			buf[position++] = _port;
+
+			for (int j = 0; j < 6; j++) {
+				int pos = chunkStart + j - 1;
+				if (pos < 0)
+					buf[position++] = 0xf0;
+				else if (pos < length)
+					buf[position++] = msg[pos];
+				else if (pos == length)
+					buf[position++] = 0x7f;
+				else
+					buf[position++] = 0xff;
+			}
+		}
+	} else {
 		buf[position++] = SEQ_MIDIPUTC;
-		buf[position++] = (unsigned char) *chr & 0x7F;
-		buf[position++] = _device_num;
+		buf[position++] = 0xF0;
+		buf[position++] = _port;
+		buf[position++] = 0;
+		for (; length; --length, ++chr) {
+			buf[position++] = SEQ_MIDIPUTC;
+			buf[position++] = (unsigned char)*chr & 0x7F;
+			buf[position++] = _port;
+			buf[position++] = 0;
+		}
+		buf[position++] = SEQ_MIDIPUTC;
+		buf[position++] = 0xF7;
+		buf[position++] = _port;
 		buf[position++] = 0;
 	}
-	buf[position++] = SEQ_MIDIPUTC;
-	buf[position++] = 0xF7;
-	buf[position++] = _device_num;
-	buf[position++] = 0;
 
-	if (write(device, buf, position) == -1)
+	if (write(_device, buf, position) == -1)
 		warning("MidiDriver_SEQ::send: write failed (%s)", strerror(errno));
 }
 
 
+const char *MidiDriver_SEQ::getDeviceName() {
+	const char *devName = getenv("SCUMMVM_MIDI");
+
+	if (devName)
+		return devName;
+	else
+		return "/dev/sequencer";
+}
+
 // Plugin interface
 
 class SeqMusicPlugin : public MusicPluginObject {
@@ -194,20 +282,103 @@ public:
 
 	MusicDevices getDevices() const;
 	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+
+private:
+	void addMidiDevices(int deviceFD, MusicDevices &devices, Common::Array<int> *portIDs) const;
+	void addSynthDevices(int deviceFD, MusicDevices &devices, Common::Array<int> *portIDs) const;
 };
 
 MusicDevices SeqMusicPlugin::getDevices() const {
 	MusicDevices devices;
-	// TODO: Return a different music type depending on the configuration
-	// TODO: List the available devices
-	devices.push_back(MusicDevice(this, "", MT_GM));
+
+	int deviceFD = ::open(MidiDriver_SEQ::getDeviceName(), O_RDWR, 0);
+	if (deviceFD >= 0) {
+		addMidiDevices(deviceFD, devices, nullptr);
+		addSynthDevices(deviceFD, devices, nullptr);
+		::close(deviceFD);
+	}
+
 	return devices;
 }
 
-Common::Error SeqMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
-	*mididriver = new MidiDriver_SEQ();
+void SeqMusicPlugin::addMidiDevices(int deviceFD, MusicDevices &devices, Common::Array<int> *portIDs) const {
+	int midiDeviceCount = 0;
+	if (ioctl(deviceFD, SNDCTL_SEQ_NRMIDIS, &midiDeviceCount) == 0) {
+		for (int i = 0; i < midiDeviceCount; i++) {
+			midi_info midiInfo;
+			midiInfo.device = i;
+			if (ioctl(deviceFD, SNDCTL_MIDI_INFO, &midiInfo) == 0) {
+				devices.push_back(MusicDevice(this, midiInfo.name, MT_GM));	// dev_type is unimplemented so we just assume GM
+				if (portIDs)
+					portIDs->push_back(i);
+			}
+		}
+	}
+}
+
+void SeqMusicPlugin::addSynthDevices(int deviceFD, MusicDevices &devices, Common::Array<int> *portIDs) const {
+	int synthDeviceCount = 0;
+	if (ioctl(deviceFD, SNDCTL_SEQ_NRSYNTHS, &synthDeviceCount) == 0) {
+		for (int i = 0; i < synthDeviceCount; i++) {
+			synth_info synthInfo;
+			synthInfo.device = i;
+			if (ioctl(deviceFD, SNDCTL_SYNTH_ID, &synthInfo) == 0) {
+				MusicType musicType = MT_GM;
+
+				if (synthInfo.synth_type == SYNTH_TYPE_FM)
+					musicType = MT_ADLIB;
+
+				devices.push_back(MusicDevice(this, synthInfo.name, musicType)); // dev_type is unimplemented so we just assume GM
+				if (portIDs)
+					portIDs->push_back(i);
+			}
+		}
+	}
+}
+
+Common::Error SeqMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle dev) const {
+	int port = 0;
+	bool isSynth = false;
+	bool found = false;
+
+	if (dev) {
+		Common::String deviceIDString = MidiDriver::getDeviceString(dev, MidiDriver::kDeviceId);
+
+		MusicDevices devices;
+		Common::Array<int> ports;
+		int firstSynthIndex = 0;
+
+		int deviceFD = ::open(MidiDriver_SEQ::getDeviceName(), O_RDONLY, 0);
+		if (deviceFD >= 0) {
+			addMidiDevices(deviceFD, devices, &ports);
+
+			firstSynthIndex = static_cast<int>(ports.size());
+
+			addSynthDevices(deviceFD, devices, &ports);
+
+			::close(deviceFD);
+		} else {
+			warning("Device enumeration failed when creating device");
+		}
+
+		int devIndex = 0;
+		for (MusicDevices::iterator d = devices.begin(); d != devices.end(); d++) {
+			if (d->getCompleteId().equals(deviceIDString)) {
+				found = true;
+				isSynth = (devIndex >= firstSynthIndex);
+				port = ports[devIndex];
+				break;
+			}
+			devIndex++;
+		}
+	}
+
+	if (found) {
+		*mididriver = new MidiDriver_SEQ(port, isSynth);
+		return Common::kNoError;
+	}
 
-	return Common::kNoError;
+	return Common::kAudioDeviceInitFailed;
 }
 
 //#if PLUGIN_ENABLED_DYNAMIC(SEQ)


Commit: becf6c529a83e85633254c0b472f227a48fde5c2
    https://github.com/scummvm/scummvm/commit/becf6c529a83e85633254c0b472f227a48fde5c2
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-11-04T23:00:57+02:00

Commit Message:
BACKENDS: Fix excessive calls to getDeviceString on Windows MIDI

Changed paths:
    backends/midi/windows.cpp


diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp
index 6c3a3f93e63..43e01c80b1e 100644
--- a/backends/midi/windows.cpp
+++ b/backends/midi/windows.cpp
@@ -236,9 +236,11 @@ Common::Error WindowsMusicPlugin::createInstance(MidiDriver **mididriver, MidiDr
 	bool found = false;
 
 	if (dev) {
+		Common::String deviceIDString = MidiDriver::getDeviceString(dev, MidiDriver::kDeviceId);
+
 		MusicDevices i = getDevices();
 		for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) {
-			if (d->getCompleteId().equals(MidiDriver::getDeviceString(dev, MidiDriver::kDeviceId))) {
+			if (d->getCompleteId().equals(deviceIDString)) {
 				found = true;
 				break;
 			}


Commit: ca88c5206401943fc542707ff35fcb571f6c0669
    https://github.com/scummvm/scummvm/commit/ca88c5206401943fc542707ff35fcb571f6c0669
Author: elasota (1137273+elasota at users.noreply.github.com)
Date: 2024-11-04T23:00:57+02:00

Commit Message:
AUDIO: Split MIDI check flags out, fail checkDevice by default for "auto"

Changed paths:
    audio/mididrv.cpp
    audio/mididrv.h
    audio/musicplugin.h
    audio/softsynth/fluidsynth.cpp
    backends/midi/seq.cpp
    backends/midi/windows.cpp


diff --git a/audio/mididrv.cpp b/audio/mididrv.cpp
index 5d2ad58ba22..e4efdc0220e 100644
--- a/audio/mididrv.cpp
+++ b/audio/mididrv.cpp
@@ -216,8 +216,12 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 		break;
 	}
 
-	int checkFlags = (flags & (MDT_SUPPLIED_SOUND_FONT));
-	flags ^= checkFlags;
+	int checkFlags = MDCK_NONE;
+
+	if (flags & MDT_SUPPLIED_SOUND_FONT) {
+		checkFlags |= MDCK_SUPPLIED_SOUND_FONT;
+		flags ^= MDT_SUPPLIED_SOUND_FONT;
+	}
 
 	Common::String failedDevStr;
 	if (getMusicType(hdl) == MT_INVALID) {
@@ -311,7 +315,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 						for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
 							if (d->getMusicType() == MT_MT32) {
 								hdl = d->getHandle();
-								if (checkDevice(hdl, checkFlags, true))
+								if (checkDevice(hdl, checkFlags | MDCK_AUTO, true))
 									return hdl;
 							}
 						}
@@ -326,7 +330,7 @@ MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) {
 						for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
 							if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS) {
 								hdl = d->getHandle();
-								if (checkDevice(hdl, checkFlags, true))
+								if (checkDevice(hdl, checkFlags | MDCK_AUTO, true))
 									return hdl;
 							}
 						}
diff --git a/audio/mididrv.h b/audio/mididrv.h
index 290031c9c29..57b89da37e2 100644
--- a/audio/mididrv.h
+++ b/audio/mididrv.h
@@ -99,6 +99,13 @@ enum MidiDriverFlags {
 	MDT_SUPPLIED_SOUND_FONT = 1 << 15,		// Engine will supply sound font (allows checkDevice to pass if it would fail due to missing sound font)
 };
 
+enum MidiDriverCheckFlags {
+	MDCK_NONE					= 0,
+
+	MDCK_SUPPLIED_SOUND_FONT	= 1 << 0,	// Sound font will be supplied by the engine
+	MDCK_AUTO					= 1 << 1,	// Driver is being checked for automatic selection (i.e. MIDI device is set to "auto")
+};
+
 /**
  * TODO: Document this, give it a better name.
  */
diff --git a/audio/musicplugin.h b/audio/musicplugin.h
index 80e2f9fe159..bfa3e805ff4 100644
--- a/audio/musicplugin.h
+++ b/audio/musicplugin.h
@@ -100,9 +100,15 @@ public:
 	/**
 	 * Checks whether a device can actually be used. Currently this is only
 	 * implemented for the MT-32 emulator to check whether the required rom
-	 * files are present.
+	 * files are present.  In the default implementation, the device is not
+	 * available as an auto-selected device.
+	 *
+	 * @param hdl         MIDI device handle
+	 * @param checkFlags  Bitwise OR mask of MidiDriverCheckFlags
+	 * @param quiet       If true, suppress and error messages on check failure.
+	 * 
 	 */
-	virtual bool checkDevice(MidiDriver::DeviceHandle hdl, int flags, bool quiet) const { return true; }
+	virtual bool checkDevice(MidiDriver::DeviceHandle hdl, int checkFlags, bool quiet) const { return (checkFlags & MDCK_AUTO) == 0; }
 
 	/**
 	 * Tries to instantiate a MIDI Driver instance based on the device
diff --git a/audio/softsynth/fluidsynth.cpp b/audio/softsynth/fluidsynth.cpp
index a1d93e0eac6..10496983d11 100644
--- a/audio/softsynth/fluidsynth.cpp
+++ b/audio/softsynth/fluidsynth.cpp
@@ -604,7 +604,7 @@ MusicDevices FluidSynthMusicPlugin::getDevices() const {
 
 bool FluidSynthMusicPlugin::checkDevice(MidiDriver::DeviceHandle, int flags, bool quiet) const {
 #ifdef FS_HAS_STREAM_SUPPORT
-	if (flags & MDT_SUPPLIED_SOUND_FONT)
+	if (flags & MDCK_SUPPLIED_SOUND_FONT)
 		return true;
 #endif
 
diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp
index 9181d8bbdc7..8f6d174fb17 100644
--- a/backends/midi/seq.cpp
+++ b/backends/midi/seq.cpp
@@ -282,6 +282,7 @@ public:
 
 	MusicDevices getDevices() const;
 	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+	bool checkDevice(MidiDriver::DeviceHandle hdl, int checkFlags, bool quiet) const;
 
 private:
 	void addMidiDevices(int deviceFD, MusicDevices &devices, Common::Array<int> *portIDs) const;
@@ -381,6 +382,10 @@ Common::Error SeqMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver
 	return Common::kAudioDeviceInitFailed;
 }
 
+bool SeqMusicPlugin::checkDevice(MidiDriver::DeviceHandle hdl, int checkFlags, bool quiet) const {
+	return true;
+}
+
 //#if PLUGIN_ENABLED_DYNAMIC(SEQ)
 	//REGISTER_PLUGIN_DYNAMIC(SEQ, PLUGIN_TYPE_MUSIC, SeqMusicPlugin);
 //#else
diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp
index 43e01c80b1e..efdee259c81 100644
--- a/backends/midi/windows.cpp
+++ b/backends/midi/windows.cpp
@@ -174,6 +174,7 @@ public:
 
 	MusicDevices getDevices() const override;
 	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const override;
+	bool checkDevice(MidiDriver::DeviceHandle hdl, int checkFlags, bool quiet) const override;
 };
 
 MusicDevices WindowsMusicPlugin::getDevices() const {
@@ -252,6 +253,10 @@ Common::Error WindowsMusicPlugin::createInstance(MidiDriver **mididriver, MidiDr
 	return Common::kNoError;
 }
 
+bool WindowsMusicPlugin::checkDevice(MidiDriver::DeviceHandle hdl, int checkFlags, bool quiet) const {
+	return true;
+}
+
 //#if PLUGIN_ENABLED_DYNAMIC(WINDOWS)
 	//REGISTER_PLUGIN_DYNAMIC(WINDOWS, PLUGIN_TYPE_MUSIC, WindowsMusicPlugin);
 //#else




More information about the Scummvm-git-logs mailing list