2 Copyright (C) 2004 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <pbd/failed_constructor.h>
25 #include <pbd/error.h>
27 #include <midi++/types.h>
28 #include <midi++/alsa_sequencer.h>
29 #include <midi++/port_request.h>
34 #define TR_FN() (cerr << __FUNCTION__ << endl)
35 #define TR_VAL(v) (cerr << __FILE__ " " << __LINE__ << " " #v "=" << v << endl)
45 snd_seq_t* ALSA_SequencerMidiPort::seq = 0;
47 ALSA_SequencerMidiPort::ALSA_SequencerMidiPort (PortRequest &req)
56 if (!seq && init_client (req.devname) < 0) {
61 if (0 <= (err = CreatePorts (req)) &&
62 0 <= (err = snd_midi_event_new (1024, &decoder)) && // Length taken from ARDOUR::Session::midi_read ()
63 0 <= (err = snd_midi_event_new (64, &encoder))) { // Length taken from ARDOUR::Session::mmc_buffer
64 snd_midi_event_init (decoder);
65 snd_midi_event_init (encoder);
67 req.status = PortRequest::OK;
69 req.status = PortRequest::Unknown;
74 ALSA_SequencerMidiPort::~ALSA_SequencerMidiPort ()
77 snd_midi_event_free (decoder);
80 snd_midi_event_free (encoder);
83 snd_seq_delete_port (seq, port_id);
88 ALSA_SequencerMidiPort::selectable () const
91 if (0 <= snd_seq_poll_descriptors (seq, pfd, 1, POLLIN | POLLOUT)) {
97 int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t timestamp)
102 snd_midi_event_reset_encode (encoder);
103 int nwritten = snd_midi_event_encode (encoder, msg, msglen, &SEv);
105 while (0 < nwritten) {
106 if (0 <= (R = snd_seq_event_output (seq, &SEv)) &&
107 0 <= (R = snd_seq_drain_output (seq))) {
108 bytes_written += nwritten;
109 totwritten += nwritten;
111 output_parser->raw_preparse (*output_parser, msg, nwritten);
112 for (int i = 0; i < nwritten; i++) {
113 output_parser->scanner (msg[i]);
115 output_parser->raw_postparse (*output_parser, msg, nwritten);
125 nwritten = snd_midi_event_encode (encoder, msg, msglen, &SEv);
137 int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp)
140 ALSA_SequencerMidiPort::read (byte *buf, size_t max)
141 >>>>>>> .merge-right.r1393
146 if (0 <= (err = snd_seq_event_input (seq, &ev))) {
148 err = snd_midi_event_decode (decoder, buf, max, ev);
155 input_parser->raw_preparse (*input_parser, buf, err);
156 for (int i = 0; i < err; i++) {
157 input_parser->scanner (buf[i]);
159 input_parser->raw_postparse (*input_parser, buf, err);
162 return -ENOENT == err ? 0 : err;
166 ALSA_SequencerMidiPort::CreatePorts (PortRequest &req)
169 unsigned int caps = 0;
171 if (req.mode == O_WRONLY || req.mode == O_RDWR)
172 caps |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
173 if (req.mode == O_RDONLY || req.mode == O_RDWR)
174 caps |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
176 if (0 <= (err = snd_seq_create_simple_port (seq, req.tagname, caps, SND_SEQ_PORT_TYPE_MIDI_GENERIC))) {
180 snd_seq_ev_clear (&SEv);
181 snd_seq_ev_set_source (&SEv, port_id);
182 snd_seq_ev_set_subs (&SEv);
183 snd_seq_ev_set_direct (&SEv);
192 ALSA_SequencerMidiPort::init_client (std::string name)
194 static bool called = false;
202 if (snd_seq_open (&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) >= 0) {
203 snd_seq_set_client_name (seq, name.c_str());
206 warning << "The ALSA MIDI system is not available. No ports based on it will be created"