Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unplug #260

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 37 additions & 4 deletions RtMidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -654,15 +654,21 @@ double MidiInApi :: getMessage( std::vector<unsigned char> *message )
return 0.0;
}

RtMidiError::Type err = RtMidiError::NO_ERROR;
std::string err_msg;
double timeStamp;
if ( !inputData_.queue.pop( message, &timeStamp ) )
if ( !inputData_.queue.pop( message, &timeStamp, &err, &err_msg ) )
return 0.0;

if ( err != RtMidiError::NO_ERROR )
error( err, err_msg );

return timeStamp;
}

// structure should be locked before using this method
unsigned int MidiInApi::MidiQueue::size( unsigned int *__back,
unsigned int *__front )
unsigned int *__front)
{
// Access back/front members exactly once and make stack copies for
// size calculation
Expand All @@ -676,6 +682,7 @@ unsigned int MidiInApi::MidiQueue::size( unsigned int *__back,
// to member variables are needed.
if ( __back ) *__back = _back;
if ( __front ) *__front = _front;

return _size;
}

Expand All @@ -685,36 +692,50 @@ bool MidiInApi::MidiQueue::push( const MidiInApi::MidiMessage& msg )
// Local stack copies of front/back
unsigned int _back, _front, _size;

lock.lock();

// Get back/front indexes exactly once and calculate current size
_size = size( &_back, &_front );

if ( _size < ringSize-1 )
{
ring[_back] = msg;
back = (back+1)%ringSize;
lock.unlock();
return true;
}

lock.unlock();

return false;
}

bool MidiInApi::MidiQueue::pop( std::vector<unsigned char> *msg, double* timeStamp )
bool MidiInApi::MidiQueue::pop( std::vector<unsigned char> *msg, double* timeStamp, RtMidiError::Type *err, std::string *err_msg )
{
// Local stack copies of front/back
unsigned int _back, _front, _size;

lock.lock();

// Get back/front indexes exactly once and calculate current size
_size = size( &_back, &_front );

if ( _size == 0 )
if ( _size == 0 ) {
lock.unlock();
return false;
}

// Copy queued message to the vector pointer argument and then "pop" it.
msg->assign( ring[_front].bytes.begin(), ring[_front].bytes.end() );
*timeStamp = ring[_front].timeStamp;
*err = ring[_front].err;
*err_msg = ring[_front].err_msg;

// Update front
front = (front+1)%ringSize;

lock.unlock();

return true;
}

Expand Down Expand Up @@ -1658,6 +1679,17 @@ static void *alsaMidiHandler( void *ptr )
<< (int) ev->data.connect.dest.port
<< std::endl;
#endif
if ( data->usingCallback ) {
std::cerr << "\nPort connection has closed!\n\n";
data->this_->error( RtMidiError::SYSTEM_ERROR, "Port connection has closed!" );
}
else {
MidiInApi::MidiMessage err_message;
err_message.err = RtMidiError::SYSTEM_ERROR;
err_message.err_msg = "Port connection has closed";
if ( !data->queue.push( err_message ) )
std::cerr << "\nMidiInCore: message queue limit reached!!\n\n";
}
break;

case SND_SEQ_EVENT_QFRAME: // MIDI time code
Expand Down Expand Up @@ -1840,6 +1872,7 @@ void MidiInAlsa :: initialize( const std::string& clientName )
data->trigger_fds[1] = -1;
apiData_ = (void *) data;
inputData_.apiData = (void *) data;
inputData_.this_ = this;

if ( pipe(data->trigger_fds) == -1 ) {
errorString_ = "MidiInAlsa::initialize: error creating pipe objects.";
Expand Down
12 changes: 10 additions & 2 deletions RtMidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@

#include <exception>
#include <iostream>
#include <mutex>
#include <string>
#include <vector>

Expand All @@ -81,6 +82,7 @@ class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception
public:
//! Defined RtMidiError types.
enum Type {
NO_ERROR = 0,
WARNING, /*!< A non-critical error. */
DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */
UNSPECIFIED, /*!< The default, unspecified error type. */
Expand Down Expand Up @@ -555,22 +557,27 @@ class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
//! Time in seconds elapsed since the previous message
double timeStamp;

// Can also contain an error (when bytes.size() == 0)
RtMidiError::Type err;
std::string err_msg;

// Default constructor.
MidiMessage()
: bytes(0), timeStamp(0.0) {}
: bytes(0), timeStamp(0.0), err(RtMidiError::NO_ERROR) {}
};

struct MidiQueue {
unsigned int front;
unsigned int back;
unsigned int ringSize;
MidiMessage *ring;
std::mutex lock;

// Default constructor.
MidiQueue()
: front(0), back(0), ringSize(0), ring(0) {}
bool push( const MidiMessage& );
bool pop( std::vector<unsigned char>*, double* );
bool pop( std::vector<unsigned char>*, double*, RtMidiError::Type*, std::string* );
unsigned int size( unsigned int *back=0, unsigned int *front=0 );
};

Expand All @@ -587,6 +594,7 @@ class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
RtMidiIn::RtMidiCallback userCallback;
void *userData;
bool continueSysex;
MidiInApi *this_;

// Default constructor.
RtMidiInData()
Expand Down