diff --git a/projects/Makefile.X64 b/projects/Makefile.X64 index 6460f413..5a6cc246 100644 --- a/projects/Makefile.X64 +++ b/projects/Makefile.X64 @@ -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) diff --git a/sources/Services/Midi/MidiService.cpp b/sources/Services/Midi/MidiService.cpp index eec2b687..64476dc0 100644 --- a/sources/Services/Midi/MidiService.cpp +++ b/sources/Services/Midi/MidiService.cpp @@ -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 @@ -14,49 +13,43 @@ MidiService::MidiService() : T_SimpleList(true), inList_(true), device_(0), sendSync_(true) { #ifndef _FEAT_MIDI_MULTITHREAD - for (int i=0;i(true); - } + for (int i = 0; i < MIDI_MAX_BUFFERS; i++) { + queues_[i] = new T_SimpleList(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(); - IteratorPtrit(inList_.GetIterator()); - for (it->Begin();!it->IsDone();it->Next()) { - MidiInDevice ¤t=it->CurrentItem(); - merger_->Insert(current); - } - - return true; -}; + Empty(); + inList_.Empty(); + buildDriverList(); + // Add a merger for the input + merger_ = new MidiInMerger(); + IteratorPtr it(inList_.GetIterator()); + for (it->Begin(); !it->IsDone(); it->Next()) { + MidiInDevice ¤t = it->CurrentItem(); + merger_->Insert(current); + } -void MidiService::Close() { - Stop(); + return true; }; +void MidiService::Close() { Stop(); }; + I_Iterator *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 @@ -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 @@ -80,13 +73,15 @@ 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 *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 *queue = queues_[currentPlayQueue_]; + MidiMessage *ms = new MidiMessage(m.status_, m.data1_, m.data2_); + queue->Insert(ms); + } +}; #endif void MidiService::Trigger() { @@ -94,8 +89,8 @@ void MidiService::Trigger() { 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); @@ -105,23 +100,26 @@ void MidiService::Trigger() { #ifndef _FEAT_MIDI_MULTITHREAD 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(); } } } @@ -129,7 +127,7 @@ void MidiService::onAudioTick() { void MidiService::Flush() { tickToFlush_ = midiDelay_; if (tickToFlush_ == 0) { - flushOutQueue(); + flushOutQueue(); } }; @@ -147,11 +145,14 @@ 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 *flushQueue = queues_[next]; if (device_) { @@ -159,7 +160,7 @@ void MidiService::flushOutQueue() { } flushQueue->Empty(); - currentOutQueue_ = next; // Advance only after safe flush + currentOutQueue_ = next; // Advance only after safe flush } #endif @@ -167,62 +168,64 @@ void MidiService::flushOutQueue() { * starts midi device */ void MidiService::startDevice() { - IteratorPtrit(GetIterator()) ; - - for (it->Begin(); !it->IsDone(); it->Next()) { - MidiOutDevice ¤t = 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_ = ¤t; - } else { - Trace::Log("MidiService", "midi device %s failed to start", deviceName_.c_str()); - current.Close(); - } - } - break; - } - } + IteratorPtr it(GetIterator()); + + for (it->Begin(); !it->IsDone(); it->Next()) { + MidiOutDevice ¤t = 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_ = ¤t; + } 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); + } }; diff --git a/sources/Services/Midi/MidiService.h b/sources/Services/Midi/MidiService.h index 6c456717..cfecc1a9 100644 --- a/sources/Services/Midi/MidiService.h +++ b/sources/Services/Midi/MidiService.h @@ -7,6 +7,7 @@ #include "MidiInDevice.h" #include "MidiInMerger.h" #include "MidiOutDevice.h" +#include "System/Process/SysMutex.h" #include "System/Timer/Timer.h" #include #ifdef _FEAT_MIDI_MULTITHREAD @@ -15,79 +16,81 @@ #define MIDI_MAX_BUFFERS 20 -class MidiService -:public T_Factory -,public T_SimpleList -,public I_Observer -{ +class MidiService : public T_Factory, + public T_SimpleList, + public I_Observer { -public: - MidiService() ; - virtual ~MidiService() ; + public: + MidiService(); + virtual ~MidiService(); - bool Init() ; - void Close() ; - bool Start() ; - void Stop() ; + bool Init(); + void Close(); + bool Start(); + void Stop(); - void SelectDevice(const std::string &name) ; + void SelectDevice(const std::string &name); - I_Iterator *GetInIterator() ; + I_Iterator *GetInIterator(); - //! player notification + //! player notification - void OnPlayerStart() ; - void OnPlayerStop() ; + void OnPlayerStart(); + void OnPlayerStop(); - //! Queues a MidiMessage to the current time chunk + //! Queues a MidiMessage to the current time chunk - void QueueMessage(MidiMessage &) ; + void QueueMessage(MidiMessage &); - //! Time chunk trigger + //! Time chunk trigger void Trigger(); #ifndef _FEAT_MIDI_MULTITHREAD void AdvancePlayQueue(); #endif - //! Flush current queue to the output + //! Flush current queue to the output void Flush(); protected: - T_SimpleList inList_ ; + T_SimpleList inList_; virtual void Update(Observable &o, I_ObservableData *d); void onAudioTick(); - //! start the selected midi device + //! start the selected midi device - void startDevice() ; + void startDevice(); - //! stop the selected midi device + //! stop the selected midi device - void stopDevice() ; + void stopDevice(); - //! build the list of available drivers + //! build the list of available drivers - virtual void buildDriverList()=0 ; + virtual void buildDriverList() = 0; -private: - void flushOutQueue(); -private: - std::string deviceName_; - MidiOutDevice *device_; + private: + void flushOutQueue(); + + private: + std::string deviceName_; + MidiOutDevice *device_; #ifdef _FEAT_MIDI_MULTITHREAD - moodycamel::ConcurrentQueue midiQueue_; + moodycamel::ConcurrentQueue midiQueue_; #else - T_SimpleList *queues_[MIDI_MAX_BUFFERS]; - int currentPlayQueue_; - int currentOutQueue_; + T_SimpleList *queues_[MIDI_MAX_BUFFERS]; + int currentPlayQueue_; + int currentOutQueue_; +#ifdef _FEAT_MIDI_LOCK + SysMutex queueMutex_; +#endif #endif - MidiInMerger *merger_; - int midiDelay_; - int tickToFlush_; - bool sendSync_; + MidiInMerger *merger_; + int midiDelay_; + int tickToFlush_; + bool sendSync_; }; #endif