diff options
| author | Matthew Hoops | 2011-05-03 17:17:27 -0400 |
|---|---|---|
| committer | Matthew Hoops | 2011-05-03 17:25:41 -0400 |
| commit | 9cb600099f4c29298707787cafad2741a1cd6686 (patch) | |
| tree | fb1930fa56b611317831d66442cba19b18d2e57a /backends/midi/alsa.cpp | |
| parent | 3b2283daf850605ca897002afbafe44489c35473 (diff) | |
| parent | 95a6098f672191dc0792bd4f9bfa18706bbe8e3a (diff) | |
| download | scummvm-rg350-9cb600099f4c29298707787cafad2741a1cd6686.tar.gz scummvm-rg350-9cb600099f4c29298707787cafad2741a1cd6686.tar.bz2 scummvm-rg350-9cb600099f4c29298707787cafad2741a1cd6686.zip | |
Merge remote branch 'upstream/master' into pegasus
Diffstat (limited to 'backends/midi/alsa.cpp')
| -rw-r--r-- | backends/midi/alsa.cpp | 55 |
1 files changed, 39 insertions, 16 deletions
diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp index 953b088958..5110734a18 100644 --- a/backends/midi/alsa.cpp +++ b/backends/midi/alsa.cpp @@ -30,6 +30,8 @@ #if defined(USE_ALSA) #include "common/config-manager.h" +#include "common/error.h" +#include "common/textconsole.h" #include "common/util.h" #include "audio/musicplugin.h" #include "audio/mpu401.h" @@ -44,7 +46,7 @@ #if SND_LIB_MAJOR >= 1 || SND_LIB_MINOR >= 6 #define snd_seq_flush_output(x) snd_seq_drain_output(x) -#define snd_seq_set_client_group(x,name) /*nop */ +#define snd_seq_set_client_group(x,name) /*nop */ #define my_snd_seq_open(seqp) snd_seq_open(seqp, "hw", SND_SEQ_OPEN_DUPLEX, 0) #else /* SND_SEQ_OPEN_OUT causes oops on early version of ALSA */ @@ -53,9 +55,8 @@ #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)) { +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; } @@ -68,10 +69,11 @@ static int check_permission(snd_seq_port_info_t *pinfo) #define ADDR_DELIM ".:" -class MidiDriver_ALSA:public MidiDriver_MPU401 { +class MidiDriver_ALSA : public MidiDriver_MPU401 { public: MidiDriver_ALSA(int client, int port); int open(); + bool isOpen() const { return _isOpen; } void close(); void send(uint32 b); void sysEx(const byte *msg, uint16 length); @@ -83,11 +85,12 @@ private: snd_seq_t *seq_handle; int seq_client, seq_port; int my_client, my_port; + // The volume controller value of the first MIDI channel + int8 _channel0Volume; }; 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) -{ + : _isOpen(false), seq_handle(0), seq_client(client), seq_port(port), my_client(0), my_port(0), _channel0Volume(127) { memset(&ev, 0, sizeof(ev)); } @@ -114,7 +117,7 @@ int MidiDriver_ALSA::open() { // with those capabilities. my_port = snd_seq_create_simple_port(seq_handle, "SCUMMVM port 0", 0, - SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); + SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); if (my_port < 0) { snd_seq_close(seq_handle); @@ -208,24 +211,41 @@ void MidiDriver_ALSA::send(uint32 b) { case 0xB0: /* is it this simple ? Wow... */ snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]); + + // We save the volume of the first MIDI channel here to utilize it in + // our workaround for broken USB-MIDI cables. + if (chanID == 0 && midiCmd[1] == 0x07) + _channel0Volume = midiCmd[2]; + send_event(1); break; case 0xC0: snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]); send_event(0); + + // Send a volume change command to work around a firmware bug in common + // USB-MIDI cables. If the first MIDI command in a USB packet is a + // Cx or Dx command, the second command in the packet is dropped + // somewhere. + send(0x07B0 | (_channel0Volume << 16)); break; case 0xD0: snd_seq_ev_set_chanpress(&ev, chanID, midiCmd[1]); send_event(1); + + // Send a volume change command to work around a firmware bug in common + // USB-MIDI cables. If the first MIDI command in a USB packet is a + // Cx or Dx command, the second command in the packet is dropped + // somewhere. + send(0x07B0 | (_channel0Volume << 16)); break; - case 0xE0:{ - // long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4; - // snd_seq_ev_set_pitchbend(&ev, chanID, theBend); - long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000; - snd_seq_ev_set_pitchbend(&ev, chanID, theBend); - send_event(1); - } - break; + case 0xE0: { + // long theBend = ((((long)midiCmd[1] + (long)(midiCmd[2] << 7))) - 0x2000) / 4; + // snd_seq_ev_set_pitchbend(&ev, chanID, theBend); + long theBend = ((long)midiCmd[1] + (long)(midiCmd[2] << 7)) - 0x2000; + snd_seq_ev_set_pitchbend(&ev, chanID, theBend); + send_event(1); + } break; default: warning("Unknown MIDI Command: %08x", (int)b); @@ -280,6 +300,9 @@ typedef Common::List<AlsaDevice> AlsaDevices; AlsaDevice::AlsaDevice(Common::String name, MusicType mt, int client) : _name(name), _type(mt), _client(client) { + // Make sure we do not get any trailing spaces to avoid problems when + // storing the name in the configuration file. + _name.trim(); } Common::String AlsaDevice::getName() { |
