Skip to content

Commit

Permalink
Support for using jack midi input (#2038)
Browse files Browse the repository at this point in the history
* Support jack midi input

* If jack is used for audio then use the same connection for midi as well

* Remove old FreeBSD adjustment for portaudio as multiple version support has been dropped.

* Disable jack midi out port until it is functional
  • Loading branch information
sambler authored and zonkmachine committed Nov 9, 2016
1 parent c961896 commit 05ace7e
Show file tree
Hide file tree
Showing 9 changed files with 366 additions and 6 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ MESSAGE(
"* ALSA : ${STATUS_ALSA}\n"
"* OSS : ${STATUS_OSS}\n"
"* Sndio : ${STATUS_SNDIO}\n"
"* JACK : ${STATUS_JACK}\n"
"* WinMM : ${STATUS_WINMM}\n"
"* AppleMidi : ${STATUS_APPLEMIDI}\n"
)
Expand Down
9 changes: 8 additions & 1 deletion include/AudioJack.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
#include "AudioDevice.h"
#include "AudioDeviceSetupWidget.h"


class QLineEdit;
class LcdSpinBox;
class MidiJack;


class AudioJack : public QObject, public AudioDevice
Expand All @@ -49,6 +49,12 @@ class AudioJack : public QObject, public AudioDevice
AudioJack( bool & _success_ful, Mixer* mixer );
virtual ~AudioJack();

// this is to allow the jack midi connection to use the same jack client connection
// the jack callback is handled here, we call the midi client so that it can read
// it's midi data during the callback
AudioJack * addMidiClient(MidiJack *midiClient);
jack_client_t * jackClient() {return m_client;};

inline static QString name()
{
return QT_TRANSLATE_NOOP( "setupWidget",
Expand Down Expand Up @@ -98,6 +104,7 @@ private slots:
bool m_active;
bool m_stopped;

MidiJack *m_midiClient;
QVector<jack_port_t *> m_outputPorts;
jack_default_audio_sample_t * * m_tempOutBufs;
surroundSampleFrame * m_outBuf;
Expand Down
4 changes: 0 additions & 4 deletions include/AudioPortAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,7 @@ public slots:

#ifdef LMMS_HAVE_PORTAUDIO

#if defined(__FreeBSD__)
#include <portaudio2/portaudio.h>
#else
#include <portaudio.h>
#endif

#include <QtCore/QSemaphore>

Expand Down
95 changes: 95 additions & 0 deletions include/MidiJack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* MidiJack.h - MIDI client for Jack
*
* Copyright (c) 2015 Shane Ambler <develop/at/shaneware.biz>
*
* This file is part of LMMS - http://lmms.io
*
* This program 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 2 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/

#ifndef MIDIJACK_H
#define MIDIJACK_H

#include "lmmsconfig.h"

#ifdef LMMS_HAVE_JACK
#include <jack/jack.h>
#include <jack/midiport.h>

#include <QtCore/QThread>
#include <QMutex>
#include <QtCore/QFile>

#include "MidiClient.h"
#include "AudioJack.h"

#define JACK_MIDI_BUFFER_MAX 64 /* events */

class QLineEdit;

class MidiJack : public MidiClientRaw, public QThread
{
public:
MidiJack();
virtual ~MidiJack();

jack_client_t* jackClient();

static QString probeDevice();

inline static QString name()
{
return( QT_TRANSLATE_NOOP( "MidiSetupWidget",
"Jack-MIDI" ) );
}

void JackMidiWrite(jack_nframes_t nframes);
void JackMidiRead(jack_nframes_t nframes);


inline static QString configSection()
{
return "MidiJack";
}


protected:
virtual void sendByte( const unsigned char c );
virtual void run();


private:
AudioJack *m_jackAudio;
jack_client_t *m_jackClient;
jack_port_t *m_input_port;
jack_port_t *m_output_port;
uint8_t m_jack_buffer[JACK_MIDI_BUFFER_MAX * 4];

void JackMidiOutEvent(uint8_t *buf, uint8_t len);
void lock();
void unlock();

void getPortInfo( const QString& sPortName, int& nClient, int& nPort );

volatile bool m_quit;

};

#endif // LMMS_HAVE_JACK

#endif // MIDIJACK_H
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ set(LMMS_SRCS
core/midi/MidiAlsaSeq.cpp
core/midi/MidiClient.cpp
core/midi/MidiController.cpp
core/midi/MidiJack.cpp
core/midi/MidiOss.cpp
core/midi/MidiSndio.cpp
core/midi/MidiApple.cpp
Expand Down
14 changes: 14 additions & 0 deletions src/core/Mixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
// platform-specific midi-interface-classes
#include "MidiAlsaRaw.h"
#include "MidiAlsaSeq.h"
#include "MidiJack.h"
#include "MidiOss.h"
#include "MidiSndio.h"
#include "MidiWinMM.h"
Expand Down Expand Up @@ -975,6 +976,19 @@ MidiClient * Mixer::tryMidiClients()
}
#endif

#ifdef LMMS_HAVE_JACK
if( client_name == MidiJack::name() || client_name == "" )
{
MidiJack * mjack = new MidiJack;
if( mjack->isRunning() )
{
m_midiClientName = MidiJack::name();
return mjack;
}
delete mjack;
}
#endif

#ifdef LMMS_HAVE_OSS
if( client_name == MidiOss::name() || client_name == "" )
{
Expand Down
19 changes: 18 additions & 1 deletion src/core/audio/AudioJack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
#include "AudioPort.h"
#include "MainWindow.h"
#include "Mixer.h"

#include "MidiJack.h"



Expand All @@ -52,6 +52,7 @@ AudioJack::AudioJack( bool & _success_ful, Mixer* _mixer ) :
_mixer ),
m_client( NULL ),
m_active( false ),
m_midiClient( NULL ),
m_tempOutBufs( new jack_default_audio_sample_t *[channels()] ),
m_outBuf( new surroundSampleFrame[mixer()->framesPerPeriod()] ),
m_framesDoneInCurBuf( 0 ),
Expand Down Expand Up @@ -123,7 +124,15 @@ void AudioJack::restartAfterZombified()



AudioJack* AudioJack::addMidiClient(MidiJack *midiClient)
{
if( m_client == NULL )
return NULL;

m_midiClient = midiClient;

return this;
}

bool AudioJack::initJackClient()
{
Expand Down Expand Up @@ -331,6 +340,14 @@ void AudioJack::renamePort( AudioPort * _port )

int AudioJack::processCallback( jack_nframes_t _nframes, void * _udata )
{
// do midi processing first so that midi input can
// add to the following sound processing
if( m_midiClient && _nframes > 0 )
{
m_midiClient->JackMidiRead(_nframes);
m_midiClient->JackMidiWrite(_nframes);
}

for( int c = 0; c < channels(); ++c )
{
m_tempOutBufs[c] =
Expand Down
Loading

0 comments on commit 05ace7e

Please sign in to comment.