[Scummvm-cvs-logs] SF.net SVN: scummvm:[51019] scummvm/trunk/backends/midi/alsa.cpp

eriktorbjorn at users.sourceforge.net eriktorbjorn at users.sourceforge.net
Mon Jul 19 09:47:11 CEST 2010


Revision: 51019
          http://scummvm.svn.sourceforge.net/scummvm/?rev=51019&view=rev
Author:   eriktorbjorn
Date:     2010-07-19 07:47:11 +0000 (Mon, 19 Jul 2010)

Log Message:
-----------
ALSA: Get ALSA port settings from the new device config settings.

This is also an attempt to make the transition from the old settings to the
new ones a little less rough, by trying to put something sensible into the
first device, which is what's used by default. Currently it prefers 17:x
and 65:x since they're the old defaults, followed by 128:x since that's
probably TiMidity.

The old SCUMMVM_PORT environment variable still overrides any config
settings. I haven't made up my mind whether or not that's a good idea, but
at least it prints a warning message.

TODO: The old 'alsa_port' setting is not handled. It should probably be
used to set sensible defaults for the new settings, but I'm not sure where
this should be done.

TODO: The documentation will need to be updated, once everything is working
the way it should.

Modified Paths:
--------------
    scummvm/trunk/backends/midi/alsa.cpp

Modified: scummvm/trunk/backends/midi/alsa.cpp
===================================================================
--- scummvm/trunk/backends/midi/alsa.cpp	2010-07-19 07:37:22 UTC (rev 51018)
+++ scummvm/trunk/backends/midi/alsa.cpp	2010-07-19 07:47:11 UTC (rev 51019)
@@ -56,7 +56,7 @@
 
 class MidiDriver_ALSA:public MidiDriver_MPU401 {
 public:
-	MidiDriver_ALSA();
+	MidiDriver_ALSA(int client, int port);
 	int open();
 	void close();
 	void send(uint32 b);
@@ -69,34 +69,19 @@
 	snd_seq_t *seq_handle;
 	int seq_client, seq_port;
 	int my_client, my_port;
-	static int parse_addr(const char *arg, int *client, int *port);
 };
 
-MidiDriver_ALSA::MidiDriver_ALSA()
- : _isOpen(false), seq_handle(0), seq_client(0), seq_port(0), my_client(0), my_port(0)
+MidiDriver_ALSA::MidiDriver_ALSA(int client, int port)
+ : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0)
 {
 	memset(&ev, 0, sizeof(ev));
 }
 
 int MidiDriver_ALSA::open() {
-	const char *var = NULL;
-
 	if (_isOpen)
 		return MERR_ALREADY_OPEN;
 	_isOpen = true;
 
-	var = getenv("SCUMMVM_PORT");
-	if (!var && ConfMan.hasKey("alsa_port")) {
-		var = ConfMan.get("alsa_port").c_str();
-	}
-
-	if (var) {
-		if (parse_addr(var, &seq_client, &seq_port) < 0) {
-			error("Invalid port %s", var);
-			return -1;
-		}
-	}
-
 	if (my_snd_seq_open(&seq_handle) < 0) {
 		error("Can't open sequencer");
 		return -1;
@@ -118,29 +103,11 @@
 		return -1;
 	}
 
-	if (var) {
-		if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) {
-			// subscribe to MIDI port
-			if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) {
-				error("Can't subscribe to MIDI port (%d:%d) see README for help", seq_client, seq_port);
-			}
+	if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) {
+		// subscribe to MIDI port
+		if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) {
+			error("Can't subscribe to MIDI port (%d:%d) see README for help", seq_client, seq_port);
 		}
-	} else {
-		int defaultPorts[] = {
-			65, 0,
-			17, 0
-		};
-		int i;
-
-		for (i = 0; i < ARRAYSIZE(defaultPorts); i += 2) {
-			seq_client = defaultPorts[i];
-			seq_port = defaultPorts[i + 1];
-			if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) >= 0)
-				break;
-		}
-
-		if (i >= ARRAYSIZE(defaultPorts))
-			error("Can't subscribe to MIDI port (65:0) or (17:0)");
 	}
 
 	printf("Connected to Alsa sequencer client [%d:%d]\n", seq_client, seq_port);
@@ -230,24 +197,6 @@
 	send_event(1);
 }
 
