1 /*
2 * Copyright (C) 1998-2015 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
4 * Copyright (C) 2015 Robin Gareus <robin@gareus.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 #include <iostream>
21 #include <cstdio>
22 #include <fcntl.h>
23 #include <errno.h>
24
25 #include "pbd/xml++.h"
26 #include "pbd/error.h"
27 #include "pbd/failed_constructor.h"
28 #include "pbd/convert.h"
29 #include "pbd/strsplit.h"
30
31 #include "midi++/types.h"
32 #include "midi++/port.h"
33 #include "midi++/channel.h"
34
35 using namespace MIDI;
36 using namespace std;
37 using namespace PBD;
38
39 string Port::state_node_name = "MIDI-port";
40
Port(string const & name,Flags flags)41 Port::Port (string const & name, Flags flags)
42 : _flags (flags)
43 , _centrally_parsed (true)
44 {
45 init (name, flags);
46 }
47
Port(const XMLNode & node)48 Port::Port (const XMLNode& node)
49 : _centrally_parsed (true)
50 {
51 Descriptor desc (node);
52
53 init (desc.tag, desc.flags);
54
55 /* derived class must call ::set_state() */
56 }
57
58 void
init(string const & name,Flags flags)59 Port::init (string const & name, Flags flags)
60 {
61 _ok = false; /* derived class must set to true if constructor
62 succeeds.
63 */
64
65 _parser = 0;
66
67 _tagname = name;
68 _flags = flags;
69
70 _parser = new Parser ();
71
72 for (int i = 0; i < 16; i++) {
73 _channel[i] = new Channel (i, *this);
74 _channel[i]->connect_signals ();
75 }
76 }
77
~Port()78 Port::~Port ()
79 {
80 for (int i = 0; i < 16; i++) {
81 delete _channel[i];
82 }
83
84 delete _parser;
85 }
86
87 /** Send a clock tick message.
88 * \return true on success.
89 */
90 bool
clock(timestamp_t timestamp)91 Port::clock (timestamp_t timestamp)
92 {
93 static byte clockmsg = 0xf8;
94
95 if (sends_output()) {
96 return midimsg (&clockmsg, 1, timestamp);
97 }
98
99 return false;
100 }
101
operator <<(std::ostream & os,const MIDI::Port & port)102 std::ostream & MIDI::operator << ( std::ostream & os, const MIDI::Port & port )
103 {
104 using namespace std;
105 os << "MIDI::Port { ";
106 os << "name: " << port.name();
107 os << "; ";
108 os << "ok: " << port.ok();
109 os << "; ";
110 os << " }";
111 return os;
112 }
113
Descriptor(const XMLNode & node)114 Port::Descriptor::Descriptor (const XMLNode& node)
115 {
116 const XMLProperty *prop;
117 bool have_tag = false;
118 bool have_mode = false;
119
120 if ((prop = node.property ("tag")) != 0) {
121 tag = prop->value();
122 have_tag = true;
123 }
124
125 if ((prop = node.property ("mode")) != 0) {
126
127 if (strings_equal_ignore_case (prop->value(), "output") || strings_equal_ignore_case (prop->value(), "out")) {
128 flags = IsOutput;
129 } else if (strings_equal_ignore_case (prop->value(), "input") || strings_equal_ignore_case (prop->value(), "in")) {
130 flags = IsInput;
131 }
132
133 have_mode = true;
134 }
135
136 if (!have_tag || !have_mode) {
137 throw failed_constructor();
138 }
139 }
140
141 XMLNode&
get_state() const142 Port::get_state () const
143 {
144 XMLNode* root = new XMLNode (state_node_name);
145 root->set_property ("tag", _tagname);
146
147 if (_flags == IsInput) {
148 root->set_property ("mode", "input");
149 } else {
150 root->set_property ("mode", "output");
151 }
152
153 #if 0
154 byte device_inquiry[6];
155
156 device_inquiry[0] = 0xf0;
157 device_inquiry[0] = 0x7e;
158 device_inquiry[0] = 0x7f;
159 device_inquiry[0] = 0x06;
160 device_inquiry[0] = 0x02;
161 device_inquiry[0] = 0xf7;
162
163 write (device_inquiry, sizeof (device_inquiry), 0);
164 #endif
165
166 return *root;
167 }
168
169 void
set_state(const XMLNode & node)170 Port::set_state (const XMLNode& node)
171 {
172 const XMLProperty* prop;
173
174 if ((prop = node.property ("tag")) == 0 || prop->value() != _tagname) {
175 return;
176 }
177 }
178
179 bool
centrally_parsed() const180 Port::centrally_parsed() const
181 {
182 return _centrally_parsed;
183 }
184