1 //========================================================= 2 // MusE 3 // Linux Music Editor 4 // $Id: jackaudio.h,v 1.20.2.4 2009/12/20 05:00:35 terminator356 Exp $ 5 // (C) Copyright 2002 Werner Schweer (ws@seh.de) 6 // (C) Copyright 2015 Tim E. Real (terminator356 on sourceforge.net) 7 // 8 // This program is free software; you can redistribute it and/or 9 // modify it under the terms of the GNU General Public License 10 // as published by the Free Software Foundation; version 2 of 11 // the License, or (at your option) any later version. 12 // 13 // This program is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 // 18 // You should have received a copy of the GNU General Public License 19 // along with this program; if not, write to the Free Software 20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 // 22 //========================================================= 23 24 #ifndef __JACKAUDIO_H__ 25 #define __JACKAUDIO_H__ 26 27 #include <jack/jack.h> 28 #include <list> 29 #include "audiodev.h" 30 #include "operations.h" 31 32 class QString; 33 34 namespace MusEGlobal { 35 bool checkAudioDevice(); 36 } 37 38 namespace MusECore { 39 40 enum JackCallbackEventType {PortRegister, PortUnregister, PortConnect, PortDisconnect, GraphChanged}; 41 struct JackCallbackEvent 42 { 43 JackCallbackEventType type; 44 jack_port_id_t port_id_A; 45 jack_port_id_t port_id_B; 46 jack_port_t* port_A; 47 jack_port_t* port_B; 48 }; 49 typedef std::list<JackCallbackEvent> JackCallbackEventList; 50 typedef std::list<JackCallbackEvent>::iterator iJackCallbackEvent; 51 52 //--------------------------------------------------------- 53 // JackAudioDevice 54 //--------------------------------------------------------- 55 56 class JackAudioDevice : public AudioDevice { 57 public: 58 enum JackSyncPhases { SyncCheck = 0, SyncStarted, Syncing, Synced }; 59 enum JackTimebaseMasterPhases { MasterCheck = 0, IsNotMaster, IsMaster }; 60 61 private: 62 jack_client_t* _client; 63 jack_transport_state_t transportState; 64 jack_position_t pos; 65 char jackRegisteredName[16]; 66 // Free-running frame counter incremented always in process. 67 jack_nframes_t _frameCounter; 68 69 PendingOperationList operations; 70 // Temporary, for processing callback event FIFO. 71 JackCallbackEventList jackCallbackEvents; 72 73 void getJackPorts(const char** ports, std::list<QString>& name_list, bool midi, bool physical, int aliases); 74 static int processAudio(jack_nframes_t frames, void*); 75 76 void processGraphChanges(); 77 void processJackCallbackEvents(const Route& our_node, jack_port_t* our_port, RouteList* route_list, bool is_input); 78 void checkNewRouteConnections(jack_port_t* our_port, int channel, RouteList* route_list); 79 // Return 0: Neither disconnect nor unregister found 80 // 1: Disconnect found followed later by unregister 81 // 2: Disconnect found (with no unregister later) 82 int checkDisconnectCallback(const jack_port_t* our_port, const jack_port_t* port); 83 // Return 0: No port register found (or it was cancelled by a later unregister) 84 // 1: Port register was found. 85 int checkPortRegisterCallback(const jack_port_t* port); 86 87 static int static_JackXRunCallback(void *); 88 89 90 public: 91 JackAudioDevice(jack_client_t* cl, char * jack_id_string); 92 virtual ~JackAudioDevice(); deviceType()93 virtual inline int deviceType() const { return JACK_AUDIO; } driverName()94 virtual const char* driverName() const { return "JackAudioDevice"; } 95 96 virtual bool start(int); 97 virtual void stop (); 98 99 // These are meant to be called from inside process thread only. 100 virtual unsigned framesAtCycleStart() const; 101 virtual unsigned framesSinceCycleStart() const; 102 jackClient()103 jack_client_t* jackClient() const { return _client; } 104 virtual void registerClient(); clientName()105 virtual const char* clientName() { return jackRegisteredName; } nullify_client()106 virtual void nullify_client() { _client = 0; } 107 108 float getDSP_Load(); 109 virtual std::list<QString> outputPorts(bool midi = false, int aliases = -1); 110 virtual std::list<QString> inputPorts(bool midi = false, int aliases = -1); 111 virtual void* registerOutPort(const char* /*name*/, bool /*midi*/); 112 virtual void* registerInPort(const char* /*name*/, bool /*midi*/); 113 virtual void unregisterPort(void*); 114 virtual AudioDevice::PortType portType(void*) const; 115 virtual AudioDevice::PortDirection portDirection(void*) const; 116 virtual bool connect(void* src, void* dst); 117 virtual bool connect(const char* src, const char* dst); 118 virtual bool disconnect(void* src, void* dst); 119 virtual bool disconnect(const char* src, const char* dst); connections(void * clientPort)120 virtual int connections(void* clientPort) { return jack_port_connected((jack_port_t*)clientPort); } portConnectedTo(void * our_port,const char * port)121 virtual bool portConnectedTo(void* our_port, const char* port) { return jack_port_connected_to((jack_port_t*)our_port, port); } 122 // Returns true if the ports are connected. 123 virtual bool portsCanDisconnect(void* src, void* dst) const; 124 // Returns true if the ports are found and they are connected. 125 virtual bool portsCanDisconnect(const char* src, const char* dst) const; 126 // Returns true if the ports are not connected and CAN be connected. 127 virtual bool portsCanConnect(void* src, void* dst) const; 128 // Returns true if the ports are found and they are not connected and CAN be connected. 129 virtual bool portsCanConnect(const char* src, const char* dst) const; 130 // Returns true if the ports CAN be connected. 131 virtual bool portsCompatible(void* src, void* dst) const; 132 // Returns true if the ports are found and they CAN be connected. 133 virtual bool portsCompatible(const char* src, const char* dst) const; 134 virtual void setPortName(void* p, const char* n); 135 // preferred_name_or_alias: -1: No preference 0: Prefer canonical name 1: Prefer 1st alias 2: Prefer 2nd alias. 136 virtual char* portName(void* port, char* str, int str_size, int preferred_name_or_alias = -1); canonicalPortName(void * port)137 virtual const char* canonicalPortName(void* port) { if(!port) return NULL; return jack_port_name((jack_port_t*)port); } 138 virtual void* findPort(const char* name); 139 virtual unsigned int portLatency(void* port, bool capture) const; getBuffer(void * port,unsigned long nframes)140 virtual float* getBuffer(void* port, unsigned long nframes) { 141 return (float*)jack_port_get_buffer((jack_port_t*)port, nframes); 142 } 143 144 // Sets the amount of time to wait before sync times out, in microseconds. 145 // Note that at least with the Jack driver, this function seems not realtime friendly. 146 virtual void setSyncTimeout(unsigned usec); 147 // The number of frames that the driver waits to switch to PLAY 148 // mode after the audio sync function says it is ready to roll. 149 // For example Jack Transport waits one cycle while our own tranport does not. 150 virtual unsigned transportSyncToPlayDelay() const; 151 // The number of frames that the driver waits to relocate or switch to PLAY 152 // mode after the a call to relocation or seek. 153 // For example Jack Transport waits two cycles while our own transport does not. 154 virtual unsigned transportRelocateOrPlayDelay() const; 155 156 virtual int getState(); 157 virtual unsigned int getCurFrame() const; 158 virtual unsigned framePos() const; frameTime()159 virtual unsigned frameTime() const { return _frameCounter; } 160 virtual uint64_t systemTimeUS() const; isRealtime()161 virtual bool isRealtime() { return jack_is_realtime(_client); } 162 // Jack does this for us. setRealTime()163 virtual bool setRealTime() { return false; } 164 virtual int realtimePriority() const; 165 virtual unsigned curTransportFrame() const; 166 167 virtual void startTransport(); 168 virtual void stopTransport(); 169 virtual void seekTransport(unsigned frame); 170 virtual void seekTransport(const Pos &p); 171 virtual void setFreewheel(bool f); 172 // Whether the device has its own transport (Jack transport etc.), beyond the one built into this class. hasOwnTransport()173 virtual bool hasOwnTransport() const { return true; }; 174 // Whether the device supports timebase master capabilities. hasTimebaseMaster()175 virtual bool hasTimebaseMaster() const { return true; }; 176 // Sets or resets timebase master. Returns 0 on success. Otherwise, may return an error code. 177 virtual int setMaster(bool f, bool unconditional = false); 178 jack_transport_state_t transportQuery(jack_position_t* pos); 179 bool timebaseQuery(unsigned frames, unsigned* bar, unsigned* beat, unsigned* tick, unsigned* curr_abs_tick, unsigned* next_ticks); 180 181 void graphChanged(); 182 }; 183 184 // Our own wrappers for functions we need to look up with dlsym: 185 typedef void(*jack_get_version_type)(int*, int*, int*, int*); 186 extern jack_get_version_type jack_get_version_fp; 187 188 typedef int(*jack_port_set_name_type)(jack_port_t*, const char*); 189 extern jack_port_set_name_type jack_port_set_name_fp; 190 191 typedef int(*jack_port_rename_type)(jack_client_t*, jack_port_t*, const char*); 192 extern jack_port_rename_type jack_port_rename_fp; 193 194 195 } // namespace MusECore 196 197 #endif 198 199