-int MidiDriver_ALSA::parse_addr(const char *arg, int *client, int *port) {
-	const char *p;
-
-	if (isdigit(*arg)) {
-		if ((p = strpbrk(arg, ADDR_DELIM)) == NULL)
-			return -1;
-		*client = atoi(arg);
-		*port = atoi(p + 1);
-	} else {
-		if (*arg == 's' || *arg == 'S') {
-			*client = SND_SEQ_ADDRESS_SUBSCRIBERS;
-			*port = 0;
-		} else
-			return -1;
-	}
-	return 0;
-}
-
 void MidiDriver_ALSA::send_event(int do_flush) {
 	snd_seq_ev_set_direct(&ev);
 	snd_seq_ev_set_source(&ev, my_port);
@@ -261,6 +210,43 @@
 
 // Plugin interface
 
+class AlsaDevice {
+public:
+	AlsaDevice(Common::String name, MusicType mt, int client, int port);
+	Common::String getName();
+	MusicType getType();
+	int getClient();
+	int getPort();
+
+private:
+	Common::String _name;
+	MusicType _type;
+	int _client;
+	int _port;
+};
+
+typedef Common::List<AlsaDevice> AlsaDevices;
+
+AlsaDevice::AlsaDevice(Common::String name, MusicType mt, int client, int port)
+	: _name(name), _type(mt), _client(client), _port(port) {
+}
+
+Common::String AlsaDevice::getName() {
+	return _name;
+}
+
+MusicType AlsaDevice::getType() {
+	return _type;
+}
+
+int AlsaDevice::getClient() {
+	return _client;
+}
+
+int AlsaDevice::getPort() {
+	return _port;
+}
+
 class AlsaMusicPlugin : public MusicPluginObject {
 public:
 	const char *getName() const {
@@ -271,8 +257,12 @@
 		return "alsa";
 	}
 
+	AlsaDevices getAlsaDevices() const;
 	MusicDevices getDevices() const;
 	Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+
+private:
+	static int parse_addr(const char *arg, int *client, int *port);
 };
 
 #define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
@@ -286,11 +276,10 @@
 	return 0;
 }
 
