aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorTorbjörn Andersson2010-07-27 17:18:02 +0000
committerTorbjörn Andersson2010-07-27 17:18:02 +0000
commitbbd3f0dbb3f76417237882ae8dfe5acfab73b50b (patch)
tree1a6f40ab0789c479b4a8aaeb17af5e9955f79af1 /backends
parent7424d39a980848e9c6783aae039aae28a4fa2b5a (diff)
downloadscummvm-rg350-bbd3f0dbb3f76417237882ae8dfe5acfab73b50b.tar.gz
scummvm-rg350-bbd3f0dbb3f76417237882ae8dfe5acfab73b50b.tar.bz2
scummvm-rg350-bbd3f0dbb3f76417237882ae8dfe5acfab73b50b.zip
ALSA: Be more intelligent when picking MIDI port
Often, a client has more than one available port. Pick the first one that isn't already in use. For instance, on my computer client 17 is the "Emu10k1 WaveTable", and it has four available ports. If, say, aplaymidi is already playing on port 17:0, ScummVM will use port 17:1 instead. Otherwise the two programs will mess up each others instruments and controller settings. Of course, in reality I doubt that anyone will run two different MIDI playing applications at once. svn-id: r51380
Diffstat (limited to 'backends')
-rw-r--r--backends/midi/alsa.cpp76
1 files changed, 51 insertions, 25 deletions
diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp
index 2b36cdc3cf..4f73d7384b 100644
--- a/backends/midi/alsa.cpp
+++ b/backends/midi/alsa.cpp
@@ -48,6 +48,17 @@
#define my_snd_seq_open(seqp) snd_seq_open(seqp, SND_SEQ_OPEN)
#endif
+#define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
+
+static int check_permission(snd_seq_port_info_t *pinfo)
+{
+ if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) {
+ if (!(snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT))
+ return 1;
+ }
+ return 0;
+}
+
/*
* parse address string
*/
@@ -109,7 +120,41 @@ int MidiDriver_ALSA::open() {
}
if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) {
- // subscribe to MIDI port
+ // Subscribe to MIDI port. Prefer one that doesn't already have
+ // any connections, unless we've forced a port number already.
+ if (seq_port == -1) {
+ snd_seq_client_info_t *cinfo;
+ snd_seq_port_info_t *pinfo;
+
+ snd_seq_client_info_alloca(&cinfo);
+ snd_seq_port_info_alloca(&pinfo);
+
+ snd_seq_get_any_client_info(seq_handle, seq_client, cinfo);
+
+ int first_port = -1;
+ int found_port = -1;
+
+ snd_seq_port_info_set_client(pinfo, seq_client);
+ snd_seq_port_info_set_port(pinfo, -1);
+ while (found_port == -1 && snd_seq_query_next_port(seq_handle, pinfo) >= 0) {
+ if (check_permission(pinfo)) {
+ if (first_port == -1)
+ first_port = snd_seq_port_info_get_port(pinfo);
+ if (found_port == -1 && snd_seq_port_info_get_write_use(pinfo) == 0)
+ found_port = snd_seq_port_info_get_port(pinfo);
+ }
+ }
+
+ if (found_port == -1) {
+ // Should we abort here? For now, use the first
+ // available port.
+ seq_port = first_port;
+ warning("MidiDriver_ALSA: All ports on client %d (%s) are already in use", seq_client, snd_seq_client_info_get_name(cinfo));
+ } else {
+ seq_port = found_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);
}
@@ -217,23 +262,21 @@ void MidiDriver_ALSA::send_event(int do_flush) {
class AlsaDevice {
public:
- AlsaDevice(Common::String name, MusicType mt, int client, int port);
+ AlsaDevice(Common::String name, MusicType mt, int client);
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) {
+AlsaDevice::AlsaDevice(Common::String name, MusicType mt, int client)
+ : _name(name), _type(mt), _client(client) {
}
Common::String AlsaDevice::getName() {
@@ -248,10 +291,6 @@ int AlsaDevice::getClient() {
return _client;
}
-int AlsaDevice::getPort() {
- return _port;
-}
-
class AlsaMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
@@ -270,17 +309,6 @@ 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))
-
-static int check_permission(snd_seq_port_info_t *pinfo)
-{
- if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE)) {
- if (!(snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT))
- return 1;
- }
- return 0;
-}
-
AlsaDevices AlsaMusicPlugin::getAlsaDevices() const {
AlsaDevices devices;
snd_seq_t *seq_handle;
@@ -306,9 +334,7 @@ AlsaDevices AlsaMusicPlugin::getAlsaDevices() const {
// 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));
+ devices.push_back(AlsaDevice(name, type, client));
}
}
}
@@ -395,7 +421,7 @@ Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver, MidiDrive
if (device.getCompleteId().equals(MidiDriver::getDeviceString(dev, MidiDriver::kDeviceId))) {
found = true;
seq_client = d->getClient();
- seq_port = d->getPort();
+ seq_port = -1;
break;
}
}