Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for using jack midi input #2038

Merged
merged 14 commits into from
Nov 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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