123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- /*
- This file is part of QTau
- Copyright (C) 2013-2018 Tobias "Tomoko" Platen <tplaten@posteo.de>
- Copyright (C) 2013 digited <https://github.com/digited>
- Copyright (C) 2010-2013 HAL@ShurabaP <https://github.com/haruneko>
- QTau is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: GPL-3.0+
- */
- #define __devloglevel__ 4
- #include "jackaudio.h"
- #include <assert.h>
- #include <stdio.h>
- #include <QDebug>
- #include <QIcon>
- #include <QMessageBox>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/eventfd.h>
- #include <unistd.h>
- #include <jack/midiport.h>
- #include <iostream>
- int JackAudio::createEFD() {
- _eventfd = eventfd(0, 0);
- return _eventfd;
- }
- int JackAudio::readMidiData(char *buffer, int maxlength) {
- int count = jack_ringbuffer_read_space(this->_midi_rb);
- if (count > 0) {
- if (count > maxlength) count = maxlength;
- jack_ringbuffer_read(this->_midi_rb, buffer, count);
- }
- return count;
- }
- int JackAudio::process(jack_nframes_t nframes, void *arg) {
- JackAudio *conn = (JackAudio *)arg;
- // midi input handing
- void *port_buf = jack_port_get_buffer(conn->_midi_port, nframes);
- jack_nframes_t event_count = jack_midi_get_event_count(port_buf);
- if (event_count > 0) {
- for (jack_nframes_t i = 0; i < event_count; i++) {
- jack_midi_event_t in_event;
- // jack_position_t position;
- jack_midi_event_get(&in_event, port_buf, i);
- // FIXME: sysex support
- jack_ringbuffer_write(conn->_midi_rb, (char *)in_event.buffer,
- in_event.size);
- }
- }
- // audio output
- sample_t *write_samp =
- (sample_t *)jack_port_get_buffer(conn->_write_port, nframes);
- if (jack_ringbuffer_read_space(conn->_write_rb) >=
- sizeof(sample_t) * nframes) {
- jack_ringbuffer_read(conn->_write_rb, (char *)write_samp,
- sizeof(sample_t) * nframes);
- } else {
- for (unsigned int i = 0; i < nframes; i++)
- write_samp[i] = 0.0; // buffer underrun
- DEVLOG_DEBUG("xrun in JackAudio::process");
- }
- // transport control
- if (conn->_use_transport) {
- conn->_transport_state = jack_transport_query(conn->_client, NULL);
- if (conn->_transport_state == JackTransportStopped &&
- conn->_previous_transport_state == JackTransportRolling) {
- conn->_state_changed = true;
- }
- if (conn->_transport_state == JackTransportStarting &&
- conn->_previous_transport_state != JackTransportStarting) {
- conn->_state_changed = true;
- }
- if (conn->_transport_state == JackTransportRolling &&
- conn->_previous_transport_state != JackTransportRolling) {
- conn->_state_changed = true;
- }
- conn->_previous_transport_state = conn->_transport_state;
- }
- if (conn->_transport_command == TRANSPORT_START)
- jack_transport_start(conn->_client);
- if (conn->_transport_command == TRANSPORT_STOP)
- jack_transport_stop(conn->_client);
- if (conn->_transport_command == TRANSPORT_ZERO) {
- jack_position_t pos;
- pos.valid = (jack_position_bits_t)0;
- pos.frame = 0;
- jack_transport_stop(conn->_client);
- jack_transport_reposition(conn->_client, &pos);
- }
- if (conn->_transport_command == TRANSPORT_STARTPOS) {
- jack_position_t pos;
- pos.valid = (jack_position_bits_t)0;
- pos.frame = conn->_startpos * conn->sampleRate();
- jack_transport_stop(conn->_client);
- jack_transport_reposition(conn->_client, &pos);
- jack_transport_start(conn->_client);
- }
- conn->_transport_command = 0;
- // notify
- uint64_t u = 1;
- if (write(conn->_eventfd, &u, sizeof(uint64_t)) != 8) return 1;
- // no error
- return 0;
- }
- int JackAudio::sync(jack_transport_state_t state, jack_position_t *pos,
- void *arg) {
- (void)state;
- // start tranport
- JackAudio *conn = (JackAudio *)arg;
- if (conn->_use_transport) {
- conn->_position = pos->frame;
- return 1;
- } else
- return 1;
- }
- JackAudio::JackAudio(bool autoconnect) {
- _client = jack_client_open("QTau", JackNoStartServer, NULL);
- if (_client == NULL) {
- QMessageBox msgbox;
- msgbox.setText("jack is not running");
- msgbox.exec();
- exit(1);
- }
- _buffer_size = jack_get_buffer_size(_client);
- // TODO configurable port names ???
- _write_port = jack_port_register(_client, "out", JACK_DEFAULT_AUDIO_TYPE,
- JackPortIsOutput, _buffer_size);
- _write_rb = jack_ringbuffer_create(sizeof(sample_t) * 4096);
- _midi_rb = jack_ringbuffer_create(4096);
- _midi_port = jack_port_register(_client, "midi_in", JACK_DEFAULT_MIDI_TYPE,
- JackPortIsInput, 0);
- jack_set_process_callback(_client, process, this);
- jack_set_sync_callback(_client, sync, this);
- jack_activate(_client);
- if (autoconnect) {
- jack_connect(_client, "QTau:out", "system:playback_2"); // FOR testing
- jack_connect(_client, "QTau:out", "system:playback_1"); // FOR testing
- }
- _transport_command = TRANSPORT_ZERO;
- _use_transport = true;
- _playback = false;
- }
- int JackAudio::sampleRate() { return jack_get_sample_rate(_client); }
- int JackAudio::writeData(void *framebuf, int bytes_per_frame) {
- if (jack_ringbuffer_write_space(_write_rb) >= (unsigned int)bytes_per_frame) {
- return jack_ringbuffer_write(_write_rb, (char *)framebuf, bytes_per_frame);
- }
- DEVLOG_DEBUG("xrun in JackAudio::writeData"); // FIXME do not log while
- // program startup
- return 0; // not data was written
- }
- float *JackAudio::allocateBuffer() {
- if (_buffer_size == 0) return NULL;
- return new float[_buffer_size];
- }
- void JackAudio::shutdown() {
- jack_deactivate(_client);
- jack_client_close(_client);
- }
|