@@ -29,6 +29,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2929
3030namespace py = pybind11;
3131
32+ PYBIND11_EMBEDDED_MODULE (oe_pyprocessor, module ){
33+
34+ py::class_<PythonProcessor> (module , " PythonProcessor" )
35+ .def (" add_python_event" , &PythonProcessor::addPythonEvent);
36+ }
3237
3338PythonProcessor::PythonProcessor ()
3439 : GenericProcessor(" Python Processor" )
@@ -74,6 +79,30 @@ void PythonProcessor::updateSettings()
7479{
7580 if (getDataStreams ().size () == 0 )
7681 currentStream = 0 ;
82+
83+ localEventChannels.clear ();
84+
85+ for (auto stream : getDataStreams ())
86+ {
87+ const uint16 streamId = stream->getStreamId ();
88+
89+ // TTL Channel
90+ EventChannel* ttlChan;
91+ EventChannel::Settings ttlChannelSettings{
92+ EventChannel::Type::TTL,
93+ " Python Processor Output" ,
94+ " TTL event triggerd by the python module." ,
95+ " pythonprocessor.ttl" ,
96+ getDataStream (stream->getStreamId ())
97+ };
98+
99+ ttlChan = new EventChannel (ttlChannelSettings);
100+ ttlChan->addProcessor (processorInfo.get ());
101+ eventChannels.add (ttlChan);
102+
103+ localEventChannels[streamId] = eventChannels.getLast ();
104+
105+ }
77106}
78107
79108void PythonProcessor::initialize (bool signalChainIsLoading)
@@ -93,12 +122,13 @@ void PythonProcessor::process(AudioBuffer<float>& buffer)
93122
94123 checkForEvents (true );
95124
125+ int64 sampleNum = getFirstSampleNumberForBlock (currentStream);
126+
96127 for (auto stream : getDataStreams ())
97128 {
98129
99130 if (stream->getStreamId () == currentStream)
100131 {
101-
102132 const uint16 streamId = stream->getStreamId ();
103133
104134 const int numSamples = getNumSamplesInBlock (streamId);
@@ -135,6 +165,16 @@ void PythonProcessor::process(AudioBuffer<float>& buffer)
135165 // py::gil_scoped_release release;
136166
137167 }
168+
169+ {
170+ ScopedLock TTLlock (TTLqueueLock);
171+ while (!TTLQueue.empty ())
172+ {
173+ const StringTTL& TTLmsg = TTLQueue.front ();
174+ triggerTTLEvent (TTLmsg, sampleNum);
175+ TTLQueue.pop ();
176+ }
177+ }
138178 }
139179}
140180
@@ -148,7 +188,7 @@ void PythonProcessor::handleTTLEvent(TTLEventPtr event)
148188 const int sourceNodeId = chanInfo->getSourceNodeId ();
149189 const int64 sampleNumber = event->getSampleNumber ();
150190 const uint8 line = event->getLine ();
151- const int state = event->getState () ? 1 : 0 ;
191+ const bool state = event->getState ();
152192
153193 // Give to python
154194 // py::gil_scoped_acquire acquire;
@@ -180,6 +220,29 @@ void PythonProcessor::handleTTLEvent(TTLEventPtr event)
180220
181221// }
182222
223+ void PythonProcessor::addPythonEvent (int line, bool state)
224+ {
225+ // LOGC("[PYTHON] Event received!! Line: ", line, " | State: ", state);
226+ {
227+ ScopedLock TTLlock (TTLqueueLock);
228+ if (CoreServices::getAcquisitionStatus ())
229+ {
230+ TTLQueue.push ({ line, state });
231+ }
232+ }
233+ }
234+
235+ void PythonProcessor::triggerTTLEvent (StringTTL TTLmsg, juce::int64 sampleNum)
236+ {
237+ TTLEventPtr event =
238+ TTLEvent::createTTLEvent (localEventChannels[currentStream],
239+ sampleNum,
240+ TTLmsg.eventLine ,
241+ TTLmsg.state );
242+ addEvent (event, 0 );
243+
244+ }
245+
183246bool PythonProcessor::startAcquisition ()
184247{
185248 if (moduleReady)
@@ -346,13 +409,20 @@ bool PythonProcessor::initInterpreter(String pythonHome)
346409 py::gil_scoped_acquire acquire;
347410
348411 if (Py_IsInitialized () > 0 )
412+ {
349413 LOGC (" Python Interpreter initialized successfully! Python Home: " , String (Py_GetPythonHome ()));
414+
415+ #if JUCE_WINDOWS
416+ py::module_ os = py::module_::import (" os" );
417+ os.attr (" add_dll_directory" )
418+ (targetFolder.getChildFile (" Library\\ bin" ).getFullPathName ().toWideCharPointer ());
419+ #endif
420+ }
350421
351422 py::module sys = py::module::import (" sys" );
352423 py::list path = sys.attr (" path" );
353424
354425 LOGD (" Python sys paths:" )
355- // Check if the path was added successfully
356426 for (auto p : path) {
357427 LOGD (p.cast <std::string>());
358428 }
@@ -472,7 +542,7 @@ void PythonProcessor::initModule()
472542 }
473543
474544 try {
475- pyObject = new py::object (pyModule->attr (" PyProcessor" )(numChans, sampleRate));
545+ pyObject = new py::object (pyModule->attr (" PyProcessor" )(this , numChans, sampleRate));
476546 }
477547
478548 catch (std::exception& exc)
0 commit comments