-MusicDevices AlsaMusicPlugin::getDevices() const {
-	MusicDevices devices;
-
-	snd_seq_t *seq;
-	if (my_snd_seq_open(&seq) < 0)
+AlsaDevices AlsaMusicPlugin::getAlsaDevices() const {
+	AlsaDevices devices;
+	snd_seq_t *seq_handle;
+	if (my_snd_seq_open(&seq_handle) < 0)
 		return devices; // can't open sequencer
 
 	snd_seq_client_info_t *cinfo;
@@ -298,32 +287,154 @@
 	snd_seq_port_info_t *pinfo;
 	snd_seq_port_info_alloca(&pinfo);
 	snd_seq_client_info_set_client(cinfo, -1);
-	while (snd_seq_query_next_client(seq, cinfo) >= 0) {
+	while (snd_seq_query_next_client(seq_handle, cinfo) >= 0) {
 		bool found_valid_port = false;
 
 		/* reset query info */
 		snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
 		snd_seq_port_info_set_port(pinfo, -1);
-		while (!found_valid_port && snd_seq_query_next_port(seq, pinfo) >= 0) {
+		while (!found_valid_port && snd_seq_query_next_port(seq_handle, pinfo) >= 0) {
 			if (check_permission(pinfo)) {
 				found_valid_port = true;
-				// TODO: Return a different music type depending on the configuration
-				devices.push_back(MusicDevice(this, snd_seq_client_info_get_name(cinfo), MT_GM));
-				//snd_seq_client_info_get_client(cinfo) : snd_seq_port_info_get_port(pinfo)
+
+				const char *name = snd_seq_client_info_get_name(cinfo);
+				// TODO: Can we figure out the appropriate music type?
+				MusicType type = MT_GM;
+				int client = snd_seq_client_info_get_client(cinfo);
+				int port = snd_seq_port_info_get_port(pinfo);
+
+				devices.push_back(AlsaDevice(name, type, client, port));
 			}
 		}
 	}
-	snd_seq_close(seq);
+	snd_seq_close(seq_handle);
 
 	return devices;
 }
 
-Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
-	*mididriver = new MidiDriver_ALSA();
+MusicDevices AlsaMusicPlugin::getDevices() const {
+	MusicDevices devices;
+	Common::Array<bool> used;
+	AlsaDevices::iterator d;
+	int i;
 
+	AlsaDevices alsaDevices = getAlsaDevices();
+
+	for (i = 0, d = alsaDevices.begin(); d != alsaDevices.end(); ++i, ++d) {
+		used.push_back(false);
+	}
+
+	// Since the default behaviour is to use the first device in the list,
+	// try to put something sensible there. We used to have 17:0 and 65:0
+	// as defaults.
+
+	for (i = 0, d = alsaDevices.begin(); d != alsaDevices.end(); ++i, ++d) {
+		int client = d->getClient();
+		if (client == 17 || client == 65) {
+			devices.push_back(MusicDevice(this, d->getName(), d->getType()));
+			used[i] = true;
+		}
+	}
+
+	// 128:0 is probably TiMidity, or something like that, so that's
+	// probably a good second choice.
+
+	for (i = 0, d = alsaDevices.begin(); d != alsaDevices.end(); ++i, ++d) {
+		if (d->getClient() == 128) {
+			devices.push_back(MusicDevice(this, d->getName(), d->getType()));
+			used[i] = true;
+		}
+	}
+
+	// Add the remaining devices in the order they were found.
+
+	for (i = 0, d = alsaDevices.begin(); d != alsaDevices.end(); ++i, ++d) {
+
+		if (!used[i]) {
+			devices.push_back(MusicDevice(this, d->getName(), d->getType()));
+		}
+	}
+
+	return devices;
+}
+
+Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle dev) const {
+	bool found = false;
+	int seq_client, seq_port;
+
+	const char *var = NULL;
+
+	// TODO: Upgrade from old alsa_port setting. This probably isn't the
+	// right place to do that, though.
+
+	if (ConfMan.hasKey("alsa_port")) {
+		warning("AlsaMusicPlugin: Found old 'alsa_port' setting, which will be ignored");
+	}
+
+	// The SCUMMVM_PORT environment variable can still be used to override
+	// any config setting.
+
+	var = getenv("SCUMMVM_PORT");
+	if (var) {
+		warning("AlsaMusicPlugin: SCUMMVM_PORT environment variable overrides config settings");
+		if (parse_addr(var, &seq_client, &seq_port) >= 0) {
+			found = true;
+		} else {
+			warning("AlsaMusicPlugin: Invalid port %s, using config settings instead", var);
+		}
+	}
+
+	// Try to match the setting to an available ALSA device.
+
+	if (!found && dev) {
+		AlsaDevices alsaDevices = getAlsaDevices();
+
+		for (AlsaDevices::iterator d = alsaDevices.begin(); d != alsaDevices.end(); ++d) {
+			MusicDevice device(this, d->getName(), d->getType());
+
+			if (device.getCompleteId().equals(MidiDriver::getDeviceString(dev, MidiDriver::kDeviceId))) {
+				found = true;
+				seq_client = d->getClient();
+				seq_port = d->getPort();
+				break;
+			}
+		}
+	}
+
+	// Still nothing? Try a sensible default.
+
+	if (!found) {
+		// TODO: What's a sensible default anyway? And exactly when do
+		// we get to this case?
+
+		warning("AlsaMusicPlugin: Using 17:0 as default ALSA port");
+		seq_client = 17;
+		seq_port = 0;
+	}
+
+	*mididriver = new MidiDriver_ALSA(seq_client, seq_port);
+
 	return Common::kNoError;
 }
 
+int AlsaMusicPlugin::parse_addr(const char *arg, int *client, int *port) {
+	const char *p;
+
+	if (isdigit(*arg)) {
+		if ((p = strpbrk(arg, ADDR_DELIM)) == NULL)
+			return -1;
+		*client = atoi(arg);
+		*port = atoi(p + 1);
+	} else {
+		if (*arg == 's' || *arg == 'S') {
+			*client = SND_SEQ_ADDRESS_SUBSCRIBERS;
+			*port = 0;
+		} else
+			return -1;
+	}
+	return 0;
+}
+
 //#if PLUGIN_ENABLED_DYNAMIC(ALSA)
 	//REGISTER_PLUGIN_DYNAMIC(ALSA, PLUGIN_TYPE_MUSIC, AlsaMusicPlugin);
 //#else


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list