int rb_read_from_buffer(ring_buffer *buffer, char *dest, int len) { if (len == 0) return 0; if (!buffer || len < 0 || len > rb_available_to_read(buffer)) return -1; // Note that rb_available_to_read also serves as a memory barrier, and so any // writes to buffer->buf_ptr that precede the update of buffer->write_idx are // visible to us now. int read_idx = buffer->read_idx; // No need for sync in reader thread. if (read_idx + len <= buffer->size) { memcpy(dest, buffer->buf_ptr + read_idx, len); } else { int d = buffer->size - read_idx; memcpy(dest, buffer->buf_ptr + read_idx, d); memcpy(dest + d, buffer->buf_ptr, len - d); } SYNC_COMPARE_AND_SWAP(&(buffer->read_idx), buffer->read_idx, (read_idx + len) % buffer->size); // Includes memory barrier. return 0; }
void libpd_queued_receive_midi_messages() { size_t available = rb_available_to_read(midi_receive_buffer); if (!available) return; static char temp_buffer[BUFFER_SIZE]; rb_read_from_buffer(midi_receive_buffer, temp_buffer, available); char *end = temp_buffer + available; char *buffer = temp_buffer; while (buffer < end) { midi_params *p = (midi_params *)buffer; buffer += S_MIDI_PARAMS; switch (p->type) { case LIBPD_NOTEON: { receive_noteon(p, &buffer); break; } case LIBPD_CONTROLCHANGE: { receive_controlchange(p, &buffer); break; } case LIBPD_PROGRAMCHANGE: { receive_programchange(p, &buffer); break; } case LIBPD_PITCHBEND: { receive_pitchbend(p, &buffer); break; } case LIBPD_AFTERTOUCH: { receive_aftertouch(p, &buffer); break; } case LIBPD_POLYAFTERTOUCH: { receive_polyaftertouch(p, &buffer); break; } case LIBPD_MIDIBYTE: { receive_midibyte(p, &buffer); break; } default: break; } } }
void libpd_queued_receive_pd_messages() { size_t available = rb_available_to_read(pd_receive_buffer); if (!available) return; static char temp_buffer[BUFFER_SIZE]; rb_read_from_buffer(pd_receive_buffer, temp_buffer, available); char *end = temp_buffer + available; char *buffer = temp_buffer; while (buffer < end) { pd_params *p = (pd_params *)buffer; buffer += S_PD_PARAMS; switch (p->type) { case LIBPD_PRINT: { receive_print(p, &buffer); break; } case LIBPD_BANG: { receive_bang(p, &buffer); break; } case LIBPD_FLOAT: { receive_float(p, &buffer); break; } case LIBPD_SYMBOL: { receive_symbol(p, &buffer); break; } case LIBPD_LIST: { receive_list(p, &buffer); break; } case LIBPD_MESSAGE: { receive_message(p, &buffer); break; } default: break; } } }