src/JackHandler.h
branchv_0
changeset 20 ccc4e509c1f0
parent 19 dcd98589f4b8
child 21 70b252d02a92
equal deleted inserted replaced
19:dcd98589f4b8 20:ccc4e509c1f0
   175 	void failInConstructor(const relpipe::common::type::StringX& errorMessage) {
   175 	void failInConstructor(const relpipe::common::type::StringX& errorMessage) {
   176 		finalize();
   176 		finalize();
   177 		throw JackException(errorMessage);
   177 		throw JackException(errorMessage);
   178 	}
   178 	}
   179 
   179 
       
   180 	/**
       
   181 	 * Wait for the signal that is emitted at the end of the real-time processCallback() cycle.
       
   182 	 */
       
   183 	void waitForRTCycle() {
       
   184 		pthread_cond_wait(&realTimeContext.processingDone, &realTimeContext.processingLock);
       
   185 	}
       
   186 
   180 public:
   187 public:
   181 
   188 
   182 	JackHandler(Configuration& configuration) : configuration(configuration) {
   189 	JackHandler(Configuration& configuration) : configuration(configuration) {
   183 		pthread_mutex_unlock(&realTimeContext.processingLock);
   190 		pthread_mutex_unlock(&realTimeContext.processingLock);
   184 
   191 
   230 	}
   237 	}
   231 
   238 
   232 	void attribute(const relpipe::common::type::StringX& value) override {
   239 	void attribute(const relpipe::common::type::StringX& value) override {
   233 		if (relationContext.skip) return;
   240 		if (relationContext.skip) return;
   234 		// TODO: switch to RelationalReaderValueHandler
   241 		// TODO: switch to RelationalReaderValueHandler
   235 		// TODO: if (continueProcessing) {} ?
       
   236 
   242 
   237 		RelationContext& rel = relationContext;
   243 		RelationContext& rel = relationContext;
   238 		RelationContext::RecordContext& rec = rel.recordContext;
   244 		RelationContext::RecordContext& rec = rel.recordContext;
   239 
   245 
   240 		const auto attributeName = rel.attributes[rec.attributeIndex].getAttributeName();
   246 		const auto attributeName = rel.attributes[rec.attributeIndex].getAttributeName();
   250 
   256 
   251 		rec.attributeIndex++;
   257 		rec.attributeIndex++;
   252 
   258 
   253 		if (rec.attributeIndex == rel.attributes.size()) {
   259 		if (rec.attributeIndex == rel.attributes.size()) {
   254 
   260 
   255 			while (jack_ringbuffer_write_space(realTimeContext.ringBuffer) < sizeof (MidiMessage)) usleep(1000); // should not happen, the real-time thread should be faster
   261 			while (continueProcessing && jack_ringbuffer_write_space(realTimeContext.ringBuffer) < sizeof (MidiMessage)) waitForRTCycle(); // should not happen, the real-time thread should be faster; see also note in endOfPipe()
       
   262 			if (!continueProcessing) return;
   256 
   263 
   257 			MidiMessage m;
   264 			MidiMessage m;
   258 
   265 
   259 			// TODO: correct timing?
   266 			// TODO: correct timing?
   260 			m.time = 0;
   267 			m.time = 0;
   298 	void endOfPipe() {
   305 	void endOfPipe() {
   299 		// TODO: optionally mute all; probably enabled by default
   306 		// TODO: optionally mute all; probably enabled by default
   300 
   307 
   301 		// Wait until the ring buffer is empty (messages dequeued from the buffer) and real-time cycle was finished (messages passed to JACK)
   308 		// Wait until the ring buffer is empty (messages dequeued from the buffer) and real-time cycle was finished (messages passed to JACK)
   302 		while (continueProcessing && jack_ringbuffer_read_space(realTimeContext.ringBuffer)) pthread_cond_wait(&realTimeContext.processingDone, &realTimeContext.processingLock);
   309 		while (continueProcessing && jack_ringbuffer_read_space(realTimeContext.ringBuffer)) pthread_cond_wait(&realTimeContext.processingDone, &realTimeContext.processingLock);
       
   310 
       
   311 		// There might be a (rare) race condition.
       
   312 		// Between jack_ringbuffer_read_space() and pthread_cond_wait() the real-time thread might finish the cycle and we will miss the pthread_cond_signal()
       
   313 		// and will sleep until the next cycle. In endOfPipe() it is not a big problem.
       
   314 		// But missing the cycle in attribute() might be worse.
       
   315 		// However it should not happen due to the buffer size
       
   316 		// and amount of work done in the real-time thread (message copying) vs. amount of work done between the jack_ringbuffer_write_space() and pthread_cond_wait() calls (nothing).
   303 	}
   317 	}
   304 
   318 
   305 	void finish(int sig) {
   319 	void finish(int sig) {
   306 		continueProcessing = false;
   320 		continueProcessing = false;
   307 	}
   321 	}