summaryrefslogtreecommitdiffstats
path: root/src/PortID.hpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-11-28 11:18:08 +0100
committerDavid Robillard <d@drobilla.net>2020-11-28 12:45:57 +0100
commit4ac8e622bb4ef5841435fc0815efb6bb756f76da (patch)
tree156fed5580687bca59fed337c9701acbcaf469f5 /src/PortID.hpp
parent4988d75f19e81c58e2cfdc068c5638b95ae9e314 (diff)
downloadpatchage-4ac8e622bb4ef5841435fc0815efb6bb756f76da.tar.gz
patchage-4ac8e622bb4ef5841435fc0815efb6bb756f76da.tar.bz2
patchage-4ac8e622bb4ef5841435fc0815efb6bb756f76da.zip
Always index Jack ports and refer to them by name
The Jack API annoyingly doesn't provide a way to get an ID from a port name. Since notification callbacks apparently don't have to worry about realtime concerns anymore, simply use the full name string as an ID everywhere. This means that every Jack port has a non-null ID, and all ports are always indexed, so the kludges for this in the canvas can be removed.
Diffstat (limited to 'src/PortID.hpp')
-rw-r--r--src/PortID.hpp153
1 files changed, 72 insertions, 81 deletions
diff --git a/src/PortID.hpp b/src/PortID.hpp
index 2d41f92..2a53881 100644
--- a/src/PortID.hpp
+++ b/src/PortID.hpp
@@ -17,126 +17,117 @@
#ifndef PATCHAGE_PORTID_HPP
#define PATCHAGE_PORTID_HPP
-#include "patchage_config.h"
-
-#include "PatchagePort.hpp"
-
-#ifdef PATCHAGE_LIBJACK
-# include <jack/jack.h>
-#endif
-#ifdef HAVE_ALSA
-# include <alsa/asoundlib.h>
-#endif
-
-#include <cstring>
+#include <cassert>
#include <iostream>
+#include <string>
+#include <tuple>
+/// An ID for some port on a client (program)
struct PortID
{
enum class Type
{
nothing,
- jack_id,
- alsa_addr,
+ jack,
+ alsa,
};
- PortID() = default;
+ PortID(const PortID& copy) = default;
+ PortID& operator=(const PortID& copy) = default;
-#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
- explicit PortID(uint32_t jack_id, bool = false)
- : type(Type::jack_id)
+ PortID(PortID&& id) = default;
+ PortID& operator=(PortID&& id) = default;
+
+ ~PortID() = default;
+
+ /// Return a null ID that refers to nothing
+ static PortID nothing() { return PortID{}; }
+
+ /// Return an ID for a JACK port by full name (like "client:port")
+ static PortID jack(std::string name)
{
- id.jack_id = jack_id;
+ return PortID{Type::jack, std::move(name)};
}
-#endif
-#ifdef HAVE_ALSA
- PortID(snd_seq_addr_t addr, bool in)
- : type(Type::alsa_addr)
+ /// Return an ID for an ALSA Sequencer port by ID
+ static PortID
+ alsa(const uint8_t client_id, const uint8_t port, const bool is_input)
{
- id.alsa_addr = addr;
- id.is_input = in;
+ return PortID{Type::alsa, client_id, port, is_input};
}
-#endif
- PortID(const PortID& copy) = default;
- PortID& operator=(const PortID& copy) = default;
-
- PortID(PortID&& id) = default;
- PortID& operator=(PortID&& id) = default;
+ Type type() const { return _type; }
+ const std::string& jack_name() const { return _jack_name; }
+ uint8_t alsa_client() const { return _alsa_client; }
+ uint8_t alsa_port() const { return _alsa_port; }
+ bool alsa_is_input() const { return _alsa_is_input; }
- ~PortID() = default;
+private:
+ PortID() = default;
- Type type = Type::nothing;
+ PortID(const Type type, std::string jack_name)
+ : _type{type}
+ , _jack_name{std::move(jack_name)}
+ {
+ assert(_type == Type::jack);
+ }
- union
+ PortID(const Type type,
+ const uint8_t alsa_client,
+ const uint8_t alsa_port,
+ const bool is_input)
+ : _type{type}
+ , _alsa_client{alsa_client}
+ , _alsa_port{alsa_port}
+ , _alsa_is_input{is_input}
{
-#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
- uint32_t jack_id;
-#endif
-#ifdef HAVE_ALSA
- struct
- {
- snd_seq_addr_t alsa_addr;
- bool is_input : 1;
- };
-#endif
- } id = {};
+ assert(_type == Type::alsa);
+ }
+
+ Type _type{Type::nothing}; ///< Determines which field is active
+ std::string _jack_name{}; ///< Full port name for Type::jack
+ uint8_t _alsa_client{}; ///< Client ID for Type::alsa
+ uint8_t _alsa_port{}; ///< Port ID for Type::alsa
+ bool _alsa_is_input{}; ///< Input flag for Type::alsa
};
static inline std::ostream&
operator<<(std::ostream& os, const PortID& id)
{
- switch (id.type) {
+ switch (id.type()) {
case PortID::Type::nothing:
return os << "(null)";
- case PortID::Type::jack_id:
-#ifdef PATCHAGE_LIBJACK
- return os << "jack:" << id.id.jack_id;
-#endif
- break;
- case PortID::Type::alsa_addr:
-#ifdef HAVE_ALSA
- return os << "alsa:" << int(id.id.alsa_addr.client) << ":"
- << int(id.id.alsa_addr.port) << ":"
- << (id.id.is_input ? "in" : "out");
-#endif
- break;
+ case PortID::Type::jack:
+ return os << "jack:" << id.jack_name();
+ case PortID::Type::alsa:
+ return os << "alsa:" << int(id.alsa_client()) << ":"
+ << int(id.alsa_port()) << ":"
+ << (id.alsa_is_input() ? "in" : "out");
}
+
assert(false);
return os;
}
static inline bool
-operator<(const PortID& a, const PortID& b)
+operator<(const PortID& lhs, const PortID& rhs)
{
- if (a.type != b.type) {
- return a.type < b.type;
+ if (lhs.type() != rhs.type()) {
+ return lhs.type() < rhs.type();
}
- switch (a.type) {
+ switch (lhs.type()) {
case PortID::Type::nothing:
return true;
- case PortID::Type::jack_id:
-#if defined(PATCHAGE_LIBJACK) || defined(HAVE_JACK_DBUS)
- return a.id.jack_id < b.id.jack_id;
-#endif
- break;
- case PortID::Type::alsa_addr:
-#ifdef HAVE_ALSA
- if ((a.id.alsa_addr.client < b.id.alsa_addr.client) ||
- ((a.id.alsa_addr.client == b.id.alsa_addr.client) &&
- a.id.alsa_addr.port < b.id.alsa_addr.port)) {
- return true;
- } else if (a.id.alsa_addr.client == b.id.alsa_addr.client &&
- a.id.alsa_addr.port == b.id.alsa_addr.port) {
- return (a.id.is_input < b.id.is_input);
- } else {
- return false;
- }
-#endif
- break;
+ case PortID::Type::jack:
+ return lhs.jack_name() < rhs.jack_name();
+ case PortID::Type::alsa:
+ return std::make_tuple(
+ lhs.alsa_client(), lhs.alsa_port(), lhs.alsa_is_input()) <
+ std::make_tuple(
+ rhs.alsa_client(), rhs.alsa_port(), rhs.alsa_is_input());
}
+
assert(false);
return false;
}