Skip to content
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
2 changes: 1 addition & 1 deletion projects/Makefile.X64
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ DEFINES := \
-DSDLAUDIO \
-DRTMIDI \
-DFFMPEG_ENABLED \
-D_FEAT_MIDI_MULTITHREAD
-D_FEAT_MIDI_LOCK

ALSA_CFLAGS := $(shell pkg-config alsa --cflags)
ALSA_LIBS := $(shell pkg-config alsa --libs)
Expand Down
185 changes: 94 additions & 91 deletions sources/Services/Midi/MidiService.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#include "MidiService.h"
#include "Application/Player/SyncMaster.h"
#include "System/Console/Trace.h"
#include "System/Timer/Timer.h"
#include "Application/Model/Config.h"
#include "Application/Player/SyncMaster.h"
#include "Services/Audio/AudioDriver.h"
#include "System/Console/Trace.h"
#include "System/Timer/Timer.h"

#ifdef SendMessage
#undef SendMessage
Expand All @@ -14,49 +13,43 @@ MidiService::MidiService()
: T_SimpleList<MidiOutDevice>(true), inList_(true), device_(0),
sendSync_(true) {
#ifndef _FEAT_MIDI_MULTITHREAD
for (int i=0;i<MIDI_MAX_BUFFERS;i++) {
queues_[i]=new T_SimpleList<MidiMessage>(true);
}
for (int i = 0; i < MIDI_MAX_BUFFERS; i++) {
queues_[i] = new T_SimpleList<MidiMessage>(true);
}
#endif
const char *delay = Config::GetInstance()->GetValue("MIDIDELAY");
midiDelay_ = delay ? atoi(delay) : 1;

const char *sendSync = Config::GetInstance()->GetValue("MIDISENDSYNC");
if (sendSync) {
sendSync_ = (strcmp(sendSync,"YES")==0);
}
sendSync_ = (strcmp(sendSync, "YES") == 0);
}
};

MidiService::~MidiService() {
Close();
};
MidiService::~MidiService() { Close(); };

bool MidiService::Init() {
Empty();
inList_.Empty();
buildDriverList();
// Add a merger for the input
merger_=new MidiInMerger();
IteratorPtr<MidiInDevice>it(inList_.GetIterator());
for (it->Begin();!it->IsDone();it->Next()) {
MidiInDevice &current=it->CurrentItem();
merger_->Insert(current);
}

return true;
};
Empty();
inList_.Empty();
buildDriverList();
// Add a merger for the input
merger_ = new MidiInMerger();
IteratorPtr<MidiInDevice> it(inList_.GetIterator());
for (it->Begin(); !it->IsDone(); it->Next()) {
MidiInDevice &current = it->CurrentItem();
merger_->Insert(current);
}

void MidiService::Close() {
Stop();
return true;
};

void MidiService::Close() { Stop(); };

I_Iterator<MidiInDevice> *MidiService::GetInIterator() {
return inList_.GetIterator();
return inList_.GetIterator();
};

void MidiService::SelectDevice(const std::string &name) {
deviceName_ = name;
};
void MidiService::SelectDevice(const std::string &name) { deviceName_ = name; };

