1 /******************************************************************************\ 2 * Copyright (c) 2004-2020 3 * 4 * Author(s): 5 * Volker Fischer 6 * 7 ****************************************************************************** 8 * 9 * This program is free software; you can redistribute it and/or modify it under 10 * the terms of the GNU General Public License as published by the Free Software 11 * Foundation; either version 2 of the License, or (at your option) any later 12 * version. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 * details. 18 * 19 * You should have received a copy of the GNU General Public License along with 20 * this program; if not, write to the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 22 * 23 \******************************************************************************/ 24 25 #pragma once 26 27 #ifndef JACK_REPLACES_ASIO // these headers are not available in Windows OS 28 # include <unistd.h> 29 # include <sys/ioctl.h> 30 #endif 31 #include <fcntl.h> 32 #include <sys/types.h> 33 #include <stdlib.h> 34 #include <stdio.h> 35 #include <QThread> 36 #include <string.h> 37 #include "util.h" 38 #include "soundbase.h" 39 #include "global.h" 40 41 #if WITH_JACK 42 # include <jack/jack.h> 43 # include <jack/midiport.h> 44 #endif 45 46 /* Definitions ****************************************************************/ 47 #define NUM_IN_OUT_CHANNELS 2 // always stereo 48 49 // the number of periods is critical for latency 50 #define NUM_PERIOD_BLOCKS_IN 2 51 #define NUM_PERIOD_BLOCKS_OUT 1 52 53 #define MAX_SND_BUF_IN 200 54 #define MAX_SND_BUF_OUT 200 55 56 /* Classes ********************************************************************/ 57 #if WITH_JACK 58 class CSound : public CSoundBase 59 { 60 Q_OBJECT 61 62 public: CSound(void (* fpNewProcessCallback)(CVector<short> & psData,void * arg),void * arg,const QString & strMIDISetup,const bool bNoAutoJackConnect,const QString & strJackClientName)63 CSound ( void ( *fpNewProcessCallback ) ( CVector<short>& psData, void* arg ), 64 void* arg, 65 const QString& strMIDISetup, 66 const bool bNoAutoJackConnect, 67 const QString& strJackClientName ) : 68 CSoundBase ( "Jack", fpNewProcessCallback, arg, strMIDISetup ), 69 iJACKBufferSizeMono ( 0 ), 70 bJackWasShutDown ( false ), 71 fInOutLatencyMs ( 0.0f ) 72 { 73 QString strJackName = QString ( APP_NAME ); 74 75 if ( !strJackClientName.isEmpty() ) 76 { 77 strJackName += " " + strJackClientName; 78 } 79 80 OpenJack ( bNoAutoJackConnect, strJackName.toLocal8Bit().data() ); 81 } 82 ~CSound()83 virtual ~CSound() { CloseJack(); } 84 85 virtual int Init ( const int iNewPrefMonoBufferSize ); 86 virtual void Start(); 87 virtual void Stop(); 88 GetInOutLatencyMs()89 virtual float GetInOutLatencyMs() { return fInOutLatencyMs; } 90 91 // these variables should be protected but cannot since we want 92 // to access them from the callback function 93 CVector<short> vecsTmpAudioSndCrdStereo; 94 int iJACKBufferSizeMono; 95 int iJACKBufferSizeStero; 96 bool bJackWasShutDown; 97 98 jack_port_t* input_port_left; 99 jack_port_t* input_port_right; 100 jack_port_t* output_port_left; 101 jack_port_t* output_port_right; 102 jack_port_t* input_port_midi; 103 104 protected: 105 void OpenJack ( const bool bNoAutoJackConnect, const char* jackClientName ); 106 107 void CloseJack(); 108 109 // callbacks 110 static int process ( jack_nframes_t nframes, void* arg ); 111 static int bufferSizeCallback ( jack_nframes_t, void* arg ); 112 static void shutdownCallback ( void* ); 113 jack_client_t* pJackClient; 114 115 float fInOutLatencyMs; 116 }; 117 #else 118 // no sound -> dummy class definition 119 # include "server.h" 120 class CSound : public CSoundBase 121 { 122 Q_OBJECT 123 124 public: CSound(void (* fpNewProcessCallback)(CVector<short> & psData,void * pParg),void * pParg,const QString & strMIDISetup,const bool,const QString &)125 CSound ( void ( *fpNewProcessCallback ) ( CVector<short>& psData, void* pParg ), 126 void* pParg, 127 const QString& strMIDISetup, 128 const bool, 129 const QString& ) : 130 CSoundBase ( "nosound", fpNewProcessCallback, pParg, strMIDISetup ), 131 HighPrecisionTimer ( true ) 132 { 133 HighPrecisionTimer.Start(); 134 QObject::connect ( &HighPrecisionTimer, &CHighPrecisionTimer::timeout, this, &CSound::OnTimer ); 135 } ~CSound()136 virtual ~CSound() {} Init(const int iNewPrefMonoBufferSize)137 virtual int Init ( const int iNewPrefMonoBufferSize ) 138 { 139 CSoundBase::Init ( iNewPrefMonoBufferSize ); 140 vecsTemp.Init ( 2 * iNewPrefMonoBufferSize ); 141 return iNewPrefMonoBufferSize; 142 } 143 CHighPrecisionTimer HighPrecisionTimer; 144 CVector<short> vecsTemp; 145 146 public slots: OnTimer()147 void OnTimer() 148 { 149 vecsTemp.Reset ( 0 ); 150 if ( IsRunning() ) 151 { 152 ProcessCallback ( vecsTemp ); 153 } 154 } 155 }; 156 #endif // WITH_JACK 157