+void
+ProcessorEntry::RoutingIcon::expose_input_map (cairo_t* cr, const double width, const double height)
+{
+ const uint32_t n_in = _in.n_total();
+ const uint32_t n_in_midi = _in.n_midi();
+ const uint32_t pc_in = _sinks.n_total();
+ const uint32_t pc_in_midi = _sinks.n_midi();
+
+ // draw inputs to this
+ for (uint32_t i = 0; i < pc_in; ++i) {
+ const bool is_midi = i < pc_in_midi;
+ bool valid_in;
+ uint32_t pn = is_midi ? i : i - pc_in_midi;
+ DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
+ uint32_t idx = _in_map.get (dt, pn, &valid_in);
+ // check if it's fed
+ bool valid_src = true;
+ if (valid_in && idx < _in.get (dt) && _fed_by) {
+ bool valid_out;
+ bool valid_thru;
+ _f_out_map.get_src (dt, idx, &valid_out);
+ _f_thru_map.get (dt, idx, &valid_thru);
+ if (!valid_out && !valid_thru) {
+ valid_src = false;
+ }
+ }
+ if (!valid_in || !valid_src) {
+ double x = pin_x_pos (i, width, pc_in, 0, is_midi);
+ draw_gnd (cr, x, 0, height, is_midi);
+ continue;
+ }
+ if (idx >= _in.get (dt)) {
+ // side-chain, probably
+ double x = pin_x_pos (i, width, pc_in, 0, is_midi);
+ draw_sidechain (cr, x, 0, height, is_midi);
+ continue;
+ }
+ double c_x1 = pin_x_pos (i, width, pc_in, 0, false);
+ double c_x0 = pin_x_pos (idx, width, n_in, n_in_midi, is_midi);
+ draw_connection (cr, c_x0, c_x1, 0, height, is_midi);
+ }
+
+ // draw reverse thru
+ for (uint32_t i = 0; i < n_in; ++i) {
+ const bool is_midi = i < n_in_midi;
+ bool valid_thru;
+ uint32_t pn = is_midi ? i : i - n_in_midi;
+ DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
+ _thru_map.get_src (dt, pn, &valid_thru);
+ if (!valid_thru) {
+ continue;
+ }
+ double x = pin_x_pos (i, width, n_in, 0, is_midi);
+ draw_thru_sink (cr, x, 0, height, is_midi);
+ }
+}
+
+void
+ProcessorEntry::RoutingIcon::expose_output_map (cairo_t* cr, const double width, const double height)
+{
+ int dh = std::max (4.f, rintf(4.f * UIConfiguration::instance().get_ui_scale()));
+ double ht = _terminal ? height - dh : height;
+
+ // draw outputs of this
+ const uint32_t pc_out = _sources.n_total();
+ const uint32_t pc_out_midi = _sources.n_midi();
+ const uint32_t n_out = _out.n_total();
+ const uint32_t n_out_midi = _out.n_midi();
+
+ for (uint32_t i = 0; i < pc_out; ++i) {
+ const bool is_midi = i < pc_out_midi;
+ bool valid_out;
+ uint32_t pn = is_midi ? i : i - pc_out_midi;
+ DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
+ uint32_t idx = _out_map.get (dt, pn, &valid_out);
+ if (!valid_out) {
+ continue;
+ }
+ // skip connections that are not used in the next's input
+ if (_feeding) {
+ bool valid_thru, valid_sink;
+ _i_in_map.get_src (dt, idx, &valid_sink);
+ _i_thru_map.get_src (dt, idx, &valid_thru);
+ if (!valid_thru && !valid_sink) {
+ if (!is_midi || i != 0) { // special case midi-bypass
+ continue;
+ }
+ }
+ }
+ double c_x0 = pin_x_pos (i, width, pc_out, 0, false);
+ double c_x1 = pin_x_pos (idx, width, n_out, n_out_midi, is_midi);
+ draw_connection (cr, c_x0, c_x1, 0, ht, is_midi);
+ }
+
+ for (uint32_t i = 0; i < n_out; ++i) {
+ const bool is_midi = i < n_out_midi;
+ uint32_t pn = is_midi ? i : i - n_out_midi;
+ DataType dt = is_midi ? DataType::MIDI : DataType::AUDIO;
+ double x = pin_x_pos (i, width, n_out, 0, is_midi);
+
+ if (!_terminal) {
+ bool valid_thru_f = false;
+ // skip connections that are not used in the next's input
+ if (_feeding) {
+ bool valid_sink;
+ _i_in_map.get_src (dt, pn, &valid_sink);
+ _i_thru_map.get_src (dt, pn, &valid_thru_f);
+ if (!valid_thru_f && !valid_sink) {
+ if (!is_midi || i != 0) { // special case midi-bypass
+ continue;
+ }
+ }
+ }
+
+ bool valid_src;
+ _out_map.get_src (dt, pn, &valid_src);
+ if (!valid_src) {
+ bool valid_thru;
+ uint32_t idx = _thru_map.get (dt, pn, &valid_thru);
+ if (valid_thru) {
+ if (idx >= _in.get (dt)) {
+ draw_sidechain (cr, x, 0, height, is_midi);
+ } else {
+ draw_thru_src (cr, x, 0, height, is_midi);
+ }
+ } else if (valid_thru_f){
+ // gnd is part of input, unless it's a thru input
+ // (also only true if !coalesced into one small display)
+ draw_gnd (cr, x, 0, height, is_midi);
+ }
+ }
+ } else {
+ // terminal node, add arrows
+ bool valid_src;
+ _out_map.get_src (dt, pn, &valid_src);
+ if (!valid_src) {
+ bool valid_thru;
+ uint32_t idx = _thru_map.get (dt, pn, &valid_thru);
+ if (valid_thru) {
+ if (idx >= _in.get (dt)) {
+ draw_sidechain (cr, x, 0, height - dh, is_midi);
+ } else {
+ draw_thru_src (cr, x, 0, height - dh, is_midi);
+ }
+ } else {
+ draw_gnd (cr, x, 0, height - dh, is_midi);
+ }
+ }