bool MidiService::Start() {
#ifndef _FEAT_MIDI_MULTITHREAD
Expand All @@ -66,7 +59,7 @@ bool MidiService::Start() {
return true;
}

void MidiService::Stop() { stopDevice(); }
void MidiService::Stop() { stopDevice(); };

#ifdef _FEAT_MIDI_MULTITHREAD
// For multi-threaded systems we use a concurrentqueue
Expand All @@ -80,22 +73,24 @@ void MidiService::QueueMessage(MidiMessage &m) {
#else
// For single-threaded systems we do it the old way
void MidiService::QueueMessage(MidiMessage &m) {
if (!device_)
return;

T_SimpleList<MidiMessage> *queue = queues_[currentPlayQueue_];
MidiMessage *ms = new MidiMessage(m.status_, m.data1_, m.data2_);
queue->Insert(ms);
}
if (device_) {
#ifdef _FEAT_MIDI_LOCK
SysMutexLocker locker(queueMutex_);
#endif
T_SimpleList<MidiMessage> *queue = queues_[currentPlayQueue_];
MidiMessage *ms = new MidiMessage(m.status_, m.data1_, m.data2_);
queue->Insert(ms);
}
};
#endif

void MidiService::Trigger() {
#ifndef _FEAT_MIDI_MULTITHREAD
AdvancePlayQueue();
#endif
if (device_ && sendSync_) {
SyncMaster *sm=SyncMaster::GetInstance();
if (sm->MidiSlice()) {
SyncMaster *sm = SyncMaster::GetInstance();
if (sm->MidiSlice()) {
MidiMessage msg;
msg.status_ = 0xF8;
QueueMessage(msg);
Expand All @@ -105,31 +100,34 @@ void MidiService::Trigger() {

#ifndef _FEAT_MIDI_MULTITHREAD
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we removed it from the related makefile, we don't need this anymore?
Or does FEAT_MIDI_MULTITHREAD still serve some role that I'm just not understanding? =)

void MidiService::AdvancePlayQueue() {
#ifdef _FEAT_MIDI_LOCK
SysMutexLocker locker(queueMutex_);
#endif
int next = (currentPlayQueue_ + 1) % MIDI_MAX_BUFFERS;
queues_[next]->Empty();
currentPlayQueue_ = next;
}
#endif

void MidiService::Update(Observable &o,I_ObservableData *d) {
AudioDriver::Event *event=(AudioDriver::Event *)d;
if (event->type_ == AudioDriver::Event::ADET_DRIVERTICK) {
onAudioTick();
}
void MidiService::Update(Observable &o, I_ObservableData *d) {
AudioDriver::Event *event = (AudioDriver::Event *)d;
if (event->type_ == AudioDriver::Event::ADET_DRIVERTICK) {
onAudioTick();
}
};

void MidiService::onAudioTick() {
if (tickToFlush_ > 0) {
if (--tickToFlush_ ==0) {
flushOutQueue();
if (--tickToFlush_ == 0) {
flushOutQueue();
}
}
}

void MidiService::Flush() {
tickToFlush_ = midiDelay_;
if (tickToFlush_ == 0) {
flushOutQueue();
flushOutQueue();
}
};

Expand All @@ -147,82 +145,87 @@ void MidiService::flushOutQueue() {
}
if (batch.Size() > 0) {
device_->SendQueue(batch);
// Trace::Log("MidiService", "flushOutQueue: batch=0x%X", batch);
// Trace::Log("MidiService", "flushOutQueue: batch=0x%X", batch);
}
}
#else
void MidiService::flushOutQueue() {
#ifdef _FEAT_MIDI_LOCK
SysMutexLocker locker(queueMutex_);
#endif
int next = (currentOutQueue_ + 1) % MIDI_MAX_BUFFERS;
T_SimpleList<MidiMessage> *flushQueue = queues_[next];
if (device_) {
device_->SendQueue(*flushQueue);
}

flushQueue->Empty();
currentOutQueue_ = next; // Advance only after safe flush
currentOutQueue_ = next; // Advance only after safe flush
}
#endif

/*
* starts midi device
*/
void MidiService::startDevice() {
IteratorPtr<MidiOutDevice>it(GetIterator()) ;

for (it->Begin(); !it->IsDone(); it->Next()) {
MidiOutDevice &current = it->CurrentItem();
if (!strcmp(deviceName_.c_str(), current.GetName())) {
if (current.Init()) {
if (current.Start()) {
Trace::Log("MidiService", "midi device %s started", deviceName_.c_str());
device_ = &current;
} else {
Trace::Log("MidiService", "midi device %s failed to start", deviceName_.c_str());
current.Close();
}
}
break;
}
}
IteratorPtr<MidiOutDevice> it(GetIterator());

for (it->Begin(); !it->IsDone(); it->Next()) {
MidiOutDevice &current = it->CurrentItem();
if (!strcmp(deviceName_.c_str(), current.GetName())) {
if (current.Init()) {
if (current.Start()) {
Trace::Log("MidiService", "midi device %s started",
deviceName_.c_str());
device_ = &current;
} else {
Trace::Log("MidiService", "midi device %s failed to start",
deviceName_.c_str());
current.Close();
}
}
break;
}
}
};

/*
* closes midi device
*/
void MidiService::stopDevice() {
if (device_) {
device_->Stop() ;
device_->Close() ;
}
device_=0 ;
} ;
if (device_) {
device_->Stop();
device_->Close();
}
device_ = 0;
};

/*
* starts midi device when playback starts
*/
void MidiService::OnPlayerStart() {
if (deviceName_.size()!=0) {
stopDevice();
startDevice();
deviceName_="";
} else {
startDevice();
}

if (sendSync_) {
MidiMessage msg ;
msg.status_=0xFA ;
QueueMessage(msg) ;
}
if (deviceName_.size() != 0) {
stopDevice();
startDevice();
deviceName_ = "";
} else {
startDevice();
}

if (sendSync_) {
MidiMessage msg;
msg.status_ = 0xFA;
QueueMessage(msg);
}
};

/*
* queues midi stop message when player stops
*/
void MidiService::OnPlayerStop() {
if (sendSync_) {
MidiMessage msg ;
msg.status_=0xFC ;
QueueMessage(msg) ;
}
if (sendSync_) {
MidiMessage msg;
msg.status_ = 0xFC;
QueueMessage(msg);
}
};
Loading
Loading