LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces - MIDI_Pipes.cpp (source / functions) Hit Total Coverage
Test: e224b347cd670555e44f06608ac41bd1ace9d9d8 Lines: 144 150 96.0 %
Date: 2020-09-08 17:44:46 Functions: 26 29 89.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include "MIDI_Pipes.hpp"
       2             : #include <AH/Error/Error.hpp>
       3             : #include <AH/STL/utility>
       4             : 
       5             : #if defined(ESP32) || !defined(ARDUINO)
       6             : #include <mutex>
       7             : #endif
       8             : 
       9             : AH_DIAGNOSTIC_WERROR()
      10             : 
      11             : BEGIN_CS_NAMESPACE
      12             : 
      13             : // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
      14             : 
      15         272 : void MIDI_Sink::connectSourcePipe(MIDI_Pipe *source) {
      16         272 :     if (this->sourcePipe == nullptr) {
      17         221 :         source->connectSink(this);
      18         221 :         this->sourcePipe = source;
      19         221 :     } else {
      20          51 :         this->sourcePipe->connectSourcePipe(source);
      21             :     }
      22         271 : }
      23             : 
      24         385 : void MIDI_Sink::disconnectSourcePipes() {
      25         385 :     if (sourcePipe != nullptr) {
      26          64 :         sourcePipe->disconnectSourcePipes();
      27          64 :         sourcePipe->disconnect();
      28          64 :         sourcePipe = nullptr;
      29          64 :     }
      30         385 : }
      31             : 
      32         220 : void MIDI_Sink::disconnectSourcePipesShallow() {
      33         220 :     if (sourcePipe != nullptr) {
      34         220 :         sourcePipe->disconnectSink();
      35         220 :         sourcePipe = nullptr;
      36         220 :     }
      37         220 : }
      38             : 
      39          13 : bool MIDI_Sink::disconnect(TrueMIDI_Source &source) {
      40          13 :     if (!hasSourcePipe())
      41           3 :         return false;
      42          10 :     return sourcePipe->disconnect(source);
      43          13 : }
      44             : 
      45         320 : MIDI_Sink::~MIDI_Sink() { disconnectSourcePipes(); }
      46             : 
      47           5 : MIDI_Sink::MIDI_Sink(MIDI_Sink &&other)
      48           5 :     : sourcePipe(std::exchange(other.sourcePipe, nullptr)) {
      49           5 :     if (this->hasSourcePipe()) {
      50           5 :         this->sourcePipe->disconnectSink();
      51           5 :         this->sourcePipe->connectSink(this);
      52           5 :     }
      53           5 : }
      54             : 
      55           2 : MIDI_Sink &MIDI_Sink::operator=(MIDI_Sink &&other) {
      56           2 :     std::swap(this->sourcePipe, other.sourcePipe);
      57           2 :     if (this->hasSourcePipe()) {
      58           2 :         this->sourcePipe->disconnectSink();
      59           2 :         this->sourcePipe->connectSink(this);
      60           2 :     }
      61           2 :     if (other.hasSourcePipe()) {
      62           0 :         other.sourcePipe->disconnectSink();
      63           0 :         other.sourcePipe->connectSink(this);
      64           0 :     }
      65           2 :     return *this;
      66             : }
      67             : 
      68             : // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
      69             : 
      70         267 : void MIDI_Source::connectSinkPipe(MIDI_Pipe *sink) {
      71         267 :     if (this->sinkPipe == nullptr) {
      72         217 :         sink->connectSource(this);
      73         217 :         this->sinkPipe = sink;
      74         217 :     } else {
      75          50 :         this->sinkPipe->connectSinkPipe(sink);
      76             :     }
      77         266 : }
      78             : 
      79         414 : void MIDI_Source::disconnectSinkPipes() {
      80         414 :     if (sinkPipe != nullptr) {
      81          96 :         sinkPipe->disconnectSinkPipes();
      82          96 :         sinkPipe->disconnect();
      83          96 :         sinkPipe = nullptr;
      84          96 :     }
      85         414 : }
      86             : 
      87         216 : void MIDI_Source::disconnectSinkPipesShallow() {
      88         216 :     if (sinkPipe != nullptr) {
      89         216 :         sinkPipe->disconnectSource();
      90         216 :         sinkPipe = nullptr;
      91         216 :     }
      92         216 : }
      93             : 
      94          13 : bool MIDI_Source::disconnect(TrueMIDI_Sink &sink) {
      95          13 :     if (!hasSinkPipe())
      96           3 :         return false;
      97          10 :     return sinkPipe->disconnect(sink);
      98          13 : }
      99             : 
     100           5 : MIDI_Source::MIDI_Source(MIDI_Source &&other)
     101           5 :     : sinkPipe(std::exchange(other.sinkPipe, nullptr)) {
     102           5 :     if (this->hasSinkPipe()) {
     103           5 :         this->sinkPipe->disconnectSource();
     104           5 :         this->sinkPipe->connectSource(this);
     105           5 :     }
     106           5 : }
     107             : 
     108           2 : MIDI_Source &MIDI_Source::operator=(MIDI_Source &&other) {
     109           2 :     std::swap(this->sinkPipe, other.sinkPipe);
     110           2 :     if (this->hasSinkPipe()) {
     111           2 :         this->sinkPipe->disconnectSource();
     112           2 :         this->sinkPipe->connectSource(this);
     113           2 :     }
     114           2 :     if (other.hasSinkPipe()) {
     115           0 :         other.sinkPipe->disconnectSource();
     116           0 :         other.sinkPipe->connectSource(this);
     117           0 :     }
     118           2 :     return *this;
     119             : }
     120             : 
     121         317 : MIDI_Source::~MIDI_Source() { disconnectSinkPipes(); }
     122             : 
     123          14 : void MIDI_Source::exclusive(cn_t cn, bool exclusive) {
     124          14 :     if (hasSinkPipe())
     125          14 :         sinkPipe->exclusive(cn, exclusive);
     126          14 : }
     127             : 
     128          61 : bool MIDI_Source::canWrite(cn_t cn) const {
     129          61 :     return !hasSinkPipe() || sinkPipe->isAvailableForWrite(cn);
     130             : }
     131             : 
     132         123 : void MIDI_Source::sourceMIDItoPipe(ChannelMessage msg) {
     133         123 :     if (sinkPipe != nullptr) {
     134         110 :         sinkPipe->pipeMIDI(msg);
     135         110 :     }
     136         123 : }
     137          12 : void MIDI_Source::sourceMIDItoPipe(SysExMessage msg) {
     138          12 :     if (sinkPipe != nullptr) {
     139           7 :         sinkPipe->pipeMIDI(msg);
     140           7 :     }
     141          12 : }
     142          18 : void MIDI_Source::sourceMIDItoPipe(RealTimeMessage msg) {
     143          18 :     if (sinkPipe != nullptr) {
     144          15 :         sinkPipe->pipeMIDI(msg);
     145          15 :     }
     146          18 : }
     147             : 
     148             : // :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
     149             : 
     150         228 : void MIDI_Pipe::connectSink(MIDI_Sink *sink) {
     151         228 :     if (this->sink != nullptr) {
     152           1 :         FATAL_ERROR(F("This pipe is already connected to a sink"), 0x9145);
     153             :         return; // LCOV_EXCL_LINE
     154             :     }
     155         227 :     this->sink = sink;
     156         228 : }
     157             : 
     158         227 : void MIDI_Pipe::disconnectSink() { this->sink = nullptr; }
     159             : 
     160         224 : void MIDI_Pipe::connectSource(MIDI_Source *source) {
     161         224 :     if (this->source != nullptr) {
     162           1 :         FATAL_ERROR(F("This pipe is already connected to a source"), 0x9146);
     163             :         return; // LCOV_EXCL_LINE
     164             :     }
     165         223 :     this->source = source;
     166         224 : }
     167             : 
     168         223 : void MIDI_Pipe::disconnectSource() { this->source = nullptr; }
     169             : 
     170         318 : void MIDI_Pipe::disconnect() {
     171         318 :     if (hasSink() && hasThroughIn()) {
     172          16 :         auto oldSink = sink;
     173          16 :         auto oldThroughIn = throughIn;
     174          16 :         sink->disconnectSourcePipesShallow();
     175          16 :         this->disconnectSourcePipesShallow(); // disconnect throughIn
     176          16 :         oldSink->connectSourcePipe(oldThroughIn);
     177          16 :     }
     178         318 :     if (hasSource() && hasThroughOut()) {
     179          14 :         auto oldSource = source;
     180          14 :         auto oldThroughOut = throughOut;
     181          14 :         source->disconnectSinkPipesShallow();
     182          14 :         this->disconnectSinkPipesShallow(); // disconnect throughOut
     183          14 :         oldSource->connectSinkPipe(oldThroughOut);
     184          14 :     }
     185         318 :     if (hasSink())
     186         188 :         sink->disconnectSourcePipesShallow();
     187             : 
     188         318 :     if (hasSource())
     189         188 :         source->disconnectSinkPipesShallow();
     190             : 
     191         318 :     if (hasThroughIn() || hasThroughOut())
     192             :         FATAL_ERROR(F("Invalid state"), 0x9147); // LCOV_EXCL_LINE
     193         318 : }
     194             : 
     195         140 : MIDI_Pipe::~MIDI_Pipe() { disconnect(); }
     196             : 
     197             : #if defined(ESP32) || !defined(ARDUINO)
     198             : static std::mutex pipe_exclusive_mutex;
     199             : #endif
     200             : 
     201          14 : void MIDI_Pipe::exclusive(cn_t cn, bool exclusive) {
     202             : #if defined(ESP32) || !defined(ARDUINO)
     203          14 :     std::lock_guard<std::mutex> lock_guard(pipe_exclusive_mutex);
     204             : #endif
     205          14 :     if (hasSink())
     206          14 :         sink->lockDownstream(cn, exclusive);
     207          14 :     if (hasThroughIn())
     208          10 :         throughIn->lockUpstream(cn, exclusive);
     209          14 : }
     210             : 
     211             : END_CS_NAMESPACE
     212             : 
     213             : AH_DIAGNOSTIC_POP()

Generated by: LCOV version 1.14-6-g40580cd