summaryrefslogtreecommitdiff
path: root/libs/midi++2/fd_midiport.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/midi++2/fd_midiport.cc')
-rw-r--r--libs/midi++2/fd_midiport.cc181
1 files changed, 181 insertions, 0 deletions
diff --git a/libs/midi++2/fd_midiport.cc b/libs/midi++2/fd_midiport.cc
new file mode 100644
index 0000000000..2ced63c259
--- /dev/null
+++ b/libs/midi++2/fd_midiport.cc
@@ -0,0 +1,181 @@
+/*
+ Copyright (C) 1999 Paul Barton-Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+*/
+
+#include <fcntl.h>
+#include <cerrno>
+
+#include <pbd/error.h>
+#include <pbd/pathscanner.h>
+
+#include <midi++/types.h>
+#include <midi++/fd_midiport.h>
+
+using namespace std;
+using namespace MIDI;
+
+string *FD_MidiPort::midi_dirpath = 0;
+string *FD_MidiPort::midi_filename_pattern = 0;
+
+FD_MidiPort::FD_MidiPort (PortRequest &req,
+ const string &dirpath,
+ const string &pattern)
+ : Port (req)
+{
+ open (req);
+
+ if (_fd < 0) {
+ switch (errno) {
+ case EBUSY:
+ error << "MIDI: port device in use" << endmsg;
+ req.status = PortRequest::Busy;
+ break;
+ case ENOENT:
+ error << "MIDI: no such port device" << endmsg;
+ req.status = PortRequest::NoSuchFile;
+ break;
+ case EACCES:
+ error << "MIDI: access to port denied" << endmsg;
+ req.status = PortRequest::NotAllowed;
+ break;
+ default:
+ req.status = PortRequest::Unknown;
+ }
+ } else {
+ _ok = true;
+ req.status = PortRequest::OK;
+
+ if (midi_dirpath == 0) {
+ midi_dirpath = new string (dirpath);
+ midi_filename_pattern = new string (pattern);
+ }
+
+ if (req.mode & O_NONBLOCK == 0) {
+ /* we unconditionally set O_NONBLOCK during
+ open, but the request didn't ask for it,
+ so remove it.
+ */
+
+ int flags = fcntl (_fd, F_GETFL, 0);
+ fcntl (_fd, F_SETFL, flags & ~(O_NONBLOCK));
+ }
+ }
+}
+
+void
+FD_MidiPort::open (PortRequest &req)
+
+{
+ int mode = req.mode | O_NONBLOCK;
+ _fd = ::open (req.devname, mode);
+}
+
+vector<string *> *
+FD_MidiPort::list_devices ()
+
+{
+ PathScanner scanner;
+
+ return scanner (*midi_dirpath, *midi_filename_pattern, false, true);
+}
+
+int
+FD_MidiPort::selectable () const
+
+{
+ long flags;
+
+ /* turn on non-blocking mode, since we plan to use select/poll
+ to tell us when there is data to read.
+ */
+
+ flags = fcntl (_fd, F_GETFL);
+ flags |= O_NONBLOCK;
+
+ if (fcntl (_fd, F_SETFL, flags)) {
+ error << "FD_MidiPort: could not turn on non-blocking mode"
+ << " (" << strerror (errno)
+ << ')'
+ << endmsg;
+
+ return -1;
+ }
+
+ return _fd;
+}
+
+
+int
+FD_MidiPort::do_slow_write (byte *msg, unsigned int msglen)
+
+{
+ size_t n;
+ size_t i;
+
+ for (n = 0; n < msglen; n++) {
+
+ if (::write (_fd, &msg[n], 1) != 1) {
+ break;
+ }
+
+ bytes_written++;
+ for (i = 0; i < slowdown * 10000; i++);
+ }
+
+
+ if (n && output_parser) {
+ output_parser->raw_preparse (*output_parser, msg, n);
+ for (unsigned int i = 0; i < n; i++) {
+ output_parser->scanner (msg[i]);
+ }
+ output_parser->raw_postparse (*output_parser, msg, n);
+ }
+
+ return n;
+}
+
+int
+FD_MidiPort::read (byte* buf, size_t max)
+{
+ int nread;
+
+ if ((_mode & O_ACCMODE) == O_WRONLY) {
+ return -EACCES;
+ }
+
+ // cerr << "MIDI: read up to " << max << " from " << _fd << " (" << name() << ')' << endl;
+
+ if ((nread = ::read (_fd, buf, max)) > 0) {
+ bytes_read += nread;
+
+ // cerr << " read " << nread << endl;
+
+ if (input_parser) {
+ input_parser->raw_preparse
+ (*input_parser, buf, nread);
+ for (int i = 0; i < nread; i++) {
+ input_parser->scanner (buf[i]);
+ }
+ input_parser->raw_postparse
+ (*input_parser, buf, nread);
+ }
+ }
+
+ return nread;